summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Qiu <zqiu@google.com>2016-12-21 15:55:04 -0800
committerPeter Qiu <zqiu@google.com>2017-01-10 13:40:40 -0800
commit50f36ec6fe906445db996bf3918e5cb3f170bc79 (patch)
tree83b32decc73983331f613b414feb710fc4ebd2f3
parent6a8e5ccb593fa239d53d1be4ac6913cfeba47ab6 (diff)
hotspot2: integration of network evaluator for Passpoint
Bug: 32714185 Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh Test: Manual testing with a Boingo Passpoint AP using a bullhead Change-Id: Ib71723bed332aa850485edd98ebdcbfcf8ec22c7
-rw-r--r--service/java/com/android/server/wifi/WifiConfigManager.java10
-rw-r--r--service/java/com/android/server/wifi/WifiConnectivityManager.java9
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java12
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java5
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java198
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java2
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java319
7 files changed, 542 insertions, 13 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index a4ae5657b..b59a75e1f 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -899,9 +899,11 @@ public class WifiConfigManager {
existingInternalConfig, config, uid);
}
- // Update the keys for enterprise networks.
+ // Update the keys for non-Passpoint enterprise networks. For Passpoint, the certificates
+ // and keys are installed at the time the provider is installed.
if (config.enterpriseConfig != null
- && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
+ && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE
+ && !config.isPasspoint()) {
if (!(mWifiKeyStore.updateNetworkKeys(newInternalConfig, existingInternalConfig))) {
return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
}
@@ -2558,8 +2560,8 @@ public class WifiConfigManager {
ArrayList<WifiConfiguration> sharedConfigurations = new ArrayList<>();
ArrayList<WifiConfiguration> userConfigurations = new ArrayList<>();
for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
- // Don't persist ephemeral networks to store.
- if (!config.ephemeral) {
+ // Don't persist ephemeral and passpoint networks to store.
+ if (!config.ephemeral && !config.isPasspoint()) {
// We push all shared networks & private networks not belonging to the current
// user to the shared store. Ideally, private networks for other users should
// not even be in memory,
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index bd4887a22..f71b7810b 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -33,6 +33,7 @@ import android.util.LocalLog;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.hotspot2.PasspointNetworkEvaluator;
import com.android.server.wifi.util.ScanResultUtil;
import java.io.FileDescriptor;
@@ -118,7 +119,8 @@ public class WifiConnectivityManager {
// Saved network evaluator priority
private static final int SAVED_NETWORK_EVALUATOR_PRIORITY = 1;
- private static final int RECOMMENDED_NETWORK_EVALUATOR_PRIORITY = 2;
+ private static final int PASSPOINT_NETWORK_EVALUATOR_PRIORITY = 2;
+ private static final int RECOMMENDED_NETWORK_EVALUATOR_PRIORITY = 3;
private final WifiStateMachine mStateMachine;
private final WifiScanner mScanner;
@@ -471,7 +473,8 @@ public class WifiConnectivityManager {
WifiLastResortWatchdog wifiLastResortWatchdog, WifiMetrics wifiMetrics,
Looper looper, Clock clock, boolean enable, FrameworkFacade frameworkFacade,
SavedNetworkEvaluator savedNetworkEvaluator,
- RecommendedNetworkEvaluator recommendedNetworkEvaluator) {
+ RecommendedNetworkEvaluator recommendedNetworkEvaluator,
+ PasspointNetworkEvaluator passpointNetworkEvaluator) {
mStateMachine = stateMachine;
mScanner = scanner;
mConfigManager = configManager;
@@ -518,6 +521,8 @@ public class WifiConnectivityManager {
// Register the network evaluators
mNetworkSelector.registerNetworkEvaluator(savedNetworkEvaluator,
SAVED_NETWORK_EVALUATOR_PRIORITY);
+ mNetworkSelector.registerNetworkEvaluator(passpointNetworkEvaluator,
+ PASSPOINT_NETWORK_EVALUATOR_PRIORITY);
mNetworkSelector.registerNetworkEvaluator(recommendedNetworkEvaluator,
RECOMMENDED_NETWORK_EVALUATOR_PRIORITY);
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 5fcfb5d79..902cc644a 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -42,6 +42,7 @@ import com.android.server.am.BatteryStatsService;
import com.android.server.net.DelayedDiskWrite;
import com.android.server.net.IpConfigStore;
import com.android.server.wifi.hotspot2.PasspointManager;
+import com.android.server.wifi.hotspot2.PasspointNetworkEvaluator;
import com.android.server.wifi.hotspot2.PasspointObjectFactory;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -91,6 +92,7 @@ public class WifiInjector {
private final WifiConfigManager mWifiConfigManager;
private final WifiNetworkSelector mWifiNetworkSelector;
private final SavedNetworkEvaluator mSavedNetworkEvaluator;
+ private final PasspointNetworkEvaluator mPasspointNetworkEvaluator;
private final RecommendedNetworkEvaluator mRecommendedNetworkEvaluator;
private final WifiNetworkScoreCache mWifiNetworkScoreCache;
private final NetworkScoreManager mNetworkScoreManager;
@@ -168,6 +170,11 @@ public class WifiInjector {
context.getContentResolver(), mWifiStateMachineHandlerThread.getLooper(),
mFrameworkFacade, mWifiNetworkScoreCache, mNetworkScoreManager, mWifiConfigManager,
localLog, externalScoreEvaluator);
+ mSimAccessor = new SIMAccessor(mContext);
+ mPasspointManager = new PasspointManager(mContext, mWifiNative, mWifiKeyStore, mClock,
+ mSimAccessor, new PasspointObjectFactory());
+ mPasspointNetworkEvaluator = new PasspointNetworkEvaluator(
+ mPasspointManager, mWifiConfigManager, localLog);
mWifiStateMachine = new WifiStateMachine(mContext, mFrameworkFacade,
mWifiStateMachineHandlerThread.getLooper(), UserManager.get(mContext),
this, mBackupManagerProxy, mCountryCode, mWifiNative);
@@ -182,9 +189,6 @@ public class WifiInjector {
mWifiPermissionsWrapper = new WifiPermissionsWrapper(mContext);
mWifiPermissionsUtil = new WifiPermissionsUtil(mWifiPermissionsWrapper, mContext,
mSettingsStore, UserManager.get(mContext), new NetworkScorerAppManager(mContext));
- mSimAccessor = new SIMAccessor(mContext);
- mPasspointManager = new PasspointManager(mContext, mWifiNative, mWifiKeyStore, mClock,
- mSimAccessor, new PasspointObjectFactory());
}
/**
@@ -376,7 +380,7 @@ public class WifiInjector {
mWifiConfigManager, wifiInfo, mWifiNetworkSelector, mWifiLastResortWatchdog,
mWifiMetrics, mWifiStateMachineHandlerThread.getLooper(), mClock,
hasConnectionRequests, mFrameworkFacade, mSavedNetworkEvaluator,
- mRecommendedNetworkEvaluator);
+ mRecommendedNetworkEvaluator, mPasspointNetworkEvaluator);
}
public WifiPermissionsUtil getWifiPermissionsUtil() {
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 540fbd827..9b62a0cd6 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -4690,8 +4690,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
// hence record the time we were connected last
WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
if (config != null) {
- if (config.ephemeral) {
- // Remove ephemeral WifiConfigurations from file
+ // Remove WifiConfiguration for ephemeral or Passpoint networks, since they're
+ // temporary networks.
+ if (config.ephemeral || config.isPasspoint()) {
mWifiConfigManager.removeNetwork(mLastNetworkId, Process.WIFI_UID);
}
}
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
new file mode 100644
index 000000000..77b29a8da
--- /dev/null
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
@@ -0,0 +1,198 @@
+/*
+ * 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 android.net.wifi.WifiConfiguration;
+import android.os.Process;
+import android.text.TextUtils;
+import android.util.LocalLog;
+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.WifiNetworkSelector;
+import com.android.server.wifi.util.ScanResultUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is the WifiNetworkSelector.NetworkEvaluator implementation for
+ * Passpoint networks.
+ */
+public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluator {
+ private static final String NAME = "PasspointNetworkEvaluator";
+
+ private final PasspointManager mPasspointManager;
+ private final WifiConfigManager mWifiConfigManager;
+ private final LocalLog mLocalLog;
+
+ public PasspointNetworkEvaluator(PasspointManager passpointManager,
+ WifiConfigManager wifiConfigManager, LocalLog localLog) {
+ mPasspointManager = passpointManager;
+ mWifiConfigManager = wifiConfigManager;
+ mLocalLog = localLog;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public void update(List<ScanDetail> scanDetails) {}
+
+ @Override
+ public WifiConfiguration evaluateNetworks(List<ScanDetail> scanDetails,
+ WifiConfiguration currentNetwork, String currentBssid,
+ boolean connected, boolean untrustedNetworkAllowed,
+ List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) {
+ // Go through each ScanDetail and find the best provider for each ScanDetail.
+ List<Pair<ScanDetail, Pair<PasspointProvider, PasspointMatch>>> providerList =
+ new ArrayList<>();
+ for (ScanDetail scanDetail : scanDetails) {
+ // Skip non-Passpoint APs.
+ if (!scanDetail.getNetworkDetail().isInterworking()) {
+ continue;
+ }
+
+ List<Pair<PasspointProvider, PasspointMatch>> matchedProviders =
+ mPasspointManager.matchProvider(scanDetail);
+
+ // Find the best provider for this ScanDetail.
+ Pair<PasspointProvider, PasspointMatch> bestProvider =
+ findBestProvider(matchedProviders);
+ if (bestProvider != null) {
+ providerList.add(Pair.create(scanDetail, bestProvider));
+ }
+ }
+
+ // Done if no matching provider is found.
+ if (providerList.isEmpty()) {
+ return null;
+ }
+
+ // Find the best Passpoint network among all matches.
+ Pair<PasspointProvider, ScanDetail> bestNetwork = findBestNetwork(providerList,
+ currentNetwork == null ? null : currentNetwork.SSID);
+
+ // Return the configuration for the current connected network if it is the best network.
+ if (currentNetwork != null && TextUtils.equals(currentNetwork.SSID,
+ ScanResultUtil.createQuotedSSID(bestNetwork.second.getSSID()))) {
+ connectableNetworks.add(Pair.create(bestNetwork.second, currentNetwork));
+ return currentNetwork;
+ }
+
+ WifiConfiguration config =
+ createWifiConfigForProvider(bestNetwork.first, bestNetwork.second);
+ connectableNetworks.add(Pair.create(bestNetwork.second, config));
+ return config;
+ }
+
+ /**
+ * Create and return a WifiConfiguration for the given ScanDetail and PasspointProvider.
+ * The newly created WifiConfiguration will also be added to WifiConfigManager.
+ *
+ * @param provider The provider to create WifiConfiguration from
+ * @param scanDetail The ScanDetail to create WifiConfiguration from
+ * @return {@link WifiConfiguration}
+ */
+ private WifiConfiguration createWifiConfigForProvider(PasspointProvider provider,
+ ScanDetail scanDetail) {
+ WifiConfiguration config = provider.getWifiConfig();
+ config.SSID = ScanResultUtil.createQuotedSSID(scanDetail.getSSID());
+
+ // Add the newly created WifiConfiguration to WifiConfigManager.
+ NetworkUpdateResult result =
+ mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);
+ if (!result.isSuccess()) {
+ localLog("Failed to add passpoint network");
+ return null;
+ }
+ mWifiConfigManager.setNetworkCandidateScanResult(result.getNetworkId(),
+ scanDetail.getScanResult(), 0);
+ return mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
+ }
+
+ /**
+ * Given a list of provider associated with a ScanDetail, determine and return the best
+ * provider from the list.
+ *
+ * Currently the only criteria is to prefer home provider over roaming provider. Additional
+ * criteria will be added when Hotspot 2.0 Release 2 support is added.
+ *
+ * A null will be returned if no match is found (providerList is empty).
+ *
+ * @param providerList The list of matched providers
+ * @return Pair of {@link PasspointProvider} with its matching status
+ */
+ private Pair<PasspointProvider, PasspointMatch> findBestProvider(
+ List<Pair<PasspointProvider, PasspointMatch>> providerList) {
+ Pair<PasspointProvider, PasspointMatch> bestMatch = null;
+ for (Pair<PasspointProvider, PasspointMatch> providerMatch : providerList) {
+ if (providerMatch.second == PasspointMatch.HomeProvider) {
+ // Home provider found, done.
+ bestMatch = providerMatch;
+ break;
+ } else if (bestMatch == null) {
+ bestMatch = providerMatch;
+ }
+ }
+ return bestMatch;
+ }
+
+ /**
+ * Given a list of Passpoint networks (with both provider and scan info), find and return
+ * the one with highest score. The score is calculated using
+ * {@link PasspointNetworkScore#calculateScore}.
+ *
+ * @param networkList List of Passpoint networks
+ * @param currentNetworkSsid The SSID of the currently connected network, null if not connected
+ * @return {@link PasspointProvider} and {@link ScanDetail} associated with the network
+ */
+ private Pair<PasspointProvider, ScanDetail> findBestNetwork(
+ List<Pair<ScanDetail, Pair<PasspointProvider, PasspointMatch>>> networkList,
+ String currentNetworkSsid) {
+ ScanDetail bestScanDetail = null;
+ PasspointProvider bestProvider = null;
+ int bestScore = Integer.MIN_VALUE;
+ for (Pair<ScanDetail, Pair<PasspointProvider, PasspointMatch>> candidate : networkList) {
+ ScanDetail scanDetail = candidate.first;
+ PasspointProvider provider = candidate.second.first;
+ PasspointMatch match = candidate.second.second;
+
+ boolean isActiveNetwork = TextUtils.equals(currentNetworkSsid,
+ ScanResultUtil.createQuotedSSID(scanDetail.getSSID()));
+ int score = PasspointNetworkScore.calculateScore(match == PasspointMatch.HomeProvider,
+ scanDetail, isActiveNetwork);
+
+ if (score > bestScore) {
+ bestScanDetail = scanDetail;
+ bestProvider = provider;
+ bestScore = score;
+ }
+ }
+ return Pair.create(bestProvider, bestScanDetail);
+ }
+
+ private void localLog(String log) {
+ if (mLocalLog != null) {
+ mLocalLog.log(log);
+ }
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index f3c0573df..56af3fbb9 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -259,7 +259,7 @@ public class WifiConnectivityManagerTest {
return new WifiConnectivityManager(mContext, mWifiStateMachine, mWifiScanner,
mWifiConfigManager, mWifiInfo, mWifiNS,
mWifiLastResortWatchdog, mWifiMetrics, mLooper.getLooper(), mClock, true,
- mFrameworkFacade, null, null);
+ mFrameworkFacade, null, null, null);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java
new file mode 100644
index 000000000..7312b3334
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java
@@ -0,0 +1,319 @@
+/*
+ * 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);
+ }
+}