| /* |
| * 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.assertTrue; |
| import static org.mockito.Mockito.*; |
| |
| 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.test.suitebuilder.annotation.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.StaEvent; |
| |
| 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 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)); |
| mWifiMetrics.setWifiConfigManager(mWcm); |
| mWifiMetrics.setPasspointManager(mPpm); |
| 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 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_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_WIFI_ON_FAILURE_DUE_TO_HAL = 13; |
| private static final int NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND = 14; |
| 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 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<PasspointProvider, PasspointMatch> providerMatch = Pair.create(provider, null); |
| when(mockNetworkDetail.isInterworking()).thenReturn(true); |
| when(mPpm.matchProvider(eq(scanResult))).thenReturn(providerMatch); |
| } |
| return mockScanDetail; |
| } |
| |
| private List<ScanDetail> buildMockScanDetailList() { |
| List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>(); |
| 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<WifiConfiguration> buildSavedNetworkList() { |
| List<WifiConfiguration> testSavedNetworks = new ArrayList<WifiConfiguration>(); |
| 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 < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { |
| for (int j = 0; j <= i; j++) { |
| mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL + i); |
| } |
| } |
| for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { |
| mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL - i); |
| } |
| for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) { |
| mWifiMetrics.incrementRssiPollRssiCount(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<ScanDetail> mockScanDetails = buildMockScanDetailList(); |
| for (int i = 0; i < NUM_SCANS; i++) { |
| mWifiMetrics.countScanResults(mockScanDetails); |
| } |
| 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_WIFI_ON_FAILURE_DUE_TO_HAL; i++) { |
| mWifiMetrics.incrementNumWifiOnFailureDueToHal(); |
| } |
| for (int i = 0; i < NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND; i++) { |
| mWifiMetrics.incrementNumWifiOnFailureDueToWificond(); |
| } |
| 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(); |
| } |
| } |
| |
| /** |
| * 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(TEST_RECORD_DURATION_SEC, |
| mDecodedProto.recordDurationSec); |
| for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) { |
| 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); |
| 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_WIFI_ON_FAILURE_DUE_TO_HAL, mDecodedProto.numWifiOnFailureDueToHal); |
| assertEquals(NUM_WIFI_ON_FAILURE_DUE_TO_WIFICOND, |
| mDecodedProto.numWifiOnFailureDueToWificond); |
| 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); |
| } |
| |
| /** |
| * 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); |
| //<TODO> test individual connectionEvents for correctness, |
| // check scanReturnEntries & wifiSystemStateEntries counts and individual elements |
| // pending their implementation</TODO> |
| } |
| |
| 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 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 = 14; |
| 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(); |
| // <msg.what> <msg.arg1> <msg.arg2> |
| private int[][] mTestStaMessageInts = { |
| {WifiMonitor.ASSOCIATION_REJECTION_EVENT, ASSOC_TIMEOUT, ASSOC_STATUS}, |
| {WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, AUTH_FAILURE_REASON}, |
| {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 |
| // <StaEvent.Type>, <StaEvent.FrameworkDisconnectReason>, <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} |
| }; |
| // Values used to generate the StaEvent log calls from WifiMonitor |
| // <type>, <reason>, <status>, <local_gen>, |
| // <auth_fail_reason>, <assoc_timed_out> <supplicantStateChangeBitmask> <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} /**/ |
| }; |
| |
| /** |
| * 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) { |
| 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++; |
| } |
| } |
| } |
| |
| /** |
| * 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<ScanDetail> scan = new ArrayList<ScanDetail>(); |
| // 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)); |
| } |
| |
| /** 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(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; |
| } |
| } |