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.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_HIGH_MVMT;
19 import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_LOW_MVMT;
20 import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_STATIONARY;
21 import static android.net.wifi.WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN;
22 
23 import static com.android.server.wifi.WifiMetricsTestUtil.assertDeviceMobilityStatePnoScanStatsEqual;
24 import static com.android.server.wifi.WifiMetricsTestUtil.assertExperimentProbeCountsEqual;
25 import static com.android.server.wifi.WifiMetricsTestUtil.assertHistogramBucketsEqual;
26 import static com.android.server.wifi.WifiMetricsTestUtil.assertKeyCountsEqual;
27 import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeFailureReasonCountsEqual;
28 import static com.android.server.wifi.WifiMetricsTestUtil.assertLinkProbeStaEventsEqual;
29 import static com.android.server.wifi.WifiMetricsTestUtil.buildDeviceMobilityStatePnoScanStats;
30 import static com.android.server.wifi.WifiMetricsTestUtil.buildExperimentProbeCounts;
31 import static com.android.server.wifi.WifiMetricsTestUtil.buildHistogramBucketInt32;
32 import static com.android.server.wifi.WifiMetricsTestUtil.buildInt32Count;
33 import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureReasonCount;
34 import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureStaEvent;
35 import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeSuccessStaEvent;
36 import static com.android.server.wifi.nano.WifiMetricsProto.StaEvent.TYPE_LINK_PROBE;
37 
38 import static org.junit.Assert.assertEquals;
39 import static org.junit.Assert.assertFalse;
40 import static org.junit.Assert.assertNotNull;
41 import static org.junit.Assert.assertNull;
42 import static org.junit.Assert.assertTrue;
43 import static org.junit.Assert.fail;
44 import static org.mockito.Mockito.any;
45 import static org.mockito.Mockito.anyBoolean;
46 import static org.mockito.Mockito.anyInt;
47 import static org.mockito.Mockito.doThrow;
48 import static org.mockito.Mockito.eq;
49 import static org.mockito.Mockito.mock;
50 import static org.mockito.Mockito.never;
51 import static org.mockito.Mockito.verify;
52 import static org.mockito.Mockito.when;
53 
54 import android.content.Context;
55 import android.net.wifi.EAPConstants;
56 import android.net.wifi.IOnWifiUsabilityStatsListener;
57 import android.net.wifi.ScanResult;
58 import android.net.wifi.SupplicantState;
59 import android.net.wifi.WifiConfiguration;
60 import android.net.wifi.WifiEnterpriseConfig;
61 import android.net.wifi.WifiInfo;
62 import android.net.wifi.WifiManager;
63 import android.net.wifi.WifiSsid;
64 import android.net.wifi.hotspot2.PasspointConfiguration;
65 import android.net.wifi.hotspot2.ProvisioningCallback;
66 import android.net.wifi.hotspot2.pps.Credential;
67 import android.os.Handler;
68 import android.os.IBinder;
69 import android.os.RemoteException;
70 import android.os.test.TestLooper;
71 import android.provider.Settings;
72 import android.telephony.TelephonyManager;
73 import android.util.Base64;
74 import android.util.Pair;
75 import android.util.SparseIntArray;
76 
77 import androidx.test.filters.MediumTest;
78 import androidx.test.filters.SmallTest;
79 
80 import com.android.server.wifi.aware.WifiAwareMetrics;
81 import com.android.server.wifi.hotspot2.NetworkDetail;
82 import com.android.server.wifi.hotspot2.PasspointManager;
83 import com.android.server.wifi.hotspot2.PasspointMatch;
84 import com.android.server.wifi.hotspot2.PasspointProvider;
85 import com.android.server.wifi.nano.WifiMetricsProto;
86 import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount;
87 import com.android.server.wifi.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats;
88 import com.android.server.wifi.nano.WifiMetricsProto.HistogramBucketInt32;
89 import com.android.server.wifi.nano.WifiMetricsProto.Int32Count;
90 import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats;
91 import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
92 import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
93 import com.android.server.wifi.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
94 import com.android.server.wifi.nano.WifiMetricsProto.PasspointProfileTypeCount;
95 import com.android.server.wifi.nano.WifiMetricsProto.PasspointProvisionStats;
96 import com.android.server.wifi.nano.WifiMetricsProto.PnoScanMetrics;
97 import com.android.server.wifi.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
98 import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
99 import com.android.server.wifi.nano.WifiMetricsProto.WifiIsUnusableEvent;
100 import com.android.server.wifi.nano.WifiMetricsProto.WifiRadioUsage;
101 import com.android.server.wifi.nano.WifiMetricsProto.WifiUsabilityStats;
102 import com.android.server.wifi.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
103 import com.android.server.wifi.nano.WifiMetricsProto.WpsMetrics;
104 import com.android.server.wifi.p2p.WifiP2pMetrics;
105 import com.android.server.wifi.rtt.RttMetrics;
106 import com.android.server.wifi.util.ExternalCallbackTracker;
107 
108 import org.junit.Before;
109 import org.junit.Test;
110 import org.mockito.ArgumentCaptor;
111 import org.mockito.Mock;
112 import org.mockito.MockitoAnnotations;
113 
114 import java.io.ByteArrayOutputStream;
115 import java.io.FileDescriptor;
116 import java.io.PrintWriter;
117 import java.io.StringWriter;
118 import java.util.ArrayList;
119 import java.util.Arrays;
120 import java.util.BitSet;
121 import java.util.HashMap;
122 import java.util.List;
123 import java.util.Map;
124 import java.util.Random;
125 import java.util.regex.Matcher;
126 import java.util.regex.Pattern;
127 
128 /**
129  * Unit tests for {@link com.android.server.wifi.WifiMetrics}.
130  */
131 @SmallTest
132 public class WifiMetricsTest {
133 
134     WifiMetrics mWifiMetrics;
135     WifiMetricsProto.WifiLog mDecodedProto;
136     TestLooper mTestLooper;
137     Random mRandom = new Random();
138     private static final int TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER = 2;
139     private static final int TEST_NETWORK_ID = 42;
140     @Mock Context mContext;
141     @Mock FrameworkFacade mFacade;
142     @Mock Clock mClock;
143     @Mock ScoringParams mScoringParams;
144     @Mock WifiConfigManager mWcm;
145     @Mock PasspointManager mPpm;
146     @Mock WifiNetworkSelector mWns;
147     @Mock WifiPowerMetrics mWifiPowerMetrics;
148     @Mock WifiDataStall mWifiDataStall;
149     @Mock IBinder mAppBinder;
150     @Mock IOnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
151     @Mock ExternalCallbackTracker<IOnWifiUsabilityStatsListener> mListenerTracker;
152     @Mock WifiP2pMetrics mWifiP2pMetrics;
153     @Mock DppMetrics mDppMetrics;
154     @Mock CellularLinkLayerStatsCollector mCellularLinkLayerStatsCollector;
155     @Mock CellularLinkLayerStats mCellularLinkLayerStats;
156 
157     @Before
setUp()158     public void setUp() throws Exception {
159         MockitoAnnotations.initMocks(this);
160         mDecodedProto = null;
161         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
162         when(mCellularLinkLayerStatsCollector.update()).thenReturn(mCellularLinkLayerStats);
163         mTestLooper = new TestLooper();
164         mWifiMetrics = new WifiMetrics(mContext, mFacade, mClock, mTestLooper.getLooper(),
165                 new WifiAwareMetrics(mClock), new RttMetrics(mClock), mWifiPowerMetrics,
166                 mWifiP2pMetrics, mDppMetrics, mCellularLinkLayerStatsCollector);
167         mWifiMetrics.setWifiConfigManager(mWcm);
168         mWifiMetrics.setPasspointManager(mPpm);
169         mWifiMetrics.setScoringParams(mScoringParams);
170         mWifiMetrics.setWifiNetworkSelector(mWns);
171         mWifiMetrics.setWifiDataStall(mWifiDataStall);
172     }
173 
174     /**
175      * Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of
176      * order. Only tests no exception occurs. Creates 3 ConnectionEvents.
177      */
178     @Test
startAndEndConnectionEventSucceeds()179     public void startAndEndConnectionEventSucceeds() throws Exception {
180         //Start and end Connection event
181         mWifiMetrics.startConnectionEvent(null, "RED",
182                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
183         mWifiMetrics.endConnectionEvent(
184                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
185                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
186                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
187         //end Connection event without starting one
188         mWifiMetrics.endConnectionEvent(
189                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
190                 WifiMetricsProto.ConnectionEvent.HLF_DHCP,
191                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
192         //start two ConnectionEvents in a row
193         mWifiMetrics.startConnectionEvent(null, "BLUE",
194                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
195         mWifiMetrics.startConnectionEvent(null, "GREEN",
196                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
197     }
198 
199     private static final long TEST_RECORD_DURATION_SEC = 12 * 60 * 60;
200     private static final long TEST_RECORD_DURATION_MILLIS = TEST_RECORD_DURATION_SEC * 1000;
201     /**
202      * Simulate how dumpsys gets the proto from mWifiMetrics, filter the proto bytes out and
203      * deserialize them into mDecodedProto
204      */
dumpProtoAndDeserialize()205     public void dumpProtoAndDeserialize() throws Exception {
206         ByteArrayOutputStream stream = new ByteArrayOutputStream();
207         PrintWriter writer = new PrintWriter(stream);
208 
209         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
210         //Test proto dump, by passing in proto arg option
211         String[] args = {WifiMetrics.PROTO_DUMP_ARG};
212         mWifiMetrics.dump(null, writer, args);
213         writer.flush();
214         Pattern pattern = Pattern.compile(
215                 "(?<=WifiMetrics:\\n)([\\s\\S]*)(?=EndWifiMetrics)");
216         Matcher matcher = pattern.matcher(stream.toString());
217         assertTrue("Proto Byte string found in WifiMetrics.dump():\n" + stream.toString(),
218                 matcher.find());
219         String protoByteString = matcher.group(1);
220         byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
221         mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
222     }
223 
224     /**
225      * Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into
226      * mDecodedProto
227      */
cleanDumpProtoAndDeserialize()228     public void cleanDumpProtoAndDeserialize() throws Exception {
229         ByteArrayOutputStream stream = new ByteArrayOutputStream();
230         PrintWriter writer = new PrintWriter(stream);
231 
232         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
233         //Test proto dump, by passing in proto arg option
234         String[] args = {WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG};
235         mWifiMetrics.dump(null, writer, args);
236         writer.flush();
237         String protoByteString = stream.toString();
238         byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
239         mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
240     }
241 
242     /** Verifies that dump() includes the expected header */
243     @Test
stateDumpIncludesHeader()244     public void stateDumpIncludesHeader() throws Exception {
245         assertStringContains(getStateDump(), "WifiMetrics");
246     }
247 
248     /** Verifies that dump() includes correct alert count when there are no alerts. */
249     @Test
stateDumpAlertCountIsCorrectWithNoAlerts()250     public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception {
251         assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()");
252     }
253 
254     /** Verifies that dump() includes correct alert count when there is one alert. */
255     @Test
stateDumpAlertCountIsCorrectWithOneAlert()256     public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception {
257         mWifiMetrics.logFirmwareAlert(1);
258         assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)");
259     }
260 
261     /** Verifies that dump() includes correct alert count when there are multiple alerts. */
262     @Test
stateDumpAlertCountIsCorrectWithMultipleAlerts()263     public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception {
264         mWifiMetrics.logFirmwareAlert(1);
265         mWifiMetrics.logFirmwareAlert(1);
266         mWifiMetrics.logFirmwareAlert(16);
267         assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)");
268     }
269 
270     @Test
testDumpProtoAndDeserialize()271     public void testDumpProtoAndDeserialize() throws Exception {
272         setAndIncrementMetrics();
273         dumpProtoAndDeserialize();
274         verify(mWifiP2pMetrics).consolidateProto();
275         assertDeserializedMetricsCorrect();
276     }
277 
278     private static final int NUM_OPEN_NETWORKS = 2;
279     private static final int NUM_LEGACY_PERSONAL_NETWORKS = 3;
280     private static final int NUM_LEGACY_ENTERPRISE_NETWORKS = 5;
281     private static final int NUM_ENHANCED_OPEN_NETWORKS = 1;
282     private static final int NUM_WPA3_PERSONAL_NETWORKS = 4;
283     private static final int NUM_WPA3_ENTERPRISE_NETWORKS = 6;
284     private static final int NUM_SAVED_NETWORKS = NUM_OPEN_NETWORKS + NUM_LEGACY_PERSONAL_NETWORKS
285             + NUM_LEGACY_ENTERPRISE_NETWORKS + NUM_ENHANCED_OPEN_NETWORKS
286             + NUM_WPA3_PERSONAL_NETWORKS + NUM_WPA3_ENTERPRISE_NETWORKS;
287     private static final int NUM_HIDDEN_NETWORKS = NUM_OPEN_NETWORKS;
288     private static final int NUM_PASSPOINT_NETWORKS = NUM_LEGACY_ENTERPRISE_NETWORKS;
289     private static final int NUM_NETWORKS_ADDED_BY_USER = 1;
290     private static final int NUM_NETWORKS_ADDED_BY_APPS = NUM_SAVED_NETWORKS
291             - NUM_NETWORKS_ADDED_BY_USER;
292     private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true;
293     private static final boolean IS_SCANNING_ALWAYS_ENABLED = true;
294     private static final int NUM_EMPTY_SCAN_RESULTS = 19;
295     private static final int NUM_NON_EMPTY_SCAN_RESULTS = 23;
296     private static final int NUM_SCAN_UNKNOWN = 1;
297     private static final int NUM_SCAN_SUCCESS = 2;
298     private static final int NUM_SCAN_FAILURE_INTERRUPTED = 3;
299     private static final int NUM_SCAN_FAILURE_INVALID_CONFIGURATION = 5;
300     private static final int NUM_WIFI_UNKNOWN_SCREEN_OFF = 3;
301     private static final int NUM_WIFI_UNKNOWN_SCREEN_ON = 5;
302     private static final int NUM_WIFI_ASSOCIATED_SCREEN_OFF = 7;
303     private static final int NUM_WIFI_ASSOCIATED_SCREEN_ON = 11;
304     private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD = 11;
305     private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_BAD = 12;
306     private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD = 13;
307     private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD = 14;
308     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS = 1;
309     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL = 2;
310     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL = 3;
311     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL = 4;
312     private static final int NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL = 5;
313     private static final int NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL = 6;
314     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION = 7;
315     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8;
316     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9;
317     private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10;
318     private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5;
319     private static final int WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER = 6;
320     private static final int RSSI_POLL_FREQUENCY = 5150;
321     private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20;
322     private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1;
323     private static final int NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS = 4;
324     private static final int NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS = 3;
325     private static final int NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS = 1;
326     private static final int NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS = 2;
327     private static final int NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS = 1;
328     private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1;
329     private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1;
330     private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2;
331     private static final int NUM_SCANS = 5;
332     private static final int NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT = 4;
333     private static final int NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS = 15;
334     private static final int NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 10;
335     private static final int NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 16;
336     // Look at buildMockScanDetailList, this number needs to match the mocked results
337     private static final int NUM_TOTAL_SCAN_RESULTS = NUM_OPEN_NETWORK_SCAN_RESULTS
338             + NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS + NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS
339             + NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS + NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS
340             + NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS;
341     private static final int MIN_RSSI_LEVEL = -127;
342     private static final int MAX_RSSI_LEVEL = 0;
343     private static final int WIFI_SCORE_RANGE_MIN = 0;
344     private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20;
345     private static final int WIFI_SCORE_RANGE_MAX = 60;
346     private static final int NUM_OUT_OF_BOUND_ENTRIES = 10;
347     private static final int MAX_NUM_SOFTAP_RETURN_CODES = 3;
348     private static final int NUM_SOFTAP_START_SUCCESS = 3;
349     private static final int NUM_SOFTAP_FAILED_GENERAL_ERROR = 2;
350     private static final int NUM_SOFTAP_FAILED_NO_CHANNEL = 1;
351     private static final int NUM_HAL_CRASHES = 11;
352     private static final int NUM_WIFICOND_CRASHES = 12;
353     private static final int NUM_SUPPLICANT_CRASHES = 23;
354     private static final int NUM_HOSTAPD_CRASHES = 7;
355     private static final int NUM_WIFI_ON_FAILURE_DUE_TO_HAL = 13;
356     private static final int NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND = 14;
357     private static final int NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT = 20;
358     private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL = 23;
359     private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND = 19;
360     private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD = 31;
361     private static final int NUM_SOFTAP_INTERFACE_DOWN = 65;
362     private static final int NUM_CLIENT_INTERFACE_DOWN = 12;
363     private static final int NUM_PASSPOINT_PROVIDERS = 7;
364     private static final int NUM_PASSPOINT_PROVIDER_INSTALLATION = 5;
365     private static final int NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS = 4;
366     private static final int NUM_PASSPOINT_PROVIDER_UNINSTALLATION = 3;
367     private static final int NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS = 2;
368     private static final int NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED = 1;
369     private static final int NUM_EAP_SIM_TYPE = 1;
370     private static final int NUM_EAP_TTLS_TYPE = 2;
371     private static final int NUM_EAP_TLS_TYPE = 3;
372     private static final int NUM_EAP_AKA_TYPE = 4;
373     private static final int NUM_EAP_AKA_PRIME_TYPE = 5;
374     private static final SparseIntArray SAVED_PASSPOINT_PROVIDERS_TYPE = new SparseIntArray();
375     static {
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_SIM, NUM_EAP_SIM_TYPE)376         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_SIM, NUM_EAP_SIM_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TTLS, NUM_EAP_TTLS_TYPE)377         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TTLS, NUM_EAP_TTLS_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TLS, NUM_EAP_TLS_TYPE)378         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_TLS, NUM_EAP_TLS_TYPE);
SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA, NUM_EAP_AKA_TYPE)379         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)380         SAVED_PASSPOINT_PROVIDERS_TYPE.put(EAPConstants.EAP_AKA_PRIME, NUM_EAP_AKA_PRIME_TYPE);
381     }
382 
383     private static final int NUM_PARTIAL_SCAN_RESULTS = 73;
384     private static final int NUM_PNO_SCAN_ATTEMPTS = 20;
385     private static final int NUM_PNO_SCAN_FAILED = 5;
386     private static final int NUM_PNO_FOUND_NETWORK_EVENTS = 10;
387     private static final int NUM_WPS_ATTEMPTS = 17;
388     private static final int NUM_WPS_SUCCESS = 21;
389     private static final int NUM_WPS_START_FAILURE = 7;
390     private static final int NUM_WPS_OVERLAP_FAILURE = 3;
391     private static final int NUM_WPS_TIMEOUT_FAILURE = 8;
392     private static final int NUM_WPS_OTHER_CONNECTION_FAILURE = 16;
393     private static final int NUM_WPS_SUPPLICANT_FAILURE = 12;
394     private static final int NUM_WPS_CANCELLATION = 11;
395     private static final int NUM_RADIO_MODE_CHANGE_TO_MCC = 4;
396     private static final int NUM_RADIO_MODE_CHANGE_TO_SCC = 13;
397     private static final int NUM_RADIO_MODE_CHANGE_TO_SBS = 19;
398     private static final int NUM_RADIO_MODE_CHANGE_TO_DBS = 34;
399     private static final int NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED = 14;
400     private static final long NUM_WATCHDOG_SUCCESS_DURATION_MS = 65;
401     private static final long WIFI_POWER_METRICS_LOGGING_DURATION = 280;
402     private static final long WIFI_POWER_METRICS_SCAN_TIME = 33;
403     private static final boolean WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING = true;
404     private static final boolean LINK_SPEED_COUNTS_LOGGING_SETTING = true;
405     private static final int DATA_STALL_MIN_TX_BAD_SETTING = 5;
406     private static final int DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING = 75;
407     private static final int NUM_SAR_SENSOR_LISTENER_REGISTRATION_FAILURES = 5;
408     private static final int NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS = 4;
409     private static final int NUM_ADD_OR_UPDATE_NETWORK_CALLS = 5;
410     private static final int NUM_ENABLE_NETWORK_CALLS = 6;
411 
412     /** Number of notifications per "Connect to Network" notification type. */
413     private static final int[] NUM_CONNECT_TO_NETWORK_NOTIFICATIONS = {0, 10, 20, 30, 40};
414     /** Number of notifications per "Connect to Network notification type and action type. */
415     private static final int[][] NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS = {
416             {0, 1, 2, 3, 4},
417             {10, 11, 12, 13, 14},
418             {20, 21, 22, 23, 24},
419             {30, 31, 32, 33, 34},
420             {40, 41, 42, 43, 44}};
421     private static final int SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST = 10;
422     private static final boolean IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = true;
423     private static final int NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND = 5;
424     private static final int NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES = 8;
425     private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG;
426 
427     private static final int NUM_SOFT_AP_EVENT_ENTRIES = 3;
428     private static final int NUM_SOFT_AP_ASSOCIATED_STATIONS = 3;
429     private static final int SOFT_AP_CHANNEL_FREQUENCY = 2437;
430     private static final int SOFT_AP_CHANNEL_BANDWIDTH = SoftApConnectedClientsEvent.BANDWIDTH_20;
431     private static final boolean IS_MAC_RANDOMIZATION_ON = true;
432     private static final int NUM_LINK_SPEED_LEVELS_TO_INCREMENT = 30;
433     private static final int TEST_RSSI_LEVEL = -80;
434 
buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease, String capabilities)435     private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease,
436             String capabilities) {
437         ScanDetail mockScanDetail = mock(ScanDetail.class);
438         NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
439         ScanResult mockScanResult = mock(ScanResult.class);
440         when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
441         when(mockScanDetail.getScanResult()).thenReturn(mockScanResult);
442         when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden);
443         when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease);
444         mockScanResult.capabilities = capabilities;
445         return mockScanDetail;
446     }
447 
buildMockScanDetail(String ssid, String bssid, boolean isOpen, boolean isSaved, boolean isProvider, boolean isWeakRssi)448     private ScanDetail buildMockScanDetail(String ssid, String bssid, boolean isOpen,
449             boolean isSaved, boolean isProvider, boolean isWeakRssi) {
450         ScanDetail mockScanDetail = mock(ScanDetail.class);
451         NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
452         ScanResult scanResult = new ScanResult();
453         scanResult.SSID = ssid;
454         scanResult.BSSID = bssid;
455         when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
456         when(mockScanDetail.getScanResult()).thenReturn(scanResult);
457         when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(isWeakRssi);
458         scanResult.capabilities = isOpen ? "" : "PSK";
459         if (isSaved) {
460             when(mWcm.getConfiguredNetworkForScanDetail(eq(mockScanDetail)))
461                     .thenReturn(mock(WifiConfiguration.class));
462         }
463         if (isProvider) {
464             PasspointProvider provider = mock(PasspointProvider.class);
465             Pair<PasspointProvider, PasspointMatch> providerMatch = Pair.create(provider, null);
466             when(mockNetworkDetail.isInterworking()).thenReturn(true);
467             when(mPpm.matchProvider(eq(scanResult))).thenReturn(providerMatch);
468         }
469         return mockScanDetail;
470     }
471 
buildMockScanDetailPasspoint(String ssid, String bssid, long hessid, int anqpDomainId, NetworkDetail.HSRelease hsRelease, boolean weakSignal)472     private ScanDetail buildMockScanDetailPasspoint(String ssid, String bssid, long hessid,
473             int anqpDomainId, NetworkDetail.HSRelease hsRelease, boolean weakSignal) {
474         ScanDetail mockScanDetail = mock(ScanDetail.class);
475         NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
476         ScanResult scanResult = new ScanResult();
477         scanResult.SSID = ssid;
478         scanResult.BSSID = bssid;
479         scanResult.hessid = hessid;
480         scanResult.capabilities = "PSK";
481         when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
482         when(mockScanDetail.getScanResult()).thenReturn(scanResult);
483         when(mockNetworkDetail.getHSRelease()).thenReturn(hsRelease);
484         when(mockNetworkDetail.getAnqpDomainID()).thenReturn(anqpDomainId);
485         when(mockNetworkDetail.isInterworking()).thenReturn(true);
486         when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(weakSignal);
487         return mockScanDetail;
488     }
489 
buildMockScanDetailList()490     private List<ScanDetail> buildMockScanDetailList() {
491         List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>();
492         mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]"));
493         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]"));
494         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]"));
495         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]"));
496         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]"));
497         mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]"));
498         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]"));
499         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-OWE-CCMP]"));
500         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-EAP-SUITE-B-192]"));
501         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
502                 "[WPA-EAP-CCMP]"));
503         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
504                 "[WPA2-EAP+FT/EAP-CCMP]"));
505         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1,
506                 "[WPA-EAP-CCMP]"));
507         return mockScanDetails;
508     }
509 
buildSavedNetworkList()510     private List<WifiConfiguration> buildSavedNetworkList() {
511         List<WifiConfiguration> testSavedNetworks = new ArrayList<WifiConfiguration>();
512         for (int i = 0; i < NUM_OPEN_NETWORKS; i++) {
513             testSavedNetworks.add(WifiConfigurationTestUtil.createOpenHiddenNetwork());
514         }
515         for (int i = 0; i < NUM_LEGACY_PERSONAL_NETWORKS; i++) {
516             testSavedNetworks.add(WifiConfigurationTestUtil.createPskNetwork());
517         }
518         for (int i = 0; i < NUM_LEGACY_ENTERPRISE_NETWORKS; i++) {
519             // Passpoint networks are counted in both Passpoint and Enterprise counters
520             testSavedNetworks.add(WifiConfigurationTestUtil.createPasspointNetwork());
521         }
522         for (int i = 0; i < NUM_ENHANCED_OPEN_NETWORKS; i++) {
523             testSavedNetworks.add(WifiConfigurationTestUtil.createOweNetwork());
524         }
525         for (int i = 0; i < NUM_WPA3_PERSONAL_NETWORKS; i++) {
526             testSavedNetworks.add(WifiConfigurationTestUtil.createSaeNetwork());
527         }
528         for (int i = 0; i < NUM_WPA3_ENTERPRISE_NETWORKS; i++) {
529             testSavedNetworks.add(WifiConfigurationTestUtil.createEapSuiteBNetwork());
530         }
531         testSavedNetworks.get(0).selfAdded = true;
532         testSavedNetworks.get(0).macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
533         return testSavedNetworks;
534     }
535 
createMockProvider(int eapType, boolean validateForR2)536     private PasspointProvider createMockProvider(int eapType, boolean validateForR2) {
537         PasspointProvider provider = mock(PasspointProvider.class);
538         PasspointConfiguration config = mock(PasspointConfiguration.class);
539         Credential credential = new Credential();
540 
541         switch (eapType) {
542             case EAPConstants.EAP_TLS:
543                 credential.setCertCredential(new Credential.CertificateCredential());
544                 break;
545             case EAPConstants.EAP_TTLS:
546                 credential.setUserCredential(new Credential.UserCredential());
547                 break;
548             case EAPConstants.EAP_AKA:
549             case EAPConstants.EAP_AKA_PRIME:
550             case EAPConstants.EAP_SIM:
551                 Credential.SimCredential simCredential = new Credential.SimCredential();
552                 simCredential.setEapType(eapType);
553                 credential.setSimCredential(simCredential);
554                 break;
555         }
556         when(provider.getConfig()).thenReturn(config);
557         when(config.getCredential()).thenReturn(credential);
558         when(config.validateForR2()).thenReturn(validateForR2);
559         return provider;
560     }
561 
562     /**
563      * Set simple metrics, increment others
564      */
setAndIncrementMetrics()565     public void setAndIncrementMetrics() throws Exception {
566         Map<String, PasspointProvider> providers = new HashMap<>();
567         mWifiMetrics.updateSavedNetworks(buildSavedNetworkList());
568         mWifiMetrics.updateSavedPasspointProfiles(NUM_PASSPOINT_PROVIDERS,
569                 NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED);
570         for (int i = 0; i < SAVED_PASSPOINT_PROVIDERS_TYPE.size(); i++) {
571             int eapType = SAVED_PASSPOINT_PROVIDERS_TYPE.keyAt(i);
572             int count = SAVED_PASSPOINT_PROVIDERS_TYPE.valueAt(i);
573             for (int j = 0; j < count; j++) {
574                 providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, false));
575             }
576             for (int j = count; j < count * 2; j++) {
577                 providers.put(Integer.toString(eapType) + j, createMockProvider(eapType, true));
578             }
579         }
580         mWifiMetrics.updateSavedPasspointProfilesInfo(providers);
581 
582         mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED);
583         mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED);
584 
585         for (int i = 0; i < NUM_EMPTY_SCAN_RESULTS; i++) {
586             mWifiMetrics.incrementEmptyScanResultCount();
587         }
588         for (int i = 0; i < NUM_NON_EMPTY_SCAN_RESULTS; i++) {
589             mWifiMetrics.incrementNonEmptyScanResultCount();
590         }
591         mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN,
592                 NUM_SCAN_UNKNOWN);
593         mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS,
594                 NUM_SCAN_SUCCESS);
595         mWifiMetrics.incrementScanReturnEntry(
596                 WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
597                 NUM_SCAN_FAILURE_INTERRUPTED);
598         mWifiMetrics.incrementScanReturnEntry(
599                 WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
600                 NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
601         for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_OFF; i++) {
602             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
603                     false);
604         }
605         for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_ON; i++) {
606             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
607                     true);
608         }
609         for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_OFF; i++) {
610             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
611                     false);
612         }
613         for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_ON; i++) {
614             mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
615                     true);
616         }
617         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD; i++) {
618             mWifiMetrics.incrementNumConnectivityWatchdogPnoGood();
619         }
620         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_BAD; i++) {
621             mWifiMetrics.incrementNumConnectivityWatchdogPnoBad();
622         }
623         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD; i++) {
624             mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood();
625         }
626         for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD; i++) {
627             mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad();
628         }
629         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS; i++) {
630             mWifiMetrics.incrementNumLastResortWatchdogTriggers();
631         }
632         mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal(
633                 NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL);
634         mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(
635                 NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL);
636         mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal(
637                 NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL);
638         mWifiMetrics.addCountToNumLastResortWatchdogBadOtherNetworksTotal(
639                 NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL);
640         mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal(
641                 NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL);
642         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION; i++) {
643             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation();
644         }
645         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION; i++) {
646             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication();
647         }
648         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP; i++) {
649             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp();
650         }
651         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) {
652             mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther();
653         }
654         for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) {
655             mWifiMetrics.incrementNumLastResortWatchdogSuccesses();
656         }
657         for (int i = 0; i < WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER; i++) {
658             mWifiMetrics.incrementWatchdogTotalConnectionFailureCountAfterTrigger();
659         }
660         for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
661             for (int j = 0; j <= i; j++) {
662                 mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL + i);
663             }
664         }
665         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
666             mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL - i);
667         }
668         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
669             mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MAX_RSSI_LEVEL + i);
670         }
671 
672         // Test alert-reason clamping.
673         mWifiMetrics.logFirmwareAlert(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1);
674         mWifiMetrics.logFirmwareAlert(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1);
675         // Simple cases for alert reason.
676         mWifiMetrics.logFirmwareAlert(1);
677         mWifiMetrics.logFirmwareAlert(1);
678         mWifiMetrics.logFirmwareAlert(1);
679         mWifiMetrics.logFirmwareAlert(2);
680         List<ScanDetail> mockScanDetails = buildMockScanDetailList();
681         for (int i = 0; i < NUM_SCANS; i++) {
682             mWifiMetrics.countScanResults(mockScanDetails);
683         }
684         // increment connectivity scan metrics
685         for (int i = 0; i < NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT; i++) {
686             mWifiMetrics.incrementConnectivityOneshotScanCount();
687         }
688         for (int i = 0; i < NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS; i++) {
689             mWifiMetrics.incrementExternalAppOneshotScanRequestsCount();
690         }
691         for (int i = 0; i < NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) {
692             mWifiMetrics.incrementExternalForegroundAppOneshotScanRequestsThrottledCount();
693         }
694         for (int i = 0; i < NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) {
695             mWifiMetrics.incrementExternalBackgroundAppOneshotScanRequestsThrottledCount();
696         }
697         for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
698             for (int offset = 0; offset <= score; offset++) {
699                 mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN + score);
700             }
701         }
702         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
703             mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN - i);
704         }
705         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
706             mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MAX + i);
707         }
708         for (int score = 0; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
709             for (int offset = 0; offset <= score; offset++) {
710                 mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MIN + score, 15);
711             }
712         }
713         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
714             mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MIN - i, 15);
715         }
716         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
717             mWifiMetrics.incrementWifiUsabilityScoreCount(1, WIFI_SCORE_RANGE_MAX + i, 15);
718         }
719 
720         // increment soft ap start return codes
721         for (int i = 0; i < NUM_SOFTAP_START_SUCCESS; i++) {
722             mWifiMetrics.incrementSoftApStartResult(true, 0);
723         }
724         for (int i = 0; i < NUM_SOFTAP_FAILED_GENERAL_ERROR; i++) {
725             mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL);
726         }
727         for (int i = 0; i < NUM_SOFTAP_FAILED_NO_CHANNEL; i++) {
728             mWifiMetrics.incrementSoftApStartResult(false,
729                     WifiManager.SAP_START_FAILURE_NO_CHANNEL);
730         }
731         for (int i = 0; i < NUM_HAL_CRASHES; i++) {
732             mWifiMetrics.incrementNumHalCrashes();
733         }
734         for (int i = 0; i < NUM_WIFICOND_CRASHES; i++) {
735             mWifiMetrics.incrementNumWificondCrashes();
736         }
737         for (int i = 0; i < NUM_SUPPLICANT_CRASHES; i++) {
738             mWifiMetrics.incrementNumSupplicantCrashes();
739         }
740         for (int i = 0; i < NUM_HOSTAPD_CRASHES; i++) {
741             mWifiMetrics.incrementNumHostapdCrashes();
742         }
743         for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_HAL; i++) {
744             mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
745         }
746         for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND; i++) {
747             mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
748         }
749         for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT; i++) {
750             mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
751         }
752         for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL; i++) {
753             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
754         }
755         for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND; i++) {
756             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond();
757         }
758         for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD; i++) {
759             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
760         }
761         for (int i = 0; i < NUM_SOFTAP_INTERFACE_DOWN; i++) {
762             mWifiMetrics.incrementNumSoftApInterfaceDown();
763         }
764         for (int i = 0; i < NUM_CLIENT_INTERFACE_DOWN; i++) {
765             mWifiMetrics.incrementNumClientInterfaceDown();
766         }
767         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALLATION; i++) {
768             mWifiMetrics.incrementNumPasspointProviderInstallation();
769         }
770         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS; i++) {
771             mWifiMetrics.incrementNumPasspointProviderInstallSuccess();
772         }
773         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALLATION; i++) {
774             mWifiMetrics.incrementNumPasspointProviderUninstallation();
775         }
776         for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS; i++) {
777             mWifiMetrics.incrementNumPasspointProviderUninstallSuccess();
778         }
779         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_MCC; i++) {
780             mWifiMetrics.incrementNumRadioModeChangeToMcc();
781         }
782         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SCC; i++) {
783             mWifiMetrics.incrementNumRadioModeChangeToScc();
784         }
785         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SBS; i++) {
786             mWifiMetrics.incrementNumRadioModeChangeToSbs();
787         }
788         for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_DBS; i++) {
789             mWifiMetrics.incrementNumRadioModeChangeToDbs();
790         }
791         for (int i = 0; i < NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED; i++) {
792             mWifiMetrics.incrementNumSoftApUserBandPreferenceUnsatisfied();
793         }
794 
795         // increment pno scan metrics
796         for (int i = 0; i < NUM_PNO_SCAN_ATTEMPTS; i++) {
797             mWifiMetrics.incrementPnoScanStartAttempCount();
798         }
799         for (int i = 0; i < NUM_PNO_SCAN_FAILED; i++) {
800             mWifiMetrics.incrementPnoScanFailedCount();
801         }
802         for (int i = 0; i < NUM_PNO_FOUND_NETWORK_EVENTS; i++) {
803             mWifiMetrics.incrementPnoFoundNetworkEventCount();
804         }
805 
806         // set and increment "connect to network" notification metrics
807         for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATIONS.length; i++) {
808             int count = NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[i];
809             for (int j = 0; j < count; j++) {
810                 mWifiMetrics.incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, i);
811             }
812         }
813         for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS.length; i++) {
814             int[] actions = NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS[i];
815             for (int j = 0; j < actions.length; j++) {
816                 int count = actions[j];
817                 for (int k = 0; k < count; k++) {
818                     mWifiMetrics.incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG,
819                             i, j);
820                 }
821             }
822         }
823         mWifiMetrics.setNetworkRecommenderBlocklistSize(OPEN_NET_NOTIFIER_TAG,
824                 SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST);
825         mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG,
826                 IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
827         for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) {
828             mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG);
829         }
830         for (int i = 0; i < NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND; i++) {
831             mWifiMetrics.incrementNumNetworkConnectMessageFailedToSend(OPEN_NET_NOTIFIER_TAG);
832         }
833 
834         addSoftApEventsToMetrics();
835 
836         // increment wps metrics
837         for (int i = 0; i < NUM_WPS_ATTEMPTS; i++) {
838             mWifiMetrics.incrementWpsAttemptCount();
839         }
840         for (int i = 0; i < NUM_WPS_SUCCESS; i++) {
841             mWifiMetrics.incrementWpsSuccessCount();
842         }
843         for (int i = 0; i < NUM_WPS_START_FAILURE; i++) {
844             mWifiMetrics.incrementWpsStartFailureCount();
845         }
846         for (int i = 0; i < NUM_WPS_OVERLAP_FAILURE; i++) {
847             mWifiMetrics.incrementWpsOverlapFailureCount();
848         }
849         for (int i = 0; i < NUM_WPS_TIMEOUT_FAILURE; i++) {
850             mWifiMetrics.incrementWpsTimeoutFailureCount();
851         }
852         for (int i = 0; i < NUM_WPS_OTHER_CONNECTION_FAILURE; i++) {
853             mWifiMetrics.incrementWpsOtherConnectionFailureCount();
854         }
855         for (int i = 0; i < NUM_WPS_SUPPLICANT_FAILURE; i++) {
856             mWifiMetrics.incrementWpsSupplicantFailureCount();
857         }
858         for (int i = 0; i < NUM_WPS_CANCELLATION; i++) {
859             mWifiMetrics.incrementWpsCancellationCount();
860         }
861         for (int i = 0; i < NUM_SAR_SENSOR_LISTENER_REGISTRATION_FAILURES; i++) {
862             mWifiMetrics.incrementNumSarSensorRegistrationFailures();
863         }
864         for (int i = 0; i < NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS; i++) {
865             mWifiMetrics.incrementOneshotScanWithDfsCount();
866         }
867         for (int i = 0; i < NUM_ADD_OR_UPDATE_NETWORK_CALLS; i++) {
868             mWifiMetrics.incrementNumAddOrUpdateNetworkCalls();
869         }
870         for (int i = 0; i < NUM_ENABLE_NETWORK_CALLS; i++) {
871             mWifiMetrics.incrementNumEnableNetworkCalls();
872         }
873 
874         mWifiMetrics.setWatchdogSuccessTimeDurationMs(NUM_WATCHDOG_SUCCESS_DURATION_MS);
875         mWifiMetrics.setIsMacRandomizationOn(IS_MAC_RANDOMIZATION_ON);
876 
877         addWifiPowerMetrics();
878 
879         mWifiMetrics.setWifiIsUnusableLoggingEnabled(WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING);
880         mWifiMetrics.setLinkSpeedCountsLoggingEnabled(LINK_SPEED_COUNTS_LOGGING_SETTING);
881         mWifiMetrics.setWifiDataStallMinTxBad(DATA_STALL_MIN_TX_BAD_SETTING);
882         mWifiMetrics.setWifiDataStallMinRxWithoutTx(DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING);
883     }
884 
addWifiPowerMetrics()885     private void addWifiPowerMetrics() {
886         WifiRadioUsage wifiRadioUsage = new WifiRadioUsage();
887         wifiRadioUsage.loggingDurationMs = WIFI_POWER_METRICS_LOGGING_DURATION;
888         wifiRadioUsage.scanTimeMs = WIFI_POWER_METRICS_SCAN_TIME;
889         when(mWifiPowerMetrics.buildWifiRadioUsageProto()).thenReturn(wifiRadioUsage);
890     }
891 
addSoftApEventsToMetrics()892     private void addSoftApEventsToMetrics() {
893         // Total number of events recorded is NUM_SOFT_AP_EVENT_ENTRIES in both modes
894 
895         mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_TETHERED);
896         mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
897                 WifiManager.IFACE_IP_MODE_TETHERED);
898         mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
899                 WifiManager.IFACE_IP_MODE_UNSPECIFIED);  // Should be dropped.
900         mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_TETHERED);
901         // Channel switch info should be added to the last Soft AP UP event in the list
902         mWifiMetrics.addSoftApChannelSwitchedEvent(SOFT_AP_CHANNEL_FREQUENCY,
903                 SOFT_AP_CHANNEL_BANDWIDTH, WifiManager.IFACE_IP_MODE_TETHERED);
904         mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
905         mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS,
906                 WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
907         // Should be dropped.
908         mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
909         mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
910     }
911 
verifySoftApEventsStoredInProto()912     private void verifySoftApEventsStoredInProto() {
913         assertEquals(NUM_SOFT_AP_EVENT_ENTRIES,
914                 mDecodedProto.softApConnectedClientsEventsTethered.length);
915         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP,
916                 mDecodedProto.softApConnectedClientsEventsTethered[0].eventType);
917         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[0].numConnectedClients);
918         assertEquals(SOFT_AP_CHANNEL_FREQUENCY,
919                 mDecodedProto.softApConnectedClientsEventsTethered[0].channelFrequency);
920         assertEquals(SOFT_AP_CHANNEL_BANDWIDTH,
921                 mDecodedProto.softApConnectedClientsEventsTethered[0].channelBandwidth);
922         assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED,
923                 mDecodedProto.softApConnectedClientsEventsTethered[1].eventType);
924         assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS,
925                 mDecodedProto.softApConnectedClientsEventsTethered[1].numConnectedClients);
926         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN,
927                 mDecodedProto.softApConnectedClientsEventsTethered[2].eventType);
928         assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[2].numConnectedClients);
929 
930         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP,
931                 mDecodedProto.softApConnectedClientsEventsLocalOnly[0].eventType);
932         assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[0].numConnectedClients);
933         assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED,
934                 mDecodedProto.softApConnectedClientsEventsLocalOnly[1].eventType);
935         assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS,
936                 mDecodedProto.softApConnectedClientsEventsLocalOnly[1].numConnectedClients);
937         assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN,
938                 mDecodedProto.softApConnectedClientsEventsLocalOnly[2].eventType);
939         assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[2].numConnectedClients);
940     }
941 
942     /**
943      * Assert that values in deserializedWifiMetrics match those set in 'setAndIncrementMetrics'
944      */
assertDeserializedMetricsCorrect()945     public void assertDeserializedMetricsCorrect() throws Exception {
946         assertEquals("mDecodedProto.numSavedNetworks == NUM_SAVED_NETWORKS",
947                 NUM_SAVED_NETWORKS, mDecodedProto.numSavedNetworks);
948         assertEquals("mDecodedProto.numSavedNetworksWithMacRandomization == NUM_SAVED_NETWORKS-1",
949                 NUM_SAVED_NETWORKS - 1, mDecodedProto.numSavedNetworksWithMacRandomization);
950         assertEquals("mDecodedProto.numOpenNetworks == NUM_OPEN_NETWORKS",
951                 NUM_OPEN_NETWORKS, mDecodedProto.numOpenNetworks);
952         assertEquals("mDecodedProto.numLegacyPersonalNetworks == NUM_LEGACY_PERSONAL_NETWORKS",
953                 NUM_LEGACY_PERSONAL_NETWORKS, mDecodedProto.numLegacyPersonalNetworks);
954         assertEquals(
955                 "mDecodedProto.numLegacyEnterpriseNetworks == NUM_LEGACY_ENTERPRISE_NETWORKS",
956                 NUM_LEGACY_ENTERPRISE_NETWORKS, mDecodedProto.numLegacyEnterpriseNetworks);
957         assertEquals("mDecodedProto.numEnhancedOpenNetworks == NUM_ENHANCED_OPEN_NETWORKS",
958                 NUM_ENHANCED_OPEN_NETWORKS, mDecodedProto.numEnhancedOpenNetworks);
959         assertEquals("mDecodedProto.numWpa3PersonalNetworks == NUM_WPA3_PERSONAL_NETWORKS",
960                 NUM_WPA3_PERSONAL_NETWORKS, mDecodedProto.numWpa3PersonalNetworks);
961         assertEquals("mDecodedProto.numWpa3EnterpriseNetworks == NUM_WPA3_ENTERPRISE_NETWORKS",
962                 NUM_WPA3_ENTERPRISE_NETWORKS, mDecodedProto.numWpa3EnterpriseNetworks);
963         assertEquals("mDecodedProto.numNetworksAddedByUser == NUM_NETWORKS_ADDED_BY_USER",
964                 NUM_NETWORKS_ADDED_BY_USER, mDecodedProto.numNetworksAddedByUser);
965         assertEquals(NUM_HIDDEN_NETWORKS, mDecodedProto.numHiddenNetworks);
966         assertEquals(NUM_PASSPOINT_NETWORKS, mDecodedProto.numPasspointNetworks);
967         assertEquals("mDecodedProto.numNetworksAddedByApps == NUM_NETWORKS_ADDED_BY_APPS",
968                 NUM_NETWORKS_ADDED_BY_APPS, mDecodedProto.numNetworksAddedByApps);
969         assertEquals("mDecodedProto.isLocationEnabled == TEST_VAL_IS_LOCATION_ENABLED",
970                 TEST_VAL_IS_LOCATION_ENABLED, mDecodedProto.isLocationEnabled);
971         assertEquals("mDecodedProto.isScanningAlwaysEnabled == IS_SCANNING_ALWAYS_ENABLED",
972                 IS_SCANNING_ALWAYS_ENABLED, mDecodedProto.isScanningAlwaysEnabled);
973         assertEquals("mDecodedProto.numEmptyScanResults == NUM_EMPTY_SCAN_RESULTS",
974                 NUM_EMPTY_SCAN_RESULTS, mDecodedProto.numEmptyScanResults);
975         assertEquals("mDecodedProto.numNonEmptyScanResults == NUM_NON_EMPTY_SCAN_RESULTS",
976                 NUM_NON_EMPTY_SCAN_RESULTS, mDecodedProto.numNonEmptyScanResults);
977         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, NUM_SCAN_UNKNOWN);
978         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_SUCCESS, NUM_SCAN_SUCCESS);
979         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
980                 NUM_SCAN_FAILURE_INTERRUPTED);
981         assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
982                 NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
983         assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false,
984                 NUM_WIFI_UNKNOWN_SCREEN_OFF);
985         assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true,
986                 NUM_WIFI_UNKNOWN_SCREEN_ON);
987         assertSystemStateEntryEquals(
988                 WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false, NUM_WIFI_ASSOCIATED_SCREEN_OFF);
989         assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true,
990                 NUM_WIFI_ASSOCIATED_SCREEN_ON);
991         assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD,
992                 mDecodedProto.numConnectivityWatchdogPnoGood);
993         assertEquals(NUM_CONNECTIVITY_WATCHDOG_PNO_BAD,
994                 mDecodedProto.numConnectivityWatchdogPnoBad);
995         assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD,
996                 mDecodedProto.numConnectivityWatchdogBackgroundGood);
997         assertEquals(NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD,
998                 mDecodedProto.numConnectivityWatchdogBackgroundBad);
999         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS,
1000                 mDecodedProto.numLastResortWatchdogTriggers);
1001         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL,
1002                 mDecodedProto.numLastResortWatchdogBadAssociationNetworksTotal);
1003         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL,
1004                 mDecodedProto.numLastResortWatchdogBadAuthenticationNetworksTotal);
1005         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL,
1006                 mDecodedProto.numLastResortWatchdogBadDhcpNetworksTotal);
1007         assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL,
1008                 mDecodedProto.numLastResortWatchdogBadOtherNetworksTotal);
1009         assertEquals(NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL,
1010                 mDecodedProto.numLastResortWatchdogAvailableNetworksTotal);
1011         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION,
1012                 mDecodedProto.numLastResortWatchdogTriggersWithBadAssociation);
1013         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION,
1014                 mDecodedProto.numLastResortWatchdogTriggersWithBadAuthentication);
1015         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP,
1016                 mDecodedProto.numLastResortWatchdogTriggersWithBadDhcp);
1017         assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER,
1018                 mDecodedProto.numLastResortWatchdogTriggersWithBadOther);
1019         assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES,
1020                 mDecodedProto.numLastResortWatchdogSuccesses);
1021         assertEquals(WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER,
1022                 mDecodedProto.watchdogTotalConnectionFailureCountAfterTrigger);
1023         assertEquals(TEST_RECORD_DURATION_SEC,
1024                 mDecodedProto.recordDurationSec);
1025         for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
1026             assertEquals(RSSI_POLL_FREQUENCY,
1027                     mDecodedProto.rssiPollRssiCount[i].frequency);
1028             assertEquals(MIN_RSSI_LEVEL + i, mDecodedProto.rssiPollRssiCount[i].rssi);
1029             assertEquals(i + 1, mDecodedProto.rssiPollRssiCount[i].count);
1030         }
1031         StringBuilder sb_rssi = new StringBuilder();
1032         sb_rssi.append("Number of RSSIs = " + mDecodedProto.rssiPollRssiCount.length);
1033         assertTrue(sb_rssi.toString(), (mDecodedProto.rssiPollRssiCount.length
1034                      <= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1)));
1035         assertEquals(2, mDecodedProto.alertReasonCount[0].count);  // Clamped reasons.
1036         assertEquals(3, mDecodedProto.alertReasonCount[1].count);
1037         assertEquals(1, mDecodedProto.alertReasonCount[2].count);
1038         assertEquals(3, mDecodedProto.alertReasonCount.length);
1039         assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS,
1040                 mDecodedProto.numTotalScanResults);
1041         assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
1042                 mDecodedProto.numOpenNetworkScanResults);
1043         assertEquals(NUM_LEGACY_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
1044                 mDecodedProto.numLegacyPersonalNetworkScanResults);
1045         assertEquals(NUM_LEGACY_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
1046                 mDecodedProto.numLegacyEnterpriseNetworkScanResults);
1047         assertEquals(NUM_ENHANCED_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
1048                 mDecodedProto.numEnhancedOpenNetworkScanResults);
1049         assertEquals(NUM_WPA3_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
1050                 mDecodedProto.numWpa3PersonalNetworkScanResults);
1051         assertEquals(NUM_WPA3_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
1052                 mDecodedProto.numWpa3EnterpriseNetworkScanResults);
1053         assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
1054                 mDecodedProto.numHiddenNetworkScanResults);
1055         assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS,
1056                 mDecodedProto.numHotspot2R1NetworkScanResults);
1057         assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS,
1058                 mDecodedProto.numHotspot2R2NetworkScanResults);
1059         assertEquals(NUM_SCANS,
1060                 mDecodedProto.numScans);
1061         assertEquals(NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT,
1062                 mDecodedProto.numConnectivityOneshotScans);
1063         assertEquals(NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS,
1064                 mDecodedProto.numExternalAppOneshotScanRequests);
1065         assertEquals(NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED,
1066                 mDecodedProto.numExternalForegroundAppOneshotScanRequestsThrottled);
1067         assertEquals(NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED,
1068                 mDecodedProto.numExternalBackgroundAppOneshotScanRequestsThrottled);
1069 
1070         for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) {
1071             assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
1072                     mDecodedProto.wifiScoreCount[score_index].score);
1073             assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1,
1074                     mDecodedProto.wifiScoreCount[score_index].count);
1075             assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
1076                     mDecodedProto.wifiUsabilityScoreCount[score_index].score);
1077             assertEquals(WIFI_SCORE_RANGE_MIN + score_index + 1,
1078                     mDecodedProto.wifiUsabilityScoreCount[score_index].count);
1079         }
1080         StringBuilder sb_wifi_score = new StringBuilder();
1081         sb_wifi_score.append("Number of wifi_scores = " + mDecodedProto.wifiScoreCount.length);
1082         assertTrue(sb_wifi_score.toString(), (mDecodedProto.wifiScoreCount.length
1083                 <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
1084         StringBuilder sb_wifi_limits = new StringBuilder();
1085         sb_wifi_limits.append("Wifi Score limit is " +  ConnectedScore.WIFI_MAX_SCORE
1086                 + ">= " + WIFI_SCORE_RANGE_MAX);
1087         assertTrue(sb_wifi_limits.toString(),
1088                 ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX);
1089         StringBuilder sb_wifi_usability_score = new StringBuilder();
1090         sb_wifi_usability_score.append("Number of wifi_usability_scores = "
1091                 + mDecodedProto.wifiUsabilityScoreCount.length);
1092         assertTrue(sb_wifi_usability_score.toString(), (mDecodedProto.wifiUsabilityScoreCount.length
1093                 <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
1094         StringBuilder sb_wifi_usablity_limits = new StringBuilder();
1095         sb_wifi_limits.append("Wifi Usability Score limit is " +  ConnectedScore.WIFI_MAX_SCORE
1096                 + ">= " + WIFI_SCORE_RANGE_MAX);
1097         assertTrue(sb_wifi_limits.toString(),
1098                 ConnectedScore.WIFI_MAX_SCORE <= WIFI_SCORE_RANGE_MAX);
1099         assertEquals(MAX_NUM_SOFTAP_RETURN_CODES, mDecodedProto.softApReturnCode.length);
1100         assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY,
1101                      mDecodedProto.softApReturnCode[0].startResult);
1102         assertEquals(NUM_SOFTAP_START_SUCCESS, mDecodedProto.softApReturnCode[0].count);
1103         assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR,
1104                      mDecodedProto.softApReturnCode[1].startResult);
1105         assertEquals(NUM_SOFTAP_FAILED_GENERAL_ERROR,
1106                      mDecodedProto.softApReturnCode[1].count);
1107         assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL,
1108                      mDecodedProto.softApReturnCode[2].startResult);
1109         assertEquals(NUM_SOFTAP_FAILED_NO_CHANNEL,
1110                      mDecodedProto.softApReturnCode[2].count);
1111         assertEquals(NUM_HAL_CRASHES, mDecodedProto.numHalCrashes);
1112         assertEquals(NUM_WIFICOND_CRASHES, mDecodedProto.numWificondCrashes);
1113         assertEquals(NUM_SUPPLICANT_CRASHES, mDecodedProto.numSupplicantCrashes);
1114         assertEquals(NUM_HOSTAPD_CRASHES, mDecodedProto.numHostapdCrashes);
1115         assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_HAL,
1116                 mDecodedProto.numSetupClientInterfaceFailureDueToHal);
1117         assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND,
1118                 mDecodedProto.numSetupClientInterfaceFailureDueToWificond);
1119         assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT,
1120                 mDecodedProto.numSetupClientInterfaceFailureDueToSupplicant);
1121         assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL,
1122                 mDecodedProto.numSetupSoftApInterfaceFailureDueToHal);
1123         assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND,
1124                 mDecodedProto.numSetupSoftApInterfaceFailureDueToWificond);
1125         assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD,
1126                 mDecodedProto.numSetupSoftApInterfaceFailureDueToHostapd);
1127         assertEquals(NUM_CLIENT_INTERFACE_DOWN, mDecodedProto.numClientInterfaceDown);
1128         assertEquals(NUM_SOFTAP_INTERFACE_DOWN, mDecodedProto.numSoftApInterfaceDown);
1129         assertEquals(NUM_PASSPOINT_PROVIDERS, mDecodedProto.numPasspointProviders);
1130         assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR1);
1131         assertPasspointProfileTypeCount(mDecodedProto.installedPasspointProfileTypeForR2);
1132         assertEquals(NUM_PASSPOINT_PROVIDER_INSTALLATION,
1133                 mDecodedProto.numPasspointProviderInstallation);
1134         assertEquals(NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS,
1135                 mDecodedProto.numPasspointProviderInstallSuccess);
1136         assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALLATION,
1137                 mDecodedProto.numPasspointProviderUninstallation);
1138         assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS,
1139                 mDecodedProto.numPasspointProviderUninstallSuccess);
1140         assertEquals(NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED,
1141                 mDecodedProto.numPasspointProvidersSuccessfullyConnected);
1142         assertEquals(NUM_RADIO_MODE_CHANGE_TO_MCC, mDecodedProto.numRadioModeChangeToMcc);
1143         assertEquals(NUM_RADIO_MODE_CHANGE_TO_SCC, mDecodedProto.numRadioModeChangeToScc);
1144         assertEquals(NUM_RADIO_MODE_CHANGE_TO_SBS, mDecodedProto.numRadioModeChangeToSbs);
1145         assertEquals(NUM_RADIO_MODE_CHANGE_TO_DBS, mDecodedProto.numRadioModeChangeToDbs);
1146         assertEquals(NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED,
1147                 mDecodedProto.numSoftApUserBandPreferenceUnsatisfied);
1148 
1149         PnoScanMetrics pno_metrics = mDecodedProto.pnoScanMetrics;
1150         assertNotNull(pno_metrics);
1151         assertEquals(NUM_PNO_SCAN_ATTEMPTS, pno_metrics.numPnoScanAttempts);
1152         assertEquals(NUM_PNO_SCAN_FAILED, pno_metrics.numPnoScanFailed);
1153         assertEquals(NUM_PNO_FOUND_NETWORK_EVENTS, pno_metrics.numPnoFoundNetworkEvents);
1154 
1155         for (ConnectToNetworkNotificationAndActionCount notificationCount
1156                 : mDecodedProto.connectToNetworkNotificationCount) {
1157             assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[notificationCount.notification],
1158                     notificationCount.count);
1159             assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN,
1160                     notificationCount.recommender);
1161         }
1162         for (ConnectToNetworkNotificationAndActionCount notificationActionCount
1163                 : mDecodedProto.connectToNetworkNotificationActionCount) {
1164             assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS
1165                             [notificationActionCount.notification]
1166                             [notificationActionCount.action],
1167                     notificationActionCount.count);
1168             assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN,
1169                     notificationActionCount.recommender);
1170         }
1171 
1172         assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST,
1173                 mDecodedProto.openNetworkRecommenderBlacklistSize);
1174         assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
1175                 mDecodedProto.isWifiNetworksAvailableNotificationOn);
1176         assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES,
1177                 mDecodedProto.numOpenNetworkRecommendationUpdates);
1178         assertEquals(NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND,
1179                 mDecodedProto.numOpenNetworkConnectMessageFailedToSend);
1180 
1181         verifySoftApEventsStoredInProto();
1182 
1183         WpsMetrics wps_metrics = mDecodedProto.wpsMetrics;
1184         assertNotNull(wps_metrics);
1185         assertEquals(NUM_WPS_ATTEMPTS, wps_metrics.numWpsAttempts);
1186         assertEquals(NUM_WPS_SUCCESS, wps_metrics.numWpsSuccess);
1187         assertEquals(NUM_WPS_START_FAILURE, wps_metrics.numWpsStartFailure);
1188         assertEquals(NUM_WPS_OVERLAP_FAILURE, wps_metrics.numWpsOverlapFailure);
1189         assertEquals(NUM_WPS_TIMEOUT_FAILURE, wps_metrics.numWpsTimeoutFailure);
1190         assertEquals(NUM_WPS_OTHER_CONNECTION_FAILURE, wps_metrics.numWpsOtherConnectionFailure);
1191         assertEquals(NUM_WPS_SUPPLICANT_FAILURE, wps_metrics.numWpsSupplicantFailure);
1192         assertEquals(NUM_WPS_CANCELLATION, wps_metrics.numWpsCancellation);
1193 
1194         assertEquals(NUM_WATCHDOG_SUCCESS_DURATION_MS,
1195                 mDecodedProto.watchdogTriggerToConnectionSuccessDurationMs);
1196         assertEquals(IS_MAC_RANDOMIZATION_ON, mDecodedProto.isMacRandomizationOn);
1197         assertEquals(WIFI_POWER_METRICS_LOGGING_DURATION,
1198                 mDecodedProto.wifiRadioUsage.loggingDurationMs);
1199         assertEquals(WIFI_POWER_METRICS_SCAN_TIME,
1200                 mDecodedProto.wifiRadioUsage.scanTimeMs);
1201         assertEquals(WIFI_IS_UNUSABLE_EVENT_LOGGING_SETTING,
1202                 mDecodedProto.experimentValues.wifiIsUnusableLoggingEnabled);
1203         assertEquals(LINK_SPEED_COUNTS_LOGGING_SETTING,
1204                 mDecodedProto.experimentValues.linkSpeedCountsLoggingEnabled);
1205         assertEquals(DATA_STALL_MIN_TX_BAD_SETTING,
1206                 mDecodedProto.experimentValues.wifiDataStallMinTxBad);
1207         assertEquals(DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX_SETTING,
1208                 mDecodedProto.experimentValues.wifiDataStallMinTxSuccessWithoutRx);
1209 
1210         assertEquals(NUM_SAR_SENSOR_LISTENER_REGISTRATION_FAILURES,
1211                 mDecodedProto.numSarSensorRegistrationFailures);
1212         assertEquals(NUM_ONESHOT_SCAN_REQUESTS_WITH_DFS_CHANNELS,
1213                 mDecodedProto.numOneshotHasDfsChannelScans);
1214         assertEquals(NUM_ADD_OR_UPDATE_NETWORK_CALLS, mDecodedProto.numAddOrUpdateNetworkCalls);
1215         assertEquals(NUM_ENABLE_NETWORK_CALLS, mDecodedProto.numEnableNetworkCalls);
1216     }
1217 
1218     /**
1219      *  Assert deserialized metrics Scan Return Entry equals count
1220      */
assertScanReturnEntryEquals(int returnCode, int count)1221     public void assertScanReturnEntryEquals(int returnCode, int count) {
1222         for (int i = 0; i < mDecodedProto.scanReturnEntries.length; i++) {
1223             if (mDecodedProto.scanReturnEntries[i].scanReturnCode == returnCode) {
1224                 assertEquals(count, mDecodedProto.scanReturnEntries[i].scanResultsCount);
1225                 return;
1226             }
1227         }
1228         assertEquals(null, count);
1229     }
1230 
1231     /**
1232      *  Assert deserialized metrics SystemState entry equals count
1233      */
assertSystemStateEntryEquals(int state, boolean screenOn, int count)1234     public void assertSystemStateEntryEquals(int state, boolean screenOn, int count) {
1235         for (int i = 0; i < mDecodedProto.wifiSystemStateEntries.length; i++) {
1236             if (mDecodedProto.wifiSystemStateEntries[i].wifiState == state
1237                     && mDecodedProto.wifiSystemStateEntries[i].isScreenOn == screenOn) {
1238                 assertEquals(count, mDecodedProto.wifiSystemStateEntries[i].wifiStateCount);
1239                 return;
1240             }
1241         }
1242         assertEquals(null, count);
1243     }
1244 
1245     /**
1246      * Test the number of Passpoint provision with the failure code are collected correctly
1247      *
1248      * @throws Exception
1249      */
1250     @Test
testPasspointProvisionMetrics()1251     public void testPasspointProvisionMetrics() throws Exception {
1252         //Increment count for provisioning success.
1253         mWifiMetrics.incrementPasspointProvisionSuccess();
1254 
1255         // Increment count for provisioning unavailable
1256         mWifiMetrics.incrementPasspointProvisionFailure(
1257                 ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
1258         mWifiMetrics.incrementPasspointProvisionFailure(
1259                 ProvisioningCallback.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
1260 
1261         // Increment count for server connection failure
1262         mWifiMetrics.incrementPasspointProvisionFailure(
1263                 ProvisioningCallback.OSU_FAILURE_AP_CONNECTION);
1264 
1265         // Dump proto and deserialize
1266         dumpProtoAndDeserialize();
1267 
1268         assertEquals(mDecodedProto.passpointProvisionStats.numProvisionSuccess, 1);
1269         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount.length, 2);
1270         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].failureCode,
1271                 PasspointProvisionStats.OSU_FAILURE_AP_CONNECTION);
1272         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[0].count, 1);
1273         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].failureCode,
1274                 PasspointProvisionStats.OSU_FAILURE_PROVISIONING_NOT_AVAILABLE);
1275         assertEquals(mDecodedProto.passpointProvisionStats.provisionFailureCount[1].count, 2);
1276     }
1277 
1278     /**
1279      * Combination of all other WifiMetrics unit tests, an internal-integration test, or functional
1280      * test
1281      */
1282     @Test
setMetricsSerializeDeserializeAssertMetricsSame()1283     public void setMetricsSerializeDeserializeAssertMetricsSame() throws Exception {
1284         setAndIncrementMetrics();
1285         startAndEndConnectionEventSucceeds();
1286         dumpProtoAndDeserialize();
1287         assertDeserializedMetricsCorrect();
1288         assertEquals("mDecodedProto.connectionEvent.length",
1289                 2, mDecodedProto.connectionEvent.length);
1290         //<TODO> test individual connectionEvents for correctness,
1291         // check scanReturnEntries & wifiSystemStateEntries counts and individual elements
1292         // pending their implementation</TODO>
1293     }
1294 
1295     /**
1296      * Test that score breach events are properly generated
1297      */
1298     @Test
testScoreBeachEvents()1299     public void testScoreBeachEvents() throws Exception {
1300         int upper = WifiMetrics.LOW_WIFI_SCORE + 7;
1301         int mid = WifiMetrics.LOW_WIFI_SCORE;
1302         int lower = WifiMetrics.LOW_WIFI_SCORE - 8;
1303         mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
1304         for (int score = upper; score >= mid; score--) mWifiMetrics.incrementWifiScoreCount(score);
1305         mWifiMetrics.incrementWifiScoreCount(mid + 1);
1306         mWifiMetrics.incrementWifiScoreCount(lower); // First breach
1307         for (int score = lower; score <= mid; score++) mWifiMetrics.incrementWifiScoreCount(score);
1308         mWifiMetrics.incrementWifiScoreCount(mid - 1);
1309         mWifiMetrics.incrementWifiScoreCount(upper); // Second breach
1310 
1311         dumpProtoAndDeserialize();
1312 
1313         assertEquals(2, mDecodedProto.staEventList.length);
1314         assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[0].type);
1315         assertEquals(lower, mDecodedProto.staEventList[0].lastScore);
1316         assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[1].type);
1317         assertEquals(upper, mDecodedProto.staEventList[1].lastScore);
1318     }
1319 
1320     /**
1321      * Test that Wifi usability score breach events are properly generated
1322      */
1323     @Test
testWifiUsabilityScoreBreachEvents()1324     public void testWifiUsabilityScoreBreachEvents() throws Exception {
1325         int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7;
1326         int mid = WifiMetrics.LOW_WIFI_USABILITY_SCORE;
1327         int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8;
1328         mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
1329         for (int score = upper; score >= mid; score--) {
1330             mWifiMetrics.incrementWifiUsabilityScoreCount(1, score, 15);
1331         }
1332         mWifiMetrics.incrementWifiUsabilityScoreCount(1, mid + 1, 15);
1333         mWifiMetrics.incrementWifiUsabilityScoreCount(1, lower, 15); // First breach
1334         for (int score = lower; score <= mid; score++) {
1335             mWifiMetrics.incrementWifiUsabilityScoreCount(1, score, 15);
1336         }
1337         mWifiMetrics.incrementWifiUsabilityScoreCount(1, mid - 1, 15);
1338         mWifiMetrics.incrementWifiUsabilityScoreCount(1, upper, 15); // Second breach
1339 
1340         dumpProtoAndDeserialize();
1341 
1342         assertEquals(2, mDecodedProto.staEventList.length);
1343         assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[0].type);
1344         assertEquals(lower, mDecodedProto.staEventList[0].lastWifiUsabilityScore);
1345         assertEquals(StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH, mDecodedProto.staEventList[1].type);
1346         assertEquals(upper, mDecodedProto.staEventList[1].lastWifiUsabilityScore);
1347     }
1348 
1349     private static final String SSID = "red";
1350     private static final int CONFIG_DTIM = 3;
1351     private static final int NETWORK_DETAIL_WIFIMODE = 5;
1352     private static final int NETWORK_DETAIL_DTIM = 7;
1353     private static final int SCAN_RESULT_LEVEL = -30;
1354     /**
1355      * Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration
1356      */
1357     @Test
testScanDetailAndWifiConfigurationUsage()1358     public void testScanDetailAndWifiConfigurationUsage() throws Exception {
1359         //Setup mock configs and scan details
1360         NetworkDetail networkDetail = mock(NetworkDetail.class);
1361         when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE);
1362         when(networkDetail.getSSID()).thenReturn(SSID);
1363         when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM);
1364         ScanResult scanResult = mock(ScanResult.class);
1365         scanResult.level = SCAN_RESULT_LEVEL;
1366         scanResult.capabilities = "EAP";
1367         WifiConfiguration config = mock(WifiConfiguration.class);
1368         config.SSID = "\"" + SSID + "\"";
1369         config.dtimInterval = CONFIG_DTIM;
1370         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
1371         config.allowedKeyManagement = new BitSet();
1372         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
1373         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
1374         config.enterpriseConfig = new WifiEnterpriseConfig();
1375         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
1376         config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
1377         WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
1378                 mock(WifiConfiguration.NetworkSelectionStatus.class);
1379         when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
1380         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
1381         ScanDetail scanDetail = mock(ScanDetail.class);
1382         when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
1383         when(scanDetail.getScanResult()).thenReturn(scanResult);
1384 
1385         config.networkId = TEST_NETWORK_ID;
1386         mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID,
1387                 WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
1388 
1389         //Create a connection event using only the config
1390         mWifiMetrics.startConnectionEvent(config, "Red",
1391                 WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1392         mWifiMetrics.endConnectionEvent(
1393                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1394                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1395                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1396 
1397         //Change configuration to open without randomization
1398         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
1399         scanResult.capabilities = "";
1400         //Create a connection event using the config and a scan detail
1401         mWifiMetrics.startConnectionEvent(config, "Green",
1402                 WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1403         mWifiMetrics.setConnectionScanDetail(scanDetail);
1404         mWifiMetrics.endConnectionEvent(
1405                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1406                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1407                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1408 
1409         //Dump proto from mWifiMetrics and deserialize it to mDecodedProto
1410         dumpProtoAndDeserialize();
1411 
1412         //Check that the correct values are being flowed through
1413         assertEquals(2, mDecodedProto.connectionEvent.length);
1414         assertEquals(CONFIG_DTIM, mDecodedProto.connectionEvent[0].routerFingerprint.dtim);
1415         assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_ENTERPRISE,
1416                 mDecodedProto.connectionEvent[0].routerFingerprint.authentication);
1417         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_TTLS,
1418                 mDecodedProto.connectionEvent[0].routerFingerprint.eapMethod);
1419         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_MSCHAPV2,
1420                 mDecodedProto.connectionEvent[0].routerFingerprint.authPhase2Method);
1421         assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[0].signalStrength);
1422         assertEquals(NETWORK_DETAIL_DTIM, mDecodedProto.connectionEvent[1].routerFingerprint.dtim);
1423         assertEquals(WifiMetricsProto.RouterFingerPrint.AUTH_OPEN,
1424                 mDecodedProto.connectionEvent[1].routerFingerprint.authentication);
1425         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_EAP_UNKNOWN,
1426                 mDecodedProto.connectionEvent[1].routerFingerprint.eapMethod);
1427         assertEquals(WifiMetricsProto.RouterFingerPrint.TYPE_PHASE2_NONE,
1428                 mDecodedProto.connectionEvent[1].routerFingerprint.authPhase2Method);
1429         assertEquals(SCAN_RESULT_LEVEL, mDecodedProto.connectionEvent[1].signalStrength);
1430         assertEquals(NETWORK_DETAIL_WIFIMODE,
1431                 mDecodedProto.connectionEvent[1].routerFingerprint.routerTechnology);
1432         assertTrue(mDecodedProto.connectionEvent[0].useRandomizedMac);
1433         assertFalse(mDecodedProto.connectionEvent[1].useRandomizedMac);
1434         assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL,
1435                 mDecodedProto.connectionEvent[0].connectionNominator);
1436     }
1437 
1438     /**
1439      * Tests that the mapping from networkId to nominatorId is not cleared.
1440      */
1441     @Test
testNetworkToNominatorNotCleared()1442     public void testNetworkToNominatorNotCleared() throws Exception {
1443         //Setup mock configs and scan details
1444         NetworkDetail networkDetail = mock(NetworkDetail.class);
1445         when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE);
1446         when(networkDetail.getSSID()).thenReturn(SSID);
1447         when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM);
1448         ScanResult scanResult = mock(ScanResult.class);
1449         scanResult.level = SCAN_RESULT_LEVEL;
1450         WifiConfiguration config = mock(WifiConfiguration.class);
1451         config.SSID = "\"" + SSID + "\"";
1452         config.dtimInterval = CONFIG_DTIM;
1453         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
1454         WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
1455                 mock(WifiConfiguration.NetworkSelectionStatus.class);
1456         when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
1457         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
1458         ScanDetail scanDetail = mock(ScanDetail.class);
1459         when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
1460         when(scanDetail.getScanResult()).thenReturn(scanResult);
1461 
1462         config.networkId = TEST_NETWORK_ID;
1463         mWifiMetrics.setNominatorForNetwork(TEST_NETWORK_ID,
1464                 WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER);
1465 
1466         // dump() calls clear() internally
1467         mWifiMetrics.dump(null, new PrintWriter(new StringWriter()),
1468                 new String[]{WifiMetrics.PROTO_DUMP_ARG});
1469 
1470         // Create a connection event using only the config
1471         mWifiMetrics.startConnectionEvent(config, "Red",
1472                 WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1473         mWifiMetrics.endConnectionEvent(
1474                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1475                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1476                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1477 
1478         dumpProtoAndDeserialize();
1479 
1480         assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_CARRIER,
1481                 mDecodedProto.connectionEvent[0].connectionNominator);
1482     }
1483 
1484     /**
1485      * Test that WifiMetrics is serializing/deserializing association time out events.
1486      */
1487     @Test
testMetricsAssociationTimedOut()1488     public void testMetricsAssociationTimedOut() throws Exception {
1489         mWifiMetrics.startConnectionEvent(null, "RED",
1490                 WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1491         mWifiMetrics.endConnectionEvent(
1492                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
1493                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1494                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1495 
1496         //Dump proto and deserialize
1497         //This should clear all the metrics in mWifiMetrics,
1498         dumpProtoAndDeserialize();
1499         //Check there is only 1 connection events
1500         assertEquals(1, mDecodedProto.connectionEvent.length);
1501         assertEquals(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT,
1502                 mDecodedProto.connectionEvent[0].level2FailureCode);
1503         assertEquals(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN,
1504                 mDecodedProto.connectionEvent[0].level2FailureReason);
1505     }
1506 
1507     /**
1508      * Test that WifiMetrics is serializing/deserializing authentication failure events.
1509      */
1510     @Test
testMetricsAuthenticationFailureReason()1511     public void testMetricsAuthenticationFailureReason() throws Exception {
1512         mWifiMetrics.startConnectionEvent(null, "RED",
1513                 WifiMetricsProto.ConnectionEvent.ROAM_NONE);
1514         mWifiMetrics.endConnectionEvent(
1515                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
1516                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1517                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD);
1518 
1519         //Dump proto and deserialize
1520         //This should clear all the metrics in mWifiMetrics,
1521         dumpProtoAndDeserialize();
1522         //Check there is only 1 connection events
1523         assertEquals(1, mDecodedProto.connectionEvent.length);
1524         assertEquals(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
1525                 mDecodedProto.connectionEvent[0].level2FailureCode);
1526         //Check the authentication failure reason
1527         assertEquals(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD,
1528                 mDecodedProto.connectionEvent[0].level2FailureReason);
1529     }
1530 
1531     /**
1532      * Test that WifiMetrics is being cleared after dumping via proto
1533      */
1534     @Test
testMetricsClearedAfterProtoRequested()1535     public void testMetricsClearedAfterProtoRequested() throws Exception {
1536         // Create 3 ConnectionEvents
1537         mWifiMetrics.startConnectionEvent(null, "RED",
1538                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1539         mWifiMetrics.endConnectionEvent(
1540                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1541                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1542                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1543         mWifiMetrics.startConnectionEvent(null, "YELLOW",
1544                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1545         mWifiMetrics.endConnectionEvent(
1546                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1547                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1548                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1549         mWifiMetrics.startConnectionEvent(null, "GREEN",
1550                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1551         mWifiMetrics.endConnectionEvent(
1552                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1553                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1554                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1555         mWifiMetrics.startConnectionEvent(null, "ORANGE",
1556                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1557         mWifiMetrics.endConnectionEvent(
1558                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1559                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1560                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1561 
1562         //Dump proto and deserialize
1563         //This should clear all the metrics in mWifiMetrics,
1564         dumpProtoAndDeserialize();
1565         //Check there are 4 connection events
1566         assertEquals(4, mDecodedProto.connectionEvent.length);
1567         assertEquals(0, mDecodedProto.rssiPollRssiCount.length);
1568         assertEquals(0, mDecodedProto.alertReasonCount.length);
1569 
1570         // Create 2 ConnectionEvents
1571         mWifiMetrics.startConnectionEvent(null,  "BLUE",
1572                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1573         mWifiMetrics.endConnectionEvent(
1574                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1575                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1576                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1577         mWifiMetrics.startConnectionEvent(null, "RED",
1578                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1579         mWifiMetrics.endConnectionEvent(
1580                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1581                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1582                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1583 
1584         //Dump proto and deserialize
1585         dumpProtoAndDeserialize();
1586         //Check there are only 2 connection events
1587         assertEquals(2, mDecodedProto.connectionEvent.length);
1588     }
1589 
1590     /**
1591      * Test that current ongoing ConnectionEvent is not cleared and logged
1592      * when proto is dumped
1593      */
1594     @Test
testCurrentConnectionEventNotClearedAfterProtoRequested()1595     public void testCurrentConnectionEventNotClearedAfterProtoRequested() throws Exception {
1596         // Create 2 complete ConnectionEvents and 1 ongoing un-ended ConnectionEvent
1597         mWifiMetrics.startConnectionEvent(null, "RED",
1598                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1599         mWifiMetrics.endConnectionEvent(
1600                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1601                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1602                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1603         mWifiMetrics.startConnectionEvent(null, "YELLOW",
1604                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1605         mWifiMetrics.endConnectionEvent(
1606                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1607                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1608                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1609         mWifiMetrics.startConnectionEvent(null, "GREEN",
1610                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
1611 
1612         // Dump proto and deserialize
1613         // This should clear the metrics in mWifiMetrics,
1614         dumpProtoAndDeserialize();
1615         assertEquals(2, mDecodedProto.connectionEvent.length);
1616 
1617         // End the ongoing ConnectionEvent
1618         mWifiMetrics.endConnectionEvent(
1619                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
1620                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
1621                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
1622 
1623         dumpProtoAndDeserialize();
1624         assertEquals(1, mDecodedProto.connectionEvent.length);
1625     }
1626 
1627     /**
1628      * Tests that after setting metrics values they can be serialized and deserialized with the
1629      *   $ adb shell dumpsys wifi wifiMetricsProto clean
1630      */
1631     @Test
testClearMetricsDump()1632     public void testClearMetricsDump() throws Exception {
1633         setAndIncrementMetrics();
1634         startAndEndConnectionEventSucceeds();
1635         cleanDumpProtoAndDeserialize();
1636         assertDeserializedMetricsCorrect();
1637         assertEquals("mDecodedProto.connectionEvent.length",
1638                 2, mDecodedProto.connectionEvent.length);
1639     }
1640 
1641     private static final int NUM_REPEATED_DELTAS = 7;
1642     private static final int REPEATED_DELTA = 0;
1643     private static final int SINGLE_GOOD_DELTA = 1;
1644     private static final int SINGLE_TIMEOUT_DELTA = 2;
1645     private static final int NUM_REPEATED_BOUND_DELTAS = 2;
1646     private static final int MAX_DELTA_LEVEL = 127;
1647     private static final int MIN_DELTA_LEVEL = -127;
1648     private static final int ARBITRARY_DELTA_LEVEL = 20;
1649 
1650     /**
1651      * Sunny day RSSI delta logging scenario.
1652      * Logs one rssi delta value multiple times
1653      * Logs a different delta value a single time
1654      */
1655     @Test
testRssiDeltasSuccessfulLogging()1656     public void testRssiDeltasSuccessfulLogging() throws Exception {
1657         // Generate some repeated deltas
1658         for (int i = 0; i < NUM_REPEATED_DELTAS; i++) {
1659             generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
1660                     WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
1661         }
1662         // Generate a single delta
1663         generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_GOOD_DELTA,
1664                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
1665         dumpProtoAndDeserialize();
1666         assertEquals(2, mDecodedProto.rssiPollDeltaCount.length);
1667         // Check the repeated deltas
1668         assertEquals(NUM_REPEATED_DELTAS, mDecodedProto.rssiPollDeltaCount[0].count);
1669         assertEquals(REPEATED_DELTA, mDecodedProto.rssiPollDeltaCount[0].rssi);
1670         // Check the single delta
1671         assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count);
1672         assertEquals(SINGLE_GOOD_DELTA, mDecodedProto.rssiPollDeltaCount[1].rssi);
1673     }
1674 
1675     /**
1676      * Tests that Rssi Delta events whose scanResult and Rssi Poll come too far apart, timeout,
1677      * and are not logged.
1678      */
1679     @Test
testRssiDeltasTimeout()1680     public void testRssiDeltasTimeout() throws Exception {
1681         // Create timed out rssi deltas
1682         generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
1683                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
1684         generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_TIMEOUT_DELTA,
1685                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
1686         dumpProtoAndDeserialize();
1687         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
1688     }
1689 
1690     /**
1691      * Tests the exact inclusive boundaries of RSSI delta logging.
1692      */
1693     @Test
testRssiDeltaSuccessfulLoggingExactBounds()1694     public void testRssiDeltaSuccessfulLoggingExactBounds() throws Exception {
1695         generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL,
1696                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
1697         generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL,
1698                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
1699         dumpProtoAndDeserialize();
1700         assertEquals(2, mDecodedProto.rssiPollDeltaCount.length);
1701         assertEquals(MIN_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi);
1702         assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count);
1703         assertEquals(MAX_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[1].rssi);
1704         assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count);
1705     }
1706 
1707     /**
1708      * Tests the exact exclusive boundaries of RSSI delta logging.
1709      * This test ensures that too much data is not generated.
1710      */
1711     @Test
testRssiDeltaOutOfBounds()1712     public void testRssiDeltaOutOfBounds() throws Exception {
1713         generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL + 1,
1714                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
1715         generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL - 1,
1716                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
1717         dumpProtoAndDeserialize();
1718         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
1719     }
1720 
1721     /**
1722      * This test ensures no rssi Delta is logged after an unsuccessful ConnectionEvent
1723      */
1724     @Test
testUnsuccesfulConnectionEventRssiDeltaIsNotLogged()1725     public void testUnsuccesfulConnectionEventRssiDeltaIsNotLogged() throws Exception {
1726         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
1727                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
1728                 false, // successfulConnectionEvent
1729                 true, // completeConnectionEvent
1730                 true, // useValidScanResult
1731                 true // dontDeserializeBeforePoll
1732         );
1733 
1734         dumpProtoAndDeserialize();
1735         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
1736     }
1737 
1738     /**
1739      * This test ensures rssi Deltas can be logged during a ConnectionEvent
1740      */
1741     @Test
testIncompleteConnectionEventRssiDeltaIsLogged()1742     public void testIncompleteConnectionEventRssiDeltaIsLogged() throws Exception {
1743         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
1744                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
1745                 true, // successfulConnectionEvent
1746                 false, // completeConnectionEvent
1747                 true, // useValidScanResult
1748                 true // dontDeserializeBeforePoll
1749         );
1750         dumpProtoAndDeserialize();
1751         assertEquals(1, mDecodedProto.rssiPollDeltaCount.length);
1752         assertEquals(ARBITRARY_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi);
1753         assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count);
1754     }
1755 
1756     /**
1757      * This test ensures that no delta is logged for a null ScanResult Candidate
1758      */
1759     @Test
testRssiDeltaNotLoggedForNullCandidateScanResult()1760     public void testRssiDeltaNotLoggedForNullCandidateScanResult() throws Exception {
1761         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
1762                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
1763                 true, // successfulConnectionEvent
1764                 true, // completeConnectionEvent
1765                 false, // useValidScanResult
1766                 true // dontDeserializeBeforePoll
1767         );
1768         dumpProtoAndDeserialize();
1769         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
1770     }
1771 
1772     /**
1773      * This test ensures that Rssi Deltas are not logged over a 'clear()' call (Metrics Serialized)
1774      */
1775     @Test
testMetricsSerializedDuringRssiDeltaEventLogsNothing()1776     public void testMetricsSerializedDuringRssiDeltaEventLogsNothing() throws Exception {
1777         generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
1778                 WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
1779                 true, // successfulConnectionEvent
1780                 true, // completeConnectionEvent
1781                 true, // useValidScanResult
1782                 false // dontDeserializeBeforePoll
1783         );
1784         dumpProtoAndDeserialize();
1785         assertEquals(0, mDecodedProto.rssiPollDeltaCount.length);
1786     }
1787 
1788     private static final int DEAUTH_REASON = 7;
1789     private static final int ASSOC_STATUS = 11;
1790     private static final int ASSOC_TIMEOUT = 1;
1791     private static final int LOCAL_GEN = 1;
1792     private static final int AUTH_FAILURE_REASON = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD;
1793     private static final int NUM_TEST_STA_EVENTS = 19;
1794     private static final String   sSSID = "\"SomeTestSsid\"";
1795     private static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
1796     private static final String   sBSSID = "01:02:03:04:05:06";
1797 
1798     private final StateChangeResult mStateDisconnected =
1799             new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED);
1800     private final StateChangeResult mStateCompleted =
1801             new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED);
1802     // Test bitmasks of supplicant state changes
1803     private final int mSupBm1 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state);
1804     private final int mSupBm2 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state)
1805             | WifiMetrics.supplicantStateToBit(mStateCompleted.state);
1806     // An invalid but interesting wifiConfiguration that exercises the StaEvent.ConfigInfo encoding
1807     private final WifiConfiguration mTestWifiConfig = createComplexWifiConfig();
1808     // <msg.what> <msg.arg1> <msg.arg2>
1809     private int[][] mTestStaMessageInts = {
1810         {WifiMonitor.ASSOCIATION_REJECTION_EVENT,   ASSOC_TIMEOUT,       ASSOC_STATUS},
1811         {WifiMonitor.AUTHENTICATION_FAILURE_EVENT,  AUTH_FAILURE_REASON, -1},
1812         {WifiMonitor.NETWORK_CONNECTION_EVENT,      0,                   0},
1813         {WifiMonitor.NETWORK_DISCONNECTION_EVENT,   LOCAL_GEN,           DEAUTH_REASON},
1814         {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0,                   0},
1815         {ClientModeImpl.CMD_ASSOCIATED_BSSID,       0,                   0},
1816         {ClientModeImpl.CMD_TARGET_BSSID,           0,                   0},
1817         {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0,                   0},
1818         {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0,                   0}
1819     };
1820     private Object[] mTestStaMessageObjs = {
1821         null,
1822         null,
1823         null,
1824         null,
1825         mStateDisconnected,
1826         null,
1827         null,
1828         mStateDisconnected,
1829         mStateCompleted
1830     };
1831     // Values used to generate the StaEvent log calls from ClientModeImpl
1832     // <StaEvent.Type>, <StaEvent.FrameworkDisconnectReason>, <1|0>(testWifiConfiguration, null)
1833     private int[][] mTestStaLogInts = {
1834         {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, 0,                          0},
1835         {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST,       0,                          0},
1836         {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST,        0,                          0},
1837         {StaEvent.TYPE_CMD_START_CONNECT,               0,                          1},
1838         {StaEvent.TYPE_CMD_START_ROAM,                  0,                          1},
1839         {StaEvent.TYPE_CONNECT_NETWORK,                 0,                          1},
1840         {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK,     0,                          0},
1841         {StaEvent.TYPE_FRAMEWORK_DISCONNECT,            StaEvent.DISCONNECT_API,    0},
1842         {StaEvent.TYPE_SCORE_BREACH,                    0,                          0},
1843         {StaEvent.TYPE_MAC_CHANGE,                      0,                          1},
1844         {StaEvent.TYPE_WIFI_ENABLED,                    0,                          0},
1845         {StaEvent.TYPE_WIFI_DISABLED,                   0,                          0},
1846         {StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH,     0,                          0}
1847     };
1848     // Values used to generate the StaEvent log calls from WifiMonitor
1849     // <type>, <reason>, <status>, <local_gen>,
1850     // <auth_fail_reason>, <assoc_timed_out> <supplicantStateChangeBitmask> <1|0>(has ConfigInfo)
1851     private int[][] mExpectedValues = {
1852         {StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT,     -1,  ASSOC_STATUS,         0,
1853             /**/                               0, ASSOC_TIMEOUT,        0, 0},    /**/
1854         {StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT,    -1,            -1,         0,
1855             /**/StaEvent.AUTH_FAILURE_WRONG_PSWD,             0,        0, 0},    /**/
1856         {StaEvent.TYPE_NETWORK_CONNECTION_EVENT,        -1,            -1,         0,
1857             /**/                               0,             0,        0, 0},    /**/
1858         {StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT, DEAUTH_REASON,     -1, LOCAL_GEN,
1859             /**/                               0,             0,        0, 0},    /**/
1860         {StaEvent.TYPE_CMD_ASSOCIATED_BSSID,            -1,            -1,         0,
1861             /**/                               0,             0,  mSupBm1, 0},    /**/
1862         {StaEvent.TYPE_CMD_TARGET_BSSID,                -1,            -1,         0,
1863             /**/                               0,             0,        0, 0},    /**/
1864         {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, -1,            -1,         0,
1865             /**/                               0,             0,  mSupBm2, 0},    /**/
1866         {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST,       -1,            -1,         0,
1867             /**/                               0,             0,        0, 0},    /**/
1868         {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST,        -1,            -1,         0,
1869             /**/                               0,             0,        0, 0},    /**/
1870         {StaEvent.TYPE_CMD_START_CONNECT,               -1,            -1,         0,
1871             /**/                               0,             0,        0, 1},    /**/
1872         {StaEvent.TYPE_CMD_START_ROAM,                  -1,            -1,         0,
1873             /**/                               0,             0,        0, 1},    /**/
1874         {StaEvent.TYPE_CONNECT_NETWORK,                 -1,            -1,         0,
1875             /**/                               0,             0,        0, 1},    /**/
1876         {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK,     -1,            -1,         0,
1877             /**/                               0,             0,        0, 0},    /**/
1878         {StaEvent.TYPE_FRAMEWORK_DISCONNECT,            -1,            -1,         0,
1879             /**/                               0,             0,        0, 0},    /**/
1880         {StaEvent.TYPE_SCORE_BREACH,                    -1,            -1,         0,
1881             /**/                               0,             0,        0, 0},    /**/
1882         {StaEvent.TYPE_MAC_CHANGE,                      -1,            -1,         0,
1883             /**/                               0,             0,        0, 1},    /**/
1884         {StaEvent.TYPE_WIFI_ENABLED,                    -1,            -1,         0,
1885             /**/                               0,             0,        0, 0},    /**/
1886         {StaEvent.TYPE_WIFI_DISABLED,                   -1,            -1,         0,
1887             /**/                               0,             0,        0, 0},     /**/
1888         {StaEvent.TYPE_WIFI_USABILITY_SCORE_BREACH,     -1,            -1,         0,
1889             /**/                               0,             0,        0, 0}    /**/
1890     };
1891 
1892     /**
1893      * Generates events from all the rows in mTestStaMessageInts, and then mTestStaLogInts
1894      */
generateStaEvents(WifiMetrics wifiMetrics)1895     private void generateStaEvents(WifiMetrics wifiMetrics) {
1896         Handler handler = wifiMetrics.getHandler();
1897         for (int i = 0; i < mTestStaMessageInts.length; i++) {
1898             int[] mia = mTestStaMessageInts[i];
1899             handler.sendMessage(
1900                     handler.obtainMessage(mia[0], mia[1], mia[2], mTestStaMessageObjs[i]));
1901         }
1902         mTestLooper.dispatchAll();
1903         for (int i = 0; i < mTestStaLogInts.length; i++) {
1904             int[] lia = mTestStaLogInts[i];
1905             wifiMetrics.logStaEvent(lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null);
1906         }
1907     }
verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog)1908     private void verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog) {
1909         assertNotNull(mTestWifiConfig);
1910         assertEquals(NUM_TEST_STA_EVENTS, wifiLog.staEventList.length);
1911         int j = 0; // De-serialized event index
1912         for (int i = 0; i < mTestStaMessageInts.length; i++) {
1913             StaEvent event = wifiLog.staEventList[j];
1914             int[] mia = mTestStaMessageInts[i];
1915             int[] evs = mExpectedValues[j];
1916             if (mia[0] != WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT) {
1917                 assertEquals(evs[0], event.type);
1918                 assertEquals(evs[1], event.reason);
1919                 assertEquals(evs[2], event.status);
1920                 assertEquals(evs[3] == 1 ? true : false, event.localGen);
1921                 assertEquals(evs[4], event.authFailureReason);
1922                 assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut);
1923                 assertEquals(evs[6], event.supplicantStateChangesBitmask);
1924                 assertConfigInfoEqualsWifiConfig(
1925                         evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
1926                 j++;
1927             }
1928         }
1929         for (int i = 0; i < mTestStaLogInts.length; i++) {
1930             StaEvent event = wifiLog.staEventList[j];
1931             int[] evs = mExpectedValues[j];
1932             assertEquals(evs[0], event.type);
1933             assertEquals(evs[1], event.reason);
1934             assertEquals(evs[2], event.status);
1935             assertEquals(evs[3] == 1 ? true : false, event.localGen);
1936             assertEquals(evs[4], event.authFailureReason);
1937             assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut);
1938             assertEquals(evs[6], event.supplicantStateChangesBitmask);
1939             assertConfigInfoEqualsWifiConfig(
1940                     evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
1941             j++;
1942         }
1943         assertEquals(mExpectedValues.length, j);
1944     }
1945 
1946     /**
1947      * Generate StaEvents of each type, ensure all the different values are logged correctly,
1948      * and that they survive serialization & de-serialization
1949      */
1950     @Test
testStaEventsLogSerializeDeserialize()1951     public void testStaEventsLogSerializeDeserialize() throws Exception {
1952         generateStaEvents(mWifiMetrics);
1953         dumpProtoAndDeserialize();
1954         verifyDeserializedStaEvents(mDecodedProto);
1955     }
1956 
1957     /**
1958      * Ensure the number of StaEvents does not exceed MAX_STA_EVENTS by generating lots of events
1959      * and checking how many are deserialized
1960      */
1961     @Test
testStaEventBounding()1962     public void testStaEventBounding() throws Exception {
1963         for (int i = 0; i < (WifiMetrics.MAX_STA_EVENTS + 10); i++) {
1964             mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT);
1965         }
1966         dumpProtoAndDeserialize();
1967         assertEquals(WifiMetrics.MAX_STA_EVENTS, mDecodedProto.staEventList.length);
1968     }
1969 
1970     /**
1971      * Tests that link probe StaEvents do not exceed
1972      * {@link WifiMetrics#MAX_LINK_PROBE_STA_EVENTS}.
1973      */
1974     @Test
testLinkProbeStaEventBounding()1975     public void testLinkProbeStaEventBounding() throws Exception {
1976         for (int i = 0; i < WifiMetrics.MAX_LINK_PROBE_STA_EVENTS; i++) {
1977             mWifiMetrics.logLinkProbeSuccess(0, 0, 0, 0);
1978             mWifiMetrics.logLinkProbeFailure(0, 0, 0, 0);
1979         }
1980         for (int i = 0; i < 10; i++) {
1981             mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT);
1982         }
1983 
1984         dumpProtoAndDeserialize();
1985 
1986         long numLinkProbeStaEvents = Arrays.stream(mDecodedProto.staEventList)
1987                 .filter(event -> event.type == TYPE_LINK_PROBE)
1988                 .count();
1989         assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS, numLinkProbeStaEvents);
1990         assertEquals(WifiMetrics.MAX_LINK_PROBE_STA_EVENTS + 10, mDecodedProto.staEventList.length);
1991     }
1992 
1993     /**
1994      * Ensure WifiMetrics doesn't cause a null pointer exception when called with null args
1995      */
1996     @Test
testDumpNullArg()1997     public void testDumpNullArg() {
1998         mWifiMetrics.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null);
1999     }
2000 
2001     /**
2002      * Test the generation of 'NumConnectableNetwork' histograms from two scans of different
2003      * ScanDetails produces the correct histogram values, and relevant bounds are observed
2004      */
2005     @MediumTest
2006     @Test
testNumConnectableNetworksGeneration()2007     public void testNumConnectableNetworksGeneration() throws Exception {
2008         List<ScanDetail> scan = new ArrayList<ScanDetail>();
2009         //                                ssid, bssid, isOpen, isSaved, isProvider, isWeakRssi)
2010         scan.add(buildMockScanDetail("PASSPOINT_1", "bssid0", false, false, true, false));
2011         scan.add(buildMockScanDetail("PASSPOINT_2", "bssid1", false, false, true, false));
2012         scan.add(buildMockScanDetail("SSID_B", "bssid2", true, true, false, false));
2013         scan.add(buildMockScanDetail("SSID_B", "bssid3", true, true, false, false));
2014         scan.add(buildMockScanDetail("SSID_C", "bssid4", true, false, false, false));
2015         scan.add(buildMockScanDetail("SSID_D", "bssid5", false, true, false, false));
2016         scan.add(buildMockScanDetail("SSID_E", "bssid6", false, true, false, false));
2017         scan.add(buildMockScanDetail("SSID_F", "bssid7", false, false, false, false));
2018         scan.add(buildMockScanDetail("SSID_G_WEAK", "bssid9", false, false, false, true));
2019         scan.add(buildMockScanDetail("SSID_H_WEAK", "bssid10", false, false, false, true));
2020         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2021         scan.add(buildMockScanDetail("SSID_B", "bssid8", true, true, false, false));
2022         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2023         for (int i = 0; i < NUM_PARTIAL_SCAN_RESULTS; i++) {
2024             mWifiMetrics.incrementAvailableNetworksHistograms(scan, false);
2025         }
2026         dumpProtoAndDeserialize();
2027         verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1,                    a(7),    a(2));
2028         verifyHist(mDecodedProto.totalBssidsInScanHistogram, 2,                   a(8, 9), a(1, 1));
2029         verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1,            a(2),    a(2));
2030         verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 2,           a(3, 4), a(1, 1));
2031         verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1,           a(3),    a(2));
2032         verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 2,          a(4, 5), a(1, 1));
2033         verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1,     a(4),    a(2));
2034         verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 2,    a(5, 6), a(1, 1));
2035         verifyHist(mDecodedProto.availableSavedPasspointProviderProfilesInScanHistogram, 1,
2036                                                                                   a(2),    a(2));
2037         verifyHist(mDecodedProto.availableSavedPasspointProviderBssidsInScanHistogram, 1,
2038                                                                                   a(2),    a(2));
2039         assertEquals(2, mDecodedProto.fullBandAllSingleScanListenerResults);
2040         assertEquals(NUM_PARTIAL_SCAN_RESULTS, mDecodedProto.partialAllSingleScanListenerResults);
2041 
2042         // Check Bounds
2043         scan.clear();
2044         int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET,
2045                 WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET) + 5;
2046         for (int i = 0; i < lotsOfSSids; i++) {
2047             scan.add(buildMockScanDetail("SSID_" + i, "bssid_" + i, true, true, false, false));
2048         }
2049         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2050         dumpProtoAndDeserialize();
2051         verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1,
2052                 a(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET), a(1));
2053         verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1,
2054                 a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
2055         verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1,
2056                 a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
2057         verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1,
2058                 a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1));
2059         scan.clear();
2060         int lotsOfBssids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET,
2061                 WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET) + 5;
2062         for (int i = 0; i < lotsOfBssids; i++) {
2063             scan.add(buildMockScanDetail("SSID", "bssid_" + i, true, true, false, false));
2064         }
2065         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2066         dumpProtoAndDeserialize();
2067         verifyHist(mDecodedProto.totalBssidsInScanHistogram, 1,
2068                 a(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET), a(1));
2069         verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 1,
2070                 a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
2071         verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 1,
2072                 a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
2073         verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 1,
2074                 a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1));
2075     }
2076 
2077     /**
2078      * Test that Hotspot 2.0 (Passpoint) scan results are collected correctly and that relevant
2079      * bounds are observed.
2080      */
2081     @Test
testObservedHotspotAps()2082     public void testObservedHotspotAps() throws Exception {
2083         List<ScanDetail> scan = new ArrayList<ScanDetail>();
2084         // 2 R1 (Unknown AP isn't counted) passpoint APs belonging to a single provider: hessid1
2085         long hessid1 = 10;
2086         int anqpDomainId1 = 5;
2087         scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX", "00:02:03:04:05:06", hessid1,
2088                 anqpDomainId1, NetworkDetail.HSRelease.R1, true));
2089         scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY", "01:02:03:04:05:06", hessid1,
2090                 anqpDomainId1, NetworkDetail.HSRelease.R1, true));
2091         scan.add(buildMockScanDetailPasspoint("PASSPOINT_XYZ", "02:02:03:04:05:06", hessid1,
2092                 anqpDomainId1, NetworkDetail.HSRelease.Unknown, true));
2093         // 2 R2 passpoint APs belonging to a single provider: hessid2
2094         long hessid2 = 12;
2095         int anqpDomainId2 = 6;
2096         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid2,
2097                 anqpDomainId2, NetworkDetail.HSRelease.R2, true));
2098         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid2,
2099                 anqpDomainId2, NetworkDetail.HSRelease.R2, true));
2100         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2101         scan = new ArrayList<ScanDetail>();
2102         // 3 R2 passpoint APs belonging to a single provider: hessid3 (in next scan)
2103         long hessid3 = 15;
2104         int anqpDomainId3 = 8;
2105         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3,
2106                 anqpDomainId3, NetworkDetail.HSRelease.R2, true));
2107         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3,
2108                 anqpDomainId3, NetworkDetail.HSRelease.R2, false));
2109         scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid3,
2110                 anqpDomainId3, NetworkDetail.HSRelease.R2, true));
2111         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2112         dumpProtoAndDeserialize();
2113 
2114         verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 2, a(0, 2), a(1, 1));
2115         verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 2, a(2, 3), a(1, 1));
2116         verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 2, a(0, 1), a(1, 1));
2117         verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1, a(1), a(2));
2118         verifyHist(mDecodedProto.observedHotspotR1ApsPerEssInScanHistogram, 1, a(2), a(1));
2119         verifyHist(mDecodedProto.observedHotspotR2ApsPerEssInScanHistogram, 2, a(2, 3), a(1, 1));
2120 
2121         // check bounds
2122         scan.clear();
2123         int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET,
2124                 WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET) + 5;
2125         for (int i = 0; i < lotsOfSSids; i++) {
2126             scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX" + i, "00:02:03:04:05:06", i,
2127                     i + 10, NetworkDetail.HSRelease.R1, true));
2128             scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY" + i, "AA:02:03:04:05:06", 1000 * i,
2129                     i + 10, NetworkDetail.HSRelease.R2, false));
2130         }
2131         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2132         dumpProtoAndDeserialize();
2133         verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 1,
2134                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
2135         verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 1,
2136                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1));
2137         verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 1,
2138                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
2139         verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1,
2140                 a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1));
2141     }
2142 
2143     /**
2144      * Test that IEEE 802.11mc scan results are collected correctly and that relevant
2145      * bounds are observed.
2146      */
2147     @Test
testObserved80211mcAps()2148     public void testObserved80211mcAps() throws Exception {
2149         ScanDetail mockScanDetailNon80211mc = mock(ScanDetail.class);
2150         ScanDetail mockScanDetail80211mc = mock(ScanDetail.class);
2151         NetworkDetail mockNetworkDetailNon80211mc = mock(NetworkDetail.class);
2152         NetworkDetail mockNetworkDetail80211mc = mock(NetworkDetail.class);
2153         when(mockNetworkDetail80211mc.is80211McResponderSupport()).thenReturn(true);
2154         ScanResult mockScanResult = mock(ScanResult.class);
2155         mockScanResult.capabilities = "";
2156         when(mockScanDetailNon80211mc.getNetworkDetail()).thenReturn(mockNetworkDetailNon80211mc);
2157         when(mockScanDetail80211mc.getNetworkDetail()).thenReturn(mockNetworkDetail80211mc);
2158         when(mockScanDetailNon80211mc.getScanResult()).thenReturn(mockScanResult);
2159         when(mockScanDetail80211mc.getScanResult()).thenReturn(mockScanResult);
2160         when(mWns.isSignalTooWeak(eq(mockScanDetail80211mc.getScanResult()))).thenReturn(true);
2161         List<ScanDetail> scan = new ArrayList<ScanDetail>();
2162 
2163         // 4 scans (a few non-802.11mc supporting APs on each)
2164         //  scan1: no 802.11mc supporting APs
2165 
2166         scan.add(mockScanDetailNon80211mc);
2167         scan.add(mockScanDetailNon80211mc);
2168         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2169 
2170         //  scan2: 2 802.11mc supporting APs
2171         scan.clear();
2172         scan.add(mockScanDetailNon80211mc);
2173         scan.add(mockScanDetail80211mc);
2174         scan.add(mockScanDetail80211mc);
2175         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2176 
2177         //  scan3: 100 802.11mc supporting APs (> limit)
2178         scan.clear();
2179         scan.add(mockScanDetailNon80211mc);
2180         scan.add(mockScanDetailNon80211mc);
2181         scan.add(mockScanDetailNon80211mc);
2182         for (int i = 0; i < 100; ++i) {
2183             scan.add(mockScanDetail80211mc);
2184         }
2185         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2186 
2187         //  scan4: 2 802.11mc supporting APs
2188         scan.clear();
2189         scan.add(mockScanDetailNon80211mc);
2190         scan.add(mockScanDetail80211mc);
2191         scan.add(mockScanDetail80211mc);
2192         scan.add(mockScanDetailNon80211mc);
2193         mWifiMetrics.incrementAvailableNetworksHistograms(scan, true);
2194 
2195         dumpProtoAndDeserialize();
2196 
2197         verifyHist(mDecodedProto.observed80211McSupportingApsInScanHistogram, 3,
2198                 a(0, 2, WifiMetrics.MAX_TOTAL_80211MC_APS_BUCKET), a(1, 2, 1));
2199     }
2200 
2201     /**
2202      * Test Open Network Notification blocklist size and feature state are not cleared when proto
2203      * is dumped.
2204      */
2205     @Test
testOpenNetworkNotificationBlocklistSizeAndFeatureStateNotCleared()2206     public void testOpenNetworkNotificationBlocklistSizeAndFeatureStateNotCleared()
2207             throws Exception {
2208         mWifiMetrics.setNetworkRecommenderBlocklistSize(OPEN_NET_NOTIFIER_TAG,
2209                 SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST);
2210         mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG,
2211                 IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
2212         for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) {
2213             mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG);
2214         }
2215 
2216         // This should clear most metrics in mWifiMetrics
2217         dumpProtoAndDeserialize();
2218         assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST,
2219                 mDecodedProto.openNetworkRecommenderBlacklistSize);
2220         assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
2221                 mDecodedProto.isWifiNetworksAvailableNotificationOn);
2222         assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES,
2223                 mDecodedProto.numOpenNetworkRecommendationUpdates);
2224 
2225         // Check that blocklist size and feature state persist on next dump but
2226         // others do not.
2227         dumpProtoAndDeserialize();
2228         assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLOCKLIST,
2229                 mDecodedProto.openNetworkRecommenderBlacklistSize);
2230         assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
2231                 mDecodedProto.isWifiNetworksAvailableNotificationOn);
2232         assertEquals(0, mDecodedProto.numOpenNetworkRecommendationUpdates);
2233     }
2234 
2235     /**
2236      * Check network selector id
2237      */
2238     @Test
testNetworkSelectorExperimentId()2239     public void testNetworkSelectorExperimentId() throws Exception {
2240         final int id = 42888888;
2241         mWifiMetrics.setNetworkSelectorExperimentId(id);
2242         mWifiMetrics.startConnectionEvent(mTestWifiConfig, "TestNetwork",
2243                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2244         mWifiMetrics.endConnectionEvent(
2245                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
2246                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
2247                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
2248         dumpProtoAndDeserialize();
2249         assertEquals(id, mDecodedProto.connectionEvent[0].networkSelectorExperimentId);
2250     }
2251 
2252     /**
2253      * Check ScoringParams
2254      */
2255     @Test
testExperimentId()2256     public void testExperimentId() throws Exception {
2257         final int id = 42;
2258         final String expectId = "x" + id;
2259         when(mScoringParams.getExperimentIdentifier()).thenReturn(id);
2260         dumpProtoAndDeserialize();
2261         assertEquals(expectId, mDecodedProto.scoreExperimentId);
2262     }
2263 
2264     /**
2265      * Check ScoringParams default case
2266      */
2267     @Test
testDefaultExperimentId()2268     public void testDefaultExperimentId() throws Exception {
2269         final int id = 0;
2270         final String expectId = "";
2271         when(mScoringParams.getExperimentIdentifier()).thenReturn(id);
2272         dumpProtoAndDeserialize();
2273         assertEquals(expectId, mDecodedProto.scoreExperimentId);
2274     }
2275 
2276     /** short hand for instantiating an anonymous int array, instead of 'new int[]{a1, a2, ...}' */
a(int... element)2277     private int[] a(int... element) {
2278         return element;
2279     }
2280 
verifyHist(WifiMetricsProto.NumConnectableNetworksBucket[] hist, int size, int[] keys, int[] counts)2281     private void verifyHist(WifiMetricsProto.NumConnectableNetworksBucket[] hist, int size,
2282             int[] keys, int[] counts) throws Exception {
2283         assertEquals(size, hist.length);
2284         for (int i = 0; i < keys.length; i++) {
2285             assertEquals(keys[i], hist[i].numConnectableNetworks);
2286             assertEquals(counts[i], hist[i].count);
2287         }
2288     }
2289 
2290     /**
2291      * Generate an RSSI delta event by creating a connection event and an RSSI poll within
2292      * 'interArrivalTime' milliseconds of each other.
2293      * Event will not be logged if interArrivalTime > mWifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS
2294      * successfulConnectionEvent, completeConnectionEvent, useValidScanResult and
2295      * dontDeserializeBeforePoll
2296      * each create an anomalous condition when set to false.
2297      */
generateRssiDelta(int scanRssi, int rssiDelta, long interArrivalTime, boolean successfulConnectionEvent, boolean completeConnectionEvent, boolean useValidScanResult, boolean dontDeserializeBeforePoll)2298     private void generateRssiDelta(int scanRssi, int rssiDelta,
2299             long interArrivalTime, boolean successfulConnectionEvent,
2300             boolean completeConnectionEvent, boolean useValidScanResult,
2301             boolean dontDeserializeBeforePoll) throws Exception {
2302         when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
2303         ScanResult scanResult = null;
2304         if (useValidScanResult) {
2305             scanResult = mock(ScanResult.class);
2306             scanResult.level = scanRssi;
2307         }
2308         WifiConfiguration config = mock(WifiConfiguration.class);
2309         WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
2310                 mock(WifiConfiguration.NetworkSelectionStatus.class);
2311         when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
2312         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
2313         mWifiMetrics.startConnectionEvent(config, "TestNetwork",
2314                 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
2315         if (completeConnectionEvent) {
2316             if (successfulConnectionEvent) {
2317                 mWifiMetrics.endConnectionEvent(
2318                         WifiMetrics.ConnectionEvent.FAILURE_NONE,
2319                         WifiMetricsProto.ConnectionEvent.HLF_NONE,
2320                         WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
2321             } else {
2322                 mWifiMetrics.endConnectionEvent(
2323                         WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
2324                         WifiMetricsProto.ConnectionEvent.HLF_NONE,
2325                         WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
2326             }
2327         }
2328         when(mClock.getElapsedSinceBootMillis()).thenReturn(interArrivalTime);
2329         if (!dontDeserializeBeforePoll) {
2330             dumpProtoAndDeserialize();
2331         }
2332         mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, scanRssi + rssiDelta);
2333     }
2334 
2335     /**
2336      * Generate an RSSI delta event, with all extra conditions set to true.
2337      */
generateRssiDelta(int scanRssi, int rssiDelta, long interArrivalTime)2338     private void generateRssiDelta(int scanRssi, int rssiDelta,
2339             long interArrivalTime) throws Exception {
2340         generateRssiDelta(scanRssi, rssiDelta, interArrivalTime, true, true, true, true);
2341     }
2342 
assertStringContains( String actualString, String expectedSubstring)2343     private void assertStringContains(
2344             String actualString, String expectedSubstring) {
2345         assertTrue("Expected text not found in: " + actualString,
2346                 actualString.contains(expectedSubstring));
2347     }
2348 
getStateDump()2349     private String getStateDump() {
2350         ByteArrayOutputStream stream = new ByteArrayOutputStream();
2351         PrintWriter writer = new PrintWriter(stream);
2352         String[] args = new String[0];
2353         mWifiMetrics.dump(null, writer, args);
2354         writer.flush();
2355         return stream.toString();
2356     }
2357 
2358     private static final int TEST_ALLOWED_KEY_MANAGEMENT = 83;
2359     private static final int TEST_ALLOWED_PROTOCOLS = 22;
2360     private static final int TEST_ALLOWED_AUTH_ALGORITHMS = 11;
2361     private static final int TEST_ALLOWED_PAIRWISE_CIPHERS = 67;
2362     private static final int TEST_ALLOWED_GROUP_CIPHERS = 231;
2363     private static final int TEST_CANDIDATE_LEVEL = -80;
2364     private static final int TEST_CANDIDATE_FREQ = 2345;
2365 
createComplexWifiConfig()2366     private WifiConfiguration createComplexWifiConfig() {
2367         WifiConfiguration config = new WifiConfiguration();
2368         config.allowedKeyManagement = intToBitSet(TEST_ALLOWED_KEY_MANAGEMENT);
2369         config.allowedProtocols = intToBitSet(TEST_ALLOWED_PROTOCOLS);
2370         config.allowedAuthAlgorithms = intToBitSet(TEST_ALLOWED_AUTH_ALGORITHMS);
2371         config.allowedPairwiseCiphers = intToBitSet(TEST_ALLOWED_PAIRWISE_CIPHERS);
2372         config.allowedGroupCiphers = intToBitSet(TEST_ALLOWED_GROUP_CIPHERS);
2373         config.hiddenSSID = true;
2374         config.ephemeral = true;
2375         config.getNetworkSelectionStatus().setHasEverConnected(true);
2376         ScanResult candidate = new ScanResult();
2377         candidate.level = TEST_CANDIDATE_LEVEL;
2378         candidate.frequency = TEST_CANDIDATE_FREQ;
2379         config.getNetworkSelectionStatus().setCandidate(candidate);
2380         return config;
2381     }
2382 
assertConfigInfoEqualsWifiConfig(WifiConfiguration config, StaEvent.ConfigInfo info)2383     private void assertConfigInfoEqualsWifiConfig(WifiConfiguration config,
2384             StaEvent.ConfigInfo info) {
2385         if (config == null && info == null) return;
2386         assertEquals(config.allowedKeyManagement,   intToBitSet(info.allowedKeyManagement));
2387         assertEquals(config.allowedProtocols,       intToBitSet(info.allowedProtocols));
2388         assertEquals(config.allowedAuthAlgorithms,  intToBitSet(info.allowedAuthAlgorithms));
2389         assertEquals(config.allowedPairwiseCiphers, intToBitSet(info.allowedPairwiseCiphers));
2390         assertEquals(config.allowedGroupCiphers,    intToBitSet(info.allowedGroupCiphers));
2391         assertEquals(config.hiddenSSID, info.hiddenSsid);
2392         assertEquals(config.ephemeral, info.isEphemeral);
2393         assertEquals(config.getNetworkSelectionStatus().getHasEverConnected(),
2394                 info.hasEverConnected);
2395         assertEquals(config.getNetworkSelectionStatus().getCandidate().level, info.scanRssi);
2396         assertEquals(config.getNetworkSelectionStatus().getCandidate().frequency, info.scanFreq);
2397     }
2398 
2399     /**
2400      * Sets the values of bitSet to match an int mask
2401      */
intToBitSet(int mask)2402     private static BitSet intToBitSet(int mask) {
2403         BitSet bitSet = new BitSet();
2404         for (int bitIndex = 0; mask > 0; mask >>>= 1, bitIndex++) {
2405             if ((mask & 1) != 0) bitSet.set(bitIndex);
2406         }
2407         return bitSet;
2408     }
2409 
2410     private static final int NUM_UNUSABLE_EVENT = 5;
2411     private static final int NUM_UNUSABLE_EVENT_TIME_THROTTLE = 3;
2412 
2413     /**
2414      * Values used to generate WifiIsUnusableEvent
2415      * <WifiIsUnusableEvent.TriggerType>, <last_score>, <tx_success_delta>, <tx_retries_delta>,
2416      * <tx_bad_delta>, <rx_success_delta>, <packet_update_time_delta>, <firmware_alert_code>,
2417      * <last_wifi_usability_score>
2418      */
2419     private int[][] mTestUnusableEvents = {
2420         {WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX,        60,  60,  50,  40,  30,  1000,  -1, 51},
2421         {WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX, 55,  40,  30,  0,   0,   500,   -1, 52},
2422         {WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH,          60,  90,  30,  30,  0,   1000,  -1, 53},
2423         {WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT,           55,  55,  30,  15,  10,  1000,   4, 54},
2424         {WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST,     50,  56,  28,  17,  12,  1000,  -1, 45}
2425     };
2426 
2427     /**
2428      * Generate all WifiIsUnusableEvents from mTestUnusableEvents
2429      */
generateAllUnusableEvents(WifiMetrics wifiMetrics)2430     private void generateAllUnusableEvents(WifiMetrics wifiMetrics) {
2431         for (int i = 0; i < mTestUnusableEvents.length; i++) {
2432             generateUnusableEventAtGivenTime(i, i * (WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000));
2433         }
2434     }
2435 
2436     /**
2437      * Generate a WifiIsUnusableEvent at the given timestamp with data from
2438      * mTestUnusableEvents[index]
2439      */
generateUnusableEventAtGivenTime(int index, long eventTime)2440     private void generateUnusableEventAtGivenTime(int index, long eventTime) {
2441         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime);
2442         int[] trigger = mTestUnusableEvents[index];
2443         mWifiMetrics.incrementWifiScoreCount(trigger[1]);
2444         mWifiMetrics.incrementWifiUsabilityScoreCount(1, trigger[8], 15);
2445         mWifiMetrics.updateWifiIsUnusableLinkLayerStats(trigger[2], trigger[3], trigger[4],
2446                 trigger[5], trigger[6]);
2447         mWifiMetrics.setScreenState(true);
2448         switch(trigger[0]) {
2449             case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
2450             case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
2451             case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
2452                 mWifiMetrics.logWifiIsUnusableEvent(trigger[0]);
2453                 break;
2454             case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
2455                 mWifiMetrics.logWifiIsUnusableEvent(trigger[0], trigger[7]);
2456                 break;
2457             case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
2458                 mWifiMetrics.logWifiIsUnusableEvent(trigger[0]);
2459                 break;
2460             default:
2461                 break;
2462         }
2463     }
2464 
2465     /**
2466      * Verify that WifiIsUnusableEvent in wifiLog matches mTestUnusableEvents
2467      */
verifyDeserializedUnusableEvents(WifiMetricsProto.WifiLog wifiLog)2468     private void verifyDeserializedUnusableEvents(WifiMetricsProto.WifiLog wifiLog) {
2469         assertEquals(NUM_UNUSABLE_EVENT, wifiLog.wifiIsUnusableEventList.length);
2470         for (int i = 0; i < mTestUnusableEvents.length; i++) {
2471             WifiIsUnusableEvent event = wifiLog.wifiIsUnusableEventList[i];
2472             verifyUnusableEvent(event, i);
2473         }
2474     }
2475 
2476     /**
2477      * Verify that the given WifiIsUnusableEvent matches mTestUnusableEvents
2478      * at given index
2479      */
verifyUnusableEvent(WifiIsUnusableEvent event, int index)2480     private void verifyUnusableEvent(WifiIsUnusableEvent event, int index) {
2481         int[] expectedValues = mTestUnusableEvents[index];
2482         assertEquals(expectedValues[0], event.type);
2483         assertEquals(expectedValues[1], event.lastScore);
2484         assertEquals(expectedValues[2], event.txSuccessDelta);
2485         assertEquals(expectedValues[3], event.txRetriesDelta);
2486         assertEquals(expectedValues[4], event.txBadDelta);
2487         assertEquals(expectedValues[5], event.rxSuccessDelta);
2488         assertEquals(expectedValues[6], event.packetUpdateTimeDelta);
2489         assertEquals(expectedValues[7], event.firmwareAlertCode);
2490         assertEquals(expectedValues[8], event.lastWifiUsabilityScore);
2491         assertEquals(true, event.screenOn);
2492     }
2493 
2494     /**
2495      * Verify that no WifiIsUnusableEvent is generated when it is disabled in the settings
2496      */
2497     @Test
testNoUnusableEventLogWhenDisabled()2498     public void testNoUnusableEventLogWhenDisabled() throws Exception {
2499         when(mFacade.getIntegerSetting(eq(mContext),
2500                 eq(Settings.Global.WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED),
2501                 anyInt())).thenReturn(0);
2502         mWifiMetrics.loadSettings();
2503         generateAllUnusableEvents(mWifiMetrics);
2504         dumpProtoAndDeserialize();
2505         assertEquals(0, mDecodedProto.wifiIsUnusableEventList.length);
2506     }
2507 
2508     /**
2509      * Generate WifiIsUnusableEvent and verify that they are logged correctly
2510      */
2511     @Test
testUnusableEventLogSerializeDeserialize()2512     public void testUnusableEventLogSerializeDeserialize() throws Exception {
2513         when(mFacade.getIntegerSetting(eq(mContext),
2514                 eq(Settings.Global.WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED),
2515                 anyInt())).thenReturn(1);
2516         mWifiMetrics.loadSettings();
2517         generateAllUnusableEvents(mWifiMetrics);
2518         dumpProtoAndDeserialize();
2519         verifyDeserializedUnusableEvents(mDecodedProto);
2520     }
2521 
2522     /**
2523      * Verify that the number of WifiIsUnusableEvents does not exceed MAX_UNUSABLE_EVENTS
2524      */
2525     @Test
testUnusableEventBounding()2526     public void testUnusableEventBounding() throws Exception {
2527         when(mFacade.getIntegerSetting(eq(mContext),
2528                 eq(Settings.Global.WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED),
2529                 anyInt())).thenReturn(1);
2530         mWifiMetrics.loadSettings();
2531         for (int i = 0; i < (WifiMetrics.MAX_UNUSABLE_EVENTS + 2); i++) {
2532             generateAllUnusableEvents(mWifiMetrics);
2533         }
2534         dumpProtoAndDeserialize();
2535         assertEquals(WifiMetrics.MAX_UNUSABLE_EVENTS, mDecodedProto.wifiIsUnusableEventList.length);
2536     }
2537 
2538     /**
2539      * Verify that we don't generate new WifiIsUnusableEvent from data stalls
2540      * until MIN_DATA_STALL_WAIT_MS has passed since the last data stall WifiIsUnusableEvent
2541      */
2542     @Test
testUnusableEventTimeThrottleForDataStall()2543     public void testUnusableEventTimeThrottleForDataStall() throws Exception {
2544         when(mFacade.getIntegerSetting(eq(mContext),
2545                 eq(Settings.Global.WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED),
2546                 anyInt())).thenReturn(1);
2547         mWifiMetrics.loadSettings();
2548         generateUnusableEventAtGivenTime(0, 0);
2549         // should be time throttled
2550         generateUnusableEventAtGivenTime(1, 1);
2551         generateUnusableEventAtGivenTime(2, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1000);
2552         // no time throttle for firmware alert
2553         generateUnusableEventAtGivenTime(3, WifiMetrics.MIN_DATA_STALL_WAIT_MS + 1001);
2554         dumpProtoAndDeserialize();
2555         assertEquals(NUM_UNUSABLE_EVENT_TIME_THROTTLE,
2556                 mDecodedProto.wifiIsUnusableEventList.length);
2557         verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[0], 0);
2558         verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[1], 2);
2559         verifyUnusableEvent(mDecodedProto.wifiIsUnusableEventList[2], 3);
2560     }
2561 
2562     /**
2563      * Verify that LinkSpeedCounts is correctly logged in metrics
2564      */
2565     @Test
testLinkSpeedCounts()2566     public void testLinkSpeedCounts() throws Exception {
2567         when(mFacade.getIntegerSetting(eq(mContext),
2568                 eq(Settings.Global.WIFI_LINK_SPEED_METRICS_ENABLED), anyInt())).thenReturn(1);
2569         mWifiMetrics.loadSettings();
2570         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
2571             for (int j = 0; j <= i; j++) {
2572                 mWifiMetrics.incrementLinkSpeedCount(
2573                         WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL);
2574             }
2575         }
2576         dumpProtoAndDeserialize();
2577         assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT, mDecodedProto.linkSpeedCounts.length);
2578         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
2579             assertEquals("Incorrect link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i,
2580                     mDecodedProto.linkSpeedCounts[i].linkSpeedMbps);
2581             assertEquals("Incorrect count of link speed",
2582                     i + 1, mDecodedProto.linkSpeedCounts[i].count);
2583             assertEquals("Incorrect sum of absolute values of rssi values",
2584                     Math.abs(TEST_RSSI_LEVEL) * (i + 1),
2585                     mDecodedProto.linkSpeedCounts[i].rssiSumDbm);
2586             assertEquals("Incorrect sum of squares of rssi values",
2587                     TEST_RSSI_LEVEL * TEST_RSSI_LEVEL * (i + 1),
2588                     mDecodedProto.linkSpeedCounts[i].rssiSumOfSquaresDbmSq);
2589         }
2590     }
2591 
2592     /**
2593      * Verify that Tx and Rx per-band LinkSpeedCounts are correctly logged in metrics
2594      */
2595     @Test
testTxRxLinkSpeedBandCounts()2596     public void testTxRxLinkSpeedBandCounts() throws Exception {
2597         when(mFacade.getIntegerSetting(eq(mContext),
2598                 eq(Settings.Global.WIFI_LINK_SPEED_METRICS_ENABLED), anyInt())).thenReturn(1);
2599         mWifiMetrics.loadSettings();
2600         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
2601             for (int j = 0; j <= i; j++) {
2602                 mWifiMetrics.incrementTxLinkSpeedBandCount(
2603                         WifiMetrics.MIN_LINK_SPEED_MBPS + i, RSSI_POLL_FREQUENCY);
2604                 mWifiMetrics.incrementRxLinkSpeedBandCount(
2605                         WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1, RSSI_POLL_FREQUENCY);
2606             }
2607         }
2608         dumpProtoAndDeserialize();
2609         assertEquals(0, mDecodedProto.txLinkSpeedCount2G.length);
2610         assertEquals(0, mDecodedProto.rxLinkSpeedCount2G.length);
2611         assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT,
2612                 mDecodedProto.txLinkSpeedCount5GLow.length);
2613         assertEquals(NUM_LINK_SPEED_LEVELS_TO_INCREMENT,
2614                 mDecodedProto.rxLinkSpeedCount5GLow.length);
2615         assertEquals(0, mDecodedProto.txLinkSpeedCount5GMid.length);
2616         assertEquals(0, mDecodedProto.rxLinkSpeedCount5GMid.length);
2617         assertEquals(0, mDecodedProto.txLinkSpeedCount5GHigh.length);
2618         assertEquals(0, mDecodedProto.rxLinkSpeedCount5GHigh.length);
2619         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
2620             assertEquals("Incorrect Tx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i,
2621                     mDecodedProto.txLinkSpeedCount5GLow[i].key);
2622             assertEquals("Incorrect Rx link speed", WifiMetrics.MIN_LINK_SPEED_MBPS + i + 1,
2623                     mDecodedProto.rxLinkSpeedCount5GLow[i].key);
2624             assertEquals("Incorrect count of Tx link speed",
2625                     i + 1, mDecodedProto.txLinkSpeedCount5GLow[i].count);
2626             assertEquals("Incorrect count of Rx link speed",
2627                     i + 1, mDecodedProto.rxLinkSpeedCount5GLow[i].count);
2628         }
2629     }
2630 
2631     /**
2632      * Verify that LinkSpeedCounts is not logged when disabled in settings
2633      */
2634     @Test
testNoLinkSpeedCountsWhenDisabled()2635     public void testNoLinkSpeedCountsWhenDisabled() throws Exception {
2636         when(mFacade.getIntegerSetting(eq(mContext),
2637                 eq(Settings.Global.WIFI_LINK_SPEED_METRICS_ENABLED), anyInt())).thenReturn(0);
2638         mWifiMetrics.loadSettings();
2639         for (int i = 0; i < NUM_LINK_SPEED_LEVELS_TO_INCREMENT; i++) {
2640             for (int j = 0; j <= i; j++) {
2641                 mWifiMetrics.incrementLinkSpeedCount(
2642                         WifiMetrics.MIN_LINK_SPEED_MBPS + i, TEST_RSSI_LEVEL);
2643                 mWifiMetrics.incrementTxLinkSpeedBandCount(
2644                         WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
2645                 mWifiMetrics.incrementRxLinkSpeedBandCount(
2646                         WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
2647             }
2648         }
2649         dumpProtoAndDeserialize();
2650         assertEquals("LinkSpeedCounts should not be logged when disabled in settings",
2651                 0, mDecodedProto.linkSpeedCounts.length);
2652         assertEquals("Tx LinkSpeedCounts should not be logged when disabled in settings",
2653                 0, mDecodedProto.txLinkSpeedCount5GLow.length);
2654         assertEquals("Rx LinkSpeedCounts should not be logged when disabled in settings",
2655                 0, mDecodedProto.rxLinkSpeedCount5GLow.length);
2656     }
2657 
2658     /**
2659      * Verify that LinkSpeedCounts is not logged when the link speed value is lower than
2660      * MIN_LINK_SPEED_MBPS or when the rssi value is outside of
2661      * [MIN_RSSI_LEVEL, MAX_RSSI_LEVEL]
2662      */
2663     @Test
testNoLinkSpeedCountsForOutOfBoundValues()2664     public void testNoLinkSpeedCountsForOutOfBoundValues() throws Exception {
2665         when(mFacade.getIntegerSetting(eq(mContext),
2666                 eq(Settings.Global.WIFI_LINK_SPEED_METRICS_ENABLED), anyInt())).thenReturn(1);
2667         mWifiMetrics.loadSettings();
2668         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
2669             mWifiMetrics.incrementLinkSpeedCount(
2670                     WifiMetrics.MIN_LINK_SPEED_MBPS - i, MIN_RSSI_LEVEL);
2671             mWifiMetrics.incrementTxLinkSpeedBandCount(
2672                     WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
2673             mWifiMetrics.incrementRxLinkSpeedBandCount(
2674                     WifiMetrics.MIN_LINK_SPEED_MBPS - i, RSSI_POLL_FREQUENCY);
2675         }
2676         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
2677             mWifiMetrics.incrementLinkSpeedCount(
2678                     WifiMetrics.MIN_LINK_SPEED_MBPS, MIN_RSSI_LEVEL - i);
2679         }
2680         for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
2681             mWifiMetrics.incrementLinkSpeedCount(
2682                     WifiMetrics.MIN_LINK_SPEED_MBPS, MAX_RSSI_LEVEL + i);
2683         }
2684         dumpProtoAndDeserialize();
2685         assertEquals("LinkSpeedCounts should not be logged for out of bound values",
2686                 0, mDecodedProto.linkSpeedCounts.length);
2687         assertEquals("Tx LinkSpeedCounts should not be logged for out of bound values",
2688                 0, mDecodedProto.txLinkSpeedCount5GLow.length);
2689         assertEquals("Rx LinkSpeedCounts should not be logged for out of bound values",
2690                 0, mDecodedProto.rxLinkSpeedCount5GLow.length);
2691     }
2692 
nextRandInt()2693     private int nextRandInt() {
2694         return mRandom.nextInt(1000);
2695     }
2696 
nextRandomStats(WifiLinkLayerStats current)2697     private WifiLinkLayerStats nextRandomStats(WifiLinkLayerStats current) {
2698         WifiLinkLayerStats out = new WifiLinkLayerStats();
2699         out.timeStampInMs = current.timeStampInMs + nextRandInt();
2700 
2701         out.rxmpdu_be = current.rxmpdu_be + nextRandInt();
2702         out.txmpdu_be = current.txmpdu_be + nextRandInt();
2703         out.lostmpdu_be = current.lostmpdu_be + nextRandInt();
2704         out.retries_be = current.retries_be + nextRandInt();
2705 
2706         out.rxmpdu_bk = current.rxmpdu_bk + nextRandInt();
2707         out.txmpdu_bk = current.txmpdu_bk + nextRandInt();
2708         out.lostmpdu_bk = current.lostmpdu_bk + nextRandInt();
2709         out.retries_bk = current.retries_bk + nextRandInt();
2710 
2711         out.rxmpdu_vi = current.rxmpdu_vi + nextRandInt();
2712         out.txmpdu_vi = current.txmpdu_vi + nextRandInt();
2713         out.lostmpdu_vi = current.lostmpdu_vi + nextRandInt();
2714         out.retries_vi = current.retries_vi + nextRandInt();
2715 
2716         out.rxmpdu_vo = current.rxmpdu_vo + nextRandInt();
2717         out.txmpdu_vo = current.txmpdu_vo + nextRandInt();
2718         out.lostmpdu_vo = current.lostmpdu_vo + nextRandInt();
2719         out.retries_vo = current.retries_vo + nextRandInt();
2720 
2721         out.on_time = current.on_time + nextRandInt();
2722         out.tx_time = current.tx_time + nextRandInt();
2723         out.rx_time = current.rx_time + nextRandInt();
2724         out.on_time_scan = current.on_time_scan + nextRandInt();
2725         out.on_time_nan_scan = current.on_time_nan_scan + nextRandInt();
2726         out.on_time_background_scan = current.on_time_background_scan + nextRandInt();
2727         out.on_time_roam_scan = current.on_time_roam_scan + nextRandInt();
2728         out.on_time_pno_scan = current.on_time_pno_scan + nextRandInt();
2729         out.on_time_hs20_scan = current.on_time_hs20_scan + nextRandInt();
2730         return out;
2731     }
2732 
assertWifiLinkLayerUsageHasDiff(WifiLinkLayerStats oldStats, WifiLinkLayerStats newStats)2733     private void assertWifiLinkLayerUsageHasDiff(WifiLinkLayerStats oldStats,
2734             WifiLinkLayerStats newStats) {
2735         assertEquals(newStats.timeStampInMs - oldStats.timeStampInMs,
2736                 mDecodedProto.wifiLinkLayerUsageStats.loggingDurationMs);
2737         assertEquals(newStats.on_time - oldStats.on_time,
2738                 mDecodedProto.wifiLinkLayerUsageStats.radioOnTimeMs);
2739         assertEquals(newStats.tx_time - oldStats.tx_time,
2740                 mDecodedProto.wifiLinkLayerUsageStats.radioTxTimeMs);
2741         assertEquals(newStats.rx_time - oldStats.rx_time,
2742                 mDecodedProto.wifiLinkLayerUsageStats.radioRxTimeMs);
2743         assertEquals(newStats.on_time_scan - oldStats.on_time_scan,
2744                 mDecodedProto.wifiLinkLayerUsageStats.radioScanTimeMs);
2745         assertEquals(newStats.on_time_nan_scan - oldStats.on_time_nan_scan,
2746                 mDecodedProto.wifiLinkLayerUsageStats.radioNanScanTimeMs);
2747         assertEquals(newStats.on_time_background_scan - oldStats.on_time_background_scan,
2748                 mDecodedProto.wifiLinkLayerUsageStats.radioBackgroundScanTimeMs);
2749         assertEquals(newStats.on_time_roam_scan - oldStats.on_time_roam_scan,
2750                 mDecodedProto.wifiLinkLayerUsageStats.radioRoamScanTimeMs);
2751         assertEquals(newStats.on_time_pno_scan - oldStats.on_time_pno_scan,
2752                 mDecodedProto.wifiLinkLayerUsageStats.radioPnoScanTimeMs);
2753         assertEquals(newStats.on_time_hs20_scan - oldStats.on_time_hs20_scan,
2754                 mDecodedProto.wifiLinkLayerUsageStats.radioHs20ScanTimeMs);
2755 
2756     }
2757 
2758     /**
2759      * Verify that WifiMetrics is counting link layer usage correctly when given a series of
2760      * valid input.
2761      * @throws Exception
2762      */
2763     @Test
testWifiLinkLayerUsageStats()2764     public void testWifiLinkLayerUsageStats() throws Exception {
2765         WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats());
2766         WifiLinkLayerStats stat2 = nextRandomStats(stat1);
2767         WifiLinkLayerStats stat3 = nextRandomStats(stat2);
2768         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1);
2769         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2);
2770         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat3);
2771         dumpProtoAndDeserialize();
2772 
2773         // After 2 increments, the counters should have difference between |stat1| and |stat3|
2774         assertWifiLinkLayerUsageHasDiff(stat1, stat3);
2775     }
2776 
2777     /**
2778      * Verify that null input is handled and wifi link layer usage stats are not incremented.
2779      * @throws Exception
2780      */
2781     @Test
testWifiLinkLayerUsageStatsNullInput()2782     public void testWifiLinkLayerUsageStatsNullInput() throws Exception {
2783         WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats());
2784         WifiLinkLayerStats stat2 = null;
2785         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1);
2786         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2);
2787         dumpProtoAndDeserialize();
2788 
2789         // Counter should be zero
2790         assertWifiLinkLayerUsageHasDiff(stat1, stat1);
2791     }
2792 
2793     /**
2794      * Verify that when the new data appears to be bad link layer usage stats are not being
2795      * incremented and the buffered WifiLinkLayerStats get cleared.
2796      * @throws Exception
2797      */
2798     @Test
testWifiLinkLayerUsageStatsChipReset()2799     public void testWifiLinkLayerUsageStatsChipReset() throws Exception {
2800         WifiLinkLayerStats stat1 = nextRandomStats(new WifiLinkLayerStats());
2801         WifiLinkLayerStats stat2 = nextRandomStats(stat1);
2802         stat2.on_time = stat1.on_time - 1;
2803         WifiLinkLayerStats stat3 = nextRandomStats(stat2);
2804         WifiLinkLayerStats stat4 = nextRandomStats(stat3);
2805         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat1);
2806         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat2);
2807         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat3);
2808         mWifiMetrics.incrementWifiLinkLayerUsageStats(stat4);
2809         dumpProtoAndDeserialize();
2810 
2811         // Should only count the difference between |stat3| and |stat4|
2812         assertWifiLinkLayerUsageHasDiff(stat3, stat4);
2813     }
2814 
assertUsabilityStatsAssignment(WifiInfo info, WifiLinkLayerStats stats, WifiUsabilityStatsEntry usabilityStats)2815     private void assertUsabilityStatsAssignment(WifiInfo info, WifiLinkLayerStats stats,
2816             WifiUsabilityStatsEntry usabilityStats) {
2817         assertEquals(info.getRssi(), usabilityStats.rssi);
2818         assertEquals(info.getLinkSpeed(), usabilityStats.linkSpeedMbps);
2819         assertEquals(info.getRxLinkSpeedMbps(), usabilityStats.rxLinkSpeedMbps);
2820         assertEquals(stats.timeStampInMs, usabilityStats.timeStampMs);
2821         assertEquals(stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo,
2822                 usabilityStats.totalTxSuccess);
2823         assertEquals(stats.retries_be + stats.retries_bk + stats.retries_vi + stats.retries_vo,
2824                 usabilityStats.totalTxRetries);
2825         assertEquals(stats.lostmpdu_be + stats.lostmpdu_bk + stats.lostmpdu_vi + stats.lostmpdu_vo,
2826                 usabilityStats.totalTxBad);
2827         assertEquals(stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo,
2828                 usabilityStats.totalRxSuccess);
2829         assertEquals(stats.on_time, usabilityStats.totalRadioOnTimeMs);
2830         assertEquals(stats.tx_time, usabilityStats.totalRadioTxTimeMs);
2831         assertEquals(stats.rx_time, usabilityStats.totalRadioRxTimeMs);
2832         assertEquals(stats.on_time_scan, usabilityStats.totalScanTimeMs);
2833         assertEquals(stats.on_time_nan_scan, usabilityStats.totalNanScanTimeMs);
2834         assertEquals(stats.on_time_background_scan, usabilityStats.totalBackgroundScanTimeMs);
2835         assertEquals(stats.on_time_roam_scan, usabilityStats.totalRoamScanTimeMs);
2836         assertEquals(stats.on_time_pno_scan, usabilityStats.totalPnoScanTimeMs);
2837         assertEquals(stats.on_time_hs20_scan, usabilityStats.totalHotspot2ScanTimeMs);
2838         assertEquals(stats.beacon_rx, usabilityStats.totalBeaconRx);
2839     }
2840 
2841     // Simulate adding a LABEL_GOOD WifiUsabilityStats
addGoodWifiUsabilityStats(WifiLinkLayerStats start)2842     private WifiLinkLayerStats addGoodWifiUsabilityStats(WifiLinkLayerStats start) {
2843         WifiInfo info = mock(WifiInfo.class);
2844         when(info.getRssi()).thenReturn(nextRandInt());
2845         when(info.getLinkSpeed()).thenReturn(nextRandInt());
2846         WifiLinkLayerStats stats = start;
2847         for (int i = 0; i < WifiMetrics.NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD; i++) {
2848             mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats);
2849             stats = nextRandomStats(stats);
2850         }
2851         return stats;
2852     }
2853 
2854     // Simulate adding a LABEL_BAD WifiUsabilityStats
addBadWifiUsabilityStats(WifiLinkLayerStats start)2855     private WifiLinkLayerStats addBadWifiUsabilityStats(WifiLinkLayerStats start) {
2856         WifiInfo info = mock(WifiInfo.class);
2857         when(info.getRssi()).thenReturn(nextRandInt());
2858         when(info.getLinkSpeed()).thenReturn(nextRandInt());
2859         WifiLinkLayerStats stats1 = start;
2860         WifiLinkLayerStats stats2 = nextRandomStats(stats1);
2861         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
2862         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
2863         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
2864                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
2865         return nextRandomStats(stats2);
2866     }
2867 
2868     /**
2869      * Verify that updateWifiUsabilityStatsEntries correctly converts the inputs into
2870      * a WifiUsabilityStatsEntry Object and then stores it.
2871      *
2872      * Verify that the converted metrics proto contains pairs of WifiUsabilityStats with
2873      * LABEL_GOOD and LABEL_BAD
2874      * @throws Exception
2875      */
2876     @Test
testUpdateWifiUsabilityStatsEntries()2877     public void testUpdateWifiUsabilityStatsEntries() throws Exception {
2878         WifiInfo info = mock(WifiInfo.class);
2879         when(info.getRssi()).thenReturn(nextRandInt());
2880         when(info.getLinkSpeed()).thenReturn(nextRandInt());
2881         when(info.getRxLinkSpeedMbps()).thenReturn(nextRandInt());
2882         when(info.getBSSID()).thenReturn("Wifi");
2883         when(info.getFrequency()).thenReturn(5745);
2884 
2885         int signalStrengthDbm = -50;
2886         int signalStrengthDb = -10;
2887         boolean isSameRegisteredCell = true;
2888         CellularLinkLayerStats cellularStats =  new CellularLinkLayerStats();
2889         cellularStats.setIsSameRegisteredCell(isSameRegisteredCell);
2890         cellularStats.setDataNetworkType(TelephonyManager.NETWORK_TYPE_LTE);
2891         cellularStats.setSignalStrengthDbm(signalStrengthDbm);
2892         cellularStats.setSignalStrengthDb(signalStrengthDb);
2893         when(mCellularLinkLayerStatsCollector.update()).thenReturn(cellularStats);
2894 
2895         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
2896         WifiLinkLayerStats stats2 = nextRandomStats(stats1);
2897         mWifiMetrics.incrementWifiScoreCount(60);
2898         mWifiMetrics.incrementWifiUsabilityScoreCount(2, 55, 15);
2899         mWifiMetrics.logLinkProbeSuccess(nextRandInt(), nextRandInt(), nextRandInt(), 12);
2900         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
2901         mWifiMetrics.incrementWifiScoreCount(58);
2902         mWifiMetrics.incrementWifiUsabilityScoreCount(3, 56, 15);
2903         mWifiMetrics.logLinkProbeFailure(nextRandInt(), nextRandInt(),
2904                 nextRandInt(), nextRandInt());
2905         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT);
2906 
2907         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
2908         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
2909                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
2910 
2911         // Add 2 LABEL_GOOD but only 1 should remain in the converted proto
2912         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats2));
2913         statsGood.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
2914         addGoodWifiUsabilityStats(statsGood);
2915 
2916         dumpProtoAndDeserialize();
2917         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
2918         assertEquals(WifiUsabilityStats.LABEL_GOOD, mDecodedProto.wifiUsabilityStatsList[0].label);
2919         assertEquals(WifiUsabilityStats.LABEL_BAD, mDecodedProto.wifiUsabilityStatsList[1].label);
2920         assertUsabilityStatsAssignment(info, stats1,
2921                 mDecodedProto.wifiUsabilityStatsList[1].stats[0]);
2922         assertUsabilityStatsAssignment(info, stats2,
2923                 mDecodedProto.wifiUsabilityStatsList[1].stats[1]);
2924 
2925         assertEquals(2, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumToFramework);
2926         assertEquals(3, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumToFramework);
2927         assertEquals(0, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumInsideFramework);
2928         assertEquals(1, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumInsideFramework);
2929         assertEquals(60, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiScore);
2930         assertEquals(58, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiScore);
2931         assertEquals(55, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiUsabilityScore);
2932         assertEquals(56, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiUsabilityScore);
2933         assertEquals(15, mDecodedProto.wifiUsabilityStatsList[1].stats[0].predictionHorizonSec);
2934         assertEquals(true, mDecodedProto.wifiUsabilityStatsList[1].stats[0].isSameBssidAndFreq);
2935         assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS,
2936                 mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeStatusSinceLastUpdate);
2937         assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE,
2938                 mDecodedProto.wifiUsabilityStatsList[1].stats[1].probeStatusSinceLastUpdate);
2939         assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE,
2940                 mDecodedProto.wifiUsabilityStatsList[0].stats[0].probeStatusSinceLastUpdate);
2941         assertEquals(12,
2942                 mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeElapsedTimeSinceLastUpdateMs);
2943         assertEquals(Integer.MAX_VALUE, mDecodedProto.wifiUsabilityStatsList[1]
2944                 .stats[1].probeElapsedTimeSinceLastUpdateMs);
2945         assertEquals(-1, mDecodedProto.wifiUsabilityStatsList[0]
2946                 .stats[0].probeElapsedTimeSinceLastUpdateMs);
2947         assertEquals(WifiUsabilityStatsEntry.NETWORK_TYPE_LTE,
2948                 mDecodedProto.wifiUsabilityStatsList[0].stats[0].cellularDataNetworkType);
2949         assertEquals(signalStrengthDbm,
2950                 mDecodedProto.wifiUsabilityStatsList[0].stats[0].cellularSignalStrengthDbm);
2951         assertEquals(signalStrengthDb,
2952                 mDecodedProto.wifiUsabilityStatsList[0].stats[0].cellularSignalStrengthDb);
2953         assertEquals(isSameRegisteredCell,
2954                 mDecodedProto.wifiUsabilityStatsList[0].stats[0].isSameRegisteredCell);
2955         assertEquals(DEVICE_MOBILITY_STATE_HIGH_MVMT, mDecodedProto.wifiUsabilityStatsList[1]
2956                 .stats[mDecodedProto.wifiUsabilityStatsList[1].stats.length - 1]
2957                 .deviceMobilityState);
2958     }
2959 
2960     /**
2961      * Verify that when there are no WifiUsability events the generated proto also contains no
2962      * such information.
2963      * @throws Exception
2964      */
2965     @Test
testWifiUsabilityStatsZeroEvents()2966     public void testWifiUsabilityStatsZeroEvents() throws Exception {
2967         dumpProtoAndDeserialize();
2968         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
2969     }
2970 
2971     /**
2972      * Verify that we discard a WifiUsabilityStats with LABEL_GOOD if there is no corresponding
2973      * LABEL_BAD
2974      * @throws Exception
2975      */
2976     @Test
testWifiUsabilityStatsIgnoreSingleLabelGood()2977     public void testWifiUsabilityStatsIgnoreSingleLabelGood() throws Exception {
2978         addGoodWifiUsabilityStats(new WifiLinkLayerStats());
2979         dumpProtoAndDeserialize();
2980         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
2981     }
2982 
2983     /**
2984      * Verify that we discard a WifiUsabilityStats with LABEL_BAD if there is no corresponding
2985      * LABEL_GOOD
2986      * @throws Exception
2987      */
2988     @Test
testWifiUsabilityStatsIgnoreSingleLabelBad()2989     public void testWifiUsabilityStatsIgnoreSingleLabelBad() throws Exception {
2990         addBadWifiUsabilityStats(new WifiLinkLayerStats());
2991         dumpProtoAndDeserialize();
2992         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
2993     }
2994 
2995     /**
2996      * Verify that the buffer for WifiUsabilityStats does not exceed the max length.
2997      * Do this by trying to add more WifiUsabilityStats than the max length and then
2998      * verifying that the decoded proto's length does not exceed the max length.
2999      *
3000      * Also verify that the length for the list of WifiUsabilityStatsEntry is capped.
3001      * @throws Exception
3002      */
3003     @Test
testWifiUsabilityStatsBufferSizeIsCapped()3004     public void testWifiUsabilityStatsBufferSizeIsCapped() throws Exception {
3005         // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
3006         WifiLinkLayerStats stats = new WifiLinkLayerStats();
3007         for (int j = 0; j < WifiMetrics.MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE + 1; j++) {
3008             stats = addGoodWifiUsabilityStats(stats);
3009             stats = addBadWifiUsabilityStats(stats);
3010             stats.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
3011         }
3012         dumpProtoAndDeserialize();
3013         assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD,
3014                 mDecodedProto.wifiUsabilityStatsList.length);
3015         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD; i++) {
3016             assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE,
3017                     mDecodedProto.wifiUsabilityStatsList[2 * i].stats.length);
3018             assertEquals(2, mDecodedProto.wifiUsabilityStatsList[2 * i + 1].stats.length);
3019         }
3020     }
3021 
3022     /**
3023      * Verify that LABEL_GOOD stats are not generated more frequently than
3024      * |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS|
3025      * @throws Exception
3026      */
3027     @Test
testWifiUsabilityStatsLabelGoodHasMinimumPeriod()3028     public void testWifiUsabilityStatsLabelGoodHasMinimumPeriod() throws Exception {
3029         // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
3030         WifiLinkLayerStats stats = new WifiLinkLayerStats();
3031         for (int j = 0; j < 2; j++) {
3032             stats = addGoodWifiUsabilityStats(stats);
3033             stats = addBadWifiUsabilityStats(stats);
3034         }
3035         dumpProtoAndDeserialize();
3036         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
3037     }
3038 
3039     /**
3040      * Verify that LABEL_BAD stats are not generated more frequently than |MIN_DATA_STALL_WAIT_MS|
3041      * @throws Exception
3042      */
3043     @Test
testWifiUsabilityStatsLabelBadNotGeneratedGapLessThanMinimum()3044     public void testWifiUsabilityStatsLabelBadNotGeneratedGapLessThanMinimum() throws Exception {
3045         // simulate adding two LABEL_GOOD WifiUsabilityStats
3046         WifiInfo info = mock(WifiInfo.class);
3047         when(info.getRssi()).thenReturn(nextRandInt());
3048         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3049         WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
3050         WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
3051         stats1 = addGoodWifiUsabilityStats(stats1);
3052         stats2.timeStampInMs = stats1.timeStampInMs
3053                 + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
3054         addGoodWifiUsabilityStats(stats2);
3055 
3056         WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
3057         WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
3058         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
3059             mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
3060             stats3 = nextRandomStats(stats3);
3061         }
3062         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
3063         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3064                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
3065         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
3066             mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
3067             stats4 = nextRandomStats(stats4);
3068         }
3069         stats4.timeStampInMs = stats3.timeStampInMs - 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
3070         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
3071         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3072                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
3073         dumpProtoAndDeserialize();
3074         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
3075     }
3076 
3077     /**
3078      * Verify that LABEL_BAD stats are generated if timestamp gap is larger than
3079      * |MIN_DATA_STALL_WAIT_MS|
3080      * @throws Exception
3081      */
3082     @Test
testWifiUsabilityStatsLabelBadGeneratedGapLargerThanMinimum()3083     public void testWifiUsabilityStatsLabelBadGeneratedGapLargerThanMinimum() throws Exception {
3084         // simulate adding two LABEL_GOOD WifiUsabilityStats
3085         WifiInfo info = mock(WifiInfo.class);
3086         when(info.getRssi()).thenReturn(nextRandInt());
3087         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3088         WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
3089         WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
3090         stats1 = addGoodWifiUsabilityStats(stats1);
3091         stats2.timeStampInMs = stats1.timeStampInMs
3092                 + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
3093         addGoodWifiUsabilityStats(stats2);
3094 
3095         WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
3096         WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
3097         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
3098             mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
3099             stats3 = nextRandomStats(stats3);
3100         }
3101         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats3);
3102         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3103                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
3104         for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
3105             mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
3106             stats4 = nextRandomStats(stats4);
3107         }
3108         stats4.timeStampInMs = stats3.timeStampInMs + 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
3109         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats4);
3110         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3111                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
3112         dumpProtoAndDeserialize();
3113         assertEquals(4, mDecodedProto.wifiUsabilityStatsList.length);
3114     }
3115 
3116     /**
3117      * Tests device mobility state metrics as states are changed.
3118      */
3119     @Test
testDeviceMobilityStateMetrics_changeState()3120     public void testDeviceMobilityStateMetrics_changeState() throws Exception {
3121         // timeMs is initialized to 0 by the setUp() method
3122         long timeMs = 1000;
3123         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3124         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
3125 
3126         timeMs += 2000;
3127         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3128         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_LOW_MVMT);
3129 
3130         dumpProtoAndDeserialize();
3131 
3132         DeviceMobilityStatePnoScanStats[] expected = {
3133                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0),
3134                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY, 1, 2000, 0),
3135                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_LOW_MVMT, 1, 0, 0)
3136         };
3137 
3138         assertDeviceMobilityStatePnoScanStatsEqual(
3139                 expected, mDecodedProto.mobilityStatePnoStatsList);
3140     }
3141 
3142     /**
3143      * Tests device mobility state metrics as PNO scans are started and stopped.
3144      */
3145     @Test
testDeviceMobilityStateMetrics_startStopPnoScans()3146     public void testDeviceMobilityStateMetrics_startStopPnoScans() throws Exception {
3147         long timeMs = 1000;
3148         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3149         mWifiMetrics.logPnoScanStart();
3150 
3151         timeMs += 2000;
3152         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3153         mWifiMetrics.logPnoScanStop();
3154         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_STATIONARY);
3155         mWifiMetrics.logPnoScanStart();
3156 
3157         timeMs += 4000;
3158         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3159         mWifiMetrics.logPnoScanStop();
3160 
3161         timeMs += 8000;
3162         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3163         mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT);
3164 
3165         dumpProtoAndDeserialize();
3166 
3167         DeviceMobilityStatePnoScanStats[] expected = {
3168                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN,
3169                         1, 1000 + 2000, 2000),
3170                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_STATIONARY,
3171                         1, 4000 + 8000, 4000),
3172                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_HIGH_MVMT, 1, 0, 0)
3173         };
3174 
3175         assertDeviceMobilityStatePnoScanStatsEqual(
3176                 expected, mDecodedProto.mobilityStatePnoStatsList);
3177     }
3178 
3179     /**
3180      * Tests that the initial state is set up correctly.
3181      */
3182     @Test
testDeviceMobilityStateMetrics_initialState()3183     public void testDeviceMobilityStateMetrics_initialState() throws Exception {
3184         dumpProtoAndDeserialize();
3185 
3186         DeviceMobilityStatePnoScanStats[] expected = {
3187                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 0, 0)
3188         };
3189 
3190         assertDeviceMobilityStatePnoScanStatsEqual(
3191                 expected, mDecodedProto.mobilityStatePnoStatsList);
3192     }
3193 
3194     /**
3195      * Tests that logPnoScanStart() updates the total duration in addition to the PNO duration.
3196      */
3197     @Test
testDeviceMobilityStateMetrics_startPnoScansUpdatesTotalDuration()3198     public void testDeviceMobilityStateMetrics_startPnoScansUpdatesTotalDuration()
3199             throws Exception {
3200         long timeMs = 1000;
3201         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3202         mWifiMetrics.logPnoScanStart();
3203 
3204         dumpProtoAndDeserialize();
3205 
3206         DeviceMobilityStatePnoScanStats[] expected = {
3207                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN, 1, 1000, 0)
3208         };
3209 
3210         assertDeviceMobilityStatePnoScanStatsEqual(
3211                 expected, mDecodedProto.mobilityStatePnoStatsList);
3212     }
3213 
3214     /**
3215      * Tests that logPnoScanStop() updates the total duration in addition to the PNO duration.
3216      */
3217     @Test
testDeviceMobilityStateMetrics_stopPnoScansUpdatesTotalDuration()3218     public void testDeviceMobilityStateMetrics_stopPnoScansUpdatesTotalDuration()
3219             throws Exception {
3220         long timeMs = 1000;
3221         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3222         mWifiMetrics.logPnoScanStart();
3223 
3224         timeMs += 2000;
3225         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
3226         mWifiMetrics.logPnoScanStop();
3227 
3228         dumpProtoAndDeserialize();
3229 
3230         DeviceMobilityStatePnoScanStats[] expected = {
3231                 buildDeviceMobilityStatePnoScanStats(DEVICE_MOBILITY_STATE_UNKNOWN,
3232                         1, 1000 + 2000, 2000)
3233         };
3234 
3235         assertDeviceMobilityStatePnoScanStatsEqual(
3236                 expected, mDecodedProto.mobilityStatePnoStatsList);
3237     }
3238 
3239     /**
3240      * Verify that clients should be notified of activity in case Wifi stats get updated.
3241      */
3242     @Test
testClientNotification()3243     public void testClientNotification() throws RemoteException {
3244         // Register Client for verification.
3245         ArgumentCaptor<android.net.wifi.WifiUsabilityStatsEntry> usabilityStats =
3246                 ArgumentCaptor.forClass(android.net.wifi.WifiUsabilityStatsEntry.class);
3247         mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
3248                 TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
3249         WifiInfo info = mock(WifiInfo.class);
3250         when(info.getRssi()).thenReturn(nextRandInt());
3251         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3252 
3253         CellularLinkLayerStats cellularStats = new CellularLinkLayerStats();
3254         cellularStats.setIsSameRegisteredCell(false);
3255         cellularStats.setDataNetworkType(TelephonyManager.NETWORK_TYPE_UMTS);
3256         cellularStats.setSignalStrengthDbm(-100);
3257         cellularStats.setSignalStrengthDb(-20);
3258         when(mCellularLinkLayerStatsCollector.update()).thenReturn(cellularStats);
3259 
3260         WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
3261         mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats);
3262 
3263         // Client should get the stats.
3264         verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(),
3265                 usabilityStats.capture());
3266         assertEquals(usabilityStats.getValue().getTotalRadioOnTimeMillis(), linkLayerStats.on_time);
3267         assertEquals(usabilityStats.getValue().getTotalTxBad(), linkLayerStats.lostmpdu_be
3268                 + linkLayerStats.lostmpdu_bk + linkLayerStats.lostmpdu_vi
3269                 + linkLayerStats.lostmpdu_vo);
3270         assertEquals(usabilityStats.getValue().getTimeStampMillis(), linkLayerStats.timeStampInMs);
3271         assertEquals(usabilityStats.getValue().getTotalRoamScanTimeMillis(),
3272                 linkLayerStats.on_time_roam_scan);
3273         assertEquals(usabilityStats.getValue().getCellularDataNetworkType(),
3274                 TelephonyManager.NETWORK_TYPE_UMTS);
3275         assertEquals(usabilityStats.getValue().getCellularSignalStrengthDbm(), -100);
3276         assertEquals(usabilityStats.getValue().getCellularSignalStrengthDb(), -20);
3277     }
3278 
3279     /**
3280      * Verify that remove client should be handled
3281      */
3282     @Test
testRemoveClient()3283     public void testRemoveClient() throws RemoteException {
3284         // Register Client for verification.
3285         mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
3286                 TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
3287         mWifiMetrics.removeOnWifiUsabilityListener(TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
3288         verify(mAppBinder).unlinkToDeath(any(), anyInt());
3289 
3290         WifiInfo info = mock(WifiInfo.class);
3291         when(info.getRssi()).thenReturn(nextRandInt());
3292         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3293         WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
3294         mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats);
3295 
3296         verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
3297                 anyBoolean(), any());
3298     }
3299 
3300     /**
3301      * Verify that WifiMetrics adds for death notification on adding client.
3302      */
3303     @Test
testAddsForBinderDeathOnAddClient()3304     public void testAddsForBinderDeathOnAddClient() throws Exception {
3305         mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
3306                 TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
3307         verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
3308     }
3309 
3310     /**
3311      * Verify that client fails to get message when listener add failed.
3312      */
3313     @Test
testAddsListenerFailureOnLinkToDeath()3314     public void testAddsListenerFailureOnLinkToDeath() throws Exception {
3315         doThrow(new RemoteException())
3316                 .when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
3317         mWifiMetrics.addOnWifiUsabilityListener(mAppBinder, mOnWifiUsabilityStatsListener,
3318                 TEST_WIFI_USABILITY_STATS_LISTENER_IDENTIFIER);
3319         verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
3320 
3321         WifiInfo info = mock(WifiInfo.class);
3322         when(info.getRssi()).thenReturn(nextRandInt());
3323         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3324         WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
3325         mWifiMetrics.updateWifiUsabilityStatsEntries(info, linkLayerStats);
3326 
3327         // Client should not get any message listener add failed.
3328         verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
3329                 anyBoolean(), any());
3330     }
3331 
3332     /**
3333      * Verify that the label and the triggerType of Wifi usability stats are saved correctly
3334      * during firmware alert is triggered.
3335      * @throws Exception
3336      */
3337     @Test
verifyFirmwareAlertUpdatesWifiUsabilityMetrics()3338     public void verifyFirmwareAlertUpdatesWifiUsabilityMetrics() throws Exception {
3339         WifiInfo info = mock(WifiInfo.class);
3340         when(info.getRssi()).thenReturn(nextRandInt());
3341         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3342         long eventTimeMs = nextRandInt();
3343         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
3344         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
3345         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
3346 
3347         // Add 1 LABEL_GOOD
3348         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
3349         // Firmware alert occurs
3350         mWifiMetrics.logFirmwareAlert(2);
3351 
3352         dumpProtoAndDeserialize();
3353         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
3354 
3355         WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
3356         assertEquals(WifiUsabilityStats.LABEL_GOOD, statsList[0].label);
3357         assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
3358         assertEquals(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, statsList[1].triggerType);
3359         assertEquals(eventTimeMs, statsList[1].timeStampMs);
3360         assertEquals(2, statsList[1].firmwareAlertCode);
3361     }
3362 
3363     /**
3364      * Verify that the label and the triggerType of Wifi usability stats are saved correctly
3365      * during Wifi data stall is triggered.
3366      * @throws Exception
3367      */
3368     @Test
verifyWifiDataStallUpdatesWifiUsabilityMetrics()3369     public void verifyWifiDataStallUpdatesWifiUsabilityMetrics() throws Exception {
3370         WifiInfo info = mock(WifiInfo.class);
3371         when(info.getRssi()).thenReturn(nextRandInt());
3372         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3373         long eventTimeMs = nextRandInt();
3374         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
3375         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
3376         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
3377 
3378         // Add 1 LABEL_GOOD
3379         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
3380         // Wifi data stall occurs
3381         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3382                 WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
3383 
3384         dumpProtoAndDeserialize();
3385         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
3386         WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
3387         assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
3388         assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, statsList[1].triggerType);
3389         assertEquals(-1, statsList[1].firmwareAlertCode);
3390         assertEquals(eventTimeMs, statsList[1].timeStampMs);
3391     }
3392 
3393     /**
3394      * Test the generation of 'WifiConfigStoreIODuration' read histograms.
3395      */
3396     @Test
testWifiConfigStoreReadDurationsHistogramGeneration()3397     public void testWifiConfigStoreReadDurationsHistogramGeneration() throws Exception {
3398         mWifiMetrics.noteWifiConfigStoreReadDuration(10);
3399         mWifiMetrics.noteWifiConfigStoreReadDuration(20);
3400         mWifiMetrics.noteWifiConfigStoreReadDuration(100);
3401         mWifiMetrics.noteWifiConfigStoreReadDuration(90);
3402         mWifiMetrics.noteWifiConfigStoreReadDuration(130);
3403         mWifiMetrics.noteWifiConfigStoreReadDuration(250);
3404         mWifiMetrics.noteWifiConfigStoreReadDuration(600);
3405 
3406         dumpProtoAndDeserialize();
3407 
3408         assertEquals(5, mDecodedProto.wifiConfigStoreIo.readDurations.length);
3409         assertEquals(0, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
3410 
3411         assertEquals(Integer.MIN_VALUE,
3412                 mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeStartMs);
3413         assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[0].rangeEndMs);
3414         assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[0].count);
3415 
3416         assertEquals(50, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeStartMs);
3417         assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[1].rangeEndMs);
3418         assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[1].count);
3419 
3420         assertEquals(100, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeStartMs);
3421         assertEquals(150, mDecodedProto.wifiConfigStoreIo.readDurations[2].rangeEndMs);
3422         assertEquals(2, mDecodedProto.wifiConfigStoreIo.readDurations[2].count);
3423 
3424         assertEquals(200, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeStartMs);
3425         assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[3].rangeEndMs);
3426         assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[3].count);
3427 
3428         assertEquals(300, mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeStartMs);
3429         assertEquals(Integer.MAX_VALUE,
3430                 mDecodedProto.wifiConfigStoreIo.readDurations[4].rangeEndMs);
3431         assertEquals(1, mDecodedProto.wifiConfigStoreIo.readDurations[4].count);
3432     }
3433 
3434     /**
3435      * Test the generation of 'WifiConfigStoreIODuration' write histograms.
3436      */
3437     @Test
testWifiConfigStoreWriteDurationsHistogramGeneration()3438     public void testWifiConfigStoreWriteDurationsHistogramGeneration() throws Exception {
3439         mWifiMetrics.noteWifiConfigStoreWriteDuration(10);
3440         mWifiMetrics.noteWifiConfigStoreWriteDuration(40);
3441         mWifiMetrics.noteWifiConfigStoreWriteDuration(60);
3442         mWifiMetrics.noteWifiConfigStoreWriteDuration(90);
3443         mWifiMetrics.noteWifiConfigStoreWriteDuration(534);
3444         mWifiMetrics.noteWifiConfigStoreWriteDuration(345);
3445 
3446         dumpProtoAndDeserialize();
3447 
3448         assertEquals(0, mDecodedProto.wifiConfigStoreIo.readDurations.length);
3449         assertEquals(3, mDecodedProto.wifiConfigStoreIo.writeDurations.length);
3450 
3451         assertEquals(Integer.MIN_VALUE,
3452                 mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeStartMs);
3453         assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[0].rangeEndMs);
3454         assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[0].count);
3455 
3456         assertEquals(50, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeStartMs);
3457         assertEquals(100, mDecodedProto.wifiConfigStoreIo.writeDurations[1].rangeEndMs);
3458         assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[1].count);
3459 
3460         assertEquals(300, mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeStartMs);
3461         assertEquals(Integer.MAX_VALUE,
3462                 mDecodedProto.wifiConfigStoreIo.writeDurations[2].rangeEndMs);
3463         assertEquals(2, mDecodedProto.wifiConfigStoreIo.writeDurations[2].count);
3464     }
3465 
3466     /**
3467      * Test link probe metrics.
3468      */
3469     @Test
testLogLinkProbeMetrics()3470     public void testLogLinkProbeMetrics() throws Exception {
3471         mWifiMetrics.logLinkProbeSuccess(10000, -75, 50, 5);
3472         mWifiMetrics.logLinkProbeFailure(30000, -80, 10,
3473                 WifiNative.SEND_MGMT_FRAME_ERROR_NO_ACK);
3474         mWifiMetrics.logLinkProbeSuccess(3000, -71, 160, 12);
3475         mWifiMetrics.logLinkProbeFailure(40000, -80, 6,
3476                 WifiNative.SEND_MGMT_FRAME_ERROR_NO_ACK);
3477         mWifiMetrics.logLinkProbeSuccess(5000, -73, 160, 10);
3478         mWifiMetrics.logLinkProbeFailure(2000, -78, 6,
3479                 WifiNative.SEND_MGMT_FRAME_ERROR_TIMEOUT);
3480 
3481         dumpProtoAndDeserialize();
3482 
3483         StaEvent[] expected = {
3484                 buildLinkProbeSuccessStaEvent(5),
3485                 buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK),
3486                 buildLinkProbeSuccessStaEvent(12),
3487                 buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK),
3488                 buildLinkProbeSuccessStaEvent(10),
3489                 buildLinkProbeFailureStaEvent(LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT)
3490         };
3491         assertLinkProbeStaEventsEqual(expected, mDecodedProto.staEventList);
3492 
3493         LinkProbeStats linkProbeStats = mDecodedProto.linkProbeStats;
3494 
3495         Int32Count[] expectedSuccessRssiHistogram = {
3496                 buildInt32Count(-75, 1),
3497                 buildInt32Count(-73, 1),
3498                 buildInt32Count(-71, 1),
3499         };
3500         assertKeyCountsEqual(expectedSuccessRssiHistogram,
3501                 linkProbeStats.successRssiCounts);
3502 
3503         Int32Count[] expectedFailureRssiHistogram = {
3504                 buildInt32Count(-80, 2),
3505                 buildInt32Count(-78, 1),
3506         };
3507         assertKeyCountsEqual(expectedFailureRssiHistogram,
3508                 linkProbeStats.failureRssiCounts);
3509 
3510         Int32Count[] expectedSuccessLinkSpeedHistogram = {
3511                 buildInt32Count(50, 1),
3512                 buildInt32Count(160, 2)
3513         };
3514         assertKeyCountsEqual(expectedSuccessLinkSpeedHistogram,
3515                 linkProbeStats.successLinkSpeedCounts);
3516 
3517         Int32Count[] expectedFailureLinkSpeedHistogram = {
3518                 buildInt32Count(6, 2),
3519                 buildInt32Count(10, 1)
3520         };
3521         assertKeyCountsEqual(expectedFailureLinkSpeedHistogram,
3522                 linkProbeStats.failureLinkSpeedCounts);
3523 
3524         HistogramBucketInt32[] expectedSuccessTimeSinceLastTxSuccessSecondsHistogram = {
3525                 buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1),
3526                 buildHistogramBucketInt32(5, 15, 2)
3527         };
3528         assertHistogramBucketsEqual(expectedSuccessTimeSinceLastTxSuccessSecondsHistogram,
3529                 linkProbeStats.successSecondsSinceLastTxSuccessHistogram);
3530 
3531         HistogramBucketInt32[] expectedFailureTimeSinceLastTxSuccessSecondsHistogram = {
3532                 buildHistogramBucketInt32(Integer.MIN_VALUE, 5, 1),
3533                 buildHistogramBucketInt32(15, 45, 2)
3534         };
3535         assertHistogramBucketsEqual(expectedFailureTimeSinceLastTxSuccessSecondsHistogram,
3536                 linkProbeStats.failureSecondsSinceLastTxSuccessHistogram);
3537 
3538         HistogramBucketInt32[] expectedSuccessElapsedTimeMsHistogram = {
3539                 buildHistogramBucketInt32(5, 10, 1),
3540                 buildHistogramBucketInt32(10, 15, 2),
3541         };
3542         assertHistogramBucketsEqual(expectedSuccessElapsedTimeMsHistogram,
3543                 linkProbeStats.successElapsedTimeMsHistogram);
3544 
3545         LinkProbeFailureReasonCount[] expectedFailureReasonCount = {
3546                 buildLinkProbeFailureReasonCount(
3547                         LinkProbeStats.LINK_PROBE_FAILURE_REASON_NO_ACK, 2),
3548                 buildLinkProbeFailureReasonCount(
3549                         LinkProbeStats.LINK_PROBE_FAILURE_REASON_TIMEOUT, 1),
3550         };
3551         assertLinkProbeFailureReasonCountsEqual(expectedFailureReasonCount,
3552                 linkProbeStats.failureReasonCounts);
3553     }
3554 
3555     /**
3556      * Tests counting the number of link probes triggered per day for each experiment.
3557      */
3558     @Test
testIncrementLinkProbeExperimentProbeCount()3559     public void testIncrementLinkProbeExperimentProbeCount() throws Exception {
3560         String experimentId1 = "screenOnDelay=6000,noTxDelay=3000,delayBetweenProbes=9000,"
3561                 + "rssiThreshold=-70,linkSpeedThreshold=15,";
3562         mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId1);
3563 
3564         String experimentId2 = "screenOnDelay=9000,noTxDelay=12000,delayBetweenProbes=15000,"
3565                 + "rssiThreshold=-72,linkSpeedThreshold=20,";
3566         mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2);
3567         mWifiMetrics.incrementLinkProbeExperimentProbeCount(experimentId2);
3568 
3569         dumpProtoAndDeserialize();
3570 
3571         ExperimentProbeCounts[] actual = mDecodedProto.linkProbeStats.experimentProbeCounts;
3572 
3573         ExperimentProbeCounts[] expected = {
3574                 buildExperimentProbeCounts(experimentId1, 1),
3575                 buildExperimentProbeCounts(experimentId2, 2)
3576         };
3577 
3578         assertExperimentProbeCountsEqual(expected, actual);
3579     }
3580 
3581     /**
3582      * Tests logNetworkSelectionDecision()
3583      */
3584     @Test
testLogNetworkSelectionDecision()3585     public void testLogNetworkSelectionDecision() throws Exception {
3586         mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6);
3587         mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 1);
3588         mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 6);
3589         mWifiMetrics.logNetworkSelectionDecision(1, 2, true, 2);
3590         mWifiMetrics.logNetworkSelectionDecision(3, 2, false, 15);
3591         mWifiMetrics.logNetworkSelectionDecision(1, 2, false, 6);
3592         mWifiMetrics.logNetworkSelectionDecision(1, 4, true, 2);
3593 
3594         dumpProtoAndDeserialize();
3595 
3596         assertEquals(3, mDecodedProto.networkSelectionExperimentDecisionsList.length);
3597 
3598         NetworkSelectionExperimentDecisions exp12 =
3599                 findUniqueNetworkSelectionExperimentDecisions(1, 2);
3600         Int32Count[] exp12SameExpected = {
3601                 buildInt32Count(2, 1),
3602                 buildInt32Count(6, 2)
3603         };
3604         assertKeyCountsEqual(exp12SameExpected, exp12.sameSelectionNumChoicesCounter);
3605         Int32Count[] exp12DiffExpected = {
3606                 buildInt32Count(1, 1),
3607                 buildInt32Count(6, 1)
3608         };
3609         assertKeyCountsEqual(exp12DiffExpected, exp12.differentSelectionNumChoicesCounter);
3610 
3611         NetworkSelectionExperimentDecisions exp32 =
3612                 findUniqueNetworkSelectionExperimentDecisions(3, 2);
3613         Int32Count[] exp32SameExpected = {};
3614         assertKeyCountsEqual(exp32SameExpected, exp32.sameSelectionNumChoicesCounter);
3615         Int32Count[] exp32DiffExpected = {
3616                 buildInt32Count(
3617                         WifiMetrics.NetworkSelectionExperimentResults.MAX_CHOICES, 1)
3618         };
3619         assertKeyCountsEqual(exp32DiffExpected, exp32.differentSelectionNumChoicesCounter);
3620 
3621         NetworkSelectionExperimentDecisions exp14 =
3622                 findUniqueNetworkSelectionExperimentDecisions(1, 4);
3623         Int32Count[] exp14SameExpected = {
3624                 buildInt32Count(2, 1)
3625         };
3626         assertKeyCountsEqual(exp14SameExpected, exp14.sameSelectionNumChoicesCounter);
3627         Int32Count[] exp14DiffExpected = {};
3628         assertKeyCountsEqual(exp14DiffExpected, exp14.differentSelectionNumChoicesCounter);
3629     }
3630 
3631     /**
3632      * Test the generation of 'WifiNetworkRequestApiLog' message.
3633      */
3634     @Test
testWifiNetworkRequestApiLog()3635     public void testWifiNetworkRequestApiLog() throws Exception {
3636         mWifiMetrics.incrementNetworkRequestApiNumRequest();
3637         mWifiMetrics.incrementNetworkRequestApiNumRequest();
3638         mWifiMetrics.incrementNetworkRequestApiNumRequest();
3639 
3640         mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(7);
3641         mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(0);
3642         mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(1);
3643 
3644         mWifiMetrics.incrementNetworkRequestApiNumConnectSuccess();
3645 
3646         mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass();
3647         mWifiMetrics.incrementNetworkRequestApiNumUserApprovalBypass();
3648 
3649         mWifiMetrics.incrementNetworkRequestApiNumUserReject();
3650 
3651         mWifiMetrics.incrementNetworkRequestApiNumApps();
3652 
3653         dumpProtoAndDeserialize();
3654 
3655         assertEquals(3, mDecodedProto.wifiNetworkRequestApiLog.numRequest);
3656         assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numConnectSuccess);
3657         assertEquals(2, mDecodedProto.wifiNetworkRequestApiLog.numUserApprovalBypass);
3658         assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numUserReject);
3659         assertEquals(1, mDecodedProto.wifiNetworkRequestApiLog.numApps);
3660 
3661         HistogramBucketInt32[] expectedNetworkMatchSizeHistogram = {
3662                 buildHistogramBucketInt32(0, 1, 1),
3663                 buildHistogramBucketInt32(1, 5, 1),
3664                 buildHistogramBucketInt32(5, 10, 1)
3665         };
3666         assertHistogramBucketsEqual(expectedNetworkMatchSizeHistogram,
3667                 mDecodedProto.wifiNetworkRequestApiLog.networkMatchSizeHistogram);
3668     }
3669 
3670     /**
3671      * Test the generation of 'WifiNetworkSuggestionApiLog' message.
3672      */
3673     @Test
testWifiNetworkSuggestionApiLog()3674     public void testWifiNetworkSuggestionApiLog() throws Exception {
3675         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
3676         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
3677         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
3678         mWifiMetrics.incrementNetworkSuggestionApiNumModification();
3679 
3680         mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess();
3681         mWifiMetrics.incrementNetworkSuggestionApiNumConnectSuccess();
3682 
3683         mWifiMetrics.incrementNetworkSuggestionApiNumConnectFailure();
3684 
3685         mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{
3686                 add(5);
3687                 add(100);
3688                 add(50);
3689                 add(120);
3690             }});
3691         // Second update should overwrite the prevous write.
3692         mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{
3693                 add(7);
3694                 add(110);
3695                 add(40);
3696                 add(60);
3697             }});
3698 
3699         dumpProtoAndDeserialize();
3700 
3701         assertEquals(4, mDecodedProto.wifiNetworkSuggestionApiLog.numModification);
3702         assertEquals(2, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectSuccess);
3703         assertEquals(1, mDecodedProto.wifiNetworkSuggestionApiLog.numConnectFailure);
3704 
3705         HistogramBucketInt32[] expectedNetworkListSizeHistogram = {
3706                 buildHistogramBucketInt32(5, 20, 1),
3707                 buildHistogramBucketInt32(20, 50, 1),
3708                 buildHistogramBucketInt32(50, 100, 1),
3709                 buildHistogramBucketInt32(100, 500, 1),
3710         };
3711         assertHistogramBucketsEqual(expectedNetworkListSizeHistogram,
3712                 mDecodedProto.wifiNetworkSuggestionApiLog.networkListSizeHistogram);
3713     }
3714 
findUniqueNetworkSelectionExperimentDecisions( int experiment1Id, int experiment2Id)3715     private NetworkSelectionExperimentDecisions findUniqueNetworkSelectionExperimentDecisions(
3716             int experiment1Id, int experiment2Id) {
3717         NetworkSelectionExperimentDecisions result = null;
3718         for (NetworkSelectionExperimentDecisions d
3719                 : mDecodedProto.networkSelectionExperimentDecisionsList) {
3720             if (d.experiment1Id == experiment1Id && d.experiment2Id == experiment2Id) {
3721                 assertNull("duplicate found!", result);
3722                 result = d;
3723             }
3724         }
3725         assertNotNull("not found!", result);
3726         return result;
3727     }
3728 
3729     /**
3730      * Verify that the label and the triggerType of Wifi usability stats are saved correctly
3731      * during IP reachability lost message is received.
3732      * @throws Exception
3733      */
3734     @Test
verifyIpReachabilityLostUpdatesWifiUsabilityMetrics()3735     public void verifyIpReachabilityLostUpdatesWifiUsabilityMetrics() throws Exception {
3736         WifiInfo info = mock(WifiInfo.class);
3737         when(info.getRssi()).thenReturn(nextRandInt());
3738         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3739         long eventTimeMs = nextRandInt();
3740         when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
3741         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
3742         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
3743 
3744         // Add 1 LABEL_GOOD
3745         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
3746         // IP reachability lost occurs
3747         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3748                 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
3749 
3750         dumpProtoAndDeserialize();
3751         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
3752         WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
3753         assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
3754         assertEquals(WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, statsList[1].triggerType);
3755         assertEquals(eventTimeMs, statsList[1].timeStampMs);
3756     }
3757 
3758     /**
3759      * Test the WifiLock active session statistics
3760      */
3761     @Test
testWifiLockActiveSession()3762     public void testWifiLockActiveSession() throws Exception {
3763         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000);
3764         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000);
3765         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000);
3766         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000);
3767 
3768         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000);
3769         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000);
3770         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000);
3771         mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000);
3772 
3773         dumpProtoAndDeserialize();
3774 
3775         assertEquals(10111000, mDecodedProto.wifiLockStats.highPerfActiveTimeMs);
3776         assertEquals(20999000, mDecodedProto.wifiLockStats.lowLatencyActiveTimeMs);
3777 
3778         HistogramBucketInt32[] expectedHighPerfHistogram = {
3779                 buildHistogramBucketInt32(1, 10, 1),
3780                 buildHistogramBucketInt32(10, 60, 1),
3781                 buildHistogramBucketInt32(60, 600, 1),
3782                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
3783         };
3784 
3785         HistogramBucketInt32[] expectedLowLatencyHistogram = {
3786                 buildHistogramBucketInt32(1, 10, 1),
3787                 buildHistogramBucketInt32(60, 600, 1),
3788                 buildHistogramBucketInt32(600, 3600, 1),
3789                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
3790         };
3791 
3792         assertHistogramBucketsEqual(expectedHighPerfHistogram,
3793                 mDecodedProto.wifiLockStats.highPerfActiveSessionDurationSecHistogram);
3794 
3795         assertHistogramBucketsEqual(expectedLowLatencyHistogram,
3796                 mDecodedProto.wifiLockStats.lowLatencyActiveSessionDurationSecHistogram);
3797     }
3798 
3799     /**
3800      * Test the WifiLock acquisition session statistics
3801      */
3802     @Test
testWifiLockAcqSession()3803     public void testWifiLockAcqSession() throws Exception {
3804         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 100000);
3805         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000);
3806         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 10000000);
3807         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 1000);
3808 
3809         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 90000);
3810         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 900000);
3811         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 9000);
3812         mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 20000000);
3813 
3814         dumpProtoAndDeserialize();
3815 
3816         HistogramBucketInt32[] expectedHighPerfHistogram = {
3817                 buildHistogramBucketInt32(1, 10, 1),
3818                 buildHistogramBucketInt32(10, 60, 1),
3819                 buildHistogramBucketInt32(60, 600, 1),
3820                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
3821         };
3822 
3823         HistogramBucketInt32[] expectedLowLatencyHistogram = {
3824                 buildHistogramBucketInt32(1, 10, 1),
3825                 buildHistogramBucketInt32(60, 600, 1),
3826                 buildHistogramBucketInt32(600, 3600, 1),
3827                 buildHistogramBucketInt32(3600, Integer.MAX_VALUE, 1),
3828         };
3829 
3830         assertHistogramBucketsEqual(expectedHighPerfHistogram,
3831                 mDecodedProto.wifiLockStats.highPerfLockAcqDurationSecHistogram);
3832 
3833         assertHistogramBucketsEqual(expectedLowLatencyHistogram,
3834                 mDecodedProto.wifiLockStats.lowLatencyLockAcqDurationSecHistogram);
3835     }
3836 
3837     /**
3838      * Verify that LABEL_GOOD stats are generated if Wifi score breaches low and there
3839      * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
3840      * @throws Exception
3841      */
3842     @Test
testGoodStatsAreGeneratedByWifiScoreBreachLow()3843     public void testGoodStatsAreGeneratedByWifiScoreBreachLow() throws Exception {
3844         // The elapsed time falls into the interval for adding good stats
3845         createTestForDataCollectionByScoreBreach(
3846                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
3847                 false, true);
3848         dumpProtoAndDeserialize();
3849         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
3850     }
3851 
3852     /**
3853      * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking
3854      * time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
3855      * @throws Exception
3856      */
3857     @Test
testGoodStatsAreNotGeneratedByWifiScoreBreachLow()3858     public void testGoodStatsAreNotGeneratedByWifiScoreBreachLow() throws Exception {
3859         // The elapsed time is shorter than necessary to add good stats
3860         createTestForDataCollectionByScoreBreach(
3861                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1,
3862                 false, true);
3863         dumpProtoAndDeserialize();
3864         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
3865     }
3866 
3867     /**
3868      * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking
3869      * time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS
3870      * @throws Exception
3871      */
3872     @Test
testGoodStatsAreNotGeneratedIfWifiScoreBreachExpires()3873     public void testGoodStatsAreNotGeneratedIfWifiScoreBreachExpires() throws Exception {
3874         // The Wifi score breaching expires for adding good stats
3875         createTestForDataCollectionByScoreBreach(
3876                 WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1,
3877                 false, true);
3878         dumpProtoAndDeserialize();
3879         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
3880     }
3881 
3882     /**
3883      * Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and there is
3884      * WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
3885      * @throws Exception
3886      */
3887     @Test
testGoodStatsAreNotGeneratedIfBadEventOccured()3888     public void testGoodStatsAreNotGeneratedIfBadEventOccured() throws Exception {
3889         // The elapsed time falls into the interval for adding good stats and bad event occurs
3890         createTestForDataCollectionByScoreBreach(
3891                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
3892                 true, true);
3893         dumpProtoAndDeserialize();
3894         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
3895     }
3896 
3897     /**
3898      * Verify that LABEL_GOOD stats are generated if Wifi usability score breaches low and there
3899      * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
3900      * @throws Exception
3901      */
3902     @Test
testGoodStatsAreGeneratedByWifiUsabilityScoreBreachLow()3903     public void testGoodStatsAreGeneratedByWifiUsabilityScoreBreachLow() throws Exception {
3904         // The elapsed time falls into the interval for adding good stats
3905         createTestForDataCollectionByScoreBreach(
3906                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
3907                 false, false);
3908         dumpProtoAndDeserialize();
3909         assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
3910     }
3911 
3912     /**
3913      * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and
3914      * the checking time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
3915      * @throws Exception
3916      */
3917     @Test
testGoodStatsAreNotGeneratedByWifiUsabilityScoreBreachLow()3918     public void testGoodStatsAreNotGeneratedByWifiUsabilityScoreBreachLow() throws Exception {
3919         // The elapsed time is shorter than necessary to add good stats
3920         createTestForDataCollectionByScoreBreach(
3921                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS - 1,
3922                 false, false);
3923         dumpProtoAndDeserialize();
3924         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
3925     }
3926 
3927     /**
3928      * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and
3929      * the checking time is greater than VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS
3930      * @throws Exception
3931      */
3932     @Test
testGoodStatsAreNotGeneratedIfWifiUsabilityScoreBreachExpires()3933     public void testGoodStatsAreNotGeneratedIfWifiUsabilityScoreBreachExpires() throws Exception {
3934         // The Wifi usability score breaching expires for adding good stats
3935         createTestForDataCollectionByScoreBreach(
3936                 WifiMetrics.VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS + 1,
3937                 false, false);
3938         dumpProtoAndDeserialize();
3939         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
3940     }
3941 
3942     /**
3943      * Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and there
3944      * is WifiIsUnusableEvent occured within MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
3945      * @throws Exception
3946      */
3947     @Test
testGoodStatsAreNotGeneratedIfBadEventOccuredForUsabilityScore()3948     public void testGoodStatsAreNotGeneratedIfBadEventOccuredForUsabilityScore() throws Exception {
3949         // The elapsed time falls into the interval for adding good stats and bad event occurs
3950         createTestForDataCollectionByScoreBreach(
3951                 WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
3952                 true, false);
3953         dumpProtoAndDeserialize();
3954         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
3955     }
3956 
3957     /**
3958      * Verify that incrementNumWifiToggles increments the corrects fields based on input.
3959      */
3960     @Test
testIncrementNumWifiToggles()3961     public void testIncrementNumWifiToggles() throws Exception {
3962         mWifiMetrics.incrementNumWifiToggles(true, true);
3963         for (int i = 0; i < 2; i++) {
3964             mWifiMetrics.incrementNumWifiToggles(true, false);
3965         }
3966         for (int i = 0; i < 3; i++) {
3967             mWifiMetrics.incrementNumWifiToggles(false, true);
3968         }
3969         for (int i = 0; i < 4; i++) {
3970             mWifiMetrics.incrementNumWifiToggles(false, false);
3971         }
3972         dumpProtoAndDeserialize();
3973         assertEquals(1, mDecodedProto.wifiToggleStats.numToggleOnPrivileged);
3974         assertEquals(2, mDecodedProto.wifiToggleStats.numToggleOffPrivileged);
3975         assertEquals(3, mDecodedProto.wifiToggleStats.numToggleOnNormal);
3976         assertEquals(4, mDecodedProto.wifiToggleStats.numToggleOffNormal);
3977     }
3978 
3979 
3980     /**
3981      * Create a test to verify data collection logic triggered by score breaching low
3982      * @param elapsedTimeAfterBreach The elapsed time after score breaches low
3983      * @param isThereBadEvent Whether there is a bad event happened after score breaches low
3984      * @param isWifiScore Whether it is Wifi score or not that breaches the threshold
3985      */
createTestForDataCollectionByScoreBreach( long elapsedTimeAfterBreach, boolean isThereBadEvent, boolean isWifiScore)3986     private void createTestForDataCollectionByScoreBreach(
3987             long elapsedTimeAfterBreach, boolean isThereBadEvent, boolean isWifiScore) {
3988         WifiInfo info = mock(WifiInfo.class);
3989         when(info.getRssi()).thenReturn(nextRandInt());
3990         when(info.getLinkSpeed()).thenReturn(nextRandInt());
3991         WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
3992         mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
3993 
3994         addOneBadWifiUsabilityStats(info);
3995         if (isWifiScore) {
3996             stats2 = wifiScoreBreachesLow(info, stats2);
3997         } else {
3998             stats2 = wifiUsabilityScoreBreachesLow(info, stats2);
3999         }
4000         if (isThereBadEvent) {
4001             mWifiMetrics.logWifiIsUnusableEvent(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
4002         }
4003         when(mClock.getElapsedSinceBootMillis()).thenReturn(elapsedTimeAfterBreach);
4004         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
4005     }
4006 
4007     // Simulate adding one LABEL_BAD WifiUsabilityStats
addOneBadWifiUsabilityStats(WifiInfo info)4008     private void addOneBadWifiUsabilityStats(WifiInfo info) {
4009         WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
4010         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
4011         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
4012                 WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
4013     }
4014 
4015     // Simulate that Wifi score breaches low
wifiScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2)4016     private WifiLinkLayerStats wifiScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2) {
4017         int upper = WifiMetrics.LOW_WIFI_SCORE + 7;
4018         int lower = WifiMetrics.LOW_WIFI_SCORE - 8;
4019         mWifiMetrics.incrementWifiScoreCount(upper);
4020         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
4021         stats2 = nextRandomStats(stats2);
4022         long timeMs = 0;
4023         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4024         // Wifi score breaches low
4025         mWifiMetrics.incrementWifiScoreCount(lower);
4026         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
4027         stats2 = nextRandomStats(stats2);
4028         return stats2;
4029     }
4030 
4031     // Simulate that Wifi usability score breaches low
wifiUsabilityScoreBreachesLow(WifiInfo info, WifiLinkLayerStats stats2)4032     private WifiLinkLayerStats wifiUsabilityScoreBreachesLow(WifiInfo info,
4033             WifiLinkLayerStats stats2) {
4034         int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7;
4035         int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8;
4036         mWifiMetrics.incrementWifiUsabilityScoreCount(1, upper, 30);
4037         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
4038         stats2 = nextRandomStats(stats2);
4039         long timeMs = 0;
4040         when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
4041         // Wifi usability score breaches low
4042         mWifiMetrics.incrementWifiUsabilityScoreCount(2, lower, 30);
4043         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats2);
4044         stats2 = nextRandomStats(stats2);
4045         return stats2;
4046     }
4047 
4048     /**
4049      * Verify the counts of passpoint profile type are correct.
4050      * @param profileTypes type and count of installed passpoint profiles
4051      */
assertPasspointProfileTypeCount(PasspointProfileTypeCount[] profileTypes)4052     private void assertPasspointProfileTypeCount(PasspointProfileTypeCount[] profileTypes) {
4053         for (PasspointProfileTypeCount passpointProfileType : profileTypes) {
4054             switch(passpointProfileType.eapMethodType) {
4055                 case PasspointProfileTypeCount.TYPE_EAP_AKA:
4056                     assertEquals(NUM_EAP_AKA_TYPE, passpointProfileType.count);
4057                     break;
4058                 case PasspointProfileTypeCount.TYPE_EAP_AKA_PRIME:
4059                     assertEquals(NUM_EAP_AKA_PRIME_TYPE, passpointProfileType.count);
4060                     break;
4061                 case PasspointProfileTypeCount.TYPE_EAP_SIM:
4062                     assertEquals(NUM_EAP_SIM_TYPE, passpointProfileType.count);
4063                     break;
4064                 case PasspointProfileTypeCount.TYPE_EAP_TLS:
4065                     assertEquals(NUM_EAP_TLS_TYPE, passpointProfileType.count);
4066                     break;
4067                 case PasspointProfileTypeCount.TYPE_EAP_TTLS:
4068                     assertEquals(NUM_EAP_TTLS_TYPE, passpointProfileType.count);
4069                     break;
4070                 default:
4071                     fail("unknown type counted");
4072             }
4073         }
4074     }
4075 
4076     /**
4077      * Verify that the LABEL_BAD Wifi usability stats are not saved if screen state is off.
4078      * @throws Exception
4079      */
4080     @Test
verifyLabelBadStatsAreNotSavedIfScreenIsOff()4081     public void verifyLabelBadStatsAreNotSavedIfScreenIsOff() throws Exception {
4082         mWifiMetrics.setScreenState(false);
4083         WifiInfo info = mock(WifiInfo.class);
4084         when(info.getRssi()).thenReturn(nextRandInt());
4085         when(info.getLinkSpeed()).thenReturn(nextRandInt());
4086         WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
4087         mWifiMetrics.updateWifiUsabilityStatsEntries(info, stats1);
4088 
4089         // Add 1 LABEL_GOOD
4090         WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
4091         // IP reachability lost occurs
4092         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
4093                 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
4094         // Wifi data stall occurs
4095         mWifiMetrics.addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
4096                 WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
4097         // Firmware alert occurs
4098         mWifiMetrics.logFirmwareAlert(2);
4099 
4100         dumpProtoAndDeserialize();
4101         assertEquals(0, mDecodedProto.wifiUsabilityStatsList.length);
4102     }
4103 }
4104