Snap for 6227479 from 3f9ddc30d980652f610f86959a3bf32669ff661e to rvc-release
Change-Id: I65b6bc752687d3530d7bc6b2167673374abbeb6d
This commit is contained in:
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.annotation.TestApi;
|
import android.annotation.TestApi;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
@@ -83,69 +84,10 @@ public final class NetworkScore implements Parcelable {
|
|||||||
uplinkBandwidthKBps = uplinkBandwidth;
|
uplinkBandwidthKBps = uplinkBandwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate whether a metrics codes for faster network is faster than another.
|
|
||||||
*
|
|
||||||
* This is a simple comparison of expected speeds. If either of the tested attributes
|
|
||||||
* are unknown, this returns zero. This implementation just assumes downlink bandwidth
|
|
||||||
* is more important than uplink bandwidth, which is more important than latency. This
|
|
||||||
* is not a very good way of evaluating network speed, but it's a start.
|
|
||||||
* TODO : do something more representative of how fast the network feels
|
|
||||||
*
|
|
||||||
* @param other the Metrics to evaluate against
|
|
||||||
* @return a negative integer, zero, or a positive integer as this metrics is worse than,
|
|
||||||
* equally good as (or unknown), or better than the passed Metrics.
|
|
||||||
* @see #compareToPreferringKnown(Metrics)
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
// Can't implement Comparable<Metrics> because this is @hide.
|
|
||||||
public int compareTo(@NonNull final Metrics other) {
|
|
||||||
if (downlinkBandwidthKBps != BANDWIDTH_UNKNOWN
|
|
||||||
&& other.downlinkBandwidthKBps != BANDWIDTH_UNKNOWN) {
|
|
||||||
if (downlinkBandwidthKBps > other.downlinkBandwidthKBps) return 1;
|
|
||||||
if (downlinkBandwidthKBps < other.downlinkBandwidthKBps) return -1;
|
|
||||||
}
|
|
||||||
if (uplinkBandwidthKBps != BANDWIDTH_UNKNOWN
|
|
||||||
&& other.uplinkBandwidthKBps != BANDWIDTH_UNKNOWN) {
|
|
||||||
if (uplinkBandwidthKBps > other.uplinkBandwidthKBps) return 1;
|
|
||||||
if (uplinkBandwidthKBps < other.uplinkBandwidthKBps) return -1;
|
|
||||||
}
|
|
||||||
if (latencyMs != LATENCY_UNKNOWN && other.latencyMs != LATENCY_UNKNOWN) {
|
|
||||||
// Latency : lower is better
|
|
||||||
if (latencyMs > other.latencyMs) return -1;
|
|
||||||
if (latencyMs < other.latencyMs) return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate whether a metrics codes for faster network is faster than another.
|
|
||||||
*
|
|
||||||
* This is a simple comparison of expected speeds. If either of the tested attributes
|
|
||||||
* are unknown, this prefers the known attributes. This implementation just assumes
|
|
||||||
* downlink bandwidth is more important than uplink bandwidth, which is more important than
|
|
||||||
* latency. This is not a very good way of evaluating network speed, but it's a start.
|
|
||||||
* TODO : do something more representative of how fast the network feels
|
|
||||||
*
|
|
||||||
* @param other the Metrics to evaluate against
|
|
||||||
* @return a negative integer, zero, or a positive integer as this metrics is worse than,
|
|
||||||
* equally good as (or unknown), or better than the passed Metrics.
|
|
||||||
* @see #compareTo(Metrics)
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public int compareToPreferringKnown(@NonNull final Metrics other) {
|
|
||||||
if (downlinkBandwidthKBps > other.downlinkBandwidthKBps) return 1;
|
|
||||||
if (downlinkBandwidthKBps < other.downlinkBandwidthKBps) return -1;
|
|
||||||
if (uplinkBandwidthKBps > other.uplinkBandwidthKBps) return 1;
|
|
||||||
if (uplinkBandwidthKBps < other.uplinkBandwidthKBps) return -1;
|
|
||||||
// Latency : lower is better
|
|
||||||
return -Integer.compare(latencyMs, other.latencyMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** toString */
|
/** toString */
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps
|
return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps
|
||||||
+ " uplinkBandwidth = " + uplinkBandwidthKBps;
|
+ "uplinkBandwidth = " + uplinkBandwidthKBps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -405,33 +347,6 @@ public final class NetworkScore implements Parcelable {
|
|||||||
return mLegacyScore;
|
return mLegacyScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the metrics to evaluate whether a network is faster than another.
|
|
||||||
*
|
|
||||||
* This is purely based on the metrics, and explicitly ignores policy or exiting. It's
|
|
||||||
* provided to get a decision on two networks when policy can not decide, or to evaluate
|
|
||||||
* how a network is expected to compare to another if it should validate.
|
|
||||||
*
|
|
||||||
* @param other the score to evaluate against
|
|
||||||
* @return whether this network is probably faster than the other
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public boolean probablyFasterThan(@NonNull final NetworkScore other) {
|
|
||||||
if (mLegacyScore > other.mLegacyScore) return true;
|
|
||||||
final int atEndToEnd = mEndToEndMetrics.compareTo(other.mEndToEndMetrics);
|
|
||||||
if (atEndToEnd > 0) return true;
|
|
||||||
if (atEndToEnd < 0) return false;
|
|
||||||
final int atLinkLayer = mLinkLayerMetrics.compareTo(other.mLinkLayerMetrics);
|
|
||||||
if (atLinkLayer > 0) return true;
|
|
||||||
if (atLinkLayer < 0) return false;
|
|
||||||
final int atEndToEndPreferringKnown =
|
|
||||||
mEndToEndMetrics.compareToPreferringKnown(other.mEndToEndMetrics);
|
|
||||||
if (atEndToEndPreferringKnown > 0) return true;
|
|
||||||
if (atEndToEndPreferringKnown < 0) return false;
|
|
||||||
// If this returns 0, neither is "probably faster" so just return false.
|
|
||||||
return mLinkLayerMetrics.compareToPreferringKnown(other.mLinkLayerMetrics) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Builder for NetworkScore. */
|
/** Builder for NetworkScore. */
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private int mPolicy = 0;
|
private int mPolicy = 0;
|
||||||
@@ -439,27 +354,17 @@ public final class NetworkScore implements Parcelable {
|
|||||||
private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN,
|
private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN,
|
||||||
Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN);
|
Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN);
|
||||||
@NonNull
|
@NonNull
|
||||||
private Metrics mEndToEndMetrics = new Metrics(Metrics.LATENCY_UNKNOWN,
|
private Metrics mEndToMetrics = new Metrics(Metrics.LATENCY_UNKNOWN,
|
||||||
Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN);
|
Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN);
|
||||||
private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH;
|
private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH;
|
||||||
private int mRange = RANGE_UNKNOWN;
|
private int mRange = RANGE_UNKNOWN;
|
||||||
private boolean mExiting = false;
|
private boolean mExiting = false;
|
||||||
private int mLegacyScore = 0;
|
private int mLegacyScore = 0;
|
||||||
|
@NonNull private Bundle mExtensions = new Bundle();
|
||||||
|
|
||||||
/** Create a new builder. */
|
/** Create a new builder. */
|
||||||
public Builder() { }
|
public Builder() { }
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
public Builder(@NonNull final NetworkScore source) {
|
|
||||||
mPolicy = source.mPolicy;
|
|
||||||
mLinkLayerMetrics = source.mLinkLayerMetrics;
|
|
||||||
mEndToEndMetrics = source.mEndToEndMetrics;
|
|
||||||
mSignalStrength = source.mSignalStrength;
|
|
||||||
mRange = source.mRange;
|
|
||||||
mExiting = source.mExiting;
|
|
||||||
mLegacyScore = source.mLegacyScore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a policy flag. */
|
/** Add a policy flag. */
|
||||||
@NonNull public Builder addPolicy(@Policy final int policy) {
|
@NonNull public Builder addPolicy(@Policy final int policy) {
|
||||||
mPolicy |= policy;
|
mPolicy |= policy;
|
||||||
@@ -480,7 +385,7 @@ public final class NetworkScore implements Parcelable {
|
|||||||
|
|
||||||
/** Set the end-to-end metrics. */
|
/** Set the end-to-end metrics. */
|
||||||
@NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) {
|
@NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) {
|
||||||
mEndToEndMetrics = endToEndMetrics;
|
mEndToMetrics = endToEndMetrics;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,7 +417,7 @@ public final class NetworkScore implements Parcelable {
|
|||||||
|
|
||||||
/** Build the NetworkScore object represented by this builder. */
|
/** Build the NetworkScore object represented by this builder. */
|
||||||
@NonNull public NetworkScore build() {
|
@NonNull public NetworkScore build() {
|
||||||
return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics,
|
return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToMetrics,
|
||||||
mSignalStrength, mRange, mExiting, mLegacyScore);
|
mSignalStrength, mRange, mExiting, mLegacyScore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3302,7 +3302,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
for (int i = 0; i < nai.numNetworkRequests(); i++) {
|
for (int i = 0; i < nai.numNetworkRequests(); i++) {
|
||||||
NetworkRequest request = nai.requestAt(i);
|
NetworkRequest request = nai.requestAt(i);
|
||||||
final NetworkRequestInfo nri = mNetworkRequests.get(request);
|
final NetworkRequestInfo nri = mNetworkRequests.get(request);
|
||||||
ensureRunningOnConnectivityServiceThread();
|
|
||||||
final NetworkAgentInfo currentNetwork = nri.mSatisfier;
|
final NetworkAgentInfo currentNetwork = nri.mSatisfier;
|
||||||
if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
|
if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
|
||||||
nri.mSatisfier = null;
|
nri.mSatisfier = null;
|
||||||
@@ -3454,18 +3453,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
// If this Network is already the highest scoring Network for a request, or if
|
// If this Network is already the highest scoring Network for a request, or if
|
||||||
// there is hope for it to become one if it validated, then it is needed.
|
// there is hope for it to become one if it validated, then it is needed.
|
||||||
ensureRunningOnConnectivityServiceThread();
|
|
||||||
if (nri.request.isRequest() && nai.satisfies(nri.request) &&
|
if (nri.request.isRequest() && nai.satisfies(nri.request) &&
|
||||||
(nai.isSatisfyingRequest(nri.request.requestId)
|
(nai.isSatisfyingRequest(nri.request.requestId) ||
|
||||||
// Note that canPossiblyBeat catches two important cases:
|
// Note that this catches two important cases:
|
||||||
// 1. Unvalidated slow networks will not be reaped when an unvalidated fast
|
// 1. Unvalidated cellular will not be reaped when unvalidated WiFi
|
||||||
// network is currently satisfying the request. This is desirable for example
|
// is currently satisfying the request. This is desirable when
|
||||||
// when cellular ends up validating but WiFi/Ethernet does not.
|
// cellular ends up validating but WiFi does not.
|
||||||
// 2. Fast networks will not be reaped when a validated slow network is
|
// 2. Unvalidated WiFi will not be reaped when validated cellular
|
||||||
// currently satisfying the request. This is desirable for example when
|
// is currently satisfying the request. This is desirable when
|
||||||
// Ethernet ends up validating and out scoring WiFi, or WiFi/Ethernet ends
|
// WiFi ends up validating and out scoring cellular.
|
||||||
// up validating and out scoring cellular.
|
nri.mSatisfier.getCurrentScore()
|
||||||
|| nai.canPossiblyBeat(nri.mSatisfier))) {
|
< nai.getCurrentScoreAsValidated())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3493,7 +3491,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
if (mNetworkRequests.get(nri.request) == null) {
|
if (mNetworkRequests.get(nri.request) == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ensureRunningOnConnectivityServiceThread();
|
|
||||||
if (nri.mSatisfier != null) {
|
if (nri.mSatisfier != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3531,7 +3528,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
mNetworkRequestInfoLogs.log("RELEASE " + nri);
|
mNetworkRequestInfoLogs.log("RELEASE " + nri);
|
||||||
if (nri.request.isRequest()) {
|
if (nri.request.isRequest()) {
|
||||||
boolean wasKept = false;
|
boolean wasKept = false;
|
||||||
ensureRunningOnConnectivityServiceThread();
|
|
||||||
final NetworkAgentInfo nai = nri.mSatisfier;
|
final NetworkAgentInfo nai = nri.mSatisfier;
|
||||||
if (nai != null) {
|
if (nai != null) {
|
||||||
boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
|
boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
|
||||||
@@ -3843,9 +3839,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
return avoidBadWifi();
|
return avoidBadWifi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void rematchForAvoidBadWifiUpdate() {
|
private void rematchForAvoidBadWifiUpdate() {
|
||||||
ensureRunningOnConnectivityServiceThread();
|
|
||||||
mixInAllNetworkScores();
|
|
||||||
rematchAllNetworksAndRequests();
|
rematchAllNetworksAndRequests();
|
||||||
for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
|
for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
|
||||||
if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
|
if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
|
||||||
@@ -7071,45 +7066,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-mixin all network scores.
|
|
||||||
* This is called when some global setting like avoidBadWifi has changed.
|
|
||||||
* TODO : remove this when all usages have been removed.
|
|
||||||
*/
|
|
||||||
private void mixInAllNetworkScores() {
|
|
||||||
ensureRunningOnConnectivityServiceThread();
|
|
||||||
for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
|
|
||||||
nai.setNetworkScore(mixInNetworkScore(nai, nai.getNetworkScore()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mix in the Connectivity-managed parts of the NetworkScore.
|
|
||||||
* @param nai The NAI this score applies to.
|
|
||||||
* @param sourceScore the score sent by the network agent, or the previous score of this NAI.
|
|
||||||
* @return A new score with the Connectivity-managed parts mixed in.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
private NetworkScore mixInNetworkScore(@NonNull final NetworkAgentInfo nai,
|
|
||||||
@NonNull final NetworkScore sourceScore) {
|
|
||||||
final NetworkScore.Builder score = new NetworkScore.Builder(sourceScore);
|
|
||||||
|
|
||||||
// TODO : this should be done in Telephony. It should be handled per-network because
|
|
||||||
// it's a carrier-dependent config.
|
|
||||||
if (nai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
|
|
||||||
if (mMultinetworkPolicyTracker.getAvoidBadWifi()) {
|
|
||||||
score.clearPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI);
|
|
||||||
} else {
|
|
||||||
score.addPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return score.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) {
|
private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) {
|
||||||
if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + ns);
|
if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + ns);
|
||||||
nai.setNetworkScore(mixInNetworkScore(nai, ns));
|
nai.setNetworkScore(ns);
|
||||||
rematchAllNetworksAndRequests();
|
rematchAllNetworksAndRequests();
|
||||||
sendUpdatedScoreToFactories(nai);
|
sendUpdatedScoreToFactories(nai);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.server.connectivity;
|
package com.android.server.connectivity;
|
||||||
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
|
|
||||||
import static android.net.NetworkCapabilities.transportNamesOf;
|
import static android.net.NetworkCapabilities.transportNamesOf;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
@@ -477,16 +475,24 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
|||||||
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the current score */
|
private int getCurrentScore(boolean pretendValidated) {
|
||||||
public int getCurrentScore() {
|
// TODO: We may want to refactor this into a NetworkScore class that takes a base score from
|
||||||
|
// the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
|
||||||
|
// score. The NetworkScore class would provide a nice place to centralize score constants
|
||||||
|
// so they are not scattered about the transports.
|
||||||
|
|
||||||
// If this network is explicitly selected and the user has decided to use it even if it's
|
// If this network is explicitly selected and the user has decided to use it even if it's
|
||||||
// unvalidated, give it the maximum score.
|
// unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly
|
||||||
if (networkAgentConfig.explicitlySelected && networkAgentConfig.acceptUnvalidated) {
|
// selected and we're trying to see what its score could be. This ensures that we don't tear
|
||||||
|
// down an explicitly selected network before the user gets a chance to prefer it when
|
||||||
|
// a higher-scoring network (e.g., Ethernet) is available.
|
||||||
|
if (networkAgentConfig.explicitlySelected
|
||||||
|
&& (networkAgentConfig.acceptUnvalidated || pretendValidated)) {
|
||||||
return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
|
return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int score = mNetworkScore.getLegacyScore();
|
int score = mNetworkScore.getLegacyScore();
|
||||||
if (!lastValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
|
if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
|
||||||
score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
|
score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
|
||||||
}
|
}
|
||||||
if (score < 0) score = 0;
|
if (score < 0) score = 0;
|
||||||
@@ -502,6 +508,18 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
|||||||
return isWifi && !avoidBadWifi && everValidated;
|
return isWifi && !avoidBadWifi && everValidated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the current score for this Network. This may be modified from what the
|
||||||
|
// NetworkAgent sent, as it has modifiers applied to it.
|
||||||
|
public int getCurrentScore() {
|
||||||
|
return getCurrentScore(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current score for this Network as if it was validated. This may be modified from
|
||||||
|
// what the NetworkAgent sent, as it has modifiers applied to it.
|
||||||
|
public int getCurrentScoreAsValidated() {
|
||||||
|
return getCurrentScore(true);
|
||||||
|
}
|
||||||
|
|
||||||
public void setNetworkScore(@NonNull NetworkScore ns) {
|
public void setNetworkScore(@NonNull NetworkScore ns) {
|
||||||
mNetworkScore = ns;
|
mNetworkScore = ns;
|
||||||
}
|
}
|
||||||
@@ -611,41 +629,6 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
|||||||
mLingering = false;
|
mLingering = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this NAI has any chance of ever beating this other agent.
|
|
||||||
*
|
|
||||||
* The chief use case of this is the decision to tear down this network. ConnectivityService
|
|
||||||
* tears down networks that don't satisfy any request, unless they have a chance to beat any
|
|
||||||
* existing satisfier.
|
|
||||||
*
|
|
||||||
* @param other the agent to beat
|
|
||||||
* @return whether this should be given more time to try and beat the other agent
|
|
||||||
* TODO : remove this and migrate to a ranker-based approach
|
|
||||||
*/
|
|
||||||
public boolean canPossiblyBeat(@NonNull final NetworkAgentInfo other) {
|
|
||||||
// Any explicitly selected network should be held on.
|
|
||||||
if (networkAgentConfig.explicitlySelected) return true;
|
|
||||||
// An outscored exiting network should be torn down.
|
|
||||||
if (mNetworkScore.isExiting()) return false;
|
|
||||||
// If this network is validated it can be torn down as it can't hope to be better than
|
|
||||||
// it already is.
|
|
||||||
if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return false;
|
|
||||||
// If neither network is validated, keep both until at least one does.
|
|
||||||
if (!other.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return true;
|
|
||||||
// If this network is not metered but the other is, it should be preferable if it validates.
|
|
||||||
if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)
|
|
||||||
&& !other.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the control comes here :
|
|
||||||
// • This network is neither exiting or explicitly selected
|
|
||||||
// • This network is not validated, but the other is
|
|
||||||
// • This network is metered, or both networks are unmetered
|
|
||||||
// Keep it if it's expected to be faster than the other., should it validate.
|
|
||||||
return mNetworkScore.probablyFasterThan(other.mNetworkScore);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dumpLingerTimers(PrintWriter pw) {
|
public void dumpLingerTimers(PrintWriter pw) {
|
||||||
for (LingerTimer timer : mLingerTimers) { pw.println(timer); }
|
for (LingerTimer timer : mLingerTimers) { pw.println(timer); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,19 +16,10 @@
|
|||||||
|
|
||||||
package com.android.server.connectivity;
|
package com.android.server.connectivity;
|
||||||
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
|
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
|
||||||
import static android.net.NetworkScore.POLICY_IGNORE_ON_WIFI;
|
|
||||||
|
|
||||||
import static com.android.internal.util.FunctionalUtils.findFirst;
|
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.net.NetworkCapabilities;
|
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,75 +31,20 @@ public class NetworkRanker {
|
|||||||
/**
|
/**
|
||||||
* Find the best network satisfying this request among the list of passed networks.
|
* Find the best network satisfying this request among the list of passed networks.
|
||||||
*/
|
*/
|
||||||
|
// Almost equivalent to Collections.max(nais), but allows returning null if no network
|
||||||
|
// satisfies the request.
|
||||||
@Nullable
|
@Nullable
|
||||||
public NetworkAgentInfo getBestNetwork(@NonNull final NetworkRequest request,
|
public NetworkAgentInfo getBestNetwork(@NonNull final NetworkRequest request,
|
||||||
@NonNull final Collection<NetworkAgentInfo> nais) {
|
@NonNull final Collection<NetworkAgentInfo> nais) {
|
||||||
final ArrayList<NetworkAgentInfo> candidates = new ArrayList<>(nais);
|
|
||||||
candidates.removeIf(nai -> !nai.satisfies(request));
|
|
||||||
|
|
||||||
// Enforce policy. The order in which the policy is computed is essential, because each
|
|
||||||
// step may remove some of the candidates. For example, filterValidated drops non-validated
|
|
||||||
// networks in presence of validated networks for INTERNET requests, but the bad wifi
|
|
||||||
// avoidance policy takes priority over this, so it must be done before.
|
|
||||||
filterVpn(candidates);
|
|
||||||
filterExplicitlySelected(candidates);
|
|
||||||
filterBadWifiAvoidance(candidates);
|
|
||||||
filterValidated(request, candidates);
|
|
||||||
|
|
||||||
NetworkAgentInfo bestNetwork = null;
|
NetworkAgentInfo bestNetwork = null;
|
||||||
int bestScore = Integer.MIN_VALUE;
|
int bestScore = Integer.MIN_VALUE;
|
||||||
for (final NetworkAgentInfo nai : candidates) {
|
for (final NetworkAgentInfo nai : nais) {
|
||||||
final int score = nai.getNetworkScore().getLegacyScore();
|
if (!nai.satisfies(request)) continue;
|
||||||
if (score > bestScore) {
|
if (nai.getCurrentScore() > bestScore) {
|
||||||
bestNetwork = nai;
|
bestNetwork = nai;
|
||||||
bestScore = score;
|
bestScore = nai.getCurrentScore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bestNetwork;
|
return bestNetwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a network is a VPN it has priority.
|
|
||||||
private void filterVpn(@NonNull final ArrayList<NetworkAgentInfo> candidates) {
|
|
||||||
final NetworkAgentInfo vpn = findFirst(candidates,
|
|
||||||
nai -> nai.networkCapabilities.hasTransport(TRANSPORT_VPN));
|
|
||||||
if (null == vpn) return; // No VPN : this policy doesn't apply.
|
|
||||||
candidates.removeIf(nai -> !nai.networkCapabilities.hasTransport(TRANSPORT_VPN));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If some network is explicitly selected and set to accept unvalidated connectivity, then
|
|
||||||
// drop all networks that are not explicitly selected.
|
|
||||||
private void filterExplicitlySelected(
|
|
||||||
@NonNull final ArrayList<NetworkAgentInfo> candidates) {
|
|
||||||
final NetworkAgentInfo explicitlySelected = findFirst(candidates,
|
|
||||||
nai -> nai.networkAgentConfig.explicitlySelected
|
|
||||||
&& nai.networkAgentConfig.acceptUnvalidated);
|
|
||||||
if (null == explicitlySelected) return; // No explicitly selected network accepting unvalid
|
|
||||||
candidates.removeIf(nai -> !nai.networkAgentConfig.explicitlySelected);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI.
|
|
||||||
private void filterBadWifiAvoidance(@NonNull final ArrayList<NetworkAgentInfo> candidates) {
|
|
||||||
final NetworkAgentInfo wifi = findFirst(candidates,
|
|
||||||
nai -> nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
|
||||||
&& nai.everValidated
|
|
||||||
// Horrible hack : there is old UI that will let a user say they want to
|
|
||||||
// override the policy only for this network only at this time and it
|
|
||||||
// feeds into the following member. This old UI should probably be removed
|
|
||||||
// but for now keep backward compatibility.
|
|
||||||
&& !nai.avoidUnvalidated);
|
|
||||||
if (null == wifi) return; // No wifi : this policy doesn't apply
|
|
||||||
candidates.removeIf(nai -> nai.getNetworkScore().hasPolicy(POLICY_IGNORE_ON_WIFI));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If some network is validated and the request asks for INTERNET, drop all networks that are
|
|
||||||
// not validated.
|
|
||||||
private void filterValidated(@NonNull final NetworkRequest request,
|
|
||||||
@NonNull final ArrayList<NetworkAgentInfo> candidates) {
|
|
||||||
if (!request.hasCapability(NET_CAPABILITY_INTERNET)) return;
|
|
||||||
final NetworkAgentInfo validated = findFirst(candidates,
|
|
||||||
nai -> nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
|
|
||||||
if (null == validated) return; // No validated network
|
|
||||||
candidates.removeIf(nai ->
|
|
||||||
!nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2058,15 +2058,14 @@ public class ConnectivityServiceTest {
|
|||||||
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
|
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
|
||||||
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
|
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
|
||||||
|
|
||||||
// Bring up validated wifi.
|
// Bring up wifi with a score of 70.
|
||||||
// Cell is lingered because it would not satisfy any request, even if it validated.
|
// Cell is lingered because it would not satisfy any request, even if it validated.
|
||||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
mWiFiNetworkAgent.connect(true); // Score: 60
|
mWiFiNetworkAgent.adjustScore(50);
|
||||||
|
mWiFiNetworkAgent.connect(false); // Score: 70
|
||||||
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
||||||
// TODO: Investigate sending validated before losing.
|
|
||||||
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
|
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
|
||||||
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
|
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
||||||
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
|
|
||||||
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
|
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
|
||||||
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
|
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
|
||||||
|
|
||||||
@@ -5850,7 +5849,7 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
mWiFiNetworkAgent.connect(true);
|
mWiFiNetworkAgent.connect(true);
|
||||||
trustedCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
|
trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
|
||||||
verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
|
verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
|
||||||
reset(mNetworkManagementService);
|
reset(mNetworkManagementService);
|
||||||
|
|
||||||
|
|||||||
@@ -16,18 +16,13 @@
|
|||||||
|
|
||||||
package com.android.server.connectivity
|
package com.android.server.connectivity
|
||||||
|
|
||||||
import android.net.ConnectivityManager.TYPE_WIFI
|
|
||||||
import android.net.LinkProperties
|
|
||||||
import android.net.Network
|
|
||||||
import android.net.NetworkAgentConfig
|
|
||||||
import android.net.NetworkCapabilities
|
|
||||||
import android.net.NetworkInfo
|
|
||||||
import android.net.NetworkRequest
|
import android.net.NetworkRequest
|
||||||
import android.net.NetworkScore
|
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import androidx.test.runner.AndroidJUnit4
|
import androidx.test.runner.AndroidJUnit4
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentMatchers.any
|
||||||
|
import org.mockito.Mockito.doReturn
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
@@ -37,24 +32,9 @@ import kotlin.test.assertNull
|
|||||||
class NetworkRankerTest {
|
class NetworkRankerTest {
|
||||||
private val ranker = NetworkRanker()
|
private val ranker = NetworkRanker()
|
||||||
|
|
||||||
private fun makeNai(satisfy: Boolean, score: Int) = object : NetworkAgentInfo(
|
private fun makeNai(satisfy: Boolean, score: Int) = mock(NetworkAgentInfo::class.java).also {
|
||||||
null /* messenger */,
|
doReturn(satisfy).`when`(it).satisfies(any())
|
||||||
null /* asyncChannel*/,
|
doReturn(score).`when`(it).currentScore
|
||||||
Network(100),
|
|
||||||
NetworkInfo(TYPE_WIFI, 0 /* subtype */, "" /* typename */, "" /* subtypename */),
|
|
||||||
LinkProperties(),
|
|
||||||
NetworkCapabilities(),
|
|
||||||
NetworkScore.Builder().setLegacyScore(score).build(),
|
|
||||||
null /* context */,
|
|
||||||
null /* handler */,
|
|
||||||
NetworkAgentConfig(),
|
|
||||||
null /* connectivityService */,
|
|
||||||
null /* netd */,
|
|
||||||
null /* dnsResolver */,
|
|
||||||
null /* networkManagementService */,
|
|
||||||
0 /* factorySerialNumber */) {
|
|
||||||
override fun satisfies(request: NetworkRequest?): Boolean = satisfy
|
|
||||||
override fun getCurrentScore(): Int = score
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user