diff options
author | Michael Plass <mplass@google.com> | 2020-03-05 17:11:53 -0800 |
---|---|---|
committer | Michael Plass <mplass@google.com> | 2020-03-20 14:39:05 -0700 |
commit | c6f842d7676f0a20ca83d3482b5177b528b25503 (patch) | |
tree | 08da42de5d2e739d389e10d0cc3832956d5810b7 | |
parent | 0588d9655753cbc043ecea3f24233be100efecde (diff) |
Prefer trusted networks to untrusted
A network marked as untrusted is not used to provide internet,
so for network selection it should lose to any trusted candidates.
If the suggestion did not come from a carrier or privileged app,
rank it even lower.
Bug: 148167150
Test: atest com.android.server.wifi
Change-Id: Ifc80ff6e81657fb10d3823ccd59724e67fab60f4
6 files changed, 149 insertions, 7 deletions
diff --git a/service/java/com/android/server/wifi/ThroughputScorer.java b/service/java/com/android/server/wifi/ThroughputScorer.java index 020f29dc5..216dd858e 100644 --- a/service/java/com/android/server/wifi/ThroughputScorer.java +++ b/service/java/com/android/server/wifi/ThroughputScorer.java @@ -16,6 +16,8 @@ package com.android.server.wifi; +import static com.android.server.wifi.WifiNetworkSelector.NetworkNominator.NOMINATOR_ID_SCORED; + import android.annotation.NonNull; import android.util.Log; @@ -50,6 +52,9 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { // config_wifi_framework_RSSI_SCORE_SLOPE public static final int RSSI_SCORE_SLOPE_IS_4 = 4; + public static final int TRUSTED_AWARD = 1000; + public static final int HALF_TRUSTED_AWARD = 1000 / 2; + private static final boolean USE_USER_CONNECT_CHOICE = true; ThroughputScorer(ScoringParams scoringParams) { @@ -85,8 +90,24 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { int savedNetworkAward = candidate.isEphemeral() ? 0 : mScoringParams.getSavedNetworkBonus(); + int trustedAward = TRUSTED_AWARD; + + if (!candidate.isTrusted()) { + savedNetworkAward = 0; // Saved networks are not untrusted, but clear anyway + unmeteredAward = 0; // Ignore metered for untrusted networks + if (candidate.isCarrierOrPrivileged()) { + trustedAward = HALF_TRUSTED_AWARD; + } else if (candidate.getNominatorId() == NOMINATOR_ID_SCORED) { + Log.e(TAG, "ScoredNetworkNominator is not carrier or privileged!"); + trustedAward = 0; + } else { + trustedAward = 0; + } + } + int score = rssiBaseScore + throughputBonusScore - + currentNetworkBoost + securityAward + unmeteredAward + savedNetworkAward; + + currentNetworkBoost + securityAward + unmeteredAward + savedNetworkAward + + trustedAward; if (candidate.getLastSelectionWeight() > 0.0) { // Put a recently-selected network in a tier above everything else, @@ -101,6 +122,7 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { + " securityAward: " + securityAward + " unmeteredAward: " + unmeteredAward + " savedNetworkAward: " + savedNetworkAward + + " trustedAward: " + trustedAward + " final score: " + score); } diff --git a/service/java/com/android/server/wifi/WifiCandidates.java b/service/java/com/android/server/wifi/WifiCandidates.java index d62ef00ca..a264a49a7 100644 --- a/service/java/com/android/server/wifi/WifiCandidates.java +++ b/service/java/com/android/server/wifi/WifiCandidates.java @@ -91,6 +91,10 @@ public class WifiCandidates { */ boolean isTrusted(); /** + * Returns true if suggestion came from a carrier or privileged app. + */ + boolean isCarrierOrPrivileged(); + /** * Returns true for a metered network. */ boolean isMetered(); @@ -151,6 +155,7 @@ public class WifiCandidates { private final boolean mPasspoint; private final boolean mEphemeral; private final boolean mTrusted; + private final boolean mCarrierOrPrivileged; private final int mPredictedThroughputMbps; CandidateImpl(Key key, WifiConfiguration config, @@ -162,6 +167,7 @@ public class WifiCandidates { boolean isCurrentNetwork, boolean isCurrentBssid, boolean isMetered, + boolean isCarrierOrPrivileged, int predictedThroughputMbps) { this.mKey = key; this.mNominatorId = nominatorId; @@ -174,8 +180,9 @@ public class WifiCandidates { this.mIsMetered = isMetered; this.mIsOpenNetwork = WifiConfigurationUtil.isConfigForOpenNetwork(config); this.mPasspoint = config.isPasspoint(); - this.mEphemeral = config.ephemeral; + this.mEphemeral = config.isEphemeral(); this.mTrusted = config.trusted; + this.mCarrierOrPrivileged = isCarrierOrPrivileged; this.mPredictedThroughputMbps = predictedThroughputMbps; } @@ -210,6 +217,11 @@ public class WifiCandidates { } @Override + public boolean isCarrierOrPrivileged() { + return mCarrierOrPrivileged; + } + + @Override public boolean isMetered() { return (mIsMetered); } @@ -253,8 +265,7 @@ public class WifiCandidates { * Accesses statistical information from the score card */ @Override - public WifiScoreCardProto.Signal - getEventStatistics(WifiScoreCardProto.Event event) { + public WifiScoreCardProto.Signal getEventStatistics(WifiScoreCardProto.Event event) { if (mPerBssid == null) return null; WifiScoreCard.PerSignal perSignal = mPerBssid.lookupSignal(event, getFrequency()); if (perSignal == null) return null; @@ -283,6 +294,7 @@ public class WifiCandidates { + (isCurrentNetwork() ? "current, " : "") + (isEphemeral() ? "ephemeral" : "saved") + ", " + (isTrusted() ? "trusted, " : "") + + (isCarrierOrPrivileged() ? "priv, " : "") + (isMetered() ? "metered, " : "") + (isPasspoint() ? "passpoint, " : "") + (isOpenNetwork() ? "open" : "secure") + " }"; @@ -405,6 +417,7 @@ public class WifiCandidates { scanDetail.getScanResult().frequency, lastSelectionWeightBetweenZeroAndOne, isMetered, + false, predictedThroughputMbps); } @@ -431,6 +444,7 @@ public class WifiCandidates { int frequency, double lastSelectionWeightBetweenZeroAndOne, boolean isMetered, + boolean isCarrierOrPrivileged, int predictedThroughputMbps) { Candidate old = mCandidates.get(key); if (old != null) { @@ -451,6 +465,7 @@ public class WifiCandidates { config.networkId == mCurrentNetworkId, key.bssid.equals(mCurrentBssid), isMetered, + isCarrierOrPrivileged, predictedThroughputMbps); mCandidates.put(key, candidate); return true; @@ -600,5 +615,4 @@ public class WifiCandidates { private boolean mPicky = false; private RuntimeException mLastFault = null; private int mFaultCount = 0; - } diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java index c5f85d05e..f6178f24c 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -27,6 +27,7 @@ import android.net.wifi.ScanResult; import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -757,7 +758,7 @@ public class WifiNetworkSelector { WifiCandidates wifiCandidates = new WifiCandidates(mWifiScoreCard, mContext); if (currentNetwork != null) { wifiCandidates.setCurrent(currentNetwork.networkId, currentBssid); - // We always want the current network to be a candidate so that it can particpate. + // We always want the current network to be a candidate so that it can participate. // It may also get re-added by a nominator, in which case this fallback // will be replaced. MacAddress bssid = MacAddress.fromString(currentBssid); @@ -770,6 +771,7 @@ public class WifiNetworkSelector { wifiInfo.getFrequency(), calculateLastSelectionWeight(currentNetwork.networkId), WifiConfiguration.isMetered(currentNetwork, wifiInfo), + isFromCarrierOrPrivilegedApp(currentNetwork), 0 /* Mbps */); } for (NetworkNominator registeredNominator : mNominators) { @@ -782,12 +784,14 @@ public class WifiNetworkSelector { scanDetail, config); if (key != null) { boolean metered = isEverMetered(config, wifiInfo); + // TODO(b/151981920) Saved passpoint candidates are marked ephemeral boolean added = wifiCandidates.add(key, config, registeredNominator.getId(), scanDetail.getScanResult().level, scanDetail.getScanResult().frequency, calculateLastSelectionWeight(config.networkId), metered, + isFromCarrierOrPrivilegedApp(config), predictThroughput(scanDetail)); if (added) { mConnectableNetworks.add(Pair.create(scanDetail, config)); @@ -1030,6 +1034,21 @@ public class WifiNetworkSelector { } } + private static boolean isFromCarrierOrPrivilegedApp(WifiConfiguration config) { + if (config.fromWifiNetworkSuggestion + && config.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { + // Privileged carrier suggestion + return true; + } + if (config.isEphemeral() + && !config.fromWifiNetworkSpecifier + && !config.fromWifiNetworkSuggestion) { + // From ScoredNetworkNominator + return true; + } + return false; + } + /** * Derives a numeric experiment identifier from a CandidateScorer's identifier. * diff --git a/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java b/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java index fd09f30cb..918e9e834 100644 --- a/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java @@ -222,4 +222,59 @@ public class CandidateScorerTest extends WifiBaseTest { .setPredictedThroughputMbps(50)))); } } + + /** + * Prefer saved over suggestion. + */ + @Test + public void testPreferSavedOverSuggestion() throws Exception { + if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; + assertThat(evaluate(mCandidate1.setScanRssi(-77).setEphemeral(false)), + greaterThan(evaluate(mCandidate2.setScanRssi(-40) + .setEphemeral(true) + .setPredictedThroughputMbps(1000)))); + } + + /** + * Prefer metered saved over unmetered suggestion. + */ + @Test + public void testPreferMeteredSavedOverUnmeteredSuggestion() throws Exception { + if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; + assertThat(evaluate(mCandidate1.setScanRssi(-77).setEphemeral(false).setMetered(false)), + greaterThan(evaluate(mCandidate2.setScanRssi(-40) + .setEphemeral(true) + .setMetered(true) + .setPredictedThroughputMbps(1000)))); + } + + /** + * Prefer trusted metered suggestion over privileged untrusted. + */ + @Test + public void testPreferTrustedOverUntrusted() throws Exception { + if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; + assertThat(evaluate(mCandidate1.setScanRssi(-77).setEphemeral(true).setMetered(true)), + greaterThan(evaluate(mCandidate2.setScanRssi(-40) + .setEphemeral(true) + .setPredictedThroughputMbps(1000) + .setTrusted(false) + .setCarrierOrPrivileged(true)))); + } + + /** + * Prefer carrier untrusted over other untrusted. + */ + @Test + public void testPreferCarrierUntrustedOverOtherUntrusted() throws Exception { + if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; + assertThat(evaluate(mCandidate1.setScanRssi(-77) + .setEphemeral(true) + .setMetered(true) + .setCarrierOrPrivileged(true)), + greaterThan(evaluate(mCandidate2.setScanRssi(-40) + .setPredictedThroughputMbps(1000) + .setTrusted(false)))); + } + } diff --git a/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java b/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java index cf75ad56c..1d84c4024 100644 --- a/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java +++ b/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java @@ -30,7 +30,8 @@ public final class ConcreteCandidate implements WifiCandidates.Candidate { private boolean mIsCurrentBssid; private boolean mIsPasspoint; private boolean mIsEphemeral; - private boolean mIsTrusted; + private boolean mIsTrusted = true; + private boolean mCarrierOrPrivileged; private boolean mIsMetered; private int mNominatorId = -1; private double mLastSelectionWeight; @@ -53,6 +54,7 @@ public final class ConcreteCandidate implements WifiCandidates.Candidate { mIsPasspoint = candidate.isPasspoint(); mIsEphemeral = candidate.isEphemeral(); mIsTrusted = candidate.isTrusted(); + mCarrierOrPrivileged = candidate.isCarrierOrPrivileged(); mIsMetered = candidate.isMetered(); mNominatorId = candidate.getNominatorId(); mLastSelectionWeight = candidate.getLastSelectionWeight(); @@ -127,6 +129,16 @@ public final class ConcreteCandidate implements WifiCandidates.Candidate { return mIsTrusted; } + public ConcreteCandidate setCarrierOrPrivileged(boolean carrierOrPrivileged) { + mCarrierOrPrivileged = carrierOrPrivileged; + return this; + } + + @Override + public boolean isCarrierOrPrivileged() { + return mCarrierOrPrivileged; + } + public ConcreteCandidate setMetered(boolean isMetered) { mIsMetered = isMetered; return this; diff --git a/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java index 4b64f71a6..16889b837 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java @@ -349,4 +349,24 @@ public class WifiCandidatesTest extends WifiBaseTest { assertEquals(2, mWifiCandidates.size()); assertEquals(0, mWifiCandidates.getFaultCount()); } + + /** + * Verify CarrierOrPrivileged bit is remembered. + */ + @Test + public void testAddCarrierOrPrivilegedCandidate() { + WifiCandidates.Key key = mWifiCandidates + .keyFromScanDetailAndConfig(mScanDetail1, mConfig1); + WifiCandidates.Candidate candidate; + // Make sure the CarrierOrPrivileged false is remembered + assertTrue(mWifiCandidates.add(key, mConfig1, 0, -50, 2412, 0.0, false, false, 100)); + candidate = mWifiCandidates.getCandidates().get(0); + assertFalse(candidate.isCarrierOrPrivileged()); + mWifiCandidates.remove(candidate); + // Make sure the CarrierOrPrivileged true is remembered + assertTrue(mWifiCandidates.add(key, mConfig1, 0, -50, 2412, 0.0, false, true, 100)); + candidate = mWifiCandidates.getCandidates().get(0); + assertTrue(candidate.isCarrierOrPrivileged()); + mWifiCandidates.remove(candidate); + } } |