blob: 7312b3334e9212f9532264f3b0adf99e2a47d59a [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.hotspot2;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;
import com.android.server.wifi.NetworkUpdateResult;
import com.android.server.wifi.ScanDetail;
import com.android.server.wifi.WifiConfigManager;
import com.android.server.wifi.util.ScanResultUtil;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Unit tests for {@link com.android.server.wifi.hotspot2.PasspointNetworkEvaluator}.
*/
@SmallTest
public class PasspointNetworkEvaluatorTest {
private static final int TEST_NETWORK_ID = 1;
private static final String TEST_SSID1 = "ssid1";
private static final String TEST_SSID2 = "ssid2";
private static final String TEST_FQDN1 = "test1.com";
private static final String TEST_FQDN2 = "test2.com";
private static final WifiConfiguration TEST_CONFIG1 = generateWifiConfig(TEST_FQDN1);
private static final WifiConfiguration TEST_CONFIG2 = generateWifiConfig(TEST_FQDN2);
private static final PasspointProvider TEST_PROVIDER1 = generateProvider(TEST_CONFIG1);
private static final PasspointProvider TEST_PROVIDER2 = generateProvider(TEST_CONFIG2);
@Mock PasspointManager mPasspointManager;
@Mock WifiConfigManager mWifiConfigManager;
PasspointNetworkEvaluator mEvaluator;
/**
* Helper function for generating {@link WifiConfiguration} for testing.
*
* @param fqdn The FQDN associated with the configuration
* @return {@link WifiConfiguration}
*/
private static WifiConfiguration generateWifiConfig(String fqdn) {
WifiConfiguration config = new WifiConfiguration();
config.FQDN = fqdn;
return config;
}
/**
* Helper function for generating {@link PasspointProvider} for testing.
*
* @param config The WifiConfiguration associated with the provider
* @return {@link PasspointProvider}
*/
private static PasspointProvider generateProvider(WifiConfiguration config) {
PasspointProvider provider = mock(PasspointProvider.class);
when(provider.getWifiConfig()).thenReturn(config);
return provider;
}
/**
* Helper function for generating {@link ScanDetail} for testing.
*
* @param ssid The SSID associated with the scan
* @param rssiLevel The RSSI level associated with the scan
* @return {@link ScanDetail}
*/
private static ScanDetail generateScanDetail(String ssid) {
NetworkDetail networkDetail = mock(NetworkDetail.class);
when(networkDetail.isInterworking()).thenReturn(true);
when(networkDetail.getAnt()).thenReturn(NetworkDetail.Ant.FreePublic);
ScanDetail scanDetail = mock(ScanDetail.class);
when(scanDetail.getSSID()).thenReturn(ssid);
when(scanDetail.getScanResult()).thenReturn(new ScanResult());
when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
return scanDetail;
}
/**
* Test setup.
*/
@Before
public void setUp() throws Exception {
initMocks(this);
mEvaluator = new PasspointNetworkEvaluator(mPasspointManager, mWifiConfigManager, null);
}
/**
* Verify that null will be returned when evaluating scans without any matching providers.
*
* @throws Exception
*/
@Test
public void evaluateScansWithNoMatch() throws Exception {
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {
generateScanDetail(TEST_SSID1), generateScanDetail(TEST_SSID2)});
List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = new ArrayList<>();
when(mPasspointManager.matchProvider(any(ScanDetail.class))).thenReturn(matchedProviders);
assertEquals(null, mEvaluator.evaluateNetworks(
scanDetails, null, null, false, false, connectableNetworks));
assertTrue(connectableNetworks.isEmpty());
}
/**
* Verify that provider matching will not be performed when evaluating scans with no
* interworking support, and null will be returned.
*
* @throws Exception
*/
@Test
public void evaulateScansWithNoInterworkingAP() throws Exception {
NetworkDetail networkDetail = mock(NetworkDetail.class);
when(networkDetail.isInterworking()).thenReturn(false);
ScanDetail scanDetail = mock(ScanDetail.class);
when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {scanDetail});
List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
assertEquals(null, mEvaluator.evaluateNetworks(
scanDetails, null, null, false, false, connectableNetworks));
assertTrue(connectableNetworks.isEmpty());
// Verify that no provider matching is performed.
verify(mPasspointManager, never()).matchProvider(any(ScanDetail.class));
}
/**
* Verify that when both home provider and roaming provider is found for the same network,
* home provider is preferred.
*
* @throws Exception
*/
@Test
public void evaluateScansWithNetworkMatchingHomeAndRoamingProvider() throws Exception {
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {
generateScanDetail(TEST_SSID1), generateScanDetail(TEST_SSID2)});
// Setup matching providers for ScanDetail with TEST_SSID1.
Pair<PasspointProvider, PasspointMatch> homeProvider = Pair.create(
TEST_PROVIDER1, PasspointMatch.HomeProvider);
Pair<PasspointProvider, PasspointMatch> roamingProvider = Pair.create(
TEST_PROVIDER2, PasspointMatch.RoamingProvider);
List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = new ArrayList<>();
matchedProviders.add(homeProvider);
matchedProviders.add(roamingProvider);
List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
// Return matchedProviders for the first ScanDetail (TEST_SSID1) and an empty list for
// for the second (TEST_SSID2);
when(mPasspointManager.matchProvider(any(ScanDetail.class))).thenReturn(matchedProviders)
.thenReturn(new ArrayList<Pair<PasspointProvider, PasspointMatch>>());
when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
.thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1);
assertNotNull(mEvaluator.evaluateNetworks(scanDetails, null, null, false,
false, connectableNetworks));
assertEquals(1, connectableNetworks.size());
// Verify the content of the WifiConfiguration that was added to WifiConfigManager.
ArgumentCaptor<WifiConfiguration> addedConfig =
ArgumentCaptor.forClass(WifiConfiguration.class);
verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt());
assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID1), addedConfig.getValue().SSID);
assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN);
}
/**
* Verify that when a network matches a roaming provider is found, the correct network
* information (WifiConfiguration) is setup and returned.
*
* @throws Exception
*/
@Test
public void evaluateScansWithNetworkMatchingRoamingProvider() throws Exception {
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {
generateScanDetail(TEST_SSID1), generateScanDetail(TEST_SSID2)});
// Setup matching providers for ScanDetail with TEST_SSID1.
Pair<PasspointProvider, PasspointMatch> roamingProvider = Pair.create(
TEST_PROVIDER1, PasspointMatch.RoamingProvider);
List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = new ArrayList<>();
matchedProviders.add(roamingProvider);
List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
// Return matchedProviders for the first ScanDetail (TEST_SSID1) and an empty list for
// for the second (TEST_SSID2);
when(mPasspointManager.matchProvider(any(ScanDetail.class))).thenReturn(matchedProviders)
.thenReturn(new ArrayList<Pair<PasspointProvider, PasspointMatch>>());
when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
.thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1);
assertNotNull(mEvaluator.evaluateNetworks(scanDetails, null, null, false,
false, connectableNetworks));
assertEquals(1, connectableNetworks.size());
// Verify the content of the WifiConfiguration that was added to WifiConfigManager.
ArgumentCaptor<WifiConfiguration> addedConfig =
ArgumentCaptor.forClass(WifiConfiguration.class);
verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt());
assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID1), addedConfig.getValue().SSID);
assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN);
}
/**
* Verify that when a network matches a home provider and another network matches a roaming
* provider are found, the network that matched to a home provider is preferred.
*
* @throws Exception
*/
@Test
public void evaluateScansWithHomeProviderNewtorkAndRoamingProviderNetwork() throws Exception {
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {
generateScanDetail(TEST_SSID1), generateScanDetail(TEST_SSID2)});
// Setup matching providers for ScanDetail with TEST_SSID1.
Pair<PasspointProvider, PasspointMatch> homeProvider = Pair.create(
TEST_PROVIDER1, PasspointMatch.HomeProvider);
Pair<PasspointProvider, PasspointMatch> roamingProvider = Pair.create(
TEST_PROVIDER2, PasspointMatch.RoamingProvider);
List<Pair<PasspointProvider, PasspointMatch>> providerForScanDetail1 = new ArrayList<>();
providerForScanDetail1.add(homeProvider);
List<Pair<PasspointProvider, PasspointMatch>> providerForScanDetail2 = new ArrayList<>();
providerForScanDetail2.add(roamingProvider);
List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
// Return providerForScanDetail1 for the first ScanDetail (TEST_SSID1) and
// providerForScanDetail2 for the second (TEST_SSID2);
when(mPasspointManager.matchProvider(any(ScanDetail.class)))
.thenReturn(providerForScanDetail1).thenReturn(providerForScanDetail2);
when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
.thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1);
assertNotNull(mEvaluator.evaluateNetworks(scanDetails, null, null, false,
false, connectableNetworks));
assertEquals(1, connectableNetworks.size());
// Verify the content of the WifiConfiguration that was added to WifiConfigManager.
ArgumentCaptor<WifiConfiguration> addedConfig =
ArgumentCaptor.forClass(WifiConfiguration.class);
verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt());
assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID1), addedConfig.getValue().SSID);
assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN);
}
/**
* Verify that when two networks both matches a home provider, with one of them being the
* active network, the active network is preferred.
*
* @throws Exception
*/
@Test
public void evaluateScansWithActiveNetworkMatchingHomeProvider() throws Exception {
List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {
generateScanDetail(TEST_SSID1), generateScanDetail(TEST_SSID2)});
// Setup matching providers for both ScanDetail.
Pair<PasspointProvider, PasspointMatch> homeProvider = Pair.create(
TEST_PROVIDER1, PasspointMatch.HomeProvider);
List<Pair<PasspointProvider, PasspointMatch>> matchedProviders = new ArrayList<>();
matchedProviders.add(homeProvider);
// Setup currently connected network
WifiConfiguration currentNetwork = new WifiConfiguration();
currentNetwork.networkId = TEST_NETWORK_ID;
currentNetwork.SSID = ScanResultUtil.createQuotedSSID(TEST_SSID2);
String currentBssid = "12:23:34:45:12:0F";
// Returning the same matching provider for both ScanDetail.
List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks = new ArrayList<>();
when(mPasspointManager.matchProvider(any(ScanDetail.class)))
.thenReturn(matchedProviders).thenReturn(matchedProviders);
WifiConfiguration config = mEvaluator.evaluateNetworks(scanDetails, currentNetwork,
currentBssid, true, false, connectableNetworks);
assertEquals(1, connectableNetworks.size());
// Verify no new network is added to WifiConfigManager.
verify(mWifiConfigManager, never()).addOrUpdateNetwork(
any(WifiConfiguration.class), anyInt());
// Verify current active network is returned.
assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID2), config.SSID);
assertEquals(TEST_NETWORK_ID, config.networkId);
}
}