diff options
author | Ningyuan Wang <nywang@google.com> | 2017-08-02 23:10:24 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-08-02 23:10:24 +0000 |
commit | cdd37192567ccf51d78dd13ffd72ab1c19363869 (patch) | |
tree | 7121f656c5027c4dbd5537aca3812004357985c7 | |
parent | b1d6ef28f4a40b4b7384859b52b176d55f7d4bae (diff) | |
parent | d4bbe1d2b40990f7281cbf038ecf3052f1821bc4 (diff) |
Merge "Stay on network during ongoing traffic" into oc-dr1-dev
am: d4bbe1d2b4
Change-Id: Ic5a7b6352c0f1eb704943a3339939bf715ba210c
-rw-r--r-- | service/java/com/android/server/wifi/WifiNetworkSelector.java | 38 | ||||
-rw-r--r-- | tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java | 305 |
2 files changed, 282 insertions, 61 deletions
diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java index 4c1df200a..57779ad08 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -25,7 +25,6 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.text.TextUtils; import android.util.LocalLog; -import android.util.Log; import android.util.Pair; import com.android.internal.R; @@ -62,6 +61,8 @@ public class WifiNetworkSelector { private final int mThresholdQualifiedRssi5; private final int mThresholdMinimumRssi24; private final int mThresholdMinimumRssi5; + private final int mStayOnNetworkMinimumTxRate; + private final int mStayOnNetworkMinimumRxRate; private final boolean mEnableAutoJoinWhenAssociated; /** @@ -147,6 +148,18 @@ public class WifiNetworkSelector { + " , ID: " + network.networkId); } + int currentRssi = wifiInfo.getRssi(); + boolean hasQualifiedRssi = + (wifiInfo.is24GHz() && (currentRssi > mThresholdQualifiedRssi24)) + || (wifiInfo.is5GHz() && (currentRssi > mThresholdQualifiedRssi5)); + // getTxSuccessRate() and getRxSuccessRate() returns the packet rate in per 5 seconds unit. + boolean hasActiveStream = (wifiInfo.getTxSuccessRatePps() > mStayOnNetworkMinimumTxRate) + || (wifiInfo.getRxSuccessRatePps() > mStayOnNetworkMinimumRxRate); + if (hasQualifiedRssi && hasActiveStream) { + localLog("Stay on current network because of good RSSI and ongoing traffic"); + return true; + } + // Ephemeral network is not qualified. if (network.ephemeral) { localLog("Current network is an ephemeral one."); @@ -159,28 +172,15 @@ public class WifiNetworkSelector { return false; } - int currentRssi = wifiInfo.getRssi(); if (wifiInfo.is24GHz()) { // 2.4GHz networks is not qualified whenever 5GHz is available if (is5GHzNetworkAvailable(scanDetails)) { localLog("Current network is 2.4GHz. 5GHz networks available."); return false; } - // When 5GHz is not available, we go through normal 2.4GHz qualification - if (currentRssi < mThresholdQualifiedRssi24) { - localLog("Current network band=2.4GHz, RSSI[" - + currentRssi + "]-acceptable but not qualified."); - return false; - } - } else if (wifiInfo.is5GHz()) { - // Must be 5GHz, so we always apply qualification checks - if (currentRssi < mThresholdQualifiedRssi5) { - localLog("Current network band=5GHz, RSSI[" - + currentRssi + "]-acceptable but not qualified."); - return false; - } - } else { - Log.e(TAG, "We're on a wifi network that's neither 2.4 or 5GHz... aliens!"); + } + if (!hasQualifiedRssi) { + localLog("Current network RSSI[" + currentRssi + "]-acceptable but not qualified."); return false; } @@ -579,5 +579,9 @@ public class WifiNetworkSelector { R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); mEnableAutoJoinWhenAssociated = context.getResources().getBoolean( R.bool.config_wifi_framework_enable_associated_network_selection); + mStayOnNetworkMinimumTxRate = context.getResources().getInteger( + R.integer.config_wifi_framework_min_tx_rate_for_staying_on_network); + mStayOnNetworkMinimumRxRate = context.getResources().getInteger( + R.integer.config_wifi_framework_min_rx_rate_for_staying_on_network); } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java index fee9033ae..4965a35c2 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java @@ -76,6 +76,10 @@ public class WifiNetworkSelectorTest { R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); mThresholdQualifiedRssi5G = mResource.getInteger( R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); + mStayOnNetworkMinimumTxRate = mResource.getInteger( + R.integer.config_wifi_framework_min_tx_rate_for_staying_on_network); + mStayOnNetworkMinimumRxRate = mResource.getInteger( + R.integer.config_wifi_framework_min_rx_rate_for_staying_on_network); mThresholdSaturatedRssi2G = mResource.getInteger( R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz); mThresholdSaturatedRssi5G = mResource.getInteger( @@ -149,6 +153,8 @@ public class WifiNetworkSelectorTest { private int mThresholdMinimumRssi5G; private int mThresholdQualifiedRssi2G; private int mThresholdQualifiedRssi5G; + private int mStayOnNetworkMinimumTxRate; + private int mStayOnNetworkMinimumRxRate; private int mThresholdSaturatedRssi2G; private int mThresholdSaturatedRssi5G; @@ -172,6 +178,12 @@ public class WifiNetworkSelectorTest { R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz)) .thenReturn(-85); when(mResource.getInteger( + R.integer.config_wifi_framework_max_tx_rate_for_full_scan)) + .thenReturn(8); + when(mResource.getInteger( + R.integer.config_wifi_framework_max_rx_rate_for_full_scan)) + .thenReturn(8); + when(mResource.getInteger( R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz)) .thenReturn(-57); when(mResource.getInteger( @@ -615,9 +627,19 @@ public class WifiNetworkSelectorTest { */ @Test public void test2GhzQualifiedNo5GhzAvailable() { + // Rssi after connected. + when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1); + // No streaming traffic. + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(0.0); + // Do not perform selection on 2GHz if current network is good and no 5GHz available - testStayOrSwitch(mThresholdQualifiedRssi2G, false, - mThresholdQualifiedRssi2G + 10, false, false); + testStayOrTryToSwitch( + mThresholdQualifiedRssi2G + 1 /* rssi before connected */, + false /* not a 5G network */, + false /* not open network */, + // Should not try to switch. + false); } /** @@ -632,24 +654,24 @@ public class WifiNetworkSelectorTest { */ @Test public void test2GhzHighQuality5GhzAvailable() { - // When on 2GHz, even with "good" signal strength, run selection if 5GHz available - testStayOrSwitch(mThresholdQualifiedRssi2G, false, - mThresholdQualifiedRssi5G - 1, true, true); - } + // Rssi after connected. + when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1); + // No streaming traffic. + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(0.0); - /** - * Wifi network selector performs network selection on 2Ghz networks if the current network - * is not of high quality. - * - * WifiStateMachine is under connected state and 2.4GHz test1 is connected. - * - * Expected behavior: network selection is performed - */ - @Test - public void test2GhzNotQualifiedOther2GhzAvailable() { - // Run Selection on 2Ghz networks when not qualified even if no 5GHz available - testStayOrSwitch(mThresholdQualifiedRssi2G - 1, false, - mThresholdQualifiedRssi2G - 10, false, true); + // 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); } /** @@ -662,10 +684,19 @@ public class WifiNetworkSelectorTest { */ @Test public void test5GhzNotQualifiedLowRssi() { - // Run Selection when the current 5Ghz network has low RSSI, regardless of what may - // be available. The second scan result is irrelevant. - testStayOrSwitch(mThresholdQualifiedRssi5G - 1, true, - mThresholdQualifiedRssi2G - 1, false, true); + // Rssi after connected. + when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G - 1); + // No streaming traffic. + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(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); } /** @@ -678,9 +709,162 @@ public class WifiNetworkSelectorTest { */ @Test public void test5GhzQualified() { + // Rssi after connected. + when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi5G + 1); + // No streaming traffic. + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(0.0); + // Connected to a high quality 5Ghz network, so the other result is irrelevant - testStayOrSwitch(mThresholdQualifiedRssi5G, true, - mThresholdQualifiedRssi5G + 10, true, false); + 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. + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(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 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. + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(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 + when(mWifiInfo.getTxSuccessRatePps()).thenReturn( + (double) (mStayOnNetworkMinimumTxRate + 1)); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(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 + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn( + (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 + when(mWifiInfo.getTxSuccessRatePps()).thenReturn( + (double) (mStayOnNetworkMinimumTxRate + 1)); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn(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 + when(mWifiInfo.getTxSuccessRatePps()).thenReturn(0.0); + when(mWifiInfo.getRxSuccessRatePps()).thenReturn( + (double) (mStayOnNetworkMinimumRxRate + 1)); + + testStayOrTryToSwitch( + mThresholdQualifiedRssi5G + 1 /* rssi before connected */, + true /* a 5G network */, + true /* open network */, + // Should not try to switch. + false); } /** @@ -690,45 +874,78 @@ public class WifiNetworkSelectorTest { * 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 testStayOrSwitch(int levelNetwork1, boolean is5GHzNetwork1, - int levelNetwork2, boolean is5GHzNetwork2, boolean shouldSelect) { - // Create an updated ScanDetails that includes a new network + 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 = new int[2]; - freqs[0] = is5GHzNetwork1 ? 5180 : 2437; - freqs[1] = is5GHzNetwork2 ? 5180 : 2437; - String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"}; - int[] levels = {levelNetwork1, levelNetwork2}; - int[] securities = {SECURITY_PSK, SECURITY_PSK}; + int[] freqs = {is5GHzNetwork1 ? 5180 : 2437, is5GHzNetwork2 ? 5180 : 2437}; + String[] caps = {isOpenNetwork1 ? "[ESS]" : "[WPA2-EAP-CCMP][ESS]", + isOpenNetwork2 ? "[ESS]" : "[WPA2-EAP-CCMP][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-EAP-CCMP][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>(); - WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(scanDetails, - blacklist, mWifiInfo, false, true, false); + // 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.getNetworkId()).thenReturn(0); when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - when(mWifiInfo.is24GHz()).thenReturn(!is5GHzNetwork1); - when(mWifiInfo.is5GHz()).thenReturn(is5GHzNetwork1); - when(mWifiInfo.getRssi()).thenReturn(levels[0]); + when(mWifiInfo.is24GHz()).thenReturn(!ScanResult.is5GHz(freqs[0])); + when(mWifiInfo.is5GHz()).thenReturn(ScanResult.is5GHz(freqs[0])); + when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime() + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000); candidate = mWifiNetworkSelector.selectNetwork(scanDetails, blacklist, mWifiInfo, true, false, false); - if (!shouldSelect) { - assertEquals("Expect null configuration", null, candidate); - } else { + // 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); - ScanResult expectedResult = scanDetails.get(0).getScanResult(); WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, - expectedResult, candidate); + scanDetails.get(0).getScanResult(), candidate); + } else { + assertEquals("Expect null configuration", null, candidate); } } |