diff options
Diffstat (limited to 'service/java/com')
5 files changed, 96 insertions, 45 deletions
diff --git a/service/java/com/android/server/wifi/BubbleFunScorer.java b/service/java/com/android/server/wifi/BubbleFunScorer.java index fd75751d2b..e14fef0eb8 100644 --- a/service/java/com/android/server/wifi/BubbleFunScorer.java +++ b/service/java/com/android/server/wifi/BubbleFunScorer.java @@ -65,7 +65,7 @@ final class BubbleFunScorer implements WifiCandidates.CandidateScorer { double score = shapeFunction(rssi) - shapeFunction(rssiEntryThreshold); // If we are below the entry threshold, make the score more negative - if (score < 0.0) score *= 10.0; + if (score < 0.0) score *= 2.0; // The gain is approximately the derivative of shapeFunction at the given rssi // This is used to estimate the error diff --git a/service/java/com/android/server/wifi/ScoringParams.java b/service/java/com/android/server/wifi/ScoringParams.java index 0a29b57c7a..7588582b3c 100644 --- a/service/java/com/android/server/wifi/ScoringParams.java +++ b/service/java/com/android/server/wifi/ScoringParams.java @@ -94,7 +94,9 @@ public class ScoringParams { public int unmeteredNetworkBonus = 1000; public int currentNetworkBonus = 20; public int secureNetworkBonus = 10; - public int lastSelectionBonus = 1999; + public int lastSelectionMinutes = 480; + public static final int MIN_MINUTES = 1; + public static final int MAX_MINUTES = Integer.MAX_VALUE / (60 * 1000); Values() { } @@ -125,6 +127,7 @@ public class ScoringParams { validateRange(horizon, MIN_HORIZON, MAX_HORIZON); validateRange(nud, MIN_NUD, MAX_NUD); validateRange(expid, MIN_EXPID, MAX_EXPID); + validateRange(lastSelectionMinutes, MIN_MINUTES, MAX_MINUTES); } private void validateRssiArray(int[] rssi) throws IllegalArgumentException { @@ -276,8 +279,8 @@ public class ScoringParams { R.integer.config_wifiFrameworkCurrentNetworkBonus); mVal.secureNetworkBonus = context.getResources().getInteger( R.integer.config_wifiFrameworkSecureNetworkBonus); - mVal.lastSelectionBonus = context.getResources().getInteger( - R.integer.config_wifiFrameworkLastSelectionBonus); + mVal.lastSelectionMinutes = context.getResources().getInteger( + R.integer.config_wifiFrameworkLastSelectionMinutes); mVal.pps[ACTIVE_TRAFFIC] = context.getResources().getInteger( R.integer.config_wifiFrameworkMinPacketPerSecondActiveTraffic); mVal.pps[HIGH_TRAFFIC] = context.getResources().getInteger( @@ -464,11 +467,11 @@ public class ScoringParams { } /* - * Returns the bonus for the network selection candidate score - * for a recently selected network. + * Returns the duration in minutes for a recently selected network + * to be strongly favored. */ - public int getLastSelectionBonus() { - return mVal.lastSelectionBonus; + public int getLastSelectionMinutes() { + return mVal.lastSelectionMinutes; } /** diff --git a/service/java/com/android/server/wifi/ThroughputScorer.java b/service/java/com/android/server/wifi/ThroughputScorer.java index 3d61beebd1..216dd858e0 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; @@ -36,6 +38,12 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { */ public static final int THROUGHPUT_SCORER_DEFAULT_EXPID = 42330058; + /** + * Base score that is large enough to override all of the other categories. + * This is applied to the last-select network for a limited duration. + */ + public static final int TOP_TIER_BASE_SCORE = 1_000_000; + private final ScoringParams mScoringParams; // config_wifi_framework_RSSI_SCORE_OFFSET @@ -44,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) { @@ -65,9 +76,6 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { int throughputBonusScore = calculateThroughputBonusScore(candidate); - int lastSelectionBonusScore = (int) - (candidate.getLastSelectionWeight() * mScoringParams.getLastSelectionBonus()); - int currentNetworkBoost = candidate.isCurrentNetwork() ? mScoringParams.getCurrentNetworkBonus() : 0; @@ -82,17 +90,39 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { int savedNetworkAward = candidate.isEphemeral() ? 0 : mScoringParams.getSavedNetworkBonus(); - int score = rssiBaseScore + throughputBonusScore + lastSelectionBonusScore - + currentNetworkBoost + securityAward + unmeteredAward + savedNetworkAward; + 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 + + trustedAward; + + if (candidate.getLastSelectionWeight() > 0.0) { + // Put a recently-selected network in a tier above everything else, + // but include rssi and throughput contributions for BSSID selection. + score = TOP_TIER_BASE_SCORE + rssiBaseScore + throughputBonusScore; + } if (DBG) { Log.d(TAG, " rssiScore: " + rssiBaseScore + " throughputScore: " + throughputBonusScore - + " lastSelectionBonus: " + lastSelectionBonusScore + " currentNetworkBoost: " + currentNetworkBoost + " 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 d62ef00cab..a264a49a7b 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 d0a97f5744..f6178f24c1 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; @@ -49,6 +50,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -69,15 +71,6 @@ public class WifiNetworkSelector { public static final int MINIMUM_NETWORK_SELECTION_INTERVAL_MS = 10 * 1000; /** - * Time that it takes for the boost given to the most recently user-selected - * network to decay to zero. - * - * In milliseconds. - */ - @VisibleForTesting - public static final int LAST_USER_SELECTION_DECAY_TO_ZERO_MS = 8 * 60 * 60 * 1000; - - /** * Connected score value used to decide whether a still-connected wifi should be treated * as unconnected when filtering scan results. */ @@ -762,14 +755,10 @@ public class WifiNetworkSelector { return null; } - // Determine the weight for the last user selection - final int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork(); - final double lastSelectionWeight = calculateLastSelectionWeight(); - 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); @@ -780,8 +769,9 @@ public class WifiNetworkSelector { NetworkNominator.NOMINATOR_ID_CURRENT, wifiInfo.getRssi(), wifiInfo.getFrequency(), - lastSelectionWeight, + calculateLastSelectionWeight(currentNetwork.networkId), WifiConfiguration.isMetered(currentNetwork, wifiInfo), + isFromCarrierOrPrivilegedApp(currentNetwork), 0 /* Mbps */); } for (NetworkNominator registeredNominator : mNominators) { @@ -794,13 +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, - (config.networkId == lastUserSelectedNetworkId) - ? lastSelectionWeight : 0.0, + calculateLastSelectionWeight(config.networkId), metered, + isFromCarrierOrPrivilegedApp(config), predictThroughput(scanDetail)); if (added) { mConnectableNetworks.add(Pair.create(scanDetail, config)); @@ -959,16 +950,14 @@ public class WifiNetworkSelector { } } - private double calculateLastSelectionWeight() { - final int lastUserSelectedNetworkId = mWifiConfigManager.getLastSelectedNetwork(); - double lastSelectionWeight = 0.0; - if (lastUserSelectedNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { - double timeDifference = mClock.getElapsedSinceBootMillis() - - mWifiConfigManager.getLastSelectedTimeStamp(); - double unclipped = 1.0 - (timeDifference / LAST_USER_SELECTION_DECAY_TO_ZERO_MS); - lastSelectionWeight = Math.min(Math.max(unclipped, 0.0), 1.0); - } - return lastSelectionWeight; + private double calculateLastSelectionWeight(int networkId) { + if (networkId != mWifiConfigManager.getLastSelectedNetwork()) return 0.0; + double timeDifference = mClock.getElapsedSinceBootMillis() + - mWifiConfigManager.getLastSelectedTimeStamp(); + long millis = TimeUnit.MINUTES.toMillis(mScoringParams.getLastSelectionMinutes()); + if (timeDifference >= millis) return 0.0; + double unclipped = 1.0 - (timeDifference / millis); + return Math.min(Math.max(unclipped, 0.0), 1.0); } private WifiCandidates.CandidateScorer getActiveCandidateScorer() { @@ -1045,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. * |