/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.wifi; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.net.NetworkAgent; import android.net.wifi.ScanResult; import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.os.Handler; import android.os.test.TestLooper; import android.support.test.filters.SmallTest; import android.util.Base64; import android.util.Pair; import com.android.server.wifi.aware.WifiAwareMetrics; import com.android.server.wifi.hotspot2.NetworkDetail; import com.android.server.wifi.hotspot2.PasspointManager; import com.android.server.wifi.hotspot2.PasspointMatch; import com.android.server.wifi.hotspot2.PasspointProvider; import com.android.server.wifi.nano.WifiMetricsProto; import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount; import com.android.server.wifi.nano.WifiMetricsProto.PnoScanMetrics; import com.android.server.wifi.nano.WifiMetricsProto.SoftApConnectedClientsEvent; import com.android.server.wifi.nano.WifiMetricsProto.StaEvent; import com.android.server.wifi.nano.WifiMetricsProto.WpsMetrics; import com.android.server.wifi.rtt.RttMetrics; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Unit tests for {@link com.android.server.wifi.WifiMetrics}. */ @SmallTest public class WifiMetricsTest { WifiMetrics mWifiMetrics; WifiMetricsProto.WifiLog mDecodedProto; TestLooper mTestLooper; @Mock Clock mClock; @Mock ScoringParams mScoringParams; @Mock WifiConfigManager mWcm; @Mock PasspointManager mPpm; @Mock WifiNetworkSelector mWns; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mDecodedProto = null; when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0); mTestLooper = new TestLooper(); mWifiMetrics = new WifiMetrics(mClock, mTestLooper.getLooper(), new WifiAwareMetrics(mClock), new RttMetrics(mClock)); mWifiMetrics.setWifiConfigManager(mWcm); mWifiMetrics.setPasspointManager(mPpm); mWifiMetrics.setScoringParams(mScoringParams); mWifiMetrics.setWifiNetworkSelector(mWns); } /** * Test that startConnectionEvent and endConnectionEvent can be called repeatedly and out of * order. Only tests no exception occurs. Creates 3 ConnectionEvents. */ @Test public void startAndEndConnectionEventSucceeds() throws Exception { //Start and end Connection event mWifiMetrics.startConnectionEvent(null, "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, WifiMetricsProto.ConnectionEvent.HLF_DHCP); //end Connection event without starting one mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, WifiMetricsProto.ConnectionEvent.HLF_DHCP); //start two ConnectionEvents in a row mWifiMetrics.startConnectionEvent(null, "BLUE", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.startConnectionEvent(null, "GREEN", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); } private static final long TEST_RECORD_DURATION_SEC = 12 * 60 * 60; private static final long TEST_RECORD_DURATION_MILLIS = TEST_RECORD_DURATION_SEC * 1000; /** * Simulate how dumpsys gets the proto from mWifiMetrics, filter the proto bytes out and * deserialize them into mDecodedProto */ public void dumpProtoAndDeserialize() throws Exception { ByteArrayOutputStream stream = new ByteArrayOutputStream(); PrintWriter writer = new PrintWriter(stream); String[] args = new String[0]; when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS); //Test proto dump, by passing in proto arg option args = new String[]{WifiMetrics.PROTO_DUMP_ARG}; mWifiMetrics.dump(null, writer, args); writer.flush(); Pattern pattern = Pattern.compile( "(?<=WifiMetrics:\\n)([\\s\\S]*)(?=EndWifiMetrics)"); Matcher matcher = pattern.matcher(stream.toString()); assertTrue("Proto Byte string found in WifiMetrics.dump():\n" + stream.toString(), matcher.find()); String protoByteString = matcher.group(1); byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT); mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes); } /** * Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into * mDecodedProto */ public void cleanDumpProtoAndDeserialize() throws Exception { ByteArrayOutputStream stream = new ByteArrayOutputStream(); PrintWriter writer = new PrintWriter(stream); String[] args = new String[0]; when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_RECORD_DURATION_MILLIS); //Test proto dump, by passing in proto arg option args = new String[]{WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG}; mWifiMetrics.dump(null, writer, args); writer.flush(); String protoByteString = stream.toString(); byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT); mDecodedProto = WifiMetricsProto.WifiLog.parseFrom(protoBytes); } /** Verifies that dump() includes the expected header */ @Test public void stateDumpIncludesHeader() throws Exception { assertStringContains(getStateDump(), "WifiMetrics"); } /** Verifies that dump() includes correct alert count when there are no alerts. */ @Test public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception { assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()"); } /** Verifies that dump() includes correct alert count when there is one alert. */ @Test public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception { mWifiMetrics.incrementAlertReasonCount(1); assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)"); } /** Verifies that dump() includes correct alert count when there are multiple alerts. */ @Test public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception { mWifiMetrics.incrementAlertReasonCount(1); mWifiMetrics.incrementAlertReasonCount(1); mWifiMetrics.incrementAlertReasonCount(16); assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)"); } @Test public void testDumpProtoAndDeserialize() throws Exception { setAndIncrementMetrics(); dumpProtoAndDeserialize(); assertDeserializedMetricsCorrect(); } private static final int NUM_OPEN_NETWORKS = 2; private static final int NUM_PERSONAL_NETWORKS = 3; private static final int NUM_ENTERPRISE_NETWORKS = 5; private static final int NUM_SAVED_NETWORKS = NUM_OPEN_NETWORKS + NUM_PERSONAL_NETWORKS + NUM_ENTERPRISE_NETWORKS; private static final int NUM_HIDDEN_NETWORKS = NUM_OPEN_NETWORKS; private static final int NUM_PASSPOINT_NETWORKS = NUM_ENTERPRISE_NETWORKS; private static final int NUM_NETWORKS_ADDED_BY_USER = 1; private static final int NUM_NETWORKS_ADDED_BY_APPS = NUM_SAVED_NETWORKS - NUM_NETWORKS_ADDED_BY_USER; private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true; private static final boolean IS_SCANNING_ALWAYS_ENABLED = true; private static final int NUM_EMPTY_SCAN_RESULTS = 19; private static final int NUM_NON_EMPTY_SCAN_RESULTS = 23; private static final int NUM_SCAN_UNKNOWN = 1; private static final int NUM_SCAN_SUCCESS = 2; private static final int NUM_SCAN_FAILURE_INTERRUPTED = 3; private static final int NUM_SCAN_FAILURE_INVALID_CONFIGURATION = 5; private static final int NUM_WIFI_UNKNOWN_SCREEN_OFF = 3; private static final int NUM_WIFI_UNKNOWN_SCREEN_ON = 5; private static final int NUM_WIFI_ASSOCIATED_SCREEN_OFF = 7; private static final int NUM_WIFI_ASSOCIATED_SCREEN_ON = 11; private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD = 11; private static final int NUM_CONNECTIVITY_WATCHDOG_PNO_BAD = 12; private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD = 13; private static final int NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD = 14; private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS = 1; private static final int NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL = 2; private static final int NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL = 3; private static final int NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL = 4; private static final int NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL = 5; private static final int NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL = 6; private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION = 7; private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8; private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9; private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10; private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5; private static final int WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER = 6; private static final int RSSI_POLL_FREQUENCY = 5150; private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20; private static final int FIRST_RSSI_LEVEL = -80; private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1; private static final int NUM_PERSONAL_NETWORK_SCAN_RESULTS = 4; private static final int NUM_ENTERPRISE_NETWORK_SCAN_RESULTS = 3; private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1; private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1; private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2; private static final int NUM_SCANS = 5; private static final int NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT = 4; private static final int NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS = 15; private static final int NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 10; private static final int NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED = 16; private static final int NUM_TOTAL_SCAN_RESULTS = 8; private static final int MIN_RSSI_LEVEL = -127; private static final int MAX_RSSI_LEVEL = 0; private static final int WIFI_SCORE_RANGE_MIN = 0; private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20; private static final int WIFI_SCORE_RANGE_MAX = 60; private static final int NUM_OUT_OF_BOUND_ENTRIES = 10; private static final int MAX_NUM_SOFTAP_RETURN_CODES = 3; private static final int NUM_SOFTAP_START_SUCCESS = 3; private static final int NUM_SOFTAP_FAILED_GENERAL_ERROR = 2; private static final int NUM_SOFTAP_FAILED_NO_CHANNEL = 1; private static final int NUM_HAL_CRASHES = 11; private static final int NUM_WIFICOND_CRASHES = 12; private static final int NUM_SUPPLICANT_CRASHES = 23; private static final int NUM_HOSTAPD_CRASHES = 7; private static final int NUM_WIFI_ON_FAILURE_DUE_TO_HAL = 13; private static final int NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND = 14; private static final int NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT = 20; private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL = 23; private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND = 19; private static final int NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD = 31; private static final int NUM_SOFTAP_INTERFACE_DOWN = 65; private static final int NUM_CLIENT_INTERFACE_DOWN = 12; private static final int NUM_PASSPOINT_PROVIDERS = 4; private static final int NUM_PASSPOINT_PROVIDER_INSTALLATION = 5; private static final int NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS = 4; private static final int NUM_PASSPOINT_PROVIDER_UNINSTALLATION = 3; private static final int NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS = 2; private static final int NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED = 1; private static final int NUM_PARTIAL_SCAN_RESULTS = 73; private static final int NUM_PNO_SCAN_ATTEMPTS = 20; private static final int NUM_PNO_SCAN_FAILED = 5; private static final int NUM_PNO_SCAN_STARTED_OVER_OFFLOAD = 17; private static final int NUM_PNO_SCAN_FAILED_OVER_OFFLOAD = 8; private static final int NUM_PNO_FOUND_NETWORK_EVENTS = 10; private static final int NUM_WPS_ATTEMPTS = 17; private static final int NUM_WPS_SUCCESS = 21; private static final int NUM_WPS_START_FAILURE = 7; private static final int NUM_WPS_OVERLAP_FAILURE = 3; private static final int NUM_WPS_TIMEOUT_FAILURE = 8; private static final int NUM_WPS_OTHER_CONNECTION_FAILURE = 16; private static final int NUM_WPS_SUPPLICANT_FAILURE = 12; private static final int NUM_WPS_CANCELLATION = 11; private static final int NUM_RADIO_MODE_CHANGE_TO_MCC = 4; private static final int NUM_RADIO_MODE_CHANGE_TO_SCC = 13; private static final int NUM_RADIO_MODE_CHANGE_TO_SBS = 19; private static final int NUM_RADIO_MODE_CHANGE_TO_DBS = 34; private static final int NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED = 14; private static final long NUM_WATCHDOG_SUCCESS_DURATION_MS = 65; /** Number of notifications per "Connect to Network" notification type. */ private static final int[] NUM_CONNECT_TO_NETWORK_NOTIFICATIONS = {0, 10, 20, 30, 40}; /** Number of notifications per "Connect to Network notification type and action type. */ private static final int[][] NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS = { {0, 1, 2, 3, 4}, {10, 11, 12, 13, 14}, {20, 21, 22, 23, 24}, {30, 31, 32, 33, 34}, {40, 41, 42, 43, 44}}; private static final int SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST = 10; private static final boolean IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = true; private static final int NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND = 5; private static final int NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES = 8; private static final String OPEN_NET_NOTIFIER_TAG = OpenNetworkNotifier.TAG; private static final int NUM_SOFT_AP_EVENT_ENTRIES = 3; private static final int NUM_SOFT_AP_ASSOCIATED_STATIONS = 3; private static final int SOFT_AP_CHANNEL_FREQUENCY = 2437; private static final int SOFT_AP_CHANNEL_BANDWIDTH = SoftApConnectedClientsEvent.BANDWIDTH_20; private static final boolean IS_MAC_RANDOMIZATION_ON = true; private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease, String capabilities) { ScanDetail mockScanDetail = mock(ScanDetail.class); NetworkDetail mockNetworkDetail = mock(NetworkDetail.class); ScanResult mockScanResult = mock(ScanResult.class); when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail); when(mockScanDetail.getScanResult()).thenReturn(mockScanResult); when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden); when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease); mockScanResult.capabilities = capabilities; return mockScanDetail; } private ScanDetail buildMockScanDetail(String ssid, String bssid, boolean isOpen, boolean isSaved, boolean isProvider, boolean isWeakRssi) { ScanDetail mockScanDetail = mock(ScanDetail.class); NetworkDetail mockNetworkDetail = mock(NetworkDetail.class); ScanResult scanResult = new ScanResult(); scanResult.SSID = ssid; scanResult.BSSID = bssid; when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail); when(mockScanDetail.getScanResult()).thenReturn(scanResult); when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(isWeakRssi); scanResult.capabilities = isOpen ? "" : "PSK"; if (isSaved) { when(mWcm.getConfiguredNetworkForScanDetail(eq(mockScanDetail))) .thenReturn(mock(WifiConfiguration.class)); } if (isProvider) { PasspointProvider provider = mock(PasspointProvider.class); Pair providerMatch = Pair.create(provider, null); when(mockNetworkDetail.isInterworking()).thenReturn(true); when(mPpm.matchProvider(eq(scanResult))).thenReturn(providerMatch); } return mockScanDetail; } private ScanDetail buildMockScanDetailPasspoint(String ssid, String bssid, long hessid, int anqpDomainId, NetworkDetail.HSRelease hsRelease, boolean weakSignal) { ScanDetail mockScanDetail = mock(ScanDetail.class); NetworkDetail mockNetworkDetail = mock(NetworkDetail.class); ScanResult scanResult = new ScanResult(); scanResult.SSID = ssid; scanResult.BSSID = bssid; scanResult.hessid = hessid; scanResult.capabilities = "PSK"; when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail); when(mockScanDetail.getScanResult()).thenReturn(scanResult); when(mockNetworkDetail.getHSRelease()).thenReturn(hsRelease); when(mockNetworkDetail.getAnqpDomainID()).thenReturn(anqpDomainId); when(mockNetworkDetail.isInterworking()).thenReturn(true); when(mWns.isSignalTooWeak(eq(scanResult))).thenReturn(weakSignal); return mockScanDetail; } private List buildMockScanDetailList() { List mockScanDetails = new ArrayList(); mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]")); mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]")); mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]")); mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]")); mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]")); mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2, "[WPA-EAP-CCMP]")); mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2, "[WPA2-EAP+FT/EAP-CCMP]")); mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1, "[WPA-EAP-CCMP]")); return mockScanDetails; } private List buildSavedNetworkList() { List testSavedNetworks = new ArrayList(); for (int i = 0; i < NUM_OPEN_NETWORKS; i++) { testSavedNetworks.add(WifiConfigurationTestUtil.createOpenHiddenNetwork()); } for (int i = 0; i < NUM_PERSONAL_NETWORKS; i++) { testSavedNetworks.add(WifiConfigurationTestUtil.createPskNetwork()); } for (int i = 0; i < NUM_ENTERPRISE_NETWORKS; i++) { // Passpoint networks are counted in both Passpoint and Enterprise counters testSavedNetworks.add(WifiConfigurationTestUtil.createPasspointNetwork()); } testSavedNetworks.get(0).selfAdded = true; return testSavedNetworks; } /** * Set simple metrics, increment others */ public void setAndIncrementMetrics() throws Exception { mWifiMetrics.updateSavedNetworks(buildSavedNetworkList()); mWifiMetrics.updateSavedPasspointProfiles(NUM_PASSPOINT_PROVIDERS, NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED); mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED); mWifiMetrics.setIsScanningAlwaysEnabled(IS_SCANNING_ALWAYS_ENABLED); for (int i = 0; i < NUM_EMPTY_SCAN_RESULTS; i++) { mWifiMetrics.incrementEmptyScanResultCount(); } for (int i = 0; i < NUM_NON_EMPTY_SCAN_RESULTS; i++) { mWifiMetrics.incrementNonEmptyScanResultCount(); } mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, NUM_SCAN_UNKNOWN); mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS, NUM_SCAN_SUCCESS); mWifiMetrics.incrementScanReturnEntry( WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED, NUM_SCAN_FAILURE_INTERRUPTED); mWifiMetrics.incrementScanReturnEntry( WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, NUM_SCAN_FAILURE_INVALID_CONFIGURATION); for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_OFF; i++) { mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false); } for (int i = 0; i < NUM_WIFI_UNKNOWN_SCREEN_ON; i++) { mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true); } for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_OFF; i++) { mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false); } for (int i = 0; i < NUM_WIFI_ASSOCIATED_SCREEN_ON; i++) { mWifiMetrics.incrementWifiSystemScanStateCount(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true); } for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD; i++) { mWifiMetrics.incrementNumConnectivityWatchdogPnoGood(); } for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_PNO_BAD; i++) { mWifiMetrics.incrementNumConnectivityWatchdogPnoBad(); } for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD; i++) { mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood(); } for (int i = 0; i < NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD; i++) { mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad(); } for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS; i++) { mWifiMetrics.incrementNumLastResortWatchdogTriggers(); } mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal( NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL); mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal( NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL); mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal( NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL); mWifiMetrics.addCountToNumLastResortWatchdogBadOtherNetworksTotal( NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL); mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal( NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL); for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION; i++) { mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation(); } for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION; i++) { mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication(); } for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP; i++) { mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp(); } for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) { mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther(); } for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) { mWifiMetrics.incrementNumLastResortWatchdogSuccesses(); } for (int i = 0; i < WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER; i++) { mWifiMetrics.incrementWatchdogTotalConnectionFailureCountAfterTrigger(); } for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { for (int j = 0; j <= i; j++) { mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL + i); } } for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MIN_RSSI_LEVEL - i); } for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, MAX_RSSI_LEVEL + i); } // Test alert-reason clamping. mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1); mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1); // Simple cases for alert reason. mWifiMetrics.incrementAlertReasonCount(1); mWifiMetrics.incrementAlertReasonCount(1); mWifiMetrics.incrementAlertReasonCount(1); mWifiMetrics.incrementAlertReasonCount(2); List mockScanDetails = buildMockScanDetailList(); for (int i = 0; i < NUM_SCANS; i++) { mWifiMetrics.countScanResults(mockScanDetails); } // increment connectivity scan metrics for (int i = 0; i < NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT; i++) { mWifiMetrics.incrementConnectivityOneshotScanCount(); } for (int i = 0; i < NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS; i++) { mWifiMetrics.incrementExternalAppOneshotScanRequestsCount(); } for (int i = 0; i < NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) { mWifiMetrics.incrementExternalForegroundAppOneshotScanRequestsThrottledCount(); } for (int i = 0; i < NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED; i++) { mWifiMetrics.incrementExternalBackgroundAppOneshotScanRequestsThrottledCount(); } for (int score = WIFI_SCORE_RANGE_MIN; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) { for (int offset = 0; offset <= score; offset++) { mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN + score); } } for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN - i); } for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MAX + i); } // increment soft ap start return codes for (int i = 0; i < NUM_SOFTAP_START_SUCCESS; i++) { mWifiMetrics.incrementSoftApStartResult(true, 0); } for (int i = 0; i < NUM_SOFTAP_FAILED_GENERAL_ERROR; i++) { mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL); } for (int i = 0; i < NUM_SOFTAP_FAILED_NO_CHANNEL; i++) { mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_NO_CHANNEL); } for (int i = 0; i < NUM_HAL_CRASHES; i++) { mWifiMetrics.incrementNumHalCrashes(); } for (int i = 0; i < NUM_WIFICOND_CRASHES; i++) { mWifiMetrics.incrementNumWificondCrashes(); } for (int i = 0; i < NUM_SUPPLICANT_CRASHES; i++) { mWifiMetrics.incrementNumSupplicantCrashes(); } for (int i = 0; i < NUM_HOSTAPD_CRASHES; i++) { mWifiMetrics.incrementNumHostapdCrashes(); } for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_HAL; i++) { mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); } for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND; i++) { mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); } for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT; i++) { mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); } for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL; i++) { mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); } for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND; i++) { mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond(); } for (int i = 0; i < NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD; i++) { mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); } for (int i = 0; i < NUM_SOFTAP_INTERFACE_DOWN; i++) { mWifiMetrics.incrementNumSoftApInterfaceDown(); } for (int i = 0; i < NUM_CLIENT_INTERFACE_DOWN; i++) { mWifiMetrics.incrementNumClientInterfaceDown(); } for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALLATION; i++) { mWifiMetrics.incrementNumPasspointProviderInstallation(); } for (int i = 0; i < NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS; i++) { mWifiMetrics.incrementNumPasspointProviderInstallSuccess(); } for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALLATION; i++) { mWifiMetrics.incrementNumPasspointProviderUninstallation(); } for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS; i++) { mWifiMetrics.incrementNumPasspointProviderUninstallSuccess(); } for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_MCC; i++) { mWifiMetrics.incrementNumRadioModeChangeToMcc(); } for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SCC; i++) { mWifiMetrics.incrementNumRadioModeChangeToScc(); } for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_SBS; i++) { mWifiMetrics.incrementNumRadioModeChangeToSbs(); } for (int i = 0; i < NUM_RADIO_MODE_CHANGE_TO_DBS; i++) { mWifiMetrics.incrementNumRadioModeChangeToDbs(); } for (int i = 0; i < NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED; i++) { mWifiMetrics.incrementNumSoftApUserBandPreferenceUnsatisfied(); } // increment pno scan metrics for (int i = 0; i < NUM_PNO_SCAN_ATTEMPTS; i++) { mWifiMetrics.incrementPnoScanStartAttempCount(); } for (int i = 0; i < NUM_PNO_SCAN_FAILED; i++) { mWifiMetrics.incrementPnoScanFailedCount(); } for (int i = 0; i < NUM_PNO_SCAN_STARTED_OVER_OFFLOAD; i++) { mWifiMetrics.incrementPnoScanStartedOverOffloadCount(); } for (int i = 0; i < NUM_PNO_SCAN_FAILED_OVER_OFFLOAD; i++) { mWifiMetrics.incrementPnoScanFailedOverOffloadCount(); } for (int i = 0; i < NUM_PNO_FOUND_NETWORK_EVENTS; i++) { mWifiMetrics.incrementPnoFoundNetworkEventCount(); } // set and increment "connect to network" notification metrics for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATIONS.length; i++) { int count = NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[i]; for (int j = 0; j < count; j++) { mWifiMetrics.incrementConnectToNetworkNotification(OPEN_NET_NOTIFIER_TAG, i); } } for (int i = 0; i < NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS.length; i++) { int[] actions = NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS[i]; for (int j = 0; j < actions.length; j++) { int count = actions[j]; for (int k = 0; k < count; k++) { mWifiMetrics.incrementConnectToNetworkNotificationAction(OPEN_NET_NOTIFIER_TAG, i, j); } } } mWifiMetrics.setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST); mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON); for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) { mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG); } for (int i = 0; i < NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND; i++) { mWifiMetrics.incrementNumNetworkConnectMessageFailedToSend(OPEN_NET_NOTIFIER_TAG); } addSoftApEventsToMetrics(); // increment wps metrics for (int i = 0; i < NUM_WPS_ATTEMPTS; i++) { mWifiMetrics.incrementWpsAttemptCount(); } for (int i = 0; i < NUM_WPS_SUCCESS; i++) { mWifiMetrics.incrementWpsSuccessCount(); } for (int i = 0; i < NUM_WPS_START_FAILURE; i++) { mWifiMetrics.incrementWpsStartFailureCount(); } for (int i = 0; i < NUM_WPS_OVERLAP_FAILURE; i++) { mWifiMetrics.incrementWpsOverlapFailureCount(); } for (int i = 0; i < NUM_WPS_TIMEOUT_FAILURE; i++) { mWifiMetrics.incrementWpsTimeoutFailureCount(); } for (int i = 0; i < NUM_WPS_OTHER_CONNECTION_FAILURE; i++) { mWifiMetrics.incrementWpsOtherConnectionFailureCount(); } for (int i = 0; i < NUM_WPS_SUPPLICANT_FAILURE; i++) { mWifiMetrics.incrementWpsSupplicantFailureCount(); } for (int i = 0; i < NUM_WPS_CANCELLATION; i++) { mWifiMetrics.incrementWpsCancellationCount(); } mWifiMetrics.setWatchdogSuccessTimeDurationMs(NUM_WATCHDOG_SUCCESS_DURATION_MS); mWifiMetrics.setIsMacRandomizationOn(IS_MAC_RANDOMIZATION_ON); } private void addSoftApEventsToMetrics() { // Total number of events recorded is NUM_SOFT_AP_EVENT_ENTRIES in both modes mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_TETHERED); mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS, WifiManager.IFACE_IP_MODE_TETHERED); mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS, WifiManager.IFACE_IP_MODE_UNSPECIFIED); // Should be dropped. mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_TETHERED); // Channel switch info should be added to the last Soft AP UP event in the list mWifiMetrics.addSoftApChannelSwitchedEvent(SOFT_AP_CHANNEL_FREQUENCY, SOFT_AP_CHANNEL_BANDWIDTH, WifiManager.IFACE_IP_MODE_TETHERED); mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); mWifiMetrics.addSoftApNumAssociatedStationsChangedEvent(NUM_SOFT_AP_ASSOCIATED_STATIONS, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); // Should be dropped. mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR); mWifiMetrics.addSoftApUpChangedEvent(false, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); } private void verifySoftApEventsStoredInProto() { assertEquals(NUM_SOFT_AP_EVENT_ENTRIES, mDecodedProto.softApConnectedClientsEventsTethered.length); assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP, mDecodedProto.softApConnectedClientsEventsTethered[0].eventType); assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[0].numConnectedClients); assertEquals(SOFT_AP_CHANNEL_FREQUENCY, mDecodedProto.softApConnectedClientsEventsTethered[0].channelFrequency); assertEquals(SOFT_AP_CHANNEL_BANDWIDTH, mDecodedProto.softApConnectedClientsEventsTethered[0].channelBandwidth); assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED, mDecodedProto.softApConnectedClientsEventsTethered[1].eventType); assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS, mDecodedProto.softApConnectedClientsEventsTethered[1].numConnectedClients); assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN, mDecodedProto.softApConnectedClientsEventsTethered[2].eventType); assertEquals(0, mDecodedProto.softApConnectedClientsEventsTethered[2].numConnectedClients); assertEquals(SoftApConnectedClientsEvent.SOFT_AP_UP, mDecodedProto.softApConnectedClientsEventsLocalOnly[0].eventType); assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[0].numConnectedClients); assertEquals(SoftApConnectedClientsEvent.NUM_CLIENTS_CHANGED, mDecodedProto.softApConnectedClientsEventsLocalOnly[1].eventType); assertEquals(NUM_SOFT_AP_ASSOCIATED_STATIONS, mDecodedProto.softApConnectedClientsEventsLocalOnly[1].numConnectedClients); assertEquals(SoftApConnectedClientsEvent.SOFT_AP_DOWN, mDecodedProto.softApConnectedClientsEventsLocalOnly[2].eventType); assertEquals(0, mDecodedProto.softApConnectedClientsEventsLocalOnly[2].numConnectedClients); } /** * Assert that values in deserializedWifiMetrics match those set in 'setAndIncrementMetrics' */ public void assertDeserializedMetricsCorrect() throws Exception { assertEquals("mDecodedProto.numSavedNetworks == NUM_SAVED_NETWORKS", mDecodedProto.numSavedNetworks, NUM_SAVED_NETWORKS); assertEquals("mDecodedProto.numOpenNetworks == NUM_OPEN_NETWORKS", mDecodedProto.numOpenNetworks, NUM_OPEN_NETWORKS); assertEquals("mDecodedProto.numPersonalNetworks == NUM_PERSONAL_NETWORKS", mDecodedProto.numPersonalNetworks, NUM_PERSONAL_NETWORKS); assertEquals("mDecodedProto.numEnterpriseNetworks == NUM_ENTERPRISE_NETWORKS", mDecodedProto.numEnterpriseNetworks, NUM_ENTERPRISE_NETWORKS); assertEquals("mDecodedProto.numNetworksAddedByUser == NUM_NETWORKS_ADDED_BY_USER", mDecodedProto.numNetworksAddedByUser, NUM_NETWORKS_ADDED_BY_USER); assertEquals(NUM_HIDDEN_NETWORKS, mDecodedProto.numHiddenNetworks); assertEquals(NUM_PASSPOINT_NETWORKS, mDecodedProto.numPasspointNetworks); assertEquals("mDecodedProto.numNetworksAddedByApps == NUM_NETWORKS_ADDED_BY_APPS", mDecodedProto.numNetworksAddedByApps, NUM_NETWORKS_ADDED_BY_APPS); assertEquals("mDecodedProto.isLocationEnabled == TEST_VAL_IS_LOCATION_ENABLED", mDecodedProto.isLocationEnabled, TEST_VAL_IS_LOCATION_ENABLED); assertEquals("mDecodedProto.isScanningAlwaysEnabled == IS_SCANNING_ALWAYS_ENABLED", mDecodedProto.isScanningAlwaysEnabled, IS_SCANNING_ALWAYS_ENABLED); assertEquals("mDecodedProto.numEmptyScanResults == NUM_EMPTY_SCAN_RESULTS", mDecodedProto.numEmptyScanResults, NUM_EMPTY_SCAN_RESULTS); assertEquals("mDecodedProto.numNonEmptyScanResults == NUM_NON_EMPTY_SCAN_RESULTS", mDecodedProto.numNonEmptyScanResults, NUM_NON_EMPTY_SCAN_RESULTS); assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_UNKNOWN, NUM_SCAN_UNKNOWN); assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_SUCCESS, NUM_SCAN_SUCCESS); assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INTERRUPTED, NUM_SCAN_FAILURE_INTERRUPTED); assertScanReturnEntryEquals(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, NUM_SCAN_FAILURE_INVALID_CONFIGURATION); assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, false, NUM_WIFI_UNKNOWN_SCREEN_OFF); assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_UNKNOWN, true, NUM_WIFI_UNKNOWN_SCREEN_ON); assertSystemStateEntryEquals( WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, false, NUM_WIFI_ASSOCIATED_SCREEN_OFF); assertSystemStateEntryEquals(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED, true, NUM_WIFI_ASSOCIATED_SCREEN_ON); assertEquals(mDecodedProto.numConnectivityWatchdogPnoGood, NUM_CONNECTIVITY_WATCHDOG_PNO_GOOD); assertEquals(mDecodedProto.numConnectivityWatchdogPnoBad, NUM_CONNECTIVITY_WATCHDOG_PNO_BAD); assertEquals(mDecodedProto.numConnectivityWatchdogBackgroundGood, NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_GOOD); assertEquals(mDecodedProto.numConnectivityWatchdogBackgroundBad, NUM_CONNECTIVITY_WATCHDOG_BACKGROUND_BAD); assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS, mDecodedProto.numLastResortWatchdogTriggers); assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_ASSOCIATION_NETWORKS_TOTAL, mDecodedProto.numLastResortWatchdogBadAssociationNetworksTotal); assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_AUTHENTICATION_NETWORKS_TOTAL, mDecodedProto.numLastResortWatchdogBadAuthenticationNetworksTotal); assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_DHCP_NETWORKS_TOTAL, mDecodedProto.numLastResortWatchdogBadDhcpNetworksTotal); assertEquals(NUM_LAST_RESORT_WATCHDOG_BAD_OTHER_NETWORKS_TOTAL, mDecodedProto.numLastResortWatchdogBadOtherNetworksTotal); assertEquals(NUM_LAST_RESORT_WATCHDOG_AVAILABLE_NETWORKS_TOTAL, mDecodedProto.numLastResortWatchdogAvailableNetworksTotal); assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_ASSOCIATION, mDecodedProto.numLastResortWatchdogTriggersWithBadAssociation); assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION, mDecodedProto.numLastResortWatchdogTriggersWithBadAuthentication); assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP, mDecodedProto.numLastResortWatchdogTriggersWithBadDhcp); assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER, mDecodedProto.numLastResortWatchdogTriggersWithBadOther); assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES, mDecodedProto.numLastResortWatchdogSuccesses); assertEquals(WATCHDOG_TOTAL_CONNECTION_FAILURE_COUNT_AFTER_TRIGGER, mDecodedProto.watchdogTotalConnectionFailureCountAfterTrigger); assertEquals(TEST_RECORD_DURATION_SEC, mDecodedProto.recordDurationSec); for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { assertEquals(RSSI_POLL_FREQUENCY, mDecodedProto.rssiPollRssiCount[i].frequency); assertEquals(MIN_RSSI_LEVEL + i, mDecodedProto.rssiPollRssiCount[i].rssi); assertEquals(i + 1, mDecodedProto.rssiPollRssiCount[i].count); } StringBuilder sb_rssi = new StringBuilder(); sb_rssi.append("Number of RSSIs = " + mDecodedProto.rssiPollRssiCount.length); assertTrue(sb_rssi.toString(), (mDecodedProto.rssiPollRssiCount.length <= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1))); assertEquals(2, mDecodedProto.alertReasonCount[0].count); // Clamped reasons. assertEquals(3, mDecodedProto.alertReasonCount[1].count); assertEquals(1, mDecodedProto.alertReasonCount[2].count); assertEquals(3, mDecodedProto.alertReasonCount.length); assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS, mDecodedProto.numTotalScanResults); assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS, mDecodedProto.numOpenNetworkScanResults); assertEquals(NUM_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS, mDecodedProto.numPersonalNetworkScanResults); assertEquals(NUM_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS, mDecodedProto.numEnterpriseNetworkScanResults); assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS, mDecodedProto.numHiddenNetworkScanResults); assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS, mDecodedProto.numHotspot2R1NetworkScanResults); assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS, mDecodedProto.numHotspot2R2NetworkScanResults); assertEquals(NUM_SCANS, mDecodedProto.numScans); assertEquals(NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT, mDecodedProto.numConnectivityOneshotScans); assertEquals(NUM_EXTERNAL_APP_ONESHOT_SCAN_REQUESTS, mDecodedProto.numExternalAppOneshotScanRequests); assertEquals(NUM_EXTERNAL_FOREGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED, mDecodedProto.numExternalForegroundAppOneshotScanRequestsThrottled); assertEquals(NUM_EXTERNAL_BACKGROUND_APP_ONESHOT_SCAN_REQUESTS_THROTTLED, mDecodedProto.numExternalBackgroundAppOneshotScanRequestsThrottled); for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) { assertEquals(WIFI_SCORE_RANGE_MIN + score_index, mDecodedProto.wifiScoreCount[score_index].score); assertEquals(score_index + 1, mDecodedProto.wifiScoreCount[score_index].count); } StringBuilder sb_wifi_score = new StringBuilder(); sb_wifi_score.append("Number of wifi_scores = " + mDecodedProto.wifiScoreCount.length); assertTrue(sb_wifi_score.toString(), (mDecodedProto.wifiScoreCount.length <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1))); StringBuilder sb_wifi_limits = new StringBuilder(); sb_wifi_limits.append("Wifi Score limit is " + NetworkAgent.WIFI_BASE_SCORE + ">= " + WIFI_SCORE_RANGE_MAX); assertTrue(sb_wifi_limits.toString(), NetworkAgent.WIFI_BASE_SCORE <= WIFI_SCORE_RANGE_MAX); assertEquals(MAX_NUM_SOFTAP_RETURN_CODES, mDecodedProto.softApReturnCode.length); assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_STARTED_SUCCESSFULLY, mDecodedProto.softApReturnCode[0].startResult); assertEquals(NUM_SOFTAP_START_SUCCESS, mDecodedProto.softApReturnCode[0].count); assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_GENERAL_ERROR, mDecodedProto.softApReturnCode[1].startResult); assertEquals(NUM_SOFTAP_FAILED_GENERAL_ERROR, mDecodedProto.softApReturnCode[1].count); assertEquals(WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL, mDecodedProto.softApReturnCode[2].startResult); assertEquals(NUM_SOFTAP_FAILED_NO_CHANNEL, mDecodedProto.softApReturnCode[2].count); assertEquals(NUM_HAL_CRASHES, mDecodedProto.numHalCrashes); assertEquals(NUM_WIFICOND_CRASHES, mDecodedProto.numWificondCrashes); assertEquals(NUM_SUPPLICANT_CRASHES, mDecodedProto.numSupplicantCrashes); assertEquals(NUM_HOSTAPD_CRASHES, mDecodedProto.numHostapdCrashes); assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_HAL, mDecodedProto.numSetupClientInterfaceFailureDueToHal); assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND, mDecodedProto.numSetupClientInterfaceFailureDueToWificond); assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_SUPPLICANT, mDecodedProto.numSetupClientInterfaceFailureDueToSupplicant); assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HAL, mDecodedProto.numSetupSoftApInterfaceFailureDueToHal); assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_WIFICOND, mDecodedProto.numSetupSoftApInterfaceFailureDueToWificond); assertEquals(NUM_SOFTAP_ON_FAILURE_DUE_TO_HOSTAPD, mDecodedProto.numSetupSoftApInterfaceFailureDueToHostapd); assertEquals(NUM_CLIENT_INTERFACE_DOWN, mDecodedProto.numClientInterfaceDown); assertEquals(NUM_SOFTAP_INTERFACE_DOWN, mDecodedProto.numSoftApInterfaceDown); assertEquals(NUM_PASSPOINT_PROVIDERS, mDecodedProto.numPasspointProviders); assertEquals(NUM_PASSPOINT_PROVIDER_INSTALLATION, mDecodedProto.numPasspointProviderInstallation); assertEquals(NUM_PASSPOINT_PROVIDER_INSTALL_SUCCESS, mDecodedProto.numPasspointProviderInstallSuccess); assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALLATION, mDecodedProto.numPasspointProviderUninstallation); assertEquals(NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS, mDecodedProto.numPasspointProviderUninstallSuccess); assertEquals(NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED, mDecodedProto.numPasspointProvidersSuccessfullyConnected); assertEquals(NUM_RADIO_MODE_CHANGE_TO_MCC, mDecodedProto.numRadioModeChangeToMcc); assertEquals(NUM_RADIO_MODE_CHANGE_TO_SCC, mDecodedProto.numRadioModeChangeToScc); assertEquals(NUM_RADIO_MODE_CHANGE_TO_SBS, mDecodedProto.numRadioModeChangeToSbs); assertEquals(NUM_RADIO_MODE_CHANGE_TO_DBS, mDecodedProto.numRadioModeChangeToDbs); assertEquals(NUM_SOFTAP_USER_BAND_PREFERENCE_UNSATISFIED, mDecodedProto.numSoftApUserBandPreferenceUnsatisfied); PnoScanMetrics pno_metrics = mDecodedProto.pnoScanMetrics; assertNotNull(pno_metrics); assertEquals(NUM_PNO_SCAN_ATTEMPTS, pno_metrics.numPnoScanAttempts); assertEquals(NUM_PNO_SCAN_FAILED, pno_metrics.numPnoScanFailed); assertEquals(NUM_PNO_SCAN_STARTED_OVER_OFFLOAD, pno_metrics.numPnoScanStartedOverOffload); assertEquals(NUM_PNO_SCAN_FAILED_OVER_OFFLOAD, pno_metrics.numPnoScanFailedOverOffload); assertEquals(NUM_PNO_FOUND_NETWORK_EVENTS, pno_metrics.numPnoFoundNetworkEvents); for (ConnectToNetworkNotificationAndActionCount notificationCount : mDecodedProto.connectToNetworkNotificationCount) { assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATIONS[notificationCount.notification], notificationCount.count); assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN, notificationCount.recommender); } for (ConnectToNetworkNotificationAndActionCount notificationActionCount : mDecodedProto.connectToNetworkNotificationActionCount) { assertEquals(NUM_CONNECT_TO_NETWORK_NOTIFICATION_ACTIONS [notificationActionCount.notification] [notificationActionCount.action], notificationActionCount.count); assertEquals(ConnectToNetworkNotificationAndActionCount.RECOMMENDER_OPEN, notificationActionCount.recommender); } assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST, mDecodedProto.openNetworkRecommenderBlacklistSize); assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, mDecodedProto.isWifiNetworksAvailableNotificationOn); assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES, mDecodedProto.numOpenNetworkRecommendationUpdates); assertEquals(NUM_OPEN_NETWORK_CONNECT_MESSAGE_FAILED_TO_SEND, mDecodedProto.numOpenNetworkConnectMessageFailedToSend); verifySoftApEventsStoredInProto(); WpsMetrics wps_metrics = mDecodedProto.wpsMetrics; assertNotNull(wps_metrics); assertEquals(NUM_WPS_ATTEMPTS, wps_metrics.numWpsAttempts); assertEquals(NUM_WPS_SUCCESS, wps_metrics.numWpsSuccess); assertEquals(NUM_WPS_START_FAILURE, wps_metrics.numWpsStartFailure); assertEquals(NUM_WPS_OVERLAP_FAILURE, wps_metrics.numWpsOverlapFailure); assertEquals(NUM_WPS_TIMEOUT_FAILURE, wps_metrics.numWpsTimeoutFailure); assertEquals(NUM_WPS_OTHER_CONNECTION_FAILURE, wps_metrics.numWpsOtherConnectionFailure); assertEquals(NUM_WPS_SUPPLICANT_FAILURE, wps_metrics.numWpsSupplicantFailure); assertEquals(NUM_WPS_CANCELLATION, wps_metrics.numWpsCancellation); assertEquals(NUM_WATCHDOG_SUCCESS_DURATION_MS, mDecodedProto.watchdogTriggerToConnectionSuccessDurationMs); assertEquals(IS_MAC_RANDOMIZATION_ON, mDecodedProto.isMacRandomizationOn); } /** * Assert deserialized metrics Scan Return Entry equals count */ public void assertScanReturnEntryEquals(int returnCode, int count) { for (int i = 0; i < mDecodedProto.scanReturnEntries.length; i++) { if (mDecodedProto.scanReturnEntries[i].scanReturnCode == returnCode) { assertEquals(mDecodedProto.scanReturnEntries[i].scanResultsCount, count); return; } } assertEquals(null, count); } /** * Assert deserialized metrics SystemState entry equals count */ public void assertSystemStateEntryEquals(int state, boolean screenOn, int count) { for (int i = 0; i < mDecodedProto.wifiSystemStateEntries.length; i++) { if (mDecodedProto.wifiSystemStateEntries[i].wifiState == state && mDecodedProto.wifiSystemStateEntries[i].isScreenOn == screenOn) { assertEquals(mDecodedProto.wifiSystemStateEntries[i].wifiStateCount, count); return; } } assertEquals(null, count); } /** * Combination of all other WifiMetrics unit tests, an internal-integration test, or functional * test */ @Test public void setMetricsSerializeDeserializeAssertMetricsSame() throws Exception { setAndIncrementMetrics(); startAndEndConnectionEventSucceeds(); dumpProtoAndDeserialize(); assertDeserializedMetricsCorrect(); assertEquals("mDecodedProto.connectionEvent.length", 2, mDecodedProto.connectionEvent.length); // test individual connectionEvents for correctness, // check scanReturnEntries & wifiSystemStateEntries counts and individual elements // pending their implementation } /** * Test that score breach events are properly generated */ @Test public void testScoreBeachEvents() throws Exception { int upper = WifiMetrics.LOW_WIFI_SCORE + 7; int mid = WifiMetrics.LOW_WIFI_SCORE; int lower = WifiMetrics.LOW_WIFI_SCORE - 8; mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); for (int score = upper; score >= mid; score--) mWifiMetrics.incrementWifiScoreCount(score); mWifiMetrics.incrementWifiScoreCount(mid + 1); mWifiMetrics.incrementWifiScoreCount(lower); // First breach for (int score = lower; score <= mid; score++) mWifiMetrics.incrementWifiScoreCount(score); mWifiMetrics.incrementWifiScoreCount(mid - 1); mWifiMetrics.incrementWifiScoreCount(upper); // Second breach dumpProtoAndDeserialize(); assertEquals(2, mDecodedProto.staEventList.length); assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[0].type); assertEquals(lower, mDecodedProto.staEventList[0].lastScore); assertEquals(StaEvent.TYPE_SCORE_BREACH, mDecodedProto.staEventList[1].type); assertEquals(upper, mDecodedProto.staEventList[1].lastScore); } private static final String SSID = "red"; private static final int CONFIG_DTIM = 3; private static final int NETWORK_DETAIL_WIFIMODE = 5; private static final int NETWORK_DETAIL_DTIM = 7; private static final int SCAN_RESULT_LEVEL = -30; /** * Test that WifiMetrics is correctly getting data from ScanDetail and WifiConfiguration */ @Test public void testScanDetailAndWifiConfigurationUsage() throws Exception { //Setup mock configs and scan details NetworkDetail networkDetail = mock(NetworkDetail.class); when(networkDetail.getWifiMode()).thenReturn(NETWORK_DETAIL_WIFIMODE); when(networkDetail.getSSID()).thenReturn(SSID); when(networkDetail.getDtimInterval()).thenReturn(NETWORK_DETAIL_DTIM); ScanResult scanResult = mock(ScanResult.class); scanResult.level = SCAN_RESULT_LEVEL; WifiConfiguration config = mock(WifiConfiguration.class); config.SSID = "\"" + SSID + "\""; config.dtimInterval = CONFIG_DTIM; WifiConfiguration.NetworkSelectionStatus networkSelectionStat = mock(WifiConfiguration.NetworkSelectionStatus.class); when(networkSelectionStat.getCandidate()).thenReturn(scanResult); when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat); ScanDetail scanDetail = mock(ScanDetail.class); when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); when(scanDetail.getScanResult()).thenReturn(scanResult); //Create a connection event using only the config mWifiMetrics.startConnectionEvent(config, "Red", WifiMetricsProto.ConnectionEvent.ROAM_NONE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); //Create a connection event using the config and a scan detail mWifiMetrics.startConnectionEvent(config, "Green", WifiMetricsProto.ConnectionEvent.ROAM_NONE); mWifiMetrics.setConnectionScanDetail(scanDetail); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); //Dump proto from mWifiMetrics and deserialize it to mDecodedProto dumpProtoAndDeserialize(); //Check that the correct values are being flowed through assertEquals(mDecodedProto.connectionEvent.length, 2); assertEquals(mDecodedProto.connectionEvent[0].routerFingerprint.dtim, CONFIG_DTIM); assertEquals(mDecodedProto.connectionEvent[0].signalStrength, SCAN_RESULT_LEVEL); assertEquals(mDecodedProto.connectionEvent[1].routerFingerprint.dtim, NETWORK_DETAIL_DTIM); assertEquals(mDecodedProto.connectionEvent[1].signalStrength, SCAN_RESULT_LEVEL); assertEquals(mDecodedProto.connectionEvent[1].routerFingerprint.routerTechnology, NETWORK_DETAIL_WIFIMODE); } /** * Test that WifiMetrics is serializing/deserializing association time out events. */ @Test public void testMetricsAssociationTimedOut() throws Exception { mWifiMetrics.startConnectionEvent(null, "RED", WifiMetricsProto.ConnectionEvent.ROAM_NONE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT, WifiMetricsProto.ConnectionEvent.HLF_NONE); //Dump proto and deserialize //This should clear all the metrics in mWifiMetrics, dumpProtoAndDeserialize(); //Check there is only 1 connection events assertEquals(mDecodedProto.connectionEvent.length, 1); assertEquals(mDecodedProto.connectionEvent[0].level2FailureCode, WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT); } /** * Test that WifiMetrics is being cleared after dumping via proto */ @Test public void testMetricsClearedAfterProtoRequested() throws Exception { // Create 3 ConnectionEvents mWifiMetrics.startConnectionEvent(null, "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); mWifiMetrics.startConnectionEvent(null, "YELLOW", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); mWifiMetrics.startConnectionEvent(null, "GREEN", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); mWifiMetrics.startConnectionEvent(null, "ORANGE", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); //Dump proto and deserialize //This should clear all the metrics in mWifiMetrics, dumpProtoAndDeserialize(); //Check there are only 3 connection events assertEquals(mDecodedProto.connectionEvent.length, 4); assertEquals(mDecodedProto.rssiPollRssiCount.length, 0); assertEquals(mDecodedProto.alertReasonCount.length, 0); // Create 2 ConnectionEvents mWifiMetrics.startConnectionEvent(null, "BLUE", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); mWifiMetrics.startConnectionEvent(null, "RED", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); //Dump proto and deserialize dumpProtoAndDeserialize(); //Check there are only 2 connection events assertEquals(mDecodedProto.connectionEvent.length, 2); } /** * Tests that after setting metrics values they can be serialized and deserialized with the * $ adb shell dumpsys wifi wifiMetricsProto clean */ @Test public void testClearMetricsDump() throws Exception { setAndIncrementMetrics(); startAndEndConnectionEventSucceeds(); cleanDumpProtoAndDeserialize(); assertDeserializedMetricsCorrect(); assertEquals("mDecodedProto.connectionEvent.length", 2, mDecodedProto.connectionEvent.length); } private static final int NUM_REPEATED_DELTAS = 7; private static final int REPEATED_DELTA = 0; private static final int SINGLE_GOOD_DELTA = 1; private static final int SINGLE_TIMEOUT_DELTA = 2; private static final int NUM_REPEATED_BOUND_DELTAS = 2; private static final int MAX_DELTA_LEVEL = 127; private static final int MIN_DELTA_LEVEL = -127; private static final int ARBITRARY_DELTA_LEVEL = 20; /** * Sunny day RSSI delta logging scenario. * Logs one rssi delta value multiple times * Logs a different delta value a single time */ @Test public void testRssiDeltasSuccessfulLogging() throws Exception { // Generate some repeated deltas for (int i = 0; i < NUM_REPEATED_DELTAS; i++) { generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); } // Generate a single delta generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_GOOD_DELTA, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); dumpProtoAndDeserialize(); assertEquals(2, mDecodedProto.rssiPollDeltaCount.length); // Check the repeated deltas assertEquals(NUM_REPEATED_DELTAS, mDecodedProto.rssiPollDeltaCount[0].count); assertEquals(REPEATED_DELTA, mDecodedProto.rssiPollDeltaCount[0].rssi); // Check the single delta assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count); assertEquals(SINGLE_GOOD_DELTA, mDecodedProto.rssiPollDeltaCount[1].rssi); } /** * Tests that Rssi Delta events whose scanResult and Rssi Poll come too far apart, timeout, * and are not logged. */ @Test public void testRssiDeltasTimeout() throws Exception { // Create timed out rssi deltas generateRssiDelta(MIN_RSSI_LEVEL, REPEATED_DELTA, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1); generateRssiDelta(MIN_RSSI_LEVEL, SINGLE_TIMEOUT_DELTA, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS + 1); dumpProtoAndDeserialize(); assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); } /** * Tests the exact inclusive boundaries of RSSI delta logging. */ @Test public void testRssiDeltaSuccessfulLoggingExactBounds() throws Exception { generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); dumpProtoAndDeserialize(); assertEquals(2, mDecodedProto.rssiPollDeltaCount.length); assertEquals(MIN_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi); assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count); assertEquals(MAX_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[1].rssi); assertEquals(1, mDecodedProto.rssiPollDeltaCount[1].count); } /** * Tests the exact exclusive boundaries of RSSI delta logging. * This test ensures that too much data is not generated. */ @Test public void testRssiDeltaOutOfBounds() throws Exception { generateRssiDelta(MIN_RSSI_LEVEL, MAX_DELTA_LEVEL + 1, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); generateRssiDelta(MAX_RSSI_LEVEL, MIN_DELTA_LEVEL - 1, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS); dumpProtoAndDeserialize(); assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); } /** * This test ensures no rssi Delta is logged after an unsuccessful ConnectionEvent */ @Test public void testUnsuccesfulConnectionEventRssiDeltaIsNotLogged() throws Exception { generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, false, // successfulConnectionEvent true, // completeConnectionEvent true, // useValidScanResult true // dontDeserializeBeforePoll ); dumpProtoAndDeserialize(); assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); } /** * This test ensures rssi Deltas can be logged during a ConnectionEvent */ @Test public void testIncompleteConnectionEventRssiDeltaIsLogged() throws Exception { generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, true, // successfulConnectionEvent false, // completeConnectionEvent true, // useValidScanResult true // dontDeserializeBeforePoll ); dumpProtoAndDeserialize(); assertEquals(1, mDecodedProto.rssiPollDeltaCount.length); assertEquals(ARBITRARY_DELTA_LEVEL, mDecodedProto.rssiPollDeltaCount[0].rssi); assertEquals(1, mDecodedProto.rssiPollDeltaCount[0].count); } /** * This test ensures that no delta is logged for a null ScanResult Candidate */ @Test public void testRssiDeltaNotLoggedForNullCandidateScanResult() throws Exception { generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, true, // successfulConnectionEvent true, // completeConnectionEvent false, // useValidScanResult true // dontDeserializeBeforePoll ); dumpProtoAndDeserialize(); assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); } /** * This test ensures that Rssi Deltas are not logged over a 'clear()' call (Metrics Serialized) */ @Test public void testMetricsSerializedDuringRssiDeltaEventLogsNothing() throws Exception { generateRssiDelta(MIN_RSSI_LEVEL, ARBITRARY_DELTA_LEVEL, WifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS, true, // successfulConnectionEvent true, // completeConnectionEvent true, // useValidScanResult false // dontDeserializeBeforePoll ); dumpProtoAndDeserialize(); assertEquals(0, mDecodedProto.rssiPollDeltaCount.length); } private static final int DEAUTH_REASON = 7; private static final int ASSOC_STATUS = 11; private static final int ASSOC_TIMEOUT = 1; private static final int LOCAL_GEN = 1; private static final int AUTH_FAILURE_REASON = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD; private static final int NUM_TEST_STA_EVENTS = 16; private static final String sSSID = "\"SomeTestSsid\""; private static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); private static final String sBSSID = "01:02:03:04:05:06"; private final StateChangeResult mStateDisconnected = new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED); private final StateChangeResult mStateCompleted = new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED); // Test bitmasks of supplicant state changes private final int mSupBm1 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state); private final int mSupBm2 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state) | WifiMetrics.supplicantStateToBit(mStateCompleted.state); // An invalid but interesting wifiConfiguration that exercises the StaEvent.ConfigInfo encoding private final WifiConfiguration mTestWifiConfig = createComplexWifiConfig(); // private int[][] mTestStaMessageInts = { {WifiMonitor.ASSOCIATION_REJECTION_EVENT, ASSOC_TIMEOUT, ASSOC_STATUS}, {WifiMonitor.AUTHENTICATION_FAILURE_EVENT, AUTH_FAILURE_REASON, -1}, {WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0}, {WifiMonitor.NETWORK_DISCONNECTION_EVENT, LOCAL_GEN, DEAUTH_REASON}, {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}, {WifiStateMachine.CMD_ASSOCIATED_BSSID, 0, 0}, {WifiStateMachine.CMD_TARGET_BSSID, 0, 0}, {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}, {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0} }; private Object[] mTestStaMessageObjs = { null, null, null, null, mStateDisconnected, null, null, mStateDisconnected, mStateCompleted }; // Values used to generate the StaEvent log calls from WifiStateMachine // , , <1|0>(testWifiConfiguration, null) private int[][] mTestStaLogInts = { {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, 0, 0}, {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, 0, 0}, {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, 0, 0}, {StaEvent.TYPE_CMD_START_CONNECT, 0, 1}, {StaEvent.TYPE_CMD_START_ROAM, 0, 1}, {StaEvent.TYPE_CONNECT_NETWORK, 0, 1}, {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, 0, 0}, {StaEvent.TYPE_FRAMEWORK_DISCONNECT, StaEvent.DISCONNECT_API, 0}, {StaEvent.TYPE_SCORE_BREACH, 0, 0}, {StaEvent.TYPE_MAC_CHANGE, 0, 1} }; // Values used to generate the StaEvent log calls from WifiMonitor // , , , , // , <1|0>(has ConfigInfo) private int[][] mExpectedValues = { {StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT, -1, ASSOC_STATUS, 0, /**/ 0, ASSOC_TIMEOUT, 0, 0}, /**/ {StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT, -1, -1, 0, /**/StaEvent.AUTH_FAILURE_WRONG_PSWD, 0, 0, 0}, /**/ {StaEvent.TYPE_NETWORK_CONNECTION_EVENT, -1, -1, 0, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT, DEAUTH_REASON, -1, LOCAL_GEN, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_CMD_ASSOCIATED_BSSID, -1, -1, 0, /**/ 0, 0, mSupBm1, 0}, /**/ {StaEvent.TYPE_CMD_TARGET_BSSID, -1, -1, 0, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, -1, -1, 0, /**/ 0, 0, mSupBm2, 0}, /**/ {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, -1, -1, 0, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, -1, -1, 0, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_CMD_START_CONNECT, -1, -1, 0, /**/ 0, 0, 0, 1}, /**/ {StaEvent.TYPE_CMD_START_ROAM, -1, -1, 0, /**/ 0, 0, 0, 1}, /**/ {StaEvent.TYPE_CONNECT_NETWORK, -1, -1, 0, /**/ 0, 0, 0, 1}, /**/ {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, -1, -1, 0, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_FRAMEWORK_DISCONNECT, -1, -1, 0, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_SCORE_BREACH, -1, -1, 0, /**/ 0, 0, 0, 0}, /**/ {StaEvent.TYPE_MAC_CHANGE, -1, -1, 0, /**/ 0, 0, 0, 1} /**/ }; /** * Generates events from all the rows in mTestStaMessageInts, and then mTestStaLogInts */ private void generateStaEvents(WifiMetrics wifiMetrics) { Handler handler = wifiMetrics.getHandler(); for (int i = 0; i < mTestStaMessageInts.length; i++) { int[] mia = mTestStaMessageInts[i]; handler.sendMessage( handler.obtainMessage(mia[0], mia[1], mia[2], mTestStaMessageObjs[i])); } mTestLooper.dispatchAll(); for (int i = 0; i < mTestStaLogInts.length; i++) { int[] lia = mTestStaLogInts[i]; wifiMetrics.logStaEvent(lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null); } } private void verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog) { assertNotNull(mTestWifiConfig); assertEquals(NUM_TEST_STA_EVENTS, wifiLog.staEventList.length); int j = 0; // De-serialized event index for (int i = 0; i < mTestStaMessageInts.length; i++) { StaEvent event = wifiLog.staEventList[j]; int[] mia = mTestStaMessageInts[i]; int[] evs = mExpectedValues[j]; if (mia[0] != WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT) { assertEquals(evs[0], event.type); assertEquals(evs[1], event.reason); assertEquals(evs[2], event.status); assertEquals(evs[3] == 1 ? true : false, event.localGen); assertEquals(evs[4], event.authFailureReason); assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut); assertEquals(evs[6], event.supplicantStateChangesBitmask); assertConfigInfoEqualsWifiConfig( evs[7] == 1 ? mTestWifiConfig : null, event.configInfo); j++; } } for (int i = 0; i < mTestStaLogInts.length; i++) { StaEvent event = wifiLog.staEventList[j]; int[] evs = mExpectedValues[j]; assertEquals(evs[0], event.type); assertEquals(evs[1], event.reason); assertEquals(evs[2], event.status); assertEquals(evs[3] == 1 ? true : false, event.localGen); assertEquals(evs[4], event.authFailureReason); assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut); assertEquals(evs[6], event.supplicantStateChangesBitmask); assertConfigInfoEqualsWifiConfig( evs[7] == 1 ? mTestWifiConfig : null, event.configInfo); j++; } assertEquals(mExpectedValues.length, j); } /** * Generate StaEvents of each type, ensure all the different values are logged correctly, * and that they survive serialization & de-serialization */ @Test public void testStaEventsLogSerializeDeserialize() throws Exception { generateStaEvents(mWifiMetrics); dumpProtoAndDeserialize(); verifyDeserializedStaEvents(mDecodedProto); } /** * Ensure the number of StaEvents does not exceed MAX_STA_EVENTS by generating lots of events * and checking how many are deserialized */ @Test public void testStaEventBounding() throws Exception { for (int i = 0; i < (WifiMetrics.MAX_STA_EVENTS + 10); i++) { mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT); } dumpProtoAndDeserialize(); assertEquals(WifiMetrics.MAX_STA_EVENTS, mDecodedProto.staEventList.length); } /** * Ensure WifiMetrics doesn't cause a null pointer exception when called with null args */ @Test public void testDumpNullArg() { mWifiMetrics.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null); } /** * Test the generation of 'NumConnectableNetwork' histograms from two scans of different * ScanDetails produces the correct histogram values, and relevant bounds are observed */ @Test public void testNumConnectableNetworksGeneration() throws Exception { List scan = new ArrayList(); // ssid, bssid, isOpen, isSaved, isProvider, isWeakRssi) scan.add(buildMockScanDetail("PASSPOINT_1", "bssid0", false, false, true, false)); scan.add(buildMockScanDetail("PASSPOINT_2", "bssid1", false, false, true, false)); scan.add(buildMockScanDetail("SSID_B", "bssid2", true, true, false, false)); scan.add(buildMockScanDetail("SSID_B", "bssid3", true, true, false, false)); scan.add(buildMockScanDetail("SSID_C", "bssid4", true, false, false, false)); scan.add(buildMockScanDetail("SSID_D", "bssid5", false, true, false, false)); scan.add(buildMockScanDetail("SSID_E", "bssid6", false, true, false, false)); scan.add(buildMockScanDetail("SSID_F", "bssid7", false, false, false, false)); scan.add(buildMockScanDetail("SSID_G_WEAK", "bssid9", false, false, false, true)); scan.add(buildMockScanDetail("SSID_H_WEAK", "bssid10", false, false, false, true)); mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); scan.add(buildMockScanDetail("SSID_B", "bssid8", true, true, false, false)); mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); for (int i = 0; i < NUM_PARTIAL_SCAN_RESULTS; i++) { mWifiMetrics.incrementAvailableNetworksHistograms(scan, false); } dumpProtoAndDeserialize(); verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1, a(7), a(2)); verifyHist(mDecodedProto.totalBssidsInScanHistogram, 2, a(8, 9), a(1, 1)); verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1, a(2), a(2)); verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 2, a(3, 4), a(1, 1)); verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1, a(3), a(2)); verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 2, a(4, 5), a(1, 1)); verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1, a(4), a(2)); verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 2, a(5, 6), a(1, 1)); verifyHist(mDecodedProto.availableSavedPasspointProviderProfilesInScanHistogram, 1, a(2), a(2)); verifyHist(mDecodedProto.availableSavedPasspointProviderBssidsInScanHistogram, 1, a(2), a(2)); assertEquals(2, mDecodedProto.fullBandAllSingleScanListenerResults); assertEquals(NUM_PARTIAL_SCAN_RESULTS, mDecodedProto.partialAllSingleScanListenerResults); // Check Bounds scan.clear(); int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET, WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET) + 5; for (int i = 0; i < lotsOfSSids; i++) { scan.add(buildMockScanDetail("SSID_" + i, "bssid_" + i, true, true, false, false)); } mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); dumpProtoAndDeserialize(); verifyHist(mDecodedProto.totalSsidsInScanHistogram, 1, a(WifiMetrics.MAX_TOTAL_SCAN_RESULT_SSIDS_BUCKET), a(1)); verifyHist(mDecodedProto.availableOpenSsidsInScanHistogram, 1, a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1)); verifyHist(mDecodedProto.availableSavedSsidsInScanHistogram, 1, a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1)); verifyHist(mDecodedProto.availableOpenOrSavedSsidsInScanHistogram, 1, a(WifiMetrics.MAX_CONNECTABLE_SSID_NETWORK_BUCKET), a(1)); scan.clear(); int lotsOfBssids = Math.max(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET, WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET) + 5; for (int i = 0; i < lotsOfBssids; i++) { scan.add(buildMockScanDetail("SSID", "bssid_" + i, true, true, false, false)); } mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); dumpProtoAndDeserialize(); verifyHist(mDecodedProto.totalBssidsInScanHistogram, 1, a(WifiMetrics.MAX_TOTAL_SCAN_RESULTS_BUCKET), a(1)); verifyHist(mDecodedProto.availableOpenBssidsInScanHistogram, 1, a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1)); verifyHist(mDecodedProto.availableSavedBssidsInScanHistogram, 1, a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1)); verifyHist(mDecodedProto.availableOpenOrSavedBssidsInScanHistogram, 1, a(WifiMetrics.MAX_CONNECTABLE_BSSID_NETWORK_BUCKET), a(1)); } /** * Test that Hotspot 2.0 (Passpoint) scan results are collected correctly and that relevant * bounds are observed. */ @Test public void testObservedHotspotAps() throws Exception { List scan = new ArrayList(); // 2 R1 (Unknown AP isn't counted) passpoint APs belonging to a single provider: hessid1 long hessid1 = 10; int anqpDomainId1 = 5; scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX", "00:02:03:04:05:06", hessid1, anqpDomainId1, NetworkDetail.HSRelease.R1, true)); scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY", "01:02:03:04:05:06", hessid1, anqpDomainId1, NetworkDetail.HSRelease.R1, true)); scan.add(buildMockScanDetailPasspoint("PASSPOINT_XYZ", "02:02:03:04:05:06", hessid1, anqpDomainId1, NetworkDetail.HSRelease.Unknown, true)); // 2 R2 passpoint APs belonging to a single provider: hessid2 long hessid2 = 12; int anqpDomainId2 = 6; scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid2, anqpDomainId2, NetworkDetail.HSRelease.R2, true)); scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid2, anqpDomainId2, NetworkDetail.HSRelease.R2, true)); mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); scan = new ArrayList(); // 3 R2 passpoint APs belonging to a single provider: hessid3 (in next scan) long hessid3 = 15; int anqpDomainId3 = 8; scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3, anqpDomainId3, NetworkDetail.HSRelease.R2, true)); scan.add(buildMockScanDetailPasspoint("PASSPOINT_Y", "AA:02:03:04:05:06", hessid3, anqpDomainId3, NetworkDetail.HSRelease.R2, false)); scan.add(buildMockScanDetailPasspoint("PASSPOINT_Z", "AB:02:03:04:05:06", hessid3, anqpDomainId3, NetworkDetail.HSRelease.R2, true)); mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); dumpProtoAndDeserialize(); verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 2, a(0, 2), a(1, 1)); verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 2, a(2, 3), a(1, 1)); verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 2, a(0, 1), a(1, 1)); verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1, a(1), a(2)); verifyHist(mDecodedProto.observedHotspotR1ApsPerEssInScanHistogram, 1, a(2), a(1)); verifyHist(mDecodedProto.observedHotspotR2ApsPerEssInScanHistogram, 2, a(2, 3), a(1, 1)); // check bounds scan.clear(); int lotsOfSSids = Math.max(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET, WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET) + 5; for (int i = 0; i < lotsOfSSids; i++) { scan.add(buildMockScanDetailPasspoint("PASSPOINT_XX" + i, "00:02:03:04:05:06", i, i + 10, NetworkDetail.HSRelease.R1, true)); scan.add(buildMockScanDetailPasspoint("PASSPOINT_XY" + i, "AA:02:03:04:05:06", 1000 * i, i + 10, NetworkDetail.HSRelease.R2, false)); } mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); dumpProtoAndDeserialize(); verifyHist(mDecodedProto.observedHotspotR1ApsInScanHistogram, 1, a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1)); verifyHist(mDecodedProto.observedHotspotR2ApsInScanHistogram, 1, a(WifiMetrics.MAX_TOTAL_PASSPOINT_APS_BUCKET), a(1)); verifyHist(mDecodedProto.observedHotspotR1EssInScanHistogram, 1, a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1)); verifyHist(mDecodedProto.observedHotspotR2EssInScanHistogram, 1, a(WifiMetrics.MAX_TOTAL_PASSPOINT_UNIQUE_ESS_BUCKET), a(1)); } /** * Test that IEEE 802.11mc scan results are collected correctly and that relevant * bounds are observed. */ @Test public void testObserved80211mcAps() throws Exception { ScanDetail mockScanDetailNon80211mc = mock(ScanDetail.class); ScanDetail mockScanDetail80211mc = mock(ScanDetail.class); NetworkDetail mockNetworkDetailNon80211mc = mock(NetworkDetail.class); NetworkDetail mockNetworkDetail80211mc = mock(NetworkDetail.class); when(mockNetworkDetail80211mc.is80211McResponderSupport()).thenReturn(true); ScanResult mockScanResult = mock(ScanResult.class); mockScanResult.capabilities = ""; when(mockScanDetailNon80211mc.getNetworkDetail()).thenReturn(mockNetworkDetailNon80211mc); when(mockScanDetail80211mc.getNetworkDetail()).thenReturn(mockNetworkDetail80211mc); when(mockScanDetailNon80211mc.getScanResult()).thenReturn(mockScanResult); when(mockScanDetail80211mc.getScanResult()).thenReturn(mockScanResult); when(mWns.isSignalTooWeak(eq(mockScanDetail80211mc.getScanResult()))).thenReturn(true); List scan = new ArrayList(); // 4 scans (a few non-802.11mc supporting APs on each) // scan1: no 802.11mc supporting APs scan.add(mockScanDetailNon80211mc); scan.add(mockScanDetailNon80211mc); mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); // scan2: 2 802.11mc supporting APs scan.clear(); scan.add(mockScanDetailNon80211mc); scan.add(mockScanDetail80211mc); scan.add(mockScanDetail80211mc); mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); // scan3: 100 802.11mc supporting APs (> limit) scan.clear(); scan.add(mockScanDetailNon80211mc); scan.add(mockScanDetailNon80211mc); scan.add(mockScanDetailNon80211mc); for (int i = 0; i < 100; ++i) { scan.add(mockScanDetail80211mc); } mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); // scan4: 2 802.11mc supporting APs scan.clear(); scan.add(mockScanDetailNon80211mc); scan.add(mockScanDetail80211mc); scan.add(mockScanDetail80211mc); scan.add(mockScanDetailNon80211mc); mWifiMetrics.incrementAvailableNetworksHistograms(scan, true); dumpProtoAndDeserialize(); verifyHist(mDecodedProto.observed80211McSupportingApsInScanHistogram, 3, a(0, 2, WifiMetrics.MAX_TOTAL_80211MC_APS_BUCKET), a(1, 2, 1)); } /** * Test Open Network Notification blacklist size and feature state are not cleared when proto * is dumped. */ @Test public void testOpenNetworkNotificationBlacklistSizeAndFeatureStateNotCleared() throws Exception { mWifiMetrics.setNetworkRecommenderBlacklistSize(OPEN_NET_NOTIFIER_TAG, SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST); mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(OPEN_NET_NOTIFIER_TAG, IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON); for (int i = 0; i < NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES; i++) { mWifiMetrics.incrementNumNetworkRecommendationUpdates(OPEN_NET_NOTIFIER_TAG); } // This should clear most metrics in mWifiMetrics dumpProtoAndDeserialize(); assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST, mDecodedProto.openNetworkRecommenderBlacklistSize); assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, mDecodedProto.isWifiNetworksAvailableNotificationOn); assertEquals(NUM_OPEN_NETWORK_RECOMMENDATION_UPDATES, mDecodedProto.numOpenNetworkRecommendationUpdates); // Check that blacklist size and feature state persist on next dump but // others do not. dumpProtoAndDeserialize(); assertEquals(SIZE_OPEN_NETWORK_RECOMMENDER_BLACKLIST, mDecodedProto.openNetworkRecommenderBlacklistSize); assertEquals(IS_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, mDecodedProto.isWifiNetworksAvailableNotificationOn); assertEquals(0, mDecodedProto.numOpenNetworkRecommendationUpdates); } /** * Check ScoringParams */ @Test public void testExperimentId() throws Exception { final int id = 42; final String expectId = "x" + id; when(mScoringParams.getExperimentIdentifier()).thenReturn(id); dumpProtoAndDeserialize(); assertEquals(expectId, mDecodedProto.scoreExperimentId); } /** * Check ScoringParams default case */ @Test public void testDefaultExperimentId() throws Exception { final int id = 0; final String expectId = ""; when(mScoringParams.getExperimentIdentifier()).thenReturn(id); dumpProtoAndDeserialize(); assertEquals(expectId, mDecodedProto.scoreExperimentId); } /** short hand for instantiating an anonymous int array, instead of 'new int[]{a1, a2, ...}' */ private int[] a(int... element) { return element; } private void verifyHist(WifiMetricsProto.NumConnectableNetworksBucket[] hist, int size, int[] keys, int[] counts) throws Exception { assertEquals(size, hist.length); for (int i = 0; i < keys.length; i++) { assertEquals(keys[i], hist[i].numConnectableNetworks); assertEquals(counts[i], hist[i].count); } } /** * Generate an RSSI delta event by creating a connection event and an RSSI poll within * 'interArrivalTime' milliseconds of each other. * Event will not be logged if interArrivalTime > mWifiMetrics.TIMEOUT_RSSI_DELTA_MILLIS * successfulConnectionEvent, completeConnectionEvent, useValidScanResult and * dontDeserializeBeforePoll * each create an anomalous condition when set to false. */ private void generateRssiDelta(int scanRssi, int rssiDelta, long interArrivalTime, boolean successfulConnectionEvent, boolean completeConnectionEvent, boolean useValidScanResult, boolean dontDeserializeBeforePoll) throws Exception { when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0); ScanResult scanResult = null; if (useValidScanResult) { scanResult = mock(ScanResult.class); scanResult.level = scanRssi; } WifiConfiguration config = mock(WifiConfiguration.class); WifiConfiguration.NetworkSelectionStatus networkSelectionStat = mock(WifiConfiguration.NetworkSelectionStatus.class); when(networkSelectionStat.getCandidate()).thenReturn(scanResult); when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStat); mWifiMetrics.startConnectionEvent(config, "TestNetwork", WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); if (completeConnectionEvent) { if (successfulConnectionEvent) { mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE); } else { mWifiMetrics.endConnectionEvent( WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, WifiMetricsProto.ConnectionEvent.HLF_NONE); } } when(mClock.getElapsedSinceBootMillis()).thenReturn(interArrivalTime); if (!dontDeserializeBeforePoll) { dumpProtoAndDeserialize(); } mWifiMetrics.incrementRssiPollRssiCount(RSSI_POLL_FREQUENCY, scanRssi + rssiDelta); } /** * Generate an RSSI delta event, with all extra conditions set to true. */ private void generateRssiDelta(int scanRssi, int rssiDelta, long interArrivalTime) throws Exception { generateRssiDelta(scanRssi, rssiDelta, interArrivalTime, true, true, true, true); } private void assertStringContains( String actualString, String expectedSubstring) { assertTrue("Expected text not found in: " + actualString, actualString.contains(expectedSubstring)); } private String getStateDump() { ByteArrayOutputStream stream = new ByteArrayOutputStream(); PrintWriter writer = new PrintWriter(stream); String[] args = new String[0]; mWifiMetrics.dump(null, writer, args); writer.flush(); return stream.toString(); } private static final int TEST_ALLOWED_KEY_MANAGEMENT = 83; private static final int TEST_ALLOWED_PROTOCOLS = 22; private static final int TEST_ALLOWED_AUTH_ALGORITHMS = 11; private static final int TEST_ALLOWED_PAIRWISE_CIPHERS = 67; private static final int TEST_ALLOWED_GROUP_CIPHERS = 231; private static final int TEST_CANDIDATE_LEVEL = -80; private static final int TEST_CANDIDATE_FREQ = 2345; private WifiConfiguration createComplexWifiConfig() { WifiConfiguration config = new WifiConfiguration(); config.allowedKeyManagement = intToBitSet(TEST_ALLOWED_KEY_MANAGEMENT); config.allowedProtocols = intToBitSet(TEST_ALLOWED_PROTOCOLS); config.allowedAuthAlgorithms = intToBitSet(TEST_ALLOWED_AUTH_ALGORITHMS); config.allowedPairwiseCiphers = intToBitSet(TEST_ALLOWED_PAIRWISE_CIPHERS); config.allowedGroupCiphers = intToBitSet(TEST_ALLOWED_GROUP_CIPHERS); config.hiddenSSID = true; config.ephemeral = true; config.getNetworkSelectionStatus().setHasEverConnected(true); ScanResult candidate = new ScanResult(); candidate.level = TEST_CANDIDATE_LEVEL; candidate.frequency = TEST_CANDIDATE_FREQ; config.getNetworkSelectionStatus().setCandidate(candidate); return config; } private void assertConfigInfoEqualsWifiConfig(WifiConfiguration config, StaEvent.ConfigInfo info) { if (config == null && info == null) return; assertEquals(config.allowedKeyManagement, intToBitSet(info.allowedKeyManagement)); assertEquals(config.allowedProtocols, intToBitSet(info.allowedProtocols)); assertEquals(config.allowedAuthAlgorithms, intToBitSet(info.allowedAuthAlgorithms)); assertEquals(config.allowedPairwiseCiphers, intToBitSet(info.allowedPairwiseCiphers)); assertEquals(config.allowedGroupCiphers, intToBitSet(info.allowedGroupCiphers)); assertEquals(config.hiddenSSID, info.hiddenSsid); assertEquals(config.ephemeral, info.isEphemeral); assertEquals(config.getNetworkSelectionStatus().getHasEverConnected(), info.hasEverConnected); assertEquals(config.getNetworkSelectionStatus().getCandidate().level, info.scanRssi); assertEquals(config.getNetworkSelectionStatus().getCandidate().frequency, info.scanFreq); } /** * Sets the values of bitSet to match an int mask */ private static BitSet intToBitSet(int mask) { BitSet bitSet = new BitSet(); for (int bitIndex = 0; mask > 0; mask >>>= 1, bitIndex++) { if ((mask & 1) != 0) bitSet.set(bitIndex); } return bitSet; } }