WifiMetricsTest.java revision 60cf847709fd2c853882a804c7d2e8206cc90371
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 */
16package com.android.server.wifi;
17
18import static org.junit.Assert.assertEquals;
19import static org.junit.Assert.assertTrue;
20import static org.mockito.Mockito.*;
21
22import android.net.NetworkAgent;
23import android.net.wifi.ScanResult;
24import android.net.wifi.WifiConfiguration;
25import android.test.suitebuilder.annotation.SmallTest;
26import android.util.Base64;
27
28import com.android.server.wifi.hotspot2.NetworkDetail;
29
30import org.junit.Before;
31import org.junit.Test;
32import org.mockito.Mock;
33import org.mockito.MockitoAnnotations;
34
35import java.io.ByteArrayOutputStream;
36import java.io.PrintWriter;
37import java.util.ArrayList;
38import java.util.List;
39import java.util.regex.Matcher;
40import java.util.regex.Pattern;
41
42/**
43 * Unit tests for {@link com.android.server.wifi.WifiMetrics}.
44 */
45@SmallTest
46public class WifiMetricsTest {
47
48    WifiMetrics mWifiMetrics;
49    WifiMetricsProto.WifiLog mDeserializedWifiMetrics;
50    @Mock Clock mClock;
51
52    @Before
53    public void setUp() throws Exception {
54        MockitoAnnotations.initMocks(this);
55        mDeserializedWifiMetrics = null;
56        when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
57        mWifiMetrics = new WifiMetrics(mClock);
58    }
59
60    /**
61     * Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of
62     * order. Only tests no exception occurs. Creates 3 ConnectionEvents.
63     */
64    @Test
65    public void startAndEndConnectionEventSucceeds() throws Exception {
66        //Start and end Connection event
67        mWifiMetrics.startConnectionEvent(null, "RED",
68                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
69        mWifiMetrics.endConnectionEvent(
70                WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
71                WifiMetricsProto.ConnectionEvent.HLF_DHCP);
72        //end Connection event without starting one
73        mWifiMetrics.endConnectionEvent(
74                WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
75                WifiMetricsProto.ConnectionEvent.HLF_DHCP);
76        //start two ConnectionEvents in a row
77        mWifiMetrics.startConnectionEvent(null, "BLUE",
78                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
79        mWifiMetrics.startConnectionEvent(null, "GREEN",
80                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
81    }
82
83    private static final long TEST_RECORD_DURATION_SEC = 12 * 60 * 60;
84    private static final long TEST_RECORD_DURATION_MILLIS = TEST_RECORD_DURATION_SEC * 1000;
85
86    /**
87     * Simulate how dumpsys gets the proto from mWifiMetrics, filter the proto bytes out and
88     * deserialize them into mDeserializedWifiMetrics
89     */
90    public void dumpProtoAndDeserialize() throws Exception {
91        ByteArrayOutputStream stream = new ByteArrayOutputStream();
92        PrintWriter writer = new PrintWriter(stream);
93        String[] args = new String[0];
94
95        when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
96        //Test proto dump, by passing in proto arg option
97        args = new String[]{WifiMetrics.PROTO_DUMP_ARG};
98        mWifiMetrics.dump(null, writer, args);
99        writer.flush();
100        Pattern pattern = Pattern.compile(
101                "(?<=WifiMetrics:\\n)([\\s\\S]*)(?=EndWifiMetrics)");
102        Matcher matcher = pattern.matcher(stream.toString());
103        assertTrue("Proto Byte string found in WifiMetrics.dump():\n" + stream.toString(),
104                matcher.find());
105        String protoByteString = matcher.group(1);
106        byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
107        mDeserializedWifiMetrics = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
108    }
109
110    /**
111     * Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into
112     * mDeserializedWifiMetrics
113     */
114    public void cleanDumpProtoAndDeserialize() throws Exception {
115        ByteArrayOutputStream stream = new ByteArrayOutputStream();
116        PrintWriter writer = new PrintWriter(stream);
117        String[] args = new String[0];
118
119        when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS);
120        //Test proto dump, by passing in proto arg option
121        args = new String[]{WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG};
122        mWifiMetrics.dump(null, writer, args);
123        writer.flush();
124        String protoByteString = stream.toString();
125        byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
126        mDeserializedWifiMetrics = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
127    }
128
129    /** Verifies that dump() includes the expected header */
130    @Test
131    public void stateDumpIncludesHeader() throws Exception {
132        assertStringContains(getStateDump(), "WifiMetrics");
133    }
134
135    /** Verifies that dump() includes correct alert count when there are no alerts. */
136    @Test
137    public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception {
138        assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()");
139    }
140
141    /** Verifies that dump() includes correct alert count when there is one alert. */
142    @Test
143    public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception {
144        mWifiMetrics.incrementAlertReasonCount(1);
145        assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)");
146    }
147
148    /** Verifies that dump() includes correct alert count when there are multiple alerts. */
149    @Test
150    public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception {
151        mWifiMetrics.incrementAlertReasonCount(1);
152        mWifiMetrics.incrementAlertReasonCount(1);
153        mWifiMetrics.incrementAlertReasonCount(16);
154        assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)");
155    }
156
157    @Test
158    public void testDumpProtoAndDeserialize() throws Exception {
159        setAndIncrementMetrics();
160        dumpProtoAndDeserialize();
161        assertDeserializedMetricsCorrect();
162    }
163
164    private static final int NUM_SAVED_NETWORKS = 1;
165    private static final int NUM_OPEN_NETWORKS = 2;
166    private static final int NUM_PERSONAL_NETWORKS = 3;
167    private static final int NUM_ENTERPRISE_NETWORKS = 5;
168    private static final int NUM_HIDDEN_NETWORKS = 3;
169    private static final int NUM_PASSPOINT_NETWORKS = 4;
170    private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true;
171    private static final boolean IS_SCANNING_ALWAYS_ENABLED = true;
172    private static final int NUM_NEWTORKS_ADDED_BY_USER = 13;
173    private static final int NUM_NEWTORKS_ADDED_BY_APPS = 17;
174    private static final int NUM_EMPTY_SCAN_RESULTS = 19;
175    private static final int NUM_NON_EMPTY_SCAN_RESULTS = 23;
176    private static final int NUM_SCAN_UNKNOWN = 1;
177    private static final int NUM_SCAN_SUCCESS = 2;
178    private static final int NUM_SCAN_FAILURE_INTERRUPTED = 3;
179    private static final int NUM_SCAN_FAILURE_INVALID_CONFIGURATION = 5;
180    private static final int NUM_WIFI_UNKNOWN_SCREEN_OFF = 3;
181    private static final int NUM_WIFI_UNKNOWN_SCREEN_ON = 5;
182    private static final int NUM_WIFI_ASSOCIATED_SCREEN_OFF = 7;
183    private static final int NUM_WIFI_ASSOCIATED_SCREEN_ON = 11;
184    private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD = 11;
185    private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_BAD = 12;
186    private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD = 13;
187    private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD = 14;
188    private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS = 1;
189    private static final int NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL = 2;
190    private static final int NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL = 3;
191    private static final int NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL = 4;
192    private static final int NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL = 5;
193    private static final int NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL = 6;
194    private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION = 7;
195    private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8;
196    private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9;
197    private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10;
198    private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5;
199    private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20;
200    private static final int FIRST_RSSI_LEVEL = -80;
201    private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1;
202    private static final int NUM_PERSONAL_NETWORK_SCAN_RESULTS = 4;
203    private static final int NUM_ENTERPRISE_NETWORK_SCAN_RESULTS = 3;
204    private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1;
205    private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1;
206    private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2;
207    private static final int NUM_SCANS = 5;
208    private static final int NUM_TOTAL_SCAN_RESULTS = 8;
209    private static final int MIN_RSSI_LEVEL = -127;
210    private static final int MAX_RSSI_LEVEL = 0;
211    private static final int WIFI_SCORE_RANGE_MIN = 0;
212    private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20;
213    private static final int WIFI_SCORE_RANGE_MAX = 60;
214    private static final int NUM_OUT_OF_BOUND_ENTRIES = 10;
215
216    private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease,
217            String capabilities) {
218        ScanDetail mockScanDetail = mock(ScanDetail.class);
219        NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
220        ScanResult mockScanResult = mock(ScanResult.class);
221        when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
222        when(mockScanDetail.getScanResult()).thenReturn(mockScanResult);
223        when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden);
224        when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease);
225        mockScanResult.capabilities = capabilities;
226        return mockScanDetail;
227    }
228
229    private List<ScanDetail> buildMockScanDetailList() {
230        List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>();
231        mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]"));
232        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]"));
233        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]"));
234        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]"));
235        mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]"));
236        mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
237                "[WPA-EAP-CCMP]"));
238        mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
239                "[WPA2-EAP+FT/EAP-CCMP]"));
240        mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1,
241                "[WPA-EAP-CCMP]"));
242        return mockScanDetails;
243    }
244
245    /**
246     * Set simple metrics, increment others
247     */
248    public void setAndIncrementMetrics() throws Exception {
249        mWifiMetrics.setNumSavedNetworks(NUM_SAVED_NETWORKS);
250        mWifiMetrics.setNumOpenNetworks(NUM_OPEN_NETWORKS);
251        mWifiMetrics.setNumPersonalNetworks(NUM_PERSONAL_NETWORKS);
252        mWifiMetrics.setNumEnterpriseNetworks(NUM_ENTERPRISE_NETWORKS);
253        mWifiMetrics.setNumHiddenNetworks(NUM_HIDDEN_NETWORKS);
254        mWifiMetrics.setNumPasspointNetworks(NUM_PASSPOINT_NETWORKS);
255        mWifiMetrics.setNumNetworksAddedByUser(NUM_NEWTORKS_ADDED_BY_USER);
256        mWifiMetrics.setNumNetworksAddedByApps(NUM_NEWTORKS_ADDED_BY_APPS);
257        mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED);
258        mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED);
259
260        for (int i = 0; i < NUM_EMPTY_SCAN_RESULTS; i++) {
261            mWifiMetrics.incrementEmptyScanResultCount();
262        }
263        for (int i = 0; i < NUM_NON_EMPTY_SCAN_RESULTS; i++) {
264            mWifiMetrics.incrementNonEmptyScanResultCount();
265        }
266        mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN,
267                NUM_SCAN_UNKNOWN);
268        mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS,
269                NUM_SCAN_SUCCESS);
270        mWifiMetrics.incrementScanReturnEntry(
271                WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
272                NUM_SCAN_FAILURE_INTERRUPTED);
273        mWifiMetrics.incrementScanReturnEntry(
274                WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
275                NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
276        for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_OFF; i++) {
277            mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
278                    false);
279        }
280        for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_ON; i++) {
281            mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN,
282                    true);
283        }
284        for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_OFF; i++) {
285            mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
286                    false);
287        }
288        for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_ON; i++) {
289            mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED,
290                    true);
291        }
292        for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD; i++) {
293            mWifiMetrics.incrementNumConnectivityWatchdogPnoGood();
294        }
295        for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_BAD; i++) {
296            mWifiMetrics.incrementNumConnectivityWatchdogPnoBad();
297        }
298        for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD; i++) {
299            mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood();
300        }
301        for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD; i++) {
302            mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad();
303        }
304        for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS; i++) {
305            mWifiMetrics.incrementNumLastResortWatchdogTriggers();
306        }
307        mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal(
308                NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL);
309        mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(
310                NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL);
311        mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal(
312                NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL);
313        mWifiMetrics.addCountToNumLastResortWatchdogBadOtherNetworksTotal(
314                NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL);
315        mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal(
316                NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL);
317        for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION; i++) {
318            mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation();
319        }
320        for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION; i++) {
321            mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication();
322        }
323        for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP; i++) {
324            mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp();
325        }
326        for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) {
327            mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther();
328        }
329        for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) {
330            mWifiMetrics.incrementNumLastResortWatchdogSuccesses();
331        }
332        for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
333            for (int j = 0; j <= i; j++) {
334                mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL + i);
335            }
336        }
337        for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
338            mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL - i);
339        }
340        for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
341            mWifiMetrics.incrementRssiPollRssiCount(MAX_RSSI_LEVEL + i);
342        }
343        // Test alert-reason clamping.
344        mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1);
345        mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1);
346        // Simple cases for alert reason.
347        mWifiMetrics.incrementAlertReasonCount(1);
348        mWifiMetrics.incrementAlertReasonCount(1);
349        mWifiMetrics.incrementAlertReasonCount(1);
350        mWifiMetrics.incrementAlertReasonCount(2);
351        List<ScanDetail> mockScanDetails = buildMockScanDetailList();
352        for (int i = 0; i < NUM_SCANS; i++) {
353            mWifiMetrics.countScanResults(mockScanDetails);
354        }
355        for (int score = WIFI_SCORE_RANGE_MIN; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
356            for (int offset = 0; offset <= score; offset++) {
357                mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN + score);
358            }
359        }
360        for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
361            mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN - i);
362        }
363        for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
364            mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MAX + i);
365        }
366    }
367
368    /**
369     * Assert that values in deserializedWifiMetrics match those set in 'setAndIncrementMetrics'
370     */
371    public void assertDeserializedMetricsCorrect() throws Exception {
372        assertEquals("mDeserializedWifiMetrics.numSavedNetworks == NUM_SAVED_NETWORKS",
373                mDeserializedWifiMetrics.numSavedNetworks, NUM_SAVED_NETWORKS);
374        assertEquals("mDeserializedWifiMetrics.numOpenNetworks == NUM_OPEN_NETWORKS",
375                mDeserializedWifiMetrics.numOpenNetworks, NUM_OPEN_NETWORKS);
376        assertEquals("mDeserializedWifiMetrics.numPersonalNetworks == NUM_PERSONAL_NETWORKS",
377                mDeserializedWifiMetrics.numPersonalNetworks, NUM_PERSONAL_NETWORKS);
378        assertEquals("mDeserializedWifiMetrics.numEnterpriseNetworks "
379                        + "== NUM_ENTERPRISE_NETWORKS",
380                mDeserializedWifiMetrics.numEnterpriseNetworks, NUM_ENTERPRISE_NETWORKS);
381        assertEquals("mDeserializedWifiMetrics.numNetworksAddedByUser "
382                        + "== NUM_NEWTORKS_ADDED_BY_USER",
383                mDeserializedWifiMetrics.numNetworksAddedByUser, NUM_NEWTORKS_ADDED_BY_USER);
384        assertEquals(NUM_HIDDEN_NETWORKS, mDeserializedWifiMetrics.numHiddenNetworks);
385        assertEquals(NUM_PASSPOINT_NETWORKS, mDeserializedWifiMetrics.numPasspointNetworks);
386        assertEquals("mDeserializedWifiMetrics.numNetworksAddedByApps "
387                        + "== NUM_NEWTORKS_ADDED_BY_APPS",
388                mDeserializedWifiMetrics.numNetworksAddedByApps, NUM_NEWTORKS_ADDED_BY_APPS);
389        assertEquals("mDeserializedWifiMetrics.isLocationEnabled == TEST_VAL_IS_LOCATION_ENABLED",
390                mDeserializedWifiMetrics.isLocationEnabled, TEST_VAL_IS_LOCATION_ENABLED);
391        assertEquals("mDeserializedWifiMetrics.isScanningAlwaysEnabled "
392                        + "== IS_SCANNING_ALWAYS_ENABLED",
393                mDeserializedWifiMetrics.isScanningAlwaysEnabled, IS_SCANNING_ALWAYS_ENABLED);
394        assertEquals("mDeserializedWifiMetrics.numEmptyScanResults == NUM_EMPTY_SCAN_RESULTS",
395                mDeserializedWifiMetrics.numEmptyScanResults, NUM_EMPTY_SCAN_RESULTS);
396        assertEquals("mDeserializedWifiMetrics.numNonEmptyScanResults == "
397                        + "NUM_NON_EMPTY_SCAN_RESULTS",
398                mDeserializedWifiMetrics.numNonEmptyScanResults, NUM_NON_EMPTY_SCAN_RESULTS);
399        assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_UNKNOWN,
400                NUM_SCAN_UNKNOWN);
401        assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_SUCCESS,
402                NUM_SCAN_SUCCESS);
403        assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED,
404                NUM_SCAN_FAILURE_INTERRUPTED);
405        assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION,
406                NUM_SCAN_FAILURE_INVALID_CONFIGURATION);
407        assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false,
408                NUM_WIFI_UNKNOWN_SCREEN_OFF);
409        assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true,
410                NUM_WIFI_UNKNOWN_SCREEN_ON);
411        assertSystemStateEntryEquals(
412                WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false, NUM_WIFI_ASSOCIATED_SCREEN_OFF);
413        assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true,
414                NUM_WIFI_ASSOCIATED_SCREEN_ON);
415        assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogPnoGood,
416                NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD);
417        assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogPnoBad,
418                NUM_CONNECTIVITY_WATCHDOG_PNO_BAD);
419        assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogBackgroundGood,
420                NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD);
421        assertEquals(mDeserializedWifiMetrics.numConnectivityWatchdogBackgroundBad,
422                NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD);
423        assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS,
424                mDeserializedWifiMetrics.numLastResortWatchdogTriggers);
425        assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL,
426                mDeserializedWifiMetrics.numLastResortWatchdogBadAssociationNetworksTotal);
427        assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL,
428                mDeserializedWifiMetrics.numLastResortWatchdogBadAuthenticationNetworksTotal);
429        assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL,
430                mDeserializedWifiMetrics.numLastResortWatchdogBadDhcpNetworksTotal);
431        assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL,
432                mDeserializedWifiMetrics.numLastResortWatchdogBadOtherNetworksTotal);
433        assertEquals(NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL,
434                mDeserializedWifiMetrics.numLastResortWatchdogAvailableNetworksTotal);
435        assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION,
436                mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadAssociation);
437        assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION,
438                mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadAuthentication);
439        assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP,
440                mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadDhcp);
441        assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER,
442                mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadOther);
443        assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES,
444                mDeserializedWifiMetrics.numLastResortWatchdogSuccesses);
445        assertEquals(TEST_RECORD_DURATION_SEC,
446                mDeserializedWifiMetrics.recordDurationSec);
447        for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
448            assertEquals(MIN_RSSI_LEVEL + i, mDeserializedWifiMetrics.rssiPollRssiCount[i].rssi);
449            assertEquals(i + 1, mDeserializedWifiMetrics.rssiPollRssiCount[i].count);
450        }
451        StringBuilder sb_rssi = new StringBuilder();
452        sb_rssi.append("Number of RSSIs = " + mDeserializedWifiMetrics.rssiPollRssiCount.length);
453        assertTrue(sb_rssi.toString(), (mDeserializedWifiMetrics.rssiPollRssiCount.length
454                     <= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1)));
455        assertEquals(2, mDeserializedWifiMetrics.alertReasonCount[0].count);  // Clamped reasons.
456        assertEquals(3, mDeserializedWifiMetrics.alertReasonCount[1].count);
457        assertEquals(1, mDeserializedWifiMetrics.alertReasonCount[2].count);
458        assertEquals(3, mDeserializedWifiMetrics.alertReasonCount.length);
459        assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS,
460                mDeserializedWifiMetrics.numTotalScanResults);
461        assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
462                mDeserializedWifiMetrics.numOpenNetworkScanResults);
463        assertEquals(NUM_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
464                mDeserializedWifiMetrics.numPersonalNetworkScanResults);
465        assertEquals(NUM_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
466                mDeserializedWifiMetrics.numEnterpriseNetworkScanResults);
467        assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
468                mDeserializedWifiMetrics.numHiddenNetworkScanResults);
469        assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS,
470                mDeserializedWifiMetrics.numHotspot2R1NetworkScanResults);
471        assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS,
472                mDeserializedWifiMetrics.numHotspot2R2NetworkScanResults);
473        assertEquals(NUM_SCANS,
474                mDeserializedWifiMetrics.numScans);
475        for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) {
476            assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
477                    mDeserializedWifiMetrics.wifiScoreCount[score_index].score);
478            assertEquals(score_index + 1,
479                    mDeserializedWifiMetrics.wifiScoreCount[score_index].count);
480        }
481        StringBuilder sb_wifi_score = new StringBuilder();
482        sb_wifi_score.append("Number of wifi_scores = "
483                + mDeserializedWifiMetrics.wifiScoreCount.length);
484        assertTrue(sb_wifi_score.toString(), (mDeserializedWifiMetrics.wifiScoreCount.length
485                <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
486        StringBuilder sb_wifi_limits = new StringBuilder();
487        sb_wifi_limits.append("Wifi Score limit is " +  NetworkAgent.WIFI_BASE_SCORE
488                + ">= " + WIFI_SCORE_RANGE_MAX);
489        assertTrue(sb_wifi_limits.toString(), NetworkAgent.WIFI_BASE_SCORE <= WIFI_SCORE_RANGE_MAX);
490    }
491
492    /**
493     *  Assert deserialized metrics Scan Return Entry equals count
494     */
495    public void assertScanReturnEntryEquals(int returnCode, int count) {
496        for (int i = 0; i < mDeserializedWifiMetrics.scanReturnEntries.length; i++) {
497            if (mDeserializedWifiMetrics.scanReturnEntries[i].scanReturnCode == returnCode) {
498                assertEquals(mDeserializedWifiMetrics.scanReturnEntries[i].scanResultsCount, count);
499                return;
500            }
501        }
502        assertEquals(null, count);
503    }
504
505    /**
506     *  Assert deserialized metrics SystemState entry equals count
507     */
508    public void assertSystemStateEntryEquals(int state, boolean screenOn, int count) {
509        for (int i = 0; i < mDeserializedWifiMetrics.wifiSystemStateEntries.length; i++) {
510            if (mDeserializedWifiMetrics.wifiSystemStateEntries[i].wifiState == state
511                    && mDeserializedWifiMetrics.wifiSystemStateEntries[i].isScreenOn == screenOn) {
512                assertEquals(mDeserializedWifiMetrics.wifiSystemStateEntries[i].wifiStateCount,
513                        count);
514                return;
515            }
516        }
517        assertEquals(null, count);
518    }
519    /**
520     * Combination of all other WifiMetrics unit tests, an internal-integration test, or functional
521     * test
522     */
523    @Test
524    public void setMetricsSerializeDeserializeAssertMetricsSame() throws Exception {
525        setAndIncrementMetrics();
526        startAndEndConnectionEventSucceeds();
527        dumpProtoAndDeserialize();
528        assertDeserializedMetricsCorrect();
529        assertEquals("mDeserializedWifiMetrics.connectionEvent.length",
530                2, mDeserializedWifiMetrics.connectionEvent.length);
531        //<TODO> test individual connectionEvents for correctness,
532        // check scanReturnEntries & wifiSystemStateEntries counts and individual elements
533        // pending their implementation</TODO>
534    }
535
536    private static final String SSID = "red";
537    private static final int CONFIG_DTIM = 3;
538    private static final int NETWORK_DETAIL_WIFIMODE = 5;
539    private static final int NETWORK_DETAIL_DTIM = 7;
540    private static final int SCAN_RESULT_LEVEL = -30;
541    /**
542     * Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration
543     */
544    @Test
545    public void testScanDetailAndWifiConfigurationUsage() throws Exception {
546        //Setup mock configs and scan details
547        NetworkDetail networkDetail = mock(NetworkDetail.class);
548        when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE);
549        when(networkDetail.getSSID()).thenReturn(SSID);
550        when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM);
551        ScanResult scanResult = mock(ScanResult.class);
552        scanResult.level = SCAN_RESULT_LEVEL;
553        WifiConfiguration config = mock(WifiConfiguration.class);
554        config.SSID = "\"" + SSID + "\"";
555        config.dtimInterval = CONFIG_DTIM;
556        WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
557                mock(WifiConfiguration.NetworkSelectionStatus.class);
558        when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
559        when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
560        ScanDetail scanDetail = mock(ScanDetail.class);
561        when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
562        when(scanDetail.getScanResult()).thenReturn(scanResult);
563
564        //Create a connection event using only the config
565        mWifiMetrics.startConnectionEvent(config, "Red",
566                WifiMetricsProto.ConnectionEvent.ROAM_NONE);
567        mWifiMetrics.endConnectionEvent(
568                WifiMetrics.ConnectionEvent.FAILURE_NONE,
569                WifiMetricsProto.ConnectionEvent.HLF_NONE);
570
571        //Create a connection event using the config and a scan detail
572        mWifiMetrics.startConnectionEvent(config, "Green",
573                WifiMetricsProto.ConnectionEvent.ROAM_NONE);
574        mWifiMetrics.setConnectionScanDetail(scanDetail);
575        mWifiMetrics.endConnectionEvent(
576                WifiMetrics.ConnectionEvent.FAILURE_NONE,
577                WifiMetricsProto.ConnectionEvent.HLF_NONE);
578
579        //Dump proto from mWifiMetrics and deserialize it to mDeserializedWifiMetrics
580        dumpProtoAndDeserialize();
581
582        //Check that the correct values are being flowed through
583        assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 2);
584        assertEquals(mDeserializedWifiMetrics.connectionEvent[0].routerFingerprint.dtim,
585                CONFIG_DTIM);
586        assertEquals(mDeserializedWifiMetrics.connectionEvent[0].signalStrength, SCAN_RESULT_LEVEL);
587        assertEquals(mDeserializedWifiMetrics.connectionEvent[1].routerFingerprint.dtim,
588                NETWORK_DETAIL_DTIM);
589        assertEquals(mDeserializedWifiMetrics.connectionEvent[1].signalStrength,
590                SCAN_RESULT_LEVEL);
591        assertEquals(mDeserializedWifiMetrics.connectionEvent[1].routerFingerprint.routerTechnology,
592                NETWORK_DETAIL_WIFIMODE);
593    }
594
595    /**
596     * Test that WifiMetrics is being cleared after dumping via proto
597     */
598    @Test
599    public void testMetricsClearedAfterProtoRequested() throws Exception {
600        // Create 3 ConnectionEvents
601        mWifiMetrics.startConnectionEvent(null, "RED",
602                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
603        mWifiMetrics.endConnectionEvent(
604                WifiMetrics.ConnectionEvent.FAILURE_NONE,
605                WifiMetricsProto.ConnectionEvent.HLF_NONE);
606        mWifiMetrics.startConnectionEvent(null, "YELLOW",
607                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
608        mWifiMetrics.endConnectionEvent(
609                WifiMetrics.ConnectionEvent.FAILURE_NONE,
610                WifiMetricsProto.ConnectionEvent.HLF_NONE);
611        mWifiMetrics.startConnectionEvent(null, "GREEN",
612                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
613        mWifiMetrics.endConnectionEvent(
614                WifiMetrics.ConnectionEvent.FAILURE_NONE,
615                WifiMetricsProto.ConnectionEvent.HLF_NONE);
616        mWifiMetrics.startConnectionEvent(null, "ORANGE",
617                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
618        mWifiMetrics.endConnectionEvent(
619                WifiMetrics.ConnectionEvent.FAILURE_NONE,
620                WifiMetricsProto.ConnectionEvent.HLF_NONE);
621
622        //Dump proto and deserialize
623        //This should clear all the metrics in mWifiMetrics,
624        dumpProtoAndDeserialize();
625        //Check there are only 3 connection events
626        assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 4);
627        assertEquals(mDeserializedWifiMetrics.rssiPollRssiCount.length, 0);
628        assertEquals(mDeserializedWifiMetrics.alertReasonCount.length, 0);
629
630        // Create 2 ConnectionEvents
631        mWifiMetrics.startConnectionEvent(null,  "BLUE",
632                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
633        mWifiMetrics.endConnectionEvent(
634                WifiMetrics.ConnectionEvent.FAILURE_NONE,
635                WifiMetricsProto.ConnectionEvent.HLF_NONE);
636        mWifiMetrics.startConnectionEvent(null, "RED",
637                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
638        mWifiMetrics.endConnectionEvent(
639                WifiMetrics.ConnectionEvent.FAILURE_NONE,
640                WifiMetricsProto.ConnectionEvent.HLF_NONE);
641
642        //Dump proto and deserialize
643        dumpProtoAndDeserialize();
644        //Check there are only 2 connection events
645        assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 2);
646    }
647
648    /**
649     * Tests that after setting metrics values they can be serialized and deserialized with the
650     *   $ adb shell dumpsys wifi wifiMetricsProto clean
651     */
652    @Test
653    public void testClearMetricsDump() throws Exception {
654        setAndIncrementMetrics();
655        startAndEndConnectionEventSucceeds();
656        cleanDumpProtoAndDeserialize();
657        assertDeserializedMetricsCorrect();
658        assertEquals("mDeserializedWifiMetrics.connectionEvent.length",
659                2, mDeserializedWifiMetrics.connectionEvent.length);
660    }
661
662    private static final int NUM_REPEATED_DELTAS = 7;
663    private static final int REPEATED_DELTA = 0;
664    private static final int SINGLE_GOOD_DELTA = 1;
665    private static final int SINGLE_TIMEOUT_DELTA = 2;
666    private static final int NUM_REPEATED_BOUND_DELTAS = 2;
667    private static final int MAX_DELTA_LEVEL = 127;
668    private static final int MIN_DELTA_LEVEL = -127;
669    private static final int ARBITRARY_DELTA_LEVEL = 20;
670
671    /**
672     * Sunny day RSSI delta logging scenario.
673     * Logs one rssi delta value multiple times
674     * Logs a different delta value a single time
675     */
676    @Test
677    public void testRssiDeltasSuccessfulLogging() throws Exception {
678        // Generate some repeated deltas
679        for (int i = 0; i < NUM_REPEATED_DELTAS; i++) {
680            generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
681                    WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
682        }
683        // Generate a single delta
684        generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_GOOD_DELTA,
685                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
686        dumpProtoAndDeserialize();
687        assertEquals(2, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
688        // Check the repeated deltas
689        assertEquals(NUM_REPEATED_DELTAS, mDeserializedWifiMetrics.rssiPollDeltaCount[0].count);
690        assertEquals(REPEATED_DELTA, mDeserializedWifiMetrics.rssiPollDeltaCount[0].rssi);
691        // Check the single delta
692        assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[1].count);
693        assertEquals(SINGLE_GOOD_DELTA, mDeserializedWifiMetrics.rssiPollDeltaCount[1].rssi);
694    }
695
696    /**
697     * Tests that Rssi Delta events whose scanResult and Rssi Poll come too far apart, timeout,
698     * and are not logged.
699     */
700    @Test
701    public void testRssiDeltasTimeout() throws Exception {
702        // Create timed out rssi deltas
703        generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA,
704                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
705        generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_TIMEOUT_DELTA,
706                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1);
707        dumpProtoAndDeserialize();
708        assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
709    }
710
711    /**
712     * Tests the exact inclusive boundaries of RSSI delta logging.
713     */
714    @Test
715    public void testRssiDeltaSuccessfulLoggingExactBounds() throws Exception {
716        generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL,
717                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
718        generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL,
719                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
720        dumpProtoAndDeserialize();
721        assertEquals(2, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
722        assertEquals(MIN_DELTA_LEVEL, mDeserializedWifiMetrics.rssiPollDeltaCount[0].rssi);
723        assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[0].count);
724        assertEquals(MAX_DELTA_LEVEL, mDeserializedWifiMetrics.rssiPollDeltaCount[1].rssi);
725        assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[1].count);
726    }
727
728    /**
729     * Tests the exact exclusive boundaries of RSSI delta logging.
730     * This test ensures that too much data is not generated.
731     */
732    @Test
733    public void testRssiDeltaOutOfBounds() throws Exception {
734        generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL + 1,
735                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
736        generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL - 1,
737                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS);
738        dumpProtoAndDeserialize();
739        assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
740    }
741
742    /**
743     * This test ensures no rssi Delta is logged after an unsuccessful ConnectionEvent
744     */
745    @Test
746    public void testUnsuccesfulConnectionEventRssiDeltaIsNotLogged() throws Exception {
747        generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
748                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
749                false, // successfulConnectionEvent
750                true, // completeConnectionEvent
751                true, // useValidScanResult
752                true // dontDeserializeBeforePoll
753        );
754
755        dumpProtoAndDeserialize();
756        assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
757    }
758
759    /**
760     * This test ensures rssi Deltas can be logged during a ConnectionEvent
761     */
762    @Test
763    public void testIncompleteConnectionEventRssiDeltaIsLogged() throws Exception {
764        generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
765                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
766                true, // successfulConnectionEvent
767                false, // completeConnectionEvent
768                true, // useValidScanResult
769                true // dontDeserializeBeforePoll
770        );
771        dumpProtoAndDeserialize();
772        assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
773        assertEquals(ARBITRARY_DELTA_LEVEL, mDeserializedWifiMetrics.rssiPollDeltaCount[0].rssi);
774        assertEquals(1, mDeserializedWifiMetrics.rssiPollDeltaCount[0].count);
775    }
776
777    /**
778     * This test ensures that no delta is logged for a null ScanResult Candidate
779     */
780    @Test
781    public void testRssiDeltaNotLoggedForNullCandidateScanResult() throws Exception {
782        generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
783                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
784                true, // successfulConnectionEvent
785                true, // completeConnectionEvent
786                false, // useValidScanResult
787                true // dontDeserializeBeforePoll
788        );
789        dumpProtoAndDeserialize();
790        assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
791    }
792
793    /**
794     * This test ensures that Rssi Deltas are not logged over a 'clear()' call (Metrics Serialized)
795     */
796    @Test
797    public void testMetricsSerializedDuringRssiDeltaEventLogsNothing() throws Exception {
798        generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL,
799                WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS,
800                true, // successfulConnectionEvent
801                true, // completeConnectionEvent
802                true, // useValidScanResult
803                false // dontDeserializeBeforePoll
804        );
805        dumpProtoAndDeserialize();
806        assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
807    }
808
809    /**
810     * Generate an RSSI delta event by creating a connection event and an RSSI poll within
811     * 'interArrivalTime' milliseconds of each other.
812     * Event will not be logged if interArrivalTime > mWifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS
813     * successfulConnectionEvent, completeConnectionEvent, useValidScanResult and
814     * dontDeserializeBeforePoll
815     * each create an anomalous condition when set to false.
816     */
817    private void generateRssiDelta(int scanRssi, int rssiDelta,
818            long interArrivalTime, boolean successfulConnectionEvent,
819            boolean completeConnectionEvent, boolean useValidScanResult,
820            boolean dontDeserializeBeforePoll) throws Exception {
821        when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
822        ScanResult scanResult = null;
823        if (useValidScanResult) {
824            scanResult = mock(ScanResult.class);
825            scanResult.level = scanRssi;
826        }
827        WifiConfiguration config = mock(WifiConfiguration.class);
828        WifiConfiguration.NetworkSelectionStatus networkSelectionStat =
829                mock(WifiConfiguration.NetworkSelectionStatus.class);
830        when(networkSelectionStat.getCandidate()).thenReturn(scanResult);
831        when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat);
832        mWifiMetrics.startConnectionEvent(config, "TestNetwork",
833                WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
834        if (completeConnectionEvent) {
835            if (successfulConnectionEvent) {
836                mWifiMetrics.endConnectionEvent(
837                        WifiMetrics.ConnectionEvent.FAILURE_NONE,
838                        WifiMetricsProto.ConnectionEvent.HLF_NONE);
839            } else {
840                mWifiMetrics.endConnectionEvent(
841                        WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
842                        WifiMetricsProto.ConnectionEvent.HLF_NONE);
843            }
844        }
845        when(mClock.getElapsedSinceBootMillis()).thenReturn(interArrivalTime);
846        if (!dontDeserializeBeforePoll) {
847            dumpProtoAndDeserialize();
848        }
849        mWifiMetrics.incrementRssiPollRssiCount(scanRssi + rssiDelta);
850    }
851    /**
852     * Generate an RSSI delta event, with all extra conditions set to true.
853     */
854    private void generateRssiDelta(int scanRssi, int rssiDelta,
855            long interArrivalTime) throws Exception {
856        generateRssiDelta(scanRssi, rssiDelta, interArrivalTime, true, true, true, true);
857    }
858
859    private void assertStringContains(
860            String actualString, String expectedSubstring) {
861        assertTrue("Expected text not found in: " + actualString,
862                actualString.contains(expectedSubstring));
863    }
864
865    private String getStateDump() {
866        ByteArrayOutputStream stream = new ByteArrayOutputStream();
867        PrintWriter writer = new PrintWriter(stream);
868        String[] args = new String[0];
869        mWifiMetrics.dump(null, writer, args);
870        writer.flush();
871        return stream.toString();
872    }
873}
874