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