summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java31
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java165
2 files changed, 190 insertions, 6 deletions
diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
index 1601f7361..8a3f7aa2b 100644
--- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
@@ -55,6 +55,8 @@ public class WifiQualifiedNetworkSelector {
private String mCurrentBssid = null;
//buffer most recent scan results
private List<ScanDetail> mScanDetails = null;
+ //buffer of filtered scan results (Scan results considered by network selection)
+ private volatile List<ScanDetail> mFilteredScanDetails = null;
//Minimum time gap between last successful Qualified Network Selection and new selection attempt
//usable only when current state is connected state default 10 s
@@ -134,6 +136,16 @@ public class WifiQualifiedNetworkSelector {
}
/**
+ * @return the list of ScanDetails scored as potential candidates by the last run of
+ * selectQualifiedNetwork, this will be empty if QNS determined no selection was needed on last
+ * run. This includes scan details of sufficient signal strength, and had an associated
+ * WifiConfiguration.
+ */
+ public List<ScanDetail> getFilteredScanDetails() {
+ return mFilteredScanDetails;
+ }
+
+ /**
* set the user selected preferred band
*
* @param band preferred band user selected
@@ -615,6 +627,7 @@ public class WifiQualifiedNetworkSelector {
boolean isSupplicantTransient) {
qnsLog("==========start qualified Network Selection==========");
mScanDetails = scanDetails;
+ List<ScanDetail> filteredScanDetails = new ArrayList<>();
if (mCurrentConnectedNetwork == null) {
mCurrentConnectedNetwork =
mWifiConfigManager.getWifiConfiguration(mWifiInfo.getNetworkId());
@@ -628,6 +641,7 @@ public class WifiQualifiedNetworkSelector {
isDisconnected, isSupplicantTransient)) {
qnsLog("Quit qualified Network Selection since it is not forced and current network is"
+ " qualified already");
+ mFilteredScanDetails = filteredScanDetails;
return null;
}
@@ -705,11 +719,11 @@ public class WifiQualifiedNetworkSelector {
}
//check whether this scan result belong to a saved network
- boolean ephemeral = false;
+ boolean potentiallyEphemeral = false;
List<WifiConfiguration> associatedWifiConfigurations =
mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetail);
if (associatedWifiConfigurations == null) {
- ephemeral = true;
+ potentiallyEphemeral = true;
if (mDbg) {
notSavedScan.append(scanId + " / ");
}
@@ -717,14 +731,14 @@ public class WifiQualifiedNetworkSelector {
//if there are more than 1 associated network, it must be a passpoint network
WifiConfiguration network = associatedWifiConfigurations.get(0);
if (network.ephemeral) {
- ephemeral = true;
+ potentiallyEphemeral = true;
}
}
- if (ephemeral) {
+ if (potentiallyEphemeral) {
if (isUntrustedConnectionsAllowed && mNetworkScoreCache != null) {
int netScore = mNetworkScoreCache.getNetworkScore(scanResult, false);
- //get network score
+ //get network score (Determine if this is an 'Ephemeral' network)
if (netScore != WifiNetworkScoreCache.INVALID_NETWORK_SCORE) {
qnsLog(scanId + "has score: " + netScore);
if (netScore > unTrustedHighestScore) {
@@ -732,9 +746,14 @@ public class WifiQualifiedNetworkSelector {
untrustedScanResultCandidate = scanResult;
qnsLog(scanId + " become the new untrusted candidate");
}
+ // scanDetail is for available ephemeral network
+ filteredScanDetails.add(scanDetail);
}
}
continue;
+ } else {
+ // scanDetail is for available saved network
+ filteredScanDetails.add(scanDetail);
}
// calculate the core of each scanresult whose associated network is not ephemeral. Due
@@ -782,6 +801,8 @@ public class WifiQualifiedNetworkSelector {
}
}
+ mFilteredScanDetails = filteredScanDetails;
+
//kick the score manager if there is any unscored network
if (mScoreManager != null && unscoredNetworks.size() != 0) {
NetworkKey[] unscoredNetworkKeys =
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
index cc42a9d61..3d7aa65f1 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
@@ -23,7 +23,6 @@ import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConf
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
@@ -258,6 +257,13 @@ public class WifiQualifiedNetworkSelectorTest {
when(mScoreCache.hasScoreCurve(scanResult)).thenReturn(true);
when(mScoreCache.getNetworkScore(eq(scanResult), anyBoolean())).thenReturn(score);
when(mScoreCache.getNetworkScore(scanResult)).thenReturn(score);
+ } else {
+ when(mScoreCache.isScoredNetwork(scanResult)).thenReturn(false);
+ when(mScoreCache.hasScoreCurve(scanResult)).thenReturn(false);
+ when(mScoreCache.getNetworkScore(eq(scanResult), anyBoolean())).thenReturn(
+ WifiNetworkScoreCache.INVALID_NETWORK_SCORE);
+ when(mScoreCache.getNetworkScore(scanResult)).thenReturn(
+ WifiNetworkScoreCache.INVALID_NETWORK_SCORE);
}
when(mScoreCache.getMeteredHint(scanResult)).thenReturn(meteredHints[i]);
}
@@ -1075,6 +1081,8 @@ public class WifiQualifiedNetworkSelectorTest {
WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
false, scanDetails, false, true, false, false);
assertEquals("choose the wrong BSSID", null, candidate);
+ assertEquals("Should receive zero filteredScanDetails", 0,
+ mWifiQualifiedNetworkSelector.getFilteredScanDetails().size());
}
/**
@@ -1645,4 +1653,159 @@ public class WifiQualifiedNetworkSelectorTest {
assertSame(candidate, unTrustedNetworkCandidate);
assertEquals(meteredHints[1], candidate.meteredHint);
}
+
+ /**
+ * Case #34 Test Filtering of potential candidate scanDetails (Untrusted allowed)
+ *
+ * In this test. we simulate following scenario
+ * WifiStateMachine is under disconnected state
+ * test1 is @ 2GHz with RSSI -60
+ * test2 is @ 5Ghz with RSSI -86, (below minimum threshold)
+ * test3 is @ 5Ghz with RSSI -50, however it has no associated saved config
+ * test4 is @ 2Ghz with RSSI -62, no associated config, but is Ephemeral
+ *
+ * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not
+ * compensate).
+ * test1 & test4's scanDetails are returned by 'getFilteredScanDetail()'
+ */
+ @Test
+ public void testGetFilteredScanDetailsReturnsOnlyConsideredScanDetails_untrustedAllowed() {
+ String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55",
+ "c0:ff:ee:ee:e3:ee"};
+ int[] frequencies = {2437, 5180, 5180, 2437};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]",
+ "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-60, -86, -50, -62};
+ int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
+ boolean[] meteredHints = {false, false, false, true};
+ Integer[] scores = {null, null, null, 120};
+
+ //Create all 4 scanDetails
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+
+ //Setup NetworkScoreCache for detecting ephemeral networks ("test4")
+ configureScoreCache(scanDetails, scores, meteredHints);
+ WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
+ unTrustedNetworkCandidate.SSID = null;
+ unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ ScanResult untrustedScanResult = scanDetails.get(3).getScanResult();
+ when(mWifiConfigManager
+ .wifiConfigurationFromScanResult(untrustedScanResult))
+ .thenReturn(unTrustedNetworkCandidate);
+ WifiConfiguration.NetworkSelectionStatus selectionStatus =
+ mock(WifiConfiguration.NetworkSelectionStatus.class);
+ when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus);
+
+ //Set up associated configs for test1 & test2
+ WifiConfiguration[] savedConfigs = generateWifiConfigurations(
+ Arrays.copyOfRange(ssids, 0, 2), Arrays.copyOfRange(security, 0, 2));
+ prepareConfigStore(savedConfigs);
+ List<ScanDetail> savedScanDetails = new ArrayList<ScanDetail>(scanDetails.subList(0, 2));
+ final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
+ when(mWifiConfigManager.getConfiguredNetworks()).thenReturn(savedNetwork);
+ scanResultLinkConfiguration(savedConfigs, savedScanDetails);
+
+ //Force mock ConfigManager to return null (and not an empty list) for "test3" & "test4"
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(2)))
+ .thenReturn(null);
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(3)))
+ .thenReturn(null);
+
+ ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
+
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
+ false /* forceSelectNetwork */,
+ true /* isUntrustedConnectionsAllowed */,
+ scanDetails,
+ false, /* isLinkDebouncing */
+ false, /* isConnected */
+ true, /* isDisconnected */
+ false /* isSupplicantTransient */);
+
+ verifySelectedResult(chosenScanResult, candidate);
+ //Verify two scanDetails returned in the filteredScanDetails
+ assertEquals(2, mWifiQualifiedNetworkSelector.getFilteredScanDetails().size());
+ assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(0).toString(),
+ scanDetails.get(0).toString());
+ assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(1).toString(),
+ scanDetails.get(3).toString());
+ }
+
+
+ /**
+ * Case #35 Test Filtering of potential candidate scanDetails (Untrusted disallowed)
+ *
+ * In this test. we simulate following scenario
+ * WifiStateMachine is under disconnected state
+ * test1 is @ 2GHz with RSSI -60
+ * test2 is @ 5Ghz with RSSI -86, (below minimum threshold)
+ * test3 is @ 5Ghz with RSSI -50, however it has no associated saved config
+ * test4 is @ 2Ghz with RSSI -62, no associated config, but is Ephemeral
+ *
+ * Expected behavior: test1 is chosen due to 5GHz signal is too weak (5GHz bonus can not
+ * compensate).
+ * test1 & test4's scanDetails are returned by 'getFilteredScanDetail()'
+ */
+ @Test
+ public void testGetFilteredScanDetailsReturnsOnlyConsideredScanDetails_untrustedDisallowed() {
+ String[] ssids = {"\"test1\"", "\"test2\"", "\"test3\"", "\"test4\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "de:ad:ba:b1:e5:55",
+ "c0:ff:ee:ee:e3:ee"};
+ int[] frequencies = {2437, 5180, 5180, 2437};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]",
+ "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-60, -86, -50, -62};
+ int[] security = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
+ boolean[] meteredHints = {false, false, false, true};
+ Integer[] scores = {null, null, null, 120};
+
+ //Create all 4 scanDetails
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+
+ //Setup NetworkScoreCache for detecting ephemeral networks ("test4")
+ configureScoreCache(scanDetails, scores, meteredHints);
+ WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class);
+ unTrustedNetworkCandidate.SSID = null;
+ unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ ScanResult untrustedScanResult = scanDetails.get(3).getScanResult();
+ when(mWifiConfigManager
+ .wifiConfigurationFromScanResult(untrustedScanResult))
+ .thenReturn(unTrustedNetworkCandidate);
+ WifiConfiguration.NetworkSelectionStatus selectionStatus =
+ mock(WifiConfiguration.NetworkSelectionStatus.class);
+ when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus);
+
+ //Set up associated configs for test1 & test2
+ WifiConfiguration[] savedConfigs = generateWifiConfigurations(
+ Arrays.copyOfRange(ssids, 0, 2), Arrays.copyOfRange(security, 0, 2));
+ prepareConfigStore(savedConfigs);
+ List<ScanDetail> savedScanDetails = new ArrayList<ScanDetail>(scanDetails.subList(0, 2));
+ final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
+ when(mWifiConfigManager.getConfiguredNetworks()).thenReturn(savedNetwork);
+ scanResultLinkConfiguration(savedConfigs, savedScanDetails);
+
+ //Force mock ConfigManager to return null (and not an empty list) for "test3" & "test4"
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(2)))
+ .thenReturn(null);
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(3)))
+ .thenReturn(null);
+
+ ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
+
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(
+ false /* forceSelectNetwork */,
+ false /* isUntrustedConnectionsAllowed */,
+ scanDetails,
+ false, /* isLinkDebouncing */
+ false, /* isConnected */
+ true, /* isDisconnected */
+ false /* isSupplicantTransient */);
+
+ verifySelectedResult(chosenScanResult, candidate);
+ //Verify two scanDetails returned in the filteredScanDetails
+ assertEquals(1, mWifiQualifiedNetworkSelector.getFilteredScanDetails().size());
+ assertEquals(mWifiQualifiedNetworkSelector.getFilteredScanDetails().get(0).toString(),
+ scanDetails.get(0).toString());
+ }
}