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