blob: 33e61a44fe31a89da867543e2074735e74cd98c6 [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 com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
import static org.mockito.Mockito.*;
import android.net.wifi.WifiConfiguration;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.LocalLog;
import android.util.Pair;
import com.android.server.wifi.WifiNetworkSelector.NetworkNominator.OnConnectableListener;
import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs;
import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper;
import com.android.server.wifi.util.WifiPermissionsUtil;
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 java.util.Arrays;
import java.util.List;
/**
* Unit tests for {@link SavedNetworkNominator}.
*/
@SmallTest
public class SavedNetworkNominatorTest extends WifiBaseTest {
/** Sets up test. */
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mLocalLog = new LocalLog(512);
mSavedNetworkNominator = new SavedNetworkNominator(mWifiConfigManager,
mPasspointNetworkNominateHelper, mLocalLog, mWifiCarrierInfoManager,
mWifiPermissionsUtil, mWifiNetworkSuggestionsManager);
when(mWifiCarrierInfoManager.isSimPresent(anyInt())).thenReturn(true);
when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any())).thenReturn(VALID_SUBID);
when(mWifiCarrierInfoManager.requiresImsiEncryption(VALID_SUBID)).thenReturn(true);
when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true);
when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(VALID_SUBID);
when(mWifiNetworkSuggestionsManager
.shouldBeIgnoredBySecureSuggestionFromSameCarrier(any(), any()))
.thenReturn(false);
}
/** Cleans up test. */
@After
public void cleanup() {
validateMockitoUsage();
}
private ArgumentCaptor<WifiConfiguration> mWifiConfigurationArgumentCaptor =
ArgumentCaptor.forClass(WifiConfiguration.class);
private static final int VALID_SUBID = 10;
private static final int INVALID_SUBID = 1;
private static final int TEST_CARRIER_ID = 100;
private static final int RSSI_LEVEL = -50;
private static final int TEST_UID = 1001;
private SavedNetworkNominator mSavedNetworkNominator;
@Mock private WifiConfigManager mWifiConfigManager;
@Mock private Clock mClock;
@Mock private OnConnectableListener mOnConnectableListener;
@Mock private WifiCarrierInfoManager mWifiCarrierInfoManager;
@Mock private PasspointNetworkNominateHelper mPasspointNetworkNominateHelper;
@Mock private WifiPermissionsUtil mWifiPermissionsUtil;
@Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
private LocalLog mLocalLog;
/**
* Do not evaluate networks that {@link WifiConfiguration#useExternalScores}.
*/
@Test
public void ignoreNetworksIfUseExternalScores() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2470, 2437};
String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"};
int[] levels = {RSSI_LEVEL, RSSI_LEVEL};
int[] securities = {SECURITY_PSK, SECURITY_PSK};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
for (WifiConfiguration wifiConfiguration : savedConfigs) {
wifiConfiguration.useExternalScores = true;
}
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener, never()).onConnectable(any(), any());
}
/**
* Do not evaluate networks which require SIM card when the SIM card is absent.
*/
@Test
public void ignoreNetworkIfSimIsAbsentForEapSimNetwork() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {2470};
int[] levels = {RSSI_LEVEL};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigForEapSimNetwork(ssids, bssids,
freqs, levels, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
savedConfigs[0].carrierId = TEST_CARRIER_ID;
// SIM is absent
when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(INVALID_SUBID);
when(mWifiCarrierInfoManager.isSimPresent(eq(INVALID_SUBID))).thenReturn(false);
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener, never()).onConnectable(any(), any());
}
/**
* Do not evaluate networks that {@link WifiConfiguration#isEphemeral}.
*/
@Test
public void ignoreEphemeralNetworks() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2470, 2437};
String[] caps = {"[ESS]", "[ESS]"};
int[] levels = {RSSI_LEVEL, RSSI_LEVEL};
int[] securities = {SECURITY_NONE, SECURITY_NONE};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
for (WifiConfiguration wifiConfiguration : savedConfigs) {
wifiConfiguration.ephemeral = true;
}
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener, never()).onConnectable(any(), any());
}
/**
* Pick a worse candidate that allows auto-join over a better candidate that
* disallows auto-join.
*/
@Test
public void ignoreNetworksIfAutojoinNotAllowed() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2470, 2437};
String[] caps = {"[ESS]", "[ESS]"};
int[] levels = {RSSI_LEVEL, RSSI_LEVEL};
int[] securities = {SECURITY_NONE, SECURITY_NONE};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener, times(2)).onConnectable(any(), any());
reset(mOnConnectableListener);
savedConfigs[1].allowAutojoin = false;
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener).onConnectable(any(),
mWifiConfigurationArgumentCaptor.capture());
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0],
mWifiConfigurationArgumentCaptor.getValue());
}
/**
* Do not return a candidate if all networks do not {@link WifiConfiguration#allowAutojoin}
*/
@Test
public void returnNoCandidateIfNoNetworksAllowAutojoin() {
String[] ssids = {"\"test1\"", "\"test2\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
int[] freqs = {2470, 2437};
String[] caps = {"[ESS]", "[ESS]"};
int[] levels = {RSSI_LEVEL, RSSI_LEVEL};
int[] securities = {SECURITY_NONE, SECURITY_NONE};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
for (WifiConfiguration wifiConfiguration : savedConfigs) {
wifiConfiguration.allowAutojoin = false;
}
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener, never()).onConnectable(any(), any());
}
/**
* Ensure that we do nominate the only matching saved passponit network with auto-join enabled .
*/
@Test
public void returnCandidatesIfPasspointNetworksAvailableWithAutojoinEnabled() {
ScanDetail scanDetail1 = mock(ScanDetail.class);
ScanDetail scanDetail2 = mock(ScanDetail.class);
List<ScanDetail> scanDetails = Arrays.asList(scanDetail1, scanDetail2);
WifiConfiguration configuration1 = mock(WifiConfiguration.class);
configuration1.allowAutojoin = true;
WifiConfiguration configuration2 = mock(WifiConfiguration.class);
configuration2.allowAutojoin = false;
List<Pair<ScanDetail, WifiConfiguration>> passpointCandidates =
Arrays.asList(Pair.create(scanDetail1, configuration1), Pair.create(scanDetail2,
configuration2));
when(mPasspointNetworkNominateHelper.getPasspointNetworkCandidates(scanDetails, false))
.thenReturn(passpointCandidates);
mSavedNetworkNominator.nominateNetworks(scanDetails, null, null,
false, false, mOnConnectableListener);
verify(mOnConnectableListener).onConnectable(scanDetail1, configuration1);
verify(mOnConnectableListener, never()).onConnectable(scanDetail2, configuration2);
}
/**
* Verify if a network is metered and with non-data sim, will not nominate as a candidate.
*/
@Test
public void testIgnoreNetworksIfMeteredAndFromNonDataSim() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {2470};
int[] levels = {RSSI_LEVEL};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigForEapSimNetwork(ssids, bssids,
freqs, levels, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
savedConfigs[0].carrierId = TEST_CARRIER_ID;
when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0]))
.thenReturn(false);
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener).onConnectable(any(), any());
reset(mOnConnectableListener);
when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0]))
.thenReturn(true);
verify(mOnConnectableListener, never()).onConnectable(any(), any());
}
/**
* Verify a saved network is from app not user, if IMSI privacy protection is not required, will
* send notification for user to approve exemption, and not consider as a candidate.
*/
@Test
public void testIgnoreNetworksFromAppIfNoImsiProtection() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {2470};
int[] levels = {RSSI_LEVEL};
when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(any()))
.thenReturn(false);
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigForEapSimNetwork(ssids, bssids,
freqs, levels, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
savedConfigs[0].carrierId = TEST_CARRIER_ID;
// Doesn't require Imsi protection and user didn't approved
when(mWifiCarrierInfoManager.requiresImsiEncryption(VALID_SUBID)).thenReturn(false);
when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
.thenReturn(false);
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener, never()).onConnectable(any(), any());
verify(mWifiCarrierInfoManager)
.sendImsiProtectionExemptionNotificationIfRequired(TEST_CARRIER_ID);
// Simulate user approved
when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
.thenReturn(true);
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener).onConnectable(any(), any());
// If from settings app, will bypass the IMSI check.
when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
.thenReturn(false);
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
}
@Test
public void testIgnoreOpenNetworkWithSameNetworkSuggestionHasSecureNetworkFromSameCarrier() {
String[] ssids = {"\"test1\""};
String[] bssids = {"6c:f3:7f:ae:8c:f3"};
int[] freqs = {2470};
String[] caps = {"[ESS]"};
int[] levels = {RSSI_LEVEL};
int[] securities = {SECURITY_NONE};
ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
freqs, caps, levels, securities, mWifiConfigManager, mClock);
List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
when(mWifiNetworkSuggestionsManager
.shouldBeIgnoredBySecureSuggestionFromSameCarrier(any(), any()))
.thenReturn(true);
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener, never()).onConnectable(any(), any());
when(mWifiNetworkSuggestionsManager
.shouldBeIgnoredBySecureSuggestionFromSameCarrier(any(), any()))
.thenReturn(false);
mSavedNetworkNominator.nominateNetworks(scanDetails,
null, null, true, false, mOnConnectableListener);
verify(mOnConnectableListener).onConnectable(any(), any());
}
}