blob: bd7256a769d7f82dc22d1a542fa43826002ce0fc [file] [log] [blame]
/*
* 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 android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
import static com.android.server.wifi.WifiNetworkSelector.experimentIdFromIdentifier;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import android.annotation.NonNull;
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiInfo;
import android.os.SystemClock;
import android.util.LocalLog;
import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs;
import com.android.server.wifi.nano.WifiMetricsProto;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/**
* Unit tests for {@link com.android.server.wifi.WifiNetworkSelector}.
*/
@SmallTest
public class WifiNetworkSelectorTest {
private static final int RSSI_BUMP = 1;
private static final int DUMMY_EVALUATOR_ID_1 = -2; // lowest index
private static final int DUMMY_EVALUATOR_ID_2 = -1;
private static final HashSet<String> EMPTY_BLACKLIST = new HashSet<>();
/** Sets up test. */
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
setupContext();
setupResources();
setupWifiConfigManager();
setupWifiInfo();
mScoringParams = new ScoringParams();
setupThresholds();
mLocalLog = new LocalLog(512);
mWifiNetworkSelector = new WifiNetworkSelector(mContext,
mWifiScoreCard,
mScoringParams,
mWifiConfigManager, mClock,
mLocalLog,
mWifiMetrics,
mWifiNative);
mWifiNetworkSelector.registerNetworkEvaluator(mDummyEvaluator);
mDummyEvaluator.setEvaluatorToSelectCandidate(true);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime());
when(mCarrierNetworkConfig.isCarrierNetwork(any())).thenReturn(true);
when(mWifiScoreCard.lookupBssid(any(), any())).thenReturn(mPerBssid);
mCompatibilityScorer = new CompatibilityScorer(mScoringParams);
mScoreCardBasedScorer = new ScoreCardBasedScorer(mScoringParams);
when(mWifiNative.getClientInterfaceName()).thenReturn("wlan0");
}
/** Cleans up test. */
@After
public void cleanup() {
validateMockitoUsage();
}
/**
* All this dummy network evaluator does is to pick the specified network in the scan results.
*/
public class DummyNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator {
private static final String NAME = "DummyNetworkEvaluator";
private boolean mEvaluatorShouldSelectCandidate = true;
private int mNetworkIndexToReturn;
private int mEvaluatorIdToReturn;
public DummyNetworkEvaluator(int networkIndexToReturn, int evaluatorIdToReturn) {
mNetworkIndexToReturn = networkIndexToReturn;
mEvaluatorIdToReturn = evaluatorIdToReturn;
}
public DummyNetworkEvaluator() {
this(0, DUMMY_EVALUATOR_ID_1);
}
public int getNetworkIndexToReturn() {
return mNetworkIndexToReturn;
}
public void setNetworkIndexToReturn(int networkIndexToReturn) {
mNetworkIndexToReturn = networkIndexToReturn;
}
@Override
public @EvaluatorId int getId() {
return mEvaluatorIdToReturn;
}
@Override
public String getName() {
return NAME;
}
@Override
public void update(List<ScanDetail> scanDetails) {}
/**
* Sets whether the evaluator should return a candidate for connection or null.
*/
public void setEvaluatorToSelectCandidate(boolean shouldSelectCandidate) {
mEvaluatorShouldSelectCandidate = shouldSelectCandidate;
}
/**
* This NetworkEvaluator can be configured to return a candidate or null. If returning a
* candidate, the first entry in the provided scanDetails will be selected. This requires
* that the mock WifiConfigManager be set up to return a WifiConfiguration for the first
* scanDetail entry, through
* {@link WifiNetworkSelectorTestUtil#setupScanDetailsAndConfigStore}.
*/
@Override
public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
WifiConfiguration currentNetwork, String currentBssid, boolean connected,
boolean untrustedNetworkAllowed,
@NonNull OnConnectableListener onConnectableListener) {
if (!mEvaluatorShouldSelectCandidate) {
return null;
}
for (ScanDetail scanDetail : scanDetails) {
WifiConfiguration config =
mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(scanDetail);
mWifiConfigManager.setNetworkCandidateScanResult(
config.networkId, scanDetail.getScanResult(), 100);
}
ScanDetail scanDetailToReturn = scanDetails.get(mNetworkIndexToReturn);
WifiConfiguration configToReturn =
mWifiConfigManager.getConfiguredNetworkForScanDetailAndCache(
scanDetailToReturn);
assertNotNull("Saved network must not be null", configToReturn);
onConnectableListener.onConnectable(scanDetailToReturn, configToReturn, 100);
return configToReturn;
}
}
private WifiNetworkSelector mWifiNetworkSelector = null;
private DummyNetworkEvaluator mDummyEvaluator = new DummyNetworkEvaluator();
@Mock private WifiConfigManager mWifiConfigManager;
@Mock private Context mContext;
@Mock private CarrierNetworkConfig mCarrierNetworkConfig;
@Mock private WifiScoreCard mWifiScoreCard;
@Mock private WifiScoreCard.PerBssid mPerBssid;
@Mock private WifiCandidates.CandidateScorer mCandidateScorer;
@Mock private WifiMetrics mWifiMetrics;
@Mock private WifiNative mWifiNative;
// For simulating the resources, we use a Spy on a MockResource
// (which is really more of a stub than a mock, in spite if its name).
// This is so that we get errors on any calls that we have not explicitly set up.
@Spy private MockResources mResource = new MockResources();
@Mock private WifiInfo mWifiInfo;
@Mock private Clock mClock;
private ScoringParams mScoringParams;
private LocalLog mLocalLog;
private int mThresholdMinimumRssi2G;
private int mThresholdMinimumRssi5G;
private int mThresholdQualifiedRssi2G;
private int mThresholdQualifiedRssi5G;
private int mStayOnNetworkMinimumTxRate;
private int mStayOnNetworkMinimumRxRate;
private CompatibilityScorer mCompatibilityScorer;
private ScoreCardBasedScorer mScoreCardBasedScorer;
private void setupContext() {
when(mContext.getResources()).thenReturn(mResource);
}
private int setupIntegerResource(int resourceName, int value) {
doReturn(value).when(mResource).getInteger(resourceName);
return value;
}
private void setupResources() {
doReturn(true).when(mResource).getBoolean(
R.bool.config_wifi_framework_enable_associated_network_selection);
mStayOnNetworkMinimumTxRate = setupIntegerResource(
R.integer.config_wifi_framework_min_tx_rate_for_staying_on_network, 16);
mStayOnNetworkMinimumRxRate = setupIntegerResource(
R.integer.config_wifi_framework_min_rx_rate_for_staying_on_network, 16);
}
private void setupThresholds() {
mThresholdMinimumRssi2G = mScoringParams.getEntryRssi(ScoringParams.BAND2);
mThresholdMinimumRssi5G = mScoringParams.getEntryRssi(ScoringParams.BAND5);
mThresholdQualifiedRssi2G = mScoringParams.getSufficientRssi(ScoringParams.BAND2);
mThresholdQualifiedRssi5G = mScoringParams.getSufficientRssi(ScoringParams.BAND5);
}
private void setupWifiInfo() {
// simulate a disconnected state
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.DISCONNECTED);
when(mWifiInfo.is24GHz()).thenReturn(true);
when(mWifiInfo.is5GHz()).thenReturn(false);
when(mWifiInfo.getFrequency()).thenReturn(2400);
when(mWifiInfo.getRssi()).thenReturn(-70);
when(mWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mWifiInfo.getBSSID()).thenReturn(null);
}
private void setupWifiConfigManager() {
setupWifiConfigManager(WifiConfiguration.INVALID_NETWORK_ID);
}
private void setupWifiConfigManager(int networkId) {
when(mWifiConfigManager.getLastSelectedNetwork())
.thenReturn(networkId);
}
/**
* No network selection if scan result is empty.
*
* ClientModeImpl is in disconnected state.
* scanDetails is empty.
*
* Expected behavior: no network recommended by Network Selector
*/
@Test
public void emptyScanResults() {
String[] ssids = new String[0];
String[] bssids = new String[0];
int[] freqs = new int[0];
String[] caps = new String[0];
int[] levels = new int[0];
int[] securities = new int[0];
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
assertEquals("Expect null configuration", null, candidate);
assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
}
/**
* No network selection if the RSSI values in scan result are too low.
*
* ClientModeImpl is in disconnected state.
* scanDetails contains a 2.4GHz and a 5GHz network, but both with RSSI lower than
* the threshold
*
* Expected behavior: no network recommended by Network Selector
*/
@Test
public void verifyMinimumRssiThreshold() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-EAP-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G - 1, mThresholdMinimumRssi5G - 1};
int[] securities = {SECURITY_PSK, SECURITY_EAP};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
assertEquals("Expect null configuration", null, candidate);
assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
}
/**
* No network selection if WiFi is connected and it is too short from last
* network selection.
*
* ClientModeImpl is in connected state.
* scanDetails contains two valid networks.
* Perform a network seletion right after the first one.
*
* Expected behavior: no network recommended by Network Selector
*/
@Test
public void verifyMinimumTimeGapWhenConnected() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-EAP-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
int[] securities = {SECURITY_PSK, SECURITY_EAP};
// Make a network selection.
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000);
// Do another network selection with CMI in CONNECTED state.
candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, true, false, false);
assertEquals("Expect null configuration", null, candidate);
assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
}
/**
* Perform network selection if WiFi is disconnected even if it is too short from last
* network selection.
*
* ClientModeImpl is in disconnected state.
* scanDetails contains two valid networks.
* Perform a network selection right after the first one.
*
* Expected behavior: the first network is recommended by Network Selector
*/
@Test
public void verifyNoMinimumTimeGapWhenDisconnected() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
int[] securities = {SECURITY_EAP, SECURITY_EAP};
// Make a network selection.
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS - 2000);
// Do another network selection with CMI in DISCONNECTED state.
candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
chosenScanResult, candidate);
}
/**
* New network selection is performed if the currently connected network
* is a open one.
*
* ClientModeImpl is connected to a open network.
* scanDetails contains a valid networks.
* Perform a network seletion after the first one.
*
* Expected behavior: the first network is recommended by Network Selector
*/
@Test
public void openNetworkIsNotSufficient() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {5180};
String[] caps = {"[ESS]"};
int[] levels = {mThresholdQualifiedRssi5G + 8};
int[] securities = {SECURITY_NONE};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
// connect to test1
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
when(mWifiInfo.getNetworkId()).thenReturn(0);
when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
when(mWifiInfo.is24GHz()).thenReturn(false);
when(mWifiInfo.is5GHz()).thenReturn(true);
when(mWifiInfo.getFrequency()).thenReturn(5000);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
// Do another network selection.
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, true, false, false);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
chosenScanResult, candidate);
}
/**
* New network selection is performed if the currently connected network
* has low RSSI value.
*
* ClientModeImpl is connected to a low RSSI 5GHz network.
* scanDetails contains a valid networks.
* Perform a network seletion after the first one.
*
* Expected behavior: the first network is recommended by Network Selector
*/
@Test
public void lowRssi5GNetworkIsNotSufficient() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {5180};
String[] caps = {"[WPA2-PSK][ESS]"};
int[] levels = {mThresholdQualifiedRssi5G - 2};
int[] securities = {SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
// connect to test1
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
when(mWifiInfo.getNetworkId()).thenReturn(0);
when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
when(mWifiInfo.is24GHz()).thenReturn(false);
when(mWifiInfo.is5GHz()).thenReturn(true);
when(mWifiInfo.getFrequency()).thenReturn(5000);
when(mWifiInfo.getRssi()).thenReturn(levels[0]);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
// Do another network selection.
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, true, false, false);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
chosenScanResult, candidate);
}
/**
* New network selection is performed if the currently connected network
* has no internet access and the user did not explicitly choose to stay connected.
*
* ClientModeImpl is connected to a network with no internet connectivity.
* scanDetails contains a valid networks.
* Perform a network selection after the first one.
*
* Expected behavior: the first network is recommended by Network Selector
*/
@Test
public void noInternetAccessNetworkIsNotSufficient() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {5180};
String[] caps = {"[WPA2-PSK][ESS]"};
int[] levels = {mThresholdQualifiedRssi5G + 5};
int[] securities = {SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
// connect to test1
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
when(mWifiInfo.getNetworkId()).thenReturn(0);
when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
when(mWifiInfo.is24GHz()).thenReturn(false);
when(mWifiInfo.is5GHz()).thenReturn(true);
when(mWifiInfo.getFrequency()).thenReturn(5000);
when(mWifiInfo.getRssi()).thenReturn(levels[0]);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
// Increment the network's no internet access reports.
savedConfigs[0].numNoInternetAccessReports = 5;
// Do another network selection.
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, true, false, false);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
chosenScanResult, candidate);
}
/**
* Ensure that network selector update's network selection status for all configured
* networks before performing network selection.
*
* Expected behavior: the first network is recommended by Network Selector
*/
@Test
public void updateConfiguredNetworks() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 2457};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + 20, mThresholdMinimumRssi2G + RSSI_BUMP};
int[] securities = {SECURITY_EAP, SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
// Do network selection.
mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, true, false, false);
verify(mWifiConfigManager).getConfiguredNetworks();
verify(mWifiConfigManager, times(savedConfigs.length)).tryEnableNetwork(anyInt());
verify(mWifiConfigManager, times(savedConfigs.length))
.clearNetworkCandidateScanResult(anyInt());
}
/**
* Blacklisted BSSID is filtered out for network selection.
*
* ClientModeImpl is disconnected.
* scanDetails contains a network which is blacklisted.
*
* Expected behavior: no network recommended by Network Selector
*/
@Test
public void filterOutBlacklistedBssid() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {5180};
String[] caps = {"[WPA2-PSK][ESS]"};
int[] levels = {mThresholdQualifiedRssi5G + 8};
int[] securities = {SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
blacklist.add(bssids[0]);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
assertEquals("Expect null configuration", null, candidate);
assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
}
/**
* Wifi network selector doesn't recommend any network if the currently connected one
* doesn't show up in the scan results.
*
* ClientModeImpl is under connected state and 2.4GHz test1 is connected.
* The second scan results contains only test2 which now has a stronger RSSI than test1.
* Test1 is not in the second scan results.
*
* Expected behavior: no network recommended by Network Selector
*/
@Test
public void noSelectionWhenCurrentNetworkNotInScanResults() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 2457};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + 20, mThresholdMinimumRssi2G + RSSI_BUMP};
int[] securities = {SECURITY_EAP, SECURITY_PSK};
// Make a network selection to connect to test1.
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
when(mWifiInfo.getNetworkId()).thenReturn(0);
when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
when(mWifiInfo.is24GHz()).thenReturn(true);
when(mWifiInfo.is5GHz()).thenReturn(false);
when(mWifiInfo.getFrequency()).thenReturn(2400);
when(mWifiInfo.getRssi()).thenReturn(levels[0]);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
// Prepare the second scan results which have no test1.
String[] ssidsNew = {"\"test2\""};
String[] bssidsNew = {"6c:f3:7f:ae:8c:f4"};
int[] freqsNew = {2457};
String[] capsNew = {"[WPA2-EAP-CCMP][ESS]"};
int[] levelsNew = {mThresholdMinimumRssi2G + 40};
scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(ssidsNew, bssidsNew,
freqsNew, capsNew, levelsNew, mClock);
candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo,
true, false, false);
// The second network selection is skipped since current connected network is
// missing from the scan results.
assertEquals("Expect null configuration", null, candidate);
assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
}
/**
* Ensures that setting the user connect choice updates the
* NetworkSelectionStatus#mConnectChoice for all other WifiConfigurations in range in the last
* round of network selection.
*
* Expected behavior: WifiConfiguration.NetworkSelectionStatus#mConnectChoice is set to
* test1's configkey for test2. test3's WifiConfiguration is unchanged.
*/
@Test
public void setUserConnectChoice() {
String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
int[] freqs = {2437, 5180, 5181};
String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP,
mThresholdMinimumRssi5G + RSSI_BUMP};
int[] securities = {SECURITY_PSK, SECURITY_EAP, SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
WifiConfiguration selectedWifiConfig = scanDetailsAndConfigs.getWifiConfigs()[0];
selectedWifiConfig.getNetworkSelectionStatus()
.setCandidate(scanDetailsAndConfigs.getScanDetails().get(0).getScanResult());
selectedWifiConfig.getNetworkSelectionStatus().setNetworkSelectionStatus(
NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
selectedWifiConfig.getNetworkSelectionStatus().setConnectChoice("bogusKey");
WifiConfiguration configInLastNetworkSelection = scanDetailsAndConfigs.getWifiConfigs()[1];
configInLastNetworkSelection.getNetworkSelectionStatus()
.setSeenInLastQualifiedNetworkSelection(true);
WifiConfiguration configNotInLastNetworkSelection =
scanDetailsAndConfigs.getWifiConfigs()[2];
assertTrue(mWifiNetworkSelector.setUserConnectChoice(selectedWifiConfig.networkId));
verify(mWifiConfigManager).updateNetworkSelectionStatus(selectedWifiConfig.networkId,
NetworkSelectionStatus.NETWORK_SELECTION_ENABLE);
verify(mWifiConfigManager).clearNetworkConnectChoice(selectedWifiConfig.networkId);
verify(mWifiConfigManager).setNetworkConnectChoice(configInLastNetworkSelection.networkId,
selectedWifiConfig.configKey(), mClock.getWallClockMillis());
verify(mWifiConfigManager, never()).setNetworkConnectChoice(
configNotInLastNetworkSelection.networkId, selectedWifiConfig.configKey(),
mClock.getWallClockMillis());
}
/**
* If two qualified networks, test1 and test2, are in range when the user selects test2 over
* test1, WifiNetworkSelector will override the NetworkSelector's choice to connect to test1
* with test2.
*
* Expected behavior: test2 is the recommended network
*/
@Test
public void userConnectChoiceOverridesNetworkEvaluators() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
int[] securities = {SECURITY_PSK, SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
// DummyEvaluator always selects the first network in the list.
WifiConfiguration networkSelectorChoice = scanDetailsAndConfigs.getWifiConfigs()[0];
networkSelectorChoice.getNetworkSelectionStatus()
.setSeenInLastQualifiedNetworkSelection(true);
WifiConfiguration userChoice = scanDetailsAndConfigs.getWifiConfigs()[1];
userChoice.getNetworkSelectionStatus()
.setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult());
// With no user choice set, networkSelectorChoice should be chosen.
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class);
verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId),
nominatorIdCaptor.capture());
// unknown because DummyEvaluator does not have a nominator ID
// getValue() returns the argument from the *last* call
assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN,
nominatorIdCaptor.getValue().intValue());
WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
assertTrue(mWifiNetworkSelector.setUserConnectChoice(userChoice.networkId));
// After user connect choice is set, userChoice should override networkSelectorChoice.
candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId),
nominatorIdCaptor.capture());
// getValue() returns the argument from the *last* call
assertEquals(WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE,
nominatorIdCaptor.getValue().intValue());
WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate);
}
/**
* Tests when multiple evaluators nominate the same candidate, any one of the nominator IDs is
* acceptable.
*/
@Test
public void testMultipleEvaluatorsSetsNominatorIdCorrectly() {
// first dummy evaluator is registered in setup, returns index 0
// register a second network evaluator that also returns index 0, but with a different ID
mWifiNetworkSelector.registerNetworkEvaluator(new DummyNetworkEvaluator(0,
WifiNetworkSelector.NetworkEvaluator.EVALUATOR_ID_SCORED));
// register a third network evaluator that also returns index 0, but with a different ID
mWifiNetworkSelector.registerNetworkEvaluator(new DummyNetworkEvaluator(0,
WifiNetworkSelector.NetworkEvaluator.EVALUATOR_ID_SAVED));
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
int[] securities = {SECURITY_PSK, SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<>();
// DummyEvaluator always selects the first network in the list.
WifiConfiguration networkSelectorChoice = scanDetailsAndConfigs.getWifiConfigs()[0];
networkSelectorChoice.getNetworkSelectionStatus()
.setSeenInLastQualifiedNetworkSelection(true);
WifiConfiguration userChoice = scanDetailsAndConfigs.getWifiConfigs()[1];
userChoice.getNetworkSelectionStatus()
.setCandidate(scanDetailsAndConfigs.getScanDetails().get(1).getScanResult());
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails,
blacklist, mWifiInfo, false, true, false);
ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class);
verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId),
nominatorIdCaptor.capture());
for (int nominatorId : nominatorIdCaptor.getAllValues()) {
assertThat(nominatorId, is(oneOf(
WifiMetricsProto.ConnectionEvent.NOMINATOR_UNKNOWN,
WifiMetricsProto.ConnectionEvent.NOMINATOR_EXTERNAL_SCORED,
WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED)));
}
verify(mWifiMetrics, atLeastOnce()).setNetworkSelectorExperimentId(anyInt());
}
/**
* Wifi network selector doesn't recommend any network if the currently connected 2.4Ghz
* network is high quality and no 5GHz networks are available
*
* ClientModeImpl is under connected state and 2.4GHz test1 is connected.
*
* Expected behavior: no network selection is performed
*/
@Test
public void test2GhzQualifiedNo5GhzAvailable() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
// No streaming traffic.
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = 0.0;
// Do not perform selection on 2GHz if current network is good and no 5GHz available
testStayOrTryToSwitch(
mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
false /* not a 5G network */,
false /* not open network */,
// Should not try to switch.
false);
}
/**
* Wifi network selector performs network selection even when the 2Ghz network is high
* quality whenever 5Ghz networks are available.
*
* ClientModeImpl is under connected state and 2.4GHz test1 is connected.
* The scan results contain a 5Ghz network, which forces network selection.
* Test1 is not in the second scan results.
*
* Expected behavior: network selection is performed
*/
@Test
public void test2GhzHighQuality5GhzAvailable() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
// No streaming traffic.
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = 0.0;
// When on 2GHz, even with "good" signal strength, run selection if 5GHz available
testStayOrTryToSwitch(
// Parameters for network1:
mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
false /* not a 5G network */,
false /* not open network */,
// Parameters for network2:
mThresholdQualifiedRssi5G + 1 /* rssi */,
true /* a 5G network */,
false /* not open network */,
// Should try to switch.
true);
}
/**
* Wifi network selector performs network selection when connected to a 5Ghz network that
* has an insufficient RSSI.
*
* ClientModeImpl is under connected state and 5GHz test1 is connected.
*
* Expected behavior: network selection is performed
*/
@Test
public void test5GhzNotQualifiedLowRssi() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G - 1);
// No streaming traffic.
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = 0.0;
// Run Selection when the current 5Ghz network has low RSSI.
testStayOrTryToSwitch(
mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
true /* a 5G network */,
false /* not open network */,
// Should try to switch.
true);
}
/**
* Wifi network selector will not run selection when on a 5Ghz network that is of sufficent
* Quality (high-enough RSSI).
*
* ClientModeImpl is under connected state and 5GHz test1 is connected.
*
* Expected behavior: network selection is not performed
*/
@Test
public void test5GhzQualified() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1);
// No streaming traffic.
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = 0.0;
// Connected to a high quality 5Ghz network, so the other result is irrelevant
testStayOrTryToSwitch(
mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
true /* a 5G network */,
false /* not open network */,
// Should not try to switch.
false);
}
/**
* New network selection is performed if the currently connected network
* band is 2G and there is no sign of streaming traffic.
*
* Expected behavior: Network Selector perform network selection after connected
* to the first one.
*/
@Test
public void band2GNetworkIsNotSufficientWhenNoOngoingTrafficAnd5GhzAvailable() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
// No streaming traffic.
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = 0.0;
testStayOrTryToSwitch(
// Parameters for network1:
mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
false /* not a 5G network */,
false /* not open network */,
// Parameters for network2:
mThresholdQualifiedRssi5G + 1 /* rssi */,
true /* a 5G network */,
false /* not open network */,
// Should try to switch.
true);
}
/**
* New network selection is not performed if the currently connected network
* was recently selected.
*/
@Test
public void networkIsSufficientWhenRecentlyUserSelected() {
// Approximate mClock.getElapsedSinceBootMillis value mocked by testStayOrTryToSwitch
long millisSinceBoot = SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000;
when(mWifiConfigManager.getLastSelectedTimeStamp())
.thenReturn(millisSinceBoot
- WifiNetworkSelector.LAST_USER_SELECTION_SUFFICIENT_MS
+ 1000);
setupWifiConfigManager(0); // testStayOrTryToSwitch first connects to network 0
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
// No streaming traffic.
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = 0.0;
testStayOrTryToSwitch(
// Parameters for network1:
mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
false /* not a 5G network */,
false /* not open network */,
// Parameters for network2:
mThresholdQualifiedRssi5G + 1 /* rssi */,
true /* a 5G network */,
false /* not open network */,
// Should not try to switch.
false);
}
/**
* New network selection is performed if the currently connected network
* band is 2G with bad rssi.
*
* Expected behavior: Network Selector perform network selection after connected
* to the first one.
*/
@Test
public void band2GNetworkIsNotSufficientWithBadRssi() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G - 1);
// No streaming traffic.
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = 0.0;
testStayOrTryToSwitch(
mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
false /* not a 5G network */,
false /* not open network */,
// Should try to switch.
true);
}
/**
* New network selection is not performed if the currently connected 2G network
* has good Rssi and sign of streaming tx traffic.
*
* Expected behavior: Network selector does not perform network selection.
*/
@Test
public void band2GNetworkIsSufficientWhenOnGoingTxTrafficCombinedWithGoodRssi() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
// Streaming traffic
mWifiInfo.txSuccessRate = ((double) (mStayOnNetworkMinimumTxRate + 1));
mWifiInfo.rxSuccessRate = 0.0;
testStayOrTryToSwitch(
mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
false /* not a 5G network */,
true /* open network */,
// Should not try to switch.
false);
}
/**
* New network selection is not performed if the currently connected 2G network
* has good Rssi and sign of streaming rx traffic.
*
* Expected behavior: Network selector does not perform network selection.
*/
@Test
public void band2GNetworkIsSufficientWhenOnGoingRxTrafficCombinedWithGoodRssi() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1);
// Streaming traffic
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = ((double) (mStayOnNetworkMinimumRxRate + 1));
testStayOrTryToSwitch(
mThresholdQualifiedRssi2G + 1 /* rssi before connected */,
false /* not a 5G network */,
true /* open network */,
// Should not try to switch.
false);
}
/**
* New network selection is not performed if the currently connected 5G network
* has good Rssi and sign of streaming tx traffic.
*
* Expected behavior: Network selector does not perform network selection.
*/
@Test
public void band5GNetworkIsSufficientWhenOnGoingTxTrafficCombinedWithGoodRssi() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1);
// Streaming traffic
mWifiInfo.txSuccessRate = ((double) (mStayOnNetworkMinimumTxRate + 1));
mWifiInfo.rxSuccessRate = 0.0;
testStayOrTryToSwitch(
mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
true /* a 5G network */,
true /* open network */,
// Should not try to switch.
false);
}
/**
* New network selection is not performed if the currently connected 5G network
* has good Rssi and sign of streaming rx traffic.
*
* Expected behavior: Network selector does not perform network selection.
*/
@Test
public void band5GNetworkIsSufficientWhenOnGoingRxTrafficCombinedWithGoodRssi() {
// Rssi after connected.
when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1);
// Streaming traffic
mWifiInfo.txSuccessRate = 0.0;
mWifiInfo.rxSuccessRate = ((double) (mStayOnNetworkMinimumRxRate + 1));
testStayOrTryToSwitch(
mThresholdQualifiedRssi5G + 1 /* rssi before connected */,
true /* a 5G network */,
true /* open network */,
// Should not try to switch.
false);
}
/**
* This is a meta-test that given two scan results of various types, will
* determine whether or not network selection should be performed.
*
* It sets up two networks, connects to the first, and then ensures that
* both are available in the scan results for the NetworkSelector.
*/
private void testStayOrTryToSwitch(
int rssiNetwork1, boolean is5GHzNetwork1, boolean isOpenNetwork1,
int rssiNetwork2, boolean is5GHzNetwork2, boolean isOpenNetwork2,
boolean shouldSelect) {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {is5GHzNetwork1 ? 5180 : 2437, is5GHzNetwork2 ? 5180 : 2437};
String[] caps = {isOpenNetwork1 ? "[ESS]" : "[WPA2-PSK][ESS]",
isOpenNetwork2 ? "[ESS]" : "[WPA2-PSK][ESS]"};
int[] levels = {rssiNetwork1, rssiNetwork2};
int[] securities = {isOpenNetwork1 ? SECURITY_NONE : SECURITY_PSK,
isOpenNetwork2 ? SECURITY_NONE : SECURITY_PSK};
testStayOrTryToSwitchImpl(ssids, bssids, freqs, caps, levels, securities, shouldSelect);
}
/**
* This is a meta-test that given one scan results, will
* determine whether or not network selection should be performed.
*
* It sets up two networks, connects to the first, and then ensures that
* the scan results for the NetworkSelector.
*/
private void testStayOrTryToSwitch(
int rssi, boolean is5GHz, boolean isOpenNetwork,
boolean shouldSelect) {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {is5GHz ? 5180 : 2437};
String[] caps = {isOpenNetwork ? "[ESS]" : "[WPA2-PSK][ESS]"};
int[] levels = {rssi};
int[] securities = {isOpenNetwork ? SECURITY_NONE : SECURITY_PSK};
testStayOrTryToSwitchImpl(ssids, bssids, freqs, caps, levels, securities, shouldSelect);
}
private void testStayOrTryToSwitchImpl(String[] ssids, String[] bssids, int[] freqs,
String[] caps, int[] levels, int[] securities,
boolean shouldSelect) {
// Make a network selection to connect to test1.
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
HashSet<String> blacklist = new HashSet<String>();
// DummyNetworkEvaluator always return the first network in the scan results
// for connection, so this should connect to the first network.
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(
scanDetails,
blacklist, mWifiInfo, false, true, true);
assertNotNull("Result should be not null", candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanDetails.get(0).getScanResult(), candidate);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
when(mWifiInfo.getNetworkId()).thenReturn(0);
when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
when(mWifiInfo.is24GHz()).thenReturn(!ScanResult.is5GHz(freqs[0]));
when(mWifiInfo.is5GHz()).thenReturn(ScanResult.is5GHz(freqs[0]));
when(mWifiInfo.getFrequency()).thenReturn(freqs[0]);
when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+ WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo,
true, false, false);
// DummyNetworkEvaluator always return the first network in the scan results
// for connection, so if nework selection is performed, the first network should
// be returned as candidate.
if (shouldSelect) {
assertNotNull("Result should be not null", candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
scanDetails.get(0).getScanResult(), candidate);
} else {
assertEquals("Expect null configuration", null, candidate);
}
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out
* networks that are not open after network selection is made.
*
* Expected behavior: return open networks only
*/
@Test
public void getfilterOpenUnsavedNetworks_filtersForOpenNetworks() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
assertEquals("Expect open unsaved networks",
expectedOpenUnsavedNetworks,
mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out
* saved networks after network selection is made. This should return an empty list when there
* are no unsaved networks available.
*
* Expected behavior: return unsaved networks only. Return empty list if there are no unsaved
* networks.
*/
@Test
public void getfilterOpenUnsavedNetworks_filtersOutSavedNetworks() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {2437, 5180};
String[] caps = {"[ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP};
int[] securities = {SECURITY_NONE};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> unSavedScanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(
unSavedScanDetails, blacklist, mWifiInfo, false, true, false);
assertEquals("Expect open unsaved networks",
unSavedScanDetails,
mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> savedScanDetails = scanDetailsAndConfigs.getScanDetails();
mWifiNetworkSelector.selectNetwork(
savedScanDetails, blacklist, mWifiInfo, false, true, false);
// Saved networks are filtered out.
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should filter out
* bssid blacklisted networks.
*
* Expected behavior: do not return blacklisted network
*/
@Test
public void getfilterOpenUnsavedNetworks_filtersOutBlacklistedNetworks() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[ESS]", "[ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
blacklist.add(bssids[0]);
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
assertEquals("Expect open unsaved networks",
expectedOpenUnsavedNetworks,
mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should return
* empty list when there are no open networks after network selection is made.
*
* Expected behavior: return empty list
*/
@Test
public void getfilterOpenUnsavedNetworks_returnsEmptyListWhenNoOpenNetworksPresent() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} should return
* empty list when no network selection has been made.
*
* Expected behavior: return empty list
*/
@Test
public void getfilterOpenUnsavedNetworks_returnsEmptyListWhenNoNetworkSelectionMade() {
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} for device that
* supports enhanced open networks, should filter out networks that are not open and not
* enhanced open after network selection is made.
*
* Expected behavior: return open and enhanced open networks only
*/
@Test
public void getfilterOpenUnsavedNetworks_filtersForOpenAndOweNetworksOweSupported() {
String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
int[] freqs = {2437, 5180, 2414};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]", "[RSN-OWE-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP,
mThresholdMinimumRssi2G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
when(mWifiNative.getSupportedFeatureSet(anyString()))
.thenReturn(new Long(WIFI_FEATURE_OWE));
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
expectedOpenUnsavedNetworks.add(scanDetails.get(2));
assertEquals("Expect open unsaved networks",
expectedOpenUnsavedNetworks,
mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForOpenUnsavedNetworks()} for device that
* does not support enhanced open networks, should filter out both networks that are not open
* and enhanced open after network selection is made.
*
* Expected behavior: return open networks only
*/
@Test
public void getfilterOpenUnsavedNetworks_filtersForOpenAndOweNetworksOweNotSupported() {
String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
int[] freqs = {2437, 5180, 2414};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]", "[RSN-OWE-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP,
mThresholdMinimumRssi2G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
when(mWifiNative.getSupportedFeatureSet(anyString()))
.thenReturn(new Long(~WIFI_FEATURE_OWE));
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
assertEquals("Expect open unsaved networks",
expectedOpenUnsavedNetworks,
mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should filter
* out networks that are not EAP after network selection is made.
*
* Expected behavior: return EAP networks only
*/
@Test
public void getfilterCarrierUnsavedNetworks_filtersForEapNetworks() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
List<ScanDetail> expectedCarrierUnsavedNetworks = new ArrayList<>();
expectedCarrierUnsavedNetworks.add(scanDetails.get(0));
assertEquals("Expect carrier unsaved networks",
expectedCarrierUnsavedNetworks,
mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
mCarrierNetworkConfig));
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should filter
* out saved networks after network selection is made. This should return an empty list when
* there are no unsaved networks available.
*
* Expected behavior: return unsaved networks only. Return empty list if there are no unsaved
* networks.
*/
@Test
public void getfilterCarrierUnsavedNetworks_filtersOutSavedNetworks() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {2437, 5180};
String[] caps = {"[WPA2-EAP-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP};
int[] securities = {SECURITY_EAP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> unSavedScanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(
unSavedScanDetails, blacklist, mWifiInfo, false, true, false);
assertEquals("Expect carrier unsaved networks",
unSavedScanDetails,
mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
mCarrierNetworkConfig));
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> savedScanDetails = scanDetailsAndConfigs.getScanDetails();
mWifiNetworkSelector.selectNetwork(
savedScanDetails, blacklist, mWifiInfo, false, true, false);
// Saved networks are filtered out.
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
mCarrierNetworkConfig).isEmpty());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should filter
* out bssid blacklisted networks.
*
* Expected behavior: do not return blacklisted network
*/
@Test
public void getfilterCarrierUnsavedNetworks_filtersOutBlacklistedNetworks() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[EAP][ESS]", "[EAP]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
blacklist.add(bssids[0]);
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
List<ScanDetail> expectedCarrierUnsavedNetworks = new ArrayList<>();
expectedCarrierUnsavedNetworks.add(scanDetails.get(1));
assertEquals("Expect carrier unsaved networks",
expectedCarrierUnsavedNetworks,
mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
mCarrierNetworkConfig));
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should return
* empty list when there are no EAP encrypted networks after network selection is made.
*
* Expected behavior: return empty list
*/
@Test
public void getfilterCarrierUnsavedNetworks_returnsEmptyListWhenNoEAPNetworksPresent() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[ESS]", "[WPA2-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
mCarrierNetworkConfig).isEmpty());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should return
* empty list when there are no carrier networks after network selection is made.
*
* Expected behavior: return empty list
*/
@Test
public void getfilterCarrierUnsavedNetworks_returnsEmptyListWhenNoCarrierNetworksPresent() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2437, 5180};
String[] caps = {"[EAP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP};
mDummyEvaluator.setEvaluatorToSelectCandidate(false);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
HashSet<String> blacklist = new HashSet<>();
mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, false, true, false);
when(mCarrierNetworkConfig.isCarrierNetwork(any())).thenReturn(false);
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
mCarrierNetworkConfig).isEmpty());
}
/**
* {@link WifiNetworkSelector#getFilteredScanDetailsForCarrierUnsavedNetworks()} should return
* empty list when no network selection has been made.
*
* Expected behavior: return empty list
*/
@Test
public void getfilterCarrierUnsavedNetworks_returnsEmptyListWhenNoNetworkSelectionMade() {
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForCarrierUnsavedNetworks(
mCarrierNetworkConfig).isEmpty());
}
/**
* Test registerCandidateScorer.
*
* Just make sure it does not crash, for now.
*/
@Test
public void testRegisterCandidateScorer() {
mWifiNetworkSelector.registerCandidateScorer(mCompatibilityScorer);
test2GhzHighQuality5GhzAvailable();
}
/**
* Test that registering a new CandidateScorer causes it to be used
*/
@Test
public void testCandidateScorerUse() throws Exception {
String myid = "Mock CandidateScorer";
when(mCandidateScorer.getIdentifier()).thenReturn(myid);
setupWifiConfigManager(13);
int experimentId = experimentIdFromIdentifier(myid);
assertTrue("" + myid, 42000000 <= experimentId && experimentId <= 42999999);
String diagnose = "" + mScoringParams + " // " + experimentId;
assertTrue(diagnose, mScoringParams.update("expid=" + experimentId));
assertEquals(experimentId, mScoringParams.getExperimentIdentifier());
mWifiNetworkSelector.registerCandidateScorer(mCandidateScorer);
WifiConfiguration selected = mWifiNetworkSelector.selectNetwork(
setUpTwoNetworks(-35, -40),
EMPTY_BLACKLIST, mWifiInfo, false, true, true);
verify(mCandidateScorer).scoreCandidates(any());
}
/**
* Tests that no metrics are recorded if there is only a single legacy scorer.
*/
@Test
public void testCandidateScorerMetrics_onlyOneScorer() {
test2GhzHighQuality5GhzAvailable();
verify(mWifiMetrics, never()).logNetworkSelectionDecision(
anyInt(), anyInt(), anyBoolean(), anyInt());
}
/**
* Tests that metrics are recorded for 2 scorers (legacy and another).
*/
@Test
public void testCandidateScorerMetrics_twoScorers() {
mWifiNetworkSelector.registerCandidateScorer(mScoreCardBasedScorer);
// add a second NetworkEvaluator that returns the second network in the scan list
mWifiNetworkSelector.registerNetworkEvaluator(
new DummyNetworkEvaluator(1, DUMMY_EVALUATOR_ID_2));
test2GhzHighQuality5GhzAvailable();
int registeredExpId = experimentIdFromIdentifier(mScoreCardBasedScorer.getIdentifier());
// Wanted 2 times since test2GhzHighQuality5GhzAvailable() calls
// WifiNetworkSelector.selectNetwork() twice
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(registeredExpId,
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, true, 2);
}
/**
* Tests that metrics are recorded for 2 scorers (legacy and legacy compatibility), when
* legacy compatibility experiment is active.
*/
@Test
public void testCandidateScorerMetrics_twoScorers_experimentActive() {
mWifiNetworkSelector.registerCandidateScorer(mCompatibilityScorer);
// add a second NetworkEvaluator that returns the second network in the scan list
mWifiNetworkSelector.registerNetworkEvaluator(
new DummyNetworkEvaluator(1, DUMMY_EVALUATOR_ID_2));
int compatibilityExpId = experimentIdFromIdentifier(mCompatibilityScorer.getIdentifier());
mScoringParams.update("expid=" + compatibilityExpId);
assertEquals(compatibilityExpId, mScoringParams.getExperimentIdentifier());
test2GhzHighQuality5GhzAvailable();
// Wanted 2 times since test2GhzHighQuality5GhzAvailable() calls
// WifiNetworkSelector.selectNetwork() twice
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, compatibilityExpId, true, 2);
}
private static final WifiCandidates.CandidateScorer NULL_SCORER =
new WifiCandidates.CandidateScorer() {
@Override
public String getIdentifier() {
return "NULL_SCORER";
}
@Override
public WifiCandidates.ScoredCandidate scoreCandidates(
Collection<WifiCandidates.Candidate> group) {
return new WifiCandidates.ScoredCandidate(0, 0, null);
}
@Override
public boolean userConnectChoiceOverrideWanted() {
return false;
}
};
/**
* Tests that metrics are recorded for 2 scorers (legacy and null) when one
* candidate scorer returns null.
*/
@Test
public void testCandidateScorerMetrics_twoScorers_oneNull() {
// add null scorer
mWifiNetworkSelector.registerCandidateScorer(NULL_SCORER);
// add a second NetworkEvaluator that returns the second network in the scan list
mWifiNetworkSelector.registerNetworkEvaluator(
new DummyNetworkEvaluator(1, DUMMY_EVALUATOR_ID_2));
test2GhzHighQuality5GhzAvailable();
int nullScorerId = experimentIdFromIdentifier(NULL_SCORER.getIdentifier());
// Wanted 2 times since test2GhzHighQuality5GhzAvailable() calls
// WifiNetworkSelector.selectNetwork() twice
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(nullScorerId,
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, false, 2);
}
/**
* Tests that metrics are recorded for 2 scorers (legacy and null) when the active
* candidate scorer returns NONE.
*/
@Test
public void testCandidateScorerMetrics_twoScorers_nullActive() {
int nullScorerId = experimentIdFromIdentifier(NULL_SCORER.getIdentifier());
mScoringParams.update("expid=" + nullScorerId);
assertEquals(nullScorerId, mScoringParams.getExperimentIdentifier());
// add null scorer
mWifiNetworkSelector.registerCandidateScorer(NULL_SCORER);
// add a second NetworkEvaluator that returns the second network in the scan list
mWifiNetworkSelector.registerNetworkEvaluator(
new DummyNetworkEvaluator(1, DUMMY_EVALUATOR_ID_2));
WifiConfiguration selected = mWifiNetworkSelector.selectNetwork(
setUpTwoNetworks(-35, -40),
EMPTY_BLACKLIST, mWifiInfo, false, true, true);
assertNull(selected);
verify(mWifiMetrics).logNetworkSelectionDecision(
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, nullScorerId, false, 2);
verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(anyInt(), anyInt());
verify(mWifiMetrics, atLeastOnce()).setNetworkSelectorExperimentId(anyInt());
verifyNoMoreInteractions(mWifiMetrics);
}
private List<ScanDetail> setUpTwoNetworks(int rssiNetwork1, int rssiNetwork2) {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {5180, 2437};
String[] caps = {"[ESS]", "[ESS]"};
int[] levels = {rssiNetwork1, rssiNetwork2};
int[] securities = {SECURITY_NONE, SECURITY_NONE};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
return scanDetailsAndConfigs.getScanDetails();
}
/**
* Tests that metrics are recorded for 3 scorers (legacy, compat, and null scorer).
*/
@Test
public void testCandidateScorerMetrics_threeScorers() {
mWifiNetworkSelector.registerCandidateScorer(mCompatibilityScorer);
mWifiNetworkSelector.registerCandidateScorer(NULL_SCORER);
// add a second NetworkEvaluator that returns the second network in the scan list
mWifiNetworkSelector.registerNetworkEvaluator(
new DummyNetworkEvaluator(1, DUMMY_EVALUATOR_ID_2));
int compatibilityExpId = experimentIdFromIdentifier(mCompatibilityScorer.getIdentifier());
mScoringParams.update("expid=" + compatibilityExpId);
assertEquals(compatibilityExpId, mScoringParams.getExperimentIdentifier());
test2GhzHighQuality5GhzAvailable();
int nullScorerId = experimentIdFromIdentifier(NULL_SCORER.getIdentifier());
// Wanted 2 times since test2GhzHighQuality5GhzAvailable() calls
// WifiNetworkSelector.selectNetwork() twice
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(nullScorerId,
compatibilityExpId, false, 2);
verify(mWifiMetrics, times(2)).logNetworkSelectionDecision(
WifiNetworkSelector.LEGACY_CANDIDATE_SCORER_EXP_ID, compatibilityExpId, true, 2);
int expid = CompatibilityScorer.COMPATIBILITY_SCORER_DEFAULT_EXPID;
verify(mWifiMetrics, atLeastOnce()).setNetworkSelectorExperimentId(eq(expid));
}
}