Merge changes from topics "enable-policy-ranking", "sendNetworkScore"
* changes:
Adjust a test for policy scoring
Enable policy ranking
Add CTS to verify NetworkAgent#setLingerDuration
Allow network providers to set the linger duration.
Fix nascent timer never get removed
[NS13] Remove the last usage of the legacy int
Add documentation
Use filter from CollectionUtils.
Fix a bug where updates of offers won't find existing offers
[NS12] Address comments on NS09
[NS11] Fix yieldToBadWifi over the policy scoring
Add doc for NetworkScore#getLegacyInt
Expose sendNetworkScore that takes a NetworkScore
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 27836c1..d1d51da 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -232,12 +232,14 @@
method @NonNull public android.net.Network register();
method public final void sendLinkProperties(@NonNull android.net.LinkProperties);
method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
+ method public final void sendNetworkScore(@NonNull android.net.NetworkScore);
method public final void sendNetworkScore(@IntRange(from=0, to=99) int);
method public final void sendQosCallbackError(int, int);
method public final void sendQosSessionAvailable(int, int, @NonNull android.net.QosSessionAttributes);
method public final void sendQosSessionLost(int, int, int);
method public final void sendSocketKeepaliveEvent(int, int);
method @Deprecated public void setLegacySubtype(int, @NonNull String);
+ method public void setLingerDuration(@NonNull java.time.Duration);
method public void setTeardownDelayMillis(@IntRange(from=0, to=0x1388) int);
method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
method public void unregister();
diff --git a/framework/src/android/net/INetworkAgentRegistry.aidl b/framework/src/android/net/INetworkAgentRegistry.aidl
index 26cb1ed..9a58add 100644
--- a/framework/src/android/net/INetworkAgentRegistry.aidl
+++ b/framework/src/android/net/INetworkAgentRegistry.aidl
@@ -42,4 +42,5 @@
void sendQosSessionLost(int qosCallbackId, in QosSession session);
void sendQosCallbackError(int qosCallbackId, int exceptionType);
void sendTeardownDelayMs(int teardownDelayMs);
+ void sendLingerDuration(int durationMs);
}
diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java
index f65acdd..adcf338 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
@@ -106,6 +107,9 @@
private final String LOG_TAG;
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ /** @hide */
+ @TestApi
+ public static final int MIN_LINGER_TIMER_MS = 2000;
private final ArrayList<RegistryAction> mPreConnectedQueue = new ArrayList<>();
private volatile long mLastBwRefreshTime = 0;
private static final long BW_REFRESH_MIN_WIN_MS = 500;
@@ -391,6 +395,15 @@
*/
public static final int CMD_NETWORK_DESTROYED = BASE + 23;
+ /**
+ * Sent by the NetworkAgent to ConnectivityService to set the linger duration for this network
+ * agent.
+ * arg1 = the linger duration, represents by {@link Duration}.
+ *
+ * @hide
+ */
+ public static final int EVENT_LINGER_DURATION_CHANGED = BASE + 24;
+
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
config.legacyTypeName, config.legacySubTypeName);
@@ -956,7 +969,6 @@
* Must be called by the agent to update the score of this network.
*
* @param score the new score.
- * @hide TODO : unhide when impl is complete
*/
public final void sendNetworkScore(@NonNull NetworkScore score) {
Objects.requireNonNull(score);
@@ -1288,6 +1300,22 @@
queueOrSendMessage(ra -> ra.sendQosCallbackError(qosCallbackId, exceptionType));
}
+ /**
+ * Set the linger duration for this network agent.
+ * @param duration the delay between the moment the network becomes unneeded and the
+ * moment the network is disconnected or moved into the background.
+ * Note that If this duration has greater than millisecond precision, then
+ * the internal implementation will drop any excess precision.
+ */
+ public void setLingerDuration(@NonNull final Duration duration) {
+ Objects.requireNonNull(duration);
+ final long durationMs = duration.toMillis();
+ if (durationMs < MIN_LINGER_TIMER_MS || durationMs > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("Duration must be within ["
+ + MIN_LINGER_TIMER_MS + "," + Integer.MAX_VALUE + "]ms");
+ }
+ queueOrSendMessage(ra -> ra.sendLingerDuration((int) durationMs));
+ }
/** @hide */
protected void log(final String s) {
diff --git a/framework/src/android/net/NetworkProvider.java b/framework/src/android/net/NetworkProvider.java
index cfb7325..0665af5 100644
--- a/framework/src/android/net/NetworkProvider.java
+++ b/framework/src/android/net/NetworkProvider.java
@@ -167,7 +167,15 @@
ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request);
}
- /** @hide */
+ /**
+ * A callback for parties registering a NetworkOffer.
+ *
+ * This is used with {@link ConnectivityManager#offerNetwork}. When offering a network,
+ * the system will use this callback to inform the caller that a network corresponding to
+ * this offer is needed or unneeded.
+ *
+ * @hide
+ */
@SystemApi
public interface NetworkOfferCallback {
/**
diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java
index 0dee225..7be7deb 100644
--- a/framework/src/android/net/NetworkScore.java
+++ b/framework/src/android/net/NetworkScore.java
@@ -48,7 +48,14 @@
})
public @interface KeepConnectedReason { }
+ /**
+ * Do not keep this network connected if there is no outstanding request for it.
+ */
public static final int KEEP_CONNECTED_NONE = 0;
+ /**
+ * Keep this network connected even if there is no outstanding request for it, because it
+ * is being considered for handover.
+ */
public static final int KEEP_CONNECTED_FOR_HANDOVER = 1;
// Agent-managed policies
@@ -93,6 +100,10 @@
mKeepConnectedReason = in.readInt();
}
+ /**
+ * Get the legacy int score embedded in this NetworkScore.
+ * @see Builder#setLegacyInt(int)
+ */
public int getLegacyInt() {
return mLegacyInt;
}
@@ -212,7 +223,9 @@
/**
* Sets the legacy int for this score.
*
- * Do not rely on this. It will be gone by the time S is released.
+ * This will be used for measurements and logs, but will no longer be used for ranking
+ * networks against each other. Callers that existed before Android S should send what
+ * they used to send as the int score.
*
* @param score the legacy int
* @return this
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index f57761f..eb7dccc 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -1400,8 +1400,8 @@
new NetworkInfo(TYPE_NONE, 0, "", ""),
new LinkProperties(), new NetworkCapabilities(),
new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
- new NetworkAgentConfig(), this, null, null, 0, INVALID_UID, mQosCallbackTracker,
- mDeps);
+ new NetworkAgentConfig(), this, null, null, 0, INVALID_UID,
+ mLingerDelayMs, mQosCallbackTracker, mDeps);
}
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -3234,6 +3234,11 @@
} else {
logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1);
}
+ break;
+ }
+ case NetworkAgent.EVENT_LINGER_DURATION_CHANGED: {
+ nai.setLingerDuration((int) arg.second);
+ break;
}
}
}
@@ -4038,17 +4043,16 @@
// multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request
// is important so as to not evaluate lower priority requests further in
// nri.mRequests.
- final boolean isNetworkNeeded = candidate.isSatisfyingRequest(req.requestId)
- // Note that this catches two important cases:
- // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
- // is currently satisfying the request. This is desirable when
- // cellular ends up validating but WiFi does not.
- // 2. Unvalidated WiFi will not be reaped when validated cellular
- // is currently satisfying the request. This is desirable when
- // WiFi ends up validating and out scoring cellular.
- || nri.getSatisfier().getCurrentScore()
- < candidate.getCurrentScoreAsValidated();
- return isNetworkNeeded;
+ final NetworkAgentInfo champion = req.equals(nri.getActiveRequest())
+ ? nri.getSatisfier() : null;
+ // Note that this catches two important cases:
+ // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
+ // is currently satisfying the request. This is desirable when
+ // cellular ends up validating but WiFi does not.
+ // 2. Unvalidated WiFi will not be reaped when validated cellular
+ // is currently satisfying the request. This is desirable when
+ // WiFi ends up validating and out scoring cellular.
+ return mNetworkRanker.mightBeat(req, champion, candidate.getValidatedScoreable());
}
}
@@ -4305,7 +4309,7 @@
// network, we should respect the user's option and don't need to popup the
// PARTIAL_CONNECTIVITY notification to user again.
nai.networkAgentConfig.acceptPartialConnectivity = accept;
- nai.updateScoreForNetworkAgentConfigUpdate();
+ nai.updateScoreForNetworkAgentUpdate();
rematchAllNetworksAndRequests();
}
@@ -4373,6 +4377,7 @@
}
if (!nai.avoidUnvalidated) {
nai.avoidUnvalidated = true;
+ nai.updateScoreForNetworkAgentUpdate();
rematchAllNetworksAndRequests();
}
}
@@ -4480,7 +4485,7 @@
private void updateAvoidBadWifi() {
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
- nai.updateScoreForNetworkAgentConfigUpdate();
+ nai.updateScoreForNetworkAgentUpdate();
}
rematchAllNetworksAndRequests();
}
@@ -6597,7 +6602,8 @@
final NetworkAgentInfo nai = new NetworkAgentInfo(na,
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
- this, mNetd, mDnsResolver, providerId, uid, mQosCallbackTracker, mDeps);
+ this, mNetd, mDnsResolver, providerId, uid, mLingerDelayMs,
+ mQosCallbackTracker, mDeps);
// Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
processCapabilitiesFromAgent(nai, nc);
@@ -6697,7 +6703,7 @@
@NonNull final INetworkOfferCallback callback) {
ensureRunningOnConnectivityServiceThread();
for (final NetworkOfferInfo noi : mNetworkOffers) {
- if (noi.offer.callback.equals(callback)) return noi;
+ if (noi.offer.callback.asBinder().equals(callback.asBinder())) return noi;
}
return null;
}
@@ -7255,6 +7261,7 @@
final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
updateUids(nai, prevNc, newNc);
+ nai.updateScoreForNetworkAgentUpdate();
if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
// If the requestable capabilities haven't changed, and the score hasn't changed, then
@@ -7840,7 +7847,7 @@
log(" accepting network in place of " + previousSatisfier.toShortString());
}
previousSatisfier.removeRequest(previousRequest.requestId);
- previousSatisfier.lingerRequest(previousRequest.requestId, now, mLingerDelayMs);
+ previousSatisfier.lingerRequest(previousRequest.requestId, now);
} else {
if (VDBG || DDBG) log(" accepting network in place of null");
}
@@ -7850,6 +7857,7 @@
// all networks except in the case of an underlying network for a VCN.
if (newSatisfier.isNascent()) {
newSatisfier.unlingerRequest(NetworkRequest.REQUEST_ID_NONE);
+ newSatisfier.unsetInactive();
}
// if newSatisfier is not null, then newRequest may not be null.
@@ -7885,7 +7893,7 @@
@NonNull final Collection<NetworkRequestInfo> networkRequests) {
final NetworkReassignment changes = new NetworkReassignment();
- // Gather the list of all relevant agents and sort them by score.
+ // Gather the list of all relevant agents.
final ArrayList<NetworkAgentInfo> nais = new ArrayList<>();
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
if (!nai.everConnected) {
@@ -8354,6 +8362,7 @@
// But it will be removed as soon as the network satisfies a request for the first time.
networkAgent.lingerRequest(NetworkRequest.REQUEST_ID_NONE,
SystemClock.elapsedRealtime(), mNascentDelayMs);
+ networkAgent.setInactive();
// Consider network even though it is not yet validated.
rematchAllNetworksAndRequests();
diff --git a/service/src/com/android/server/connectivity/FullScore.java b/service/src/com/android/server/connectivity/FullScore.java
index a8a83fc..14cec09 100644
--- a/service/src/com/android/server/connectivity/FullScore.java
+++ b/service/src/com/android/server/connectivity/FullScore.java
@@ -91,17 +91,26 @@
/** @hide */
public static final int POLICY_IS_INVINCIBLE = 58;
+ // This network has been validated at least once since it was connected, but not explicitly
+ // avoided in UI.
+ // TODO : remove setAvoidUnvalidated and instead disconnect the network when the user
+ // chooses to move away from this network, and remove this flag.
+ /** @hide */
+ public static final int POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD = 57;
+
// To help iterate when printing
@VisibleForTesting
- static final int MIN_CS_MANAGED_POLICY = POLICY_IS_INVINCIBLE;
+ static final int MIN_CS_MANAGED_POLICY = POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD;
@VisibleForTesting
static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED;
// Mask for policies in NetworkScore. This should have all bits managed by NetworkScore set
// and all bits managed by FullScore unset. As bits are handled from 0 up in NetworkScore and
- // from 63 down in FullScore, cut at the 32rd bit for simplicity, but change this if some day
+ // from 63 down in FullScore, cut at the 32nd bit for simplicity, but change this if some day
// there are more than 32 bits handled on either side.
- private static final int EXTERNAL_POLICIES_MASK = 0x0000FFFF;
+ // YIELD_TO_BAD_WIFI is temporarily handled by ConnectivityService.
+ private static final long EXTERNAL_POLICIES_MASK =
+ 0x00000000FFFFFFFFL & ~(1L << POLICY_YIELD_TO_BAD_WIFI);
@VisibleForTesting
static @NonNull String policyNameOf(final int policy) {
@@ -115,6 +124,7 @@
case POLICY_TRANSPORT_PRIMARY: return "TRANSPORT_PRIMARY";
case POLICY_EXITING: return "EXITING";
case POLICY_IS_INVINCIBLE: return "INVINCIBLE";
+ case POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD: return "EVER_VALIDATED";
}
throw new IllegalArgumentException("Unknown policy : " + policy);
}
@@ -137,6 +147,7 @@
* @param score the score supplied by the agent
* @param caps the NetworkCapabilities of the network
* @param config the NetworkAgentConfig of the network
+ * @param everValidated whether this network has ever validated
* @param yieldToBadWiFi whether this network yields to a previously validated wifi gone bad
* @return a FullScore that is appropriate to use for ranking.
*/
@@ -145,12 +156,13 @@
// connectivity for backward compatibility.
public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
@NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config,
- final boolean yieldToBadWiFi) {
+ final boolean everValidated, final boolean yieldToBadWiFi) {
return withPolicies(score.getLegacyInt(), score.getPolicies(),
score.getKeepConnectedReason(),
caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ everValidated,
config.explicitlySelected,
config.acceptUnvalidated,
yieldToBadWiFi,
@@ -179,6 +191,8 @@
// Prospective scores are always unmetered, because unmetered networks are stronger
// than metered networks, and it's not known in advance whether the network is metered.
final boolean unmetered = true;
+ // If the offer may validate, then it should be considered to have validated at some point
+ final boolean everValidated = mayValidate;
// The network hasn't been chosen by the user (yet, at least).
final boolean everUserSelected = false;
// Don't assume the user will accept unvalidated connectivity.
@@ -189,8 +203,8 @@
// score.
final boolean invincible = score.getLegacyInt() > NetworkRanker.LEGACY_INT_MAX;
return withPolicies(score.getLegacyInt(), score.getPolicies(), KEEP_CONNECTED_NONE,
- mayValidate, vpn, unmetered, everUserSelected, acceptUnvalidated, yieldToBadWiFi,
- invincible);
+ mayValidate, vpn, unmetered, everValidated, everUserSelected, acceptUnvalidated,
+ yieldToBadWiFi, invincible);
}
/**
@@ -204,11 +218,14 @@
// telephony factory, so that it depends on the carrier. For now this is handled by
// connectivity for backward compatibility.
public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
- @NonNull final NetworkAgentConfig config, final boolean yieldToBadWifi) {
+ @NonNull final NetworkAgentConfig config,
+ final boolean everValidated,
+ final boolean yieldToBadWifi) {
return withPolicies(mLegacyInt, mPolicies, mKeepConnectedReason,
caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ everValidated,
config.explicitlySelected,
config.acceptUnvalidated,
yieldToBadWifi,
@@ -224,6 +241,7 @@
final boolean isValidated,
final boolean isVpn,
final boolean isUnmetered,
+ final boolean everValidated,
final boolean everUserSelected,
final boolean acceptUnvalidated,
final boolean yieldToBadWiFi,
@@ -232,6 +250,7 @@
| (isValidated ? 1L << POLICY_IS_VALIDATED : 0)
| (isVpn ? 1L << POLICY_IS_VPN : 0)
| (isUnmetered ? 1L << POLICY_IS_UNMETERED : 0)
+ | (everValidated ? 1L << POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD : 0)
| (everUserSelected ? 1L << POLICY_EVER_USER_SELECTED : 0)
| (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0)
| (yieldToBadWiFi ? 1L << POLICY_YIELD_TO_BAD_WIFI : 0)
@@ -240,6 +259,14 @@
}
/**
+ * Returns this score but validated.
+ */
+ public FullScore asValidated() {
+ return new FullScore(mLegacyInt, mPolicies | (1L << POLICY_IS_VALIDATED),
+ mKeepConnectedReason);
+ }
+
+ /**
* For backward compatibility, get the legacy int.
* This will be removed before S is published.
*/
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index 5d793fd..18becd4 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -59,6 +59,7 @@
import com.android.server.ConnectivityService;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
@@ -281,6 +282,9 @@
*/
public static final int ARG_AGENT_SUCCESS = 1;
+ // How long this network should linger for.
+ private int mLingerDurationMs;
+
// All inactivity timers for this network, sorted by expiry time. A timer is added whenever
// a request is moved to a network with a better score, regardless of whether the network is or
// was lingering or not. An inactivity timer is also added when a network connects
@@ -349,7 +353,8 @@
@NonNull NetworkScore score, Context context,
Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
- QosCallbackTracker qosCallbackTracker, ConnectivityService.Dependencies deps) {
+ int lingerDurationMs, QosCallbackTracker qosCallbackTracker,
+ ConnectivityService.Dependencies deps) {
Objects.requireNonNull(net);
Objects.requireNonNull(info);
Objects.requireNonNull(lp);
@@ -370,6 +375,7 @@
mHandler = handler;
this.factorySerialNumber = factorySerialNumber;
this.creatorUid = creatorUid;
+ mLingerDurationMs = lingerDurationMs;
mQosCallbackTracker = qosCallbackTracker;
}
@@ -685,6 +691,12 @@
mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
}
+
+ @Override
+ public void sendLingerDuration(final int durationMs) {
+ mHandler.obtainMessage(NetworkAgent.EVENT_LINGER_DURATION_CHANGED,
+ new Pair<>(NetworkAgentInfo.this, durationMs)).sendToTarget();
+ }
}
/**
@@ -707,7 +719,8 @@
@NonNull final NetworkCapabilities nc) {
final NetworkCapabilities oldNc = networkCapabilities;
networkCapabilities = nc;
- mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, everValidatedForYield(),
+ yieldToBadWiFi());
final NetworkMonitorManager nm = mNetworkMonitor;
if (nm != null) {
nm.notifyNetworkCapabilitiesChanged(nc);
@@ -893,7 +906,7 @@
// Caller must not mutate. This method is called frequently and making a defensive copy
// would be too expensive. This is used by NetworkRanker.Scoreable, so it can be compared
// against other scoreables.
- @Override public NetworkCapabilities getCaps() {
+ @Override public NetworkCapabilities getCapsNoCopy() {
return networkCapabilities;
}
@@ -919,7 +932,7 @@
*/
public void setScore(final NetworkScore score) {
mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig,
- yieldToBadWiFi());
+ everValidatedForYield(), yieldToBadWiFi());
}
/**
@@ -927,8 +940,33 @@
*
* Call this after updating the network agent config.
*/
- public void updateScoreForNetworkAgentConfigUpdate() {
- mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
+ public void updateScoreForNetworkAgentUpdate() {
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig,
+ everValidatedForYield(), yieldToBadWiFi());
+ }
+
+ private boolean everValidatedForYield() {
+ return everValidated && !avoidUnvalidated;
+ }
+
+ /**
+ * Returns a Scoreable identical to this NAI, but validated.
+ *
+ * This is useful to probe what scoring would be if this network validated, to know
+ * whether to provisionally keep a network that may or may not validate.
+ *
+ * @return a Scoreable identical to this NAI, but validated.
+ */
+ public NetworkRanker.Scoreable getValidatedScoreable() {
+ return new NetworkRanker.Scoreable() {
+ @Override public FullScore getScore() {
+ return mScore.asValidated();
+ }
+
+ @Override public NetworkCapabilities getCapsNoCopy() {
+ return networkCapabilities;
+ }
+ };
}
/**
@@ -948,13 +986,14 @@
/**
* Sets the specified requestId to linger on this network for the specified time. Called by
- * ConnectivityService when the request is moved to another network with a higher score, or
+ * ConnectivityService when any request is moved to another network with a higher score, or
* when a network is newly created.
*
* @param requestId The requestId of the request that no longer need to be served by this
* network. Or {@link NetworkRequest.REQUEST_ID_NONE} if this is the
- * {@code LingerTimer} for a newly created network.
+ * {@code InactivityTimer} for a newly created network.
*/
+ // TODO: Consider creating a dedicated function for nascent network, e.g. start/stopNascent.
public void lingerRequest(int requestId, long now, long duration) {
if (mInactivityTimerForRequest.get(requestId) != null) {
// Cannot happen. Once a request is lingering on a particular network, we cannot
@@ -970,6 +1009,19 @@
}
/**
+ * Sets the specified requestId to linger on this network for the timeout set when
+ * initializing or modified by {@link #setLingerDuration(int)}. Called by
+ * ConnectivityService when any request is moved to another network with a higher score.
+ *
+ * @param requestId The requestId of the request that no longer need to be served by this
+ * network.
+ * @param now current system timestamp obtained by {@code SystemClock.elapsedRealtime}.
+ */
+ public void lingerRequest(int requestId, long now) {
+ lingerRequest(requestId, now, mLingerDurationMs);
+ }
+
+ /**
* Cancel lingering. Called by ConnectivityService when a request is added to this network.
* Returns true if the given requestId was lingering on this network, false otherwise.
*/
@@ -1006,6 +1058,7 @@
}
if (newExpiry > 0) {
+ // If the newExpiry timestamp is in the past, the wakeup message will fire immediately.
mInactivityMessage = new WakeupMessage(
mContext, mHandler,
"NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
@@ -1035,8 +1088,33 @@
}
/**
- * Return whether the network is just connected and about to be torn down because of not
- * satisfying any request.
+ * Set the linger duration for this NAI.
+ * @param durationMs The new linger duration, in milliseconds.
+ */
+ public void setLingerDuration(final int durationMs) {
+ final long diff = durationMs - mLingerDurationMs;
+ final ArrayList<InactivityTimer> newTimers = new ArrayList<>();
+ for (final InactivityTimer timer : mInactivityTimers) {
+ if (timer.requestId == NetworkRequest.REQUEST_ID_NONE) {
+ // Don't touch nascent timer, re-add as is.
+ newTimers.add(timer);
+ } else {
+ newTimers.add(new InactivityTimer(timer.requestId, timer.expiryMs + diff));
+ }
+ }
+ mInactivityTimers.clear();
+ mInactivityTimers.addAll(newTimers);
+ updateInactivityTimer();
+ mLingerDurationMs = durationMs;
+ }
+
+ /**
+ * Return whether the network satisfies no request, but is still being kept up
+ * because it has just connected less than
+ * {@code ConnectivityService#DEFAULT_NASCENT_DELAY_MS}ms ago and is thus still considered
+ * nascent. Note that nascent mechanism uses inactivity timer which isn't
+ * associated with a request. Thus, use {@link NetworkRequest#REQUEST_ID_NONE} to identify it.
+ *
*/
public boolean isNascent() {
return mInactive && mInactivityTimers.size() == 1
diff --git a/service/src/com/android/server/connectivity/NetworkOffer.java b/service/src/com/android/server/connectivity/NetworkOffer.java
index 5336593..8285e7a 100644
--- a/service/src/com/android/server/connectivity/NetworkOffer.java
+++ b/service/src/com/android/server/connectivity/NetworkOffer.java
@@ -76,7 +76,7 @@
/**
* Get the capabilities filter of this offer
*/
- @Override @NonNull public NetworkCapabilities getCaps() {
+ @Override @NonNull public NetworkCapabilities getCapsNoCopy() {
return caps;
}
@@ -133,7 +133,7 @@
* @param previousOffer the previous offer
*/
public void migrateFrom(@NonNull final NetworkOffer previousOffer) {
- if (!callback.equals(previousOffer.callback)) {
+ if (!callback.asBinder().equals(previousOffer.callback.asBinder())) {
throw new IllegalArgumentException("Can only migrate from a previous version of"
+ " the same offer");
}
diff --git a/service/src/com/android/server/connectivity/NetworkRanker.java b/service/src/com/android/server/connectivity/NetworkRanker.java
index 3aaff59..e839837 100644
--- a/service/src/com/android/server/connectivity/NetworkRanker.java
+++ b/service/src/com/android/server/connectivity/NetworkRanker.java
@@ -24,8 +24,10 @@
import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY;
import static android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI;
+import static com.android.net.module.util.CollectionUtils.filter;
import static com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED;
import static com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED;
+import static com.android.server.connectivity.FullScore.POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD;
import static com.android.server.connectivity.FullScore.POLICY_IS_INVINCIBLE;
import static com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED;
import static com.android.server.connectivity.FullScore.POLICY_IS_VPN;
@@ -58,25 +60,13 @@
/** Get score of this scoreable */
FullScore getScore();
/** Get capabilities of this scoreable */
- NetworkCapabilities getCaps();
+ NetworkCapabilities getCapsNoCopy();
}
- private static final boolean USE_POLICY_RANKING = false;
+ private static final boolean USE_POLICY_RANKING = true;
public NetworkRanker() { }
- // TODO : move to module utils CollectionUtils.
- @NonNull private static <T> ArrayList<T> filter(@NonNull final Collection<T> source,
- @NonNull final Predicate<T> test) {
- final ArrayList<T> matches = new ArrayList<>();
- for (final T e : source) {
- if (test.test(e)) {
- matches.add(e);
- }
- }
- return matches;
- }
-
/**
* Find the best network satisfying this request among the list of passed networks.
*/
@@ -158,11 +148,12 @@
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted);
- // Yield to bad wifi policy : if any wifi has ever been validated, keep only networks
- // that don't yield to such a wifi network.
+ // Yield to bad wifi policy : if any wifi has ever been validated (even if it's now
+ // unvalidated), and unless it's been explicitly avoided when bad in UI, then keep only
+ // networks that don't yield to such a wifi network.
final boolean anyWiFiEverValidated = CollectionUtils.any(candidates,
- nai -> nai.getScore().hasPolicy(POLICY_EVER_USER_SELECTED)
- && nai.getCaps().hasTransport(TRANSPORT_WIFI));
+ nai -> nai.getScore().hasPolicy(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD)
+ && nai.getCapsNoCopy().hasTransport(TRANSPORT_WIFI));
if (anyWiFiEverValidated) {
partitionInto(candidates, nai -> !nai.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI),
accepted, rejected);
@@ -206,18 +197,18 @@
for (final Scoreable defaultSubNai : accepted) {
// Remove all networks without the DEFAULT_SUBSCRIPTION policy and the same transports
// as a network that has it.
- final int[] transports = defaultSubNai.getCaps().getTransportTypes();
+ final int[] transports = defaultSubNai.getCapsNoCopy().getTransportTypes();
candidates.removeIf(nai -> !nai.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY)
- && Arrays.equals(transports, nai.getCaps().getTransportTypes()));
+ && Arrays.equals(transports, nai.getCapsNoCopy().getTransportTypes()));
}
if (1 == candidates.size()) return candidates.get(0);
- // It's guaranteed candidates.size() > 0 because there is at least one with DEFAULT_SUB
- // policy and only those without it were removed.
+ // It's guaranteed candidates.size() > 0 because there is at least one with the
+ // TRANSPORT_PRIMARY policy and only those without it were removed.
// If some of the networks have a better transport than others, keep only the ones with
// the best transports.
for (final int transport : PREFERRED_TRANSPORTS_ORDER) {
- partitionInto(candidates, nai -> nai.getCaps().hasTransport(transport),
+ partitionInto(candidates, nai -> nai.getCapsNoCopy().hasTransport(transport),
accepted, rejected);
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) {
@@ -243,16 +234,17 @@
NetworkAgentInfo bestNetwork = null;
int bestScore = Integer.MIN_VALUE;
for (final NetworkAgentInfo nai : nais) {
- if (nai.getCurrentScore() > bestScore) {
+ final int naiScore = nai.getCurrentScore();
+ if (naiScore > bestScore) {
bestNetwork = nai;
- bestScore = nai.getCurrentScore();
+ bestScore = naiScore;
}
}
return bestNetwork;
}
/**
- * Returns whether an offer has a chance to beat a champion network for a request.
+ * Returns whether a {@link Scoreable} has a chance to beat a champion network for a request.
*
* Offers are sent by network providers when they think they might be able to make a network
* with the characteristics contained in the offer. If the offer has no chance to beat
@@ -266,15 +258,15 @@
*
* @param request The request to evaluate against.
* @param champion The currently best network for this request.
- * @param offer The offer.
+ * @param contestant The offer.
* @return Whether the offer stands a chance to beat the champion.
*/
public boolean mightBeat(@NonNull final NetworkRequest request,
@Nullable final NetworkAgentInfo champion,
- @NonNull final NetworkOffer offer) {
+ @NonNull final Scoreable contestant) {
// If this network can't even satisfy the request then it can't beat anything, not
// even an absence of network. It can't satisfy it anyway.
- if (!request.canBeSatisfiedBy(offer.caps)) return false;
+ if (!request.canBeSatisfiedBy(contestant.getCapsNoCopy())) return false;
// If there is no satisfying network, then this network can beat, because some network
// is always better than no network.
if (null == champion) return true;
@@ -283,25 +275,24 @@
// Otherwise rank them.
final ArrayList<Scoreable> candidates = new ArrayList<>();
candidates.add(champion);
- candidates.add(offer);
- return offer == getBestNetworkByPolicy(candidates, champion);
+ candidates.add(contestant);
+ return contestant == getBestNetworkByPolicy(candidates, champion);
} else {
- return mightBeatByLegacyInt(request, champion.getScore(), offer);
+ return mightBeatByLegacyInt(champion.getScore(), contestant);
}
}
/**
- * Returns whether an offer might beat a champion according to the legacy int.
+ * Returns whether a contestant might beat a champion according to the legacy int.
*/
- public boolean mightBeatByLegacyInt(@NonNull final NetworkRequest request,
- @Nullable final FullScore championScore,
- @NonNull final NetworkOffer offer) {
+ private boolean mightBeatByLegacyInt(@Nullable final FullScore championScore,
+ @NonNull final Scoreable contestant) {
final int offerIntScore;
- if (offer.caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+ if (contestant.getCapsNoCopy().hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
// If the offer might have Internet access, then it might validate.
- offerIntScore = offer.score.getLegacyIntAsValidated();
+ offerIntScore = contestant.getScore().getLegacyIntAsValidated();
} else {
- offerIntScore = offer.score.getLegacyInt();
+ offerIntScore = contestant.getScore().getLegacyInt();
}
return championScore.getLegacyInt() < offerIntScore;
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index dac2e5c..1a75a7f 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -68,6 +68,7 @@
import android.os.HandlerThread
import android.os.Looper
import android.os.Message
+import android.os.SystemClock
import android.util.DebugUtils.valueToString
import androidx.test.InstrumentationRegistry
import com.android.modules.utils.build.SdkLevel
@@ -76,6 +77,7 @@
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.RecorderCallback.CallbackEntry.Available
+import com.android.testutils.RecorderCallback.CallbackEntry.Losing
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
import com.android.testutils.TestableNetworkCallback
import org.junit.After
@@ -114,6 +116,7 @@
// requests filed by the test and should never match normal internet requests. 70 is the default
// score of Ethernet networks, it's as good a value as any other.
private const val TEST_NETWORK_SCORE = 70
+private const val WORSE_NETWORK_SCORE = 65
private const val BETTER_NETWORK_SCORE = 75
private const val FAKE_NET_ID = 1098
private val instrumentation: Instrumentation
@@ -543,16 +546,23 @@
// Connect the first Network
createConnectedNetworkAgent(name = name1).let { (agent1, _) ->
callback.expectAvailableThenValidatedCallbacks(agent1.network)
- // Upgrade agent1 to a better score so that there is no ambiguity when
- // agent2 connects that agent1 is still better
- agent1.sendNetworkScore(BETTER_NETWORK_SCORE - 1)
+ // If using the int ranking, agent1 must be upgraded to a better score so that there is
+ // no ambiguity when agent2 connects that agent1 is still better. If using policy
+ // ranking, this is not necessary.
+ agent1.sendNetworkScore(NetworkScore.Builder().setLegacyInt(BETTER_NETWORK_SCORE)
+ .build())
// Connect the second agent
createConnectedNetworkAgent(name = name2).let { (agent2, _) ->
agent2.markConnected()
- // The callback should not see anything yet
+ // The callback should not see anything yet. With int ranking, agent1 was upgraded
+ // to a stronger score beforehand. With policy ranking, agent1 is preferred by
+ // virtue of already satisfying the request.
callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
- // Now update the score and expect the callback now prefers agent2
- agent2.sendNetworkScore(BETTER_NETWORK_SCORE)
+ // Now downgrade the score and expect the callback now prefers agent2
+ agent1.sendNetworkScore(NetworkScore.Builder()
+ .setLegacyInt(WORSE_NETWORK_SCORE)
+ .setExiting(true)
+ .build())
callback.expectCallback<Available>(agent2.network)
}
}
@@ -768,4 +778,71 @@
// tearDown() will unregister the requests and agents
}
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ fun testSetLingerDuration() {
+ // This test will create two networks and check that the one with the stronger
+ // score wins out for a request that matches them both. And the weaker agent will
+ // be disconnected after customized linger duration.
+
+ // Connect the first Network
+ val name1 = UUID.randomUUID().toString()
+ val name2 = UUID.randomUUID().toString()
+ val (agent1, callback) = createConnectedNetworkAgent(name = name1)
+ callback.expectAvailableThenValidatedCallbacks(agent1.network!!)
+ // Downgrade agent1 to a worse score so that there is no ambiguity when
+ // agent2 connects.
+ agent1.sendNetworkScore(NetworkScore.Builder().setLegacyInt(WORSE_NETWORK_SCORE)
+ .setExiting(true).build())
+
+ // Verify invalid linger duration cannot be set.
+ assertFailsWith<IllegalArgumentException> {
+ agent1.setLingerDuration(Duration.ofMillis(-1))
+ }
+ assertFailsWith<IllegalArgumentException> { agent1.setLingerDuration(Duration.ZERO) }
+ assertFailsWith<IllegalArgumentException> {
+ agent1.setLingerDuration(Duration.ofMillis(Integer.MIN_VALUE.toLong()))
+ }
+ assertFailsWith<IllegalArgumentException> {
+ agent1.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong() + 1))
+ }
+ assertFailsWith<IllegalArgumentException> {
+ agent1.setLingerDuration(Duration.ofMillis(
+ NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - 1))
+ }
+ // Verify valid linger timer can be set, but it should not take effect since the network
+ // is still needed.
+ agent1.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong()))
+ callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
+ // Set to the value we want to verify the functionality.
+ agent1.setLingerDuration(Duration.ofMillis(NetworkAgent.MIN_LINGER_TIMER_MS.toLong()))
+ // Make a listener which can observe agent1 lost later.
+ val callbackWeaker = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
+ registerNetworkCallback(NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(TRANSPORT_TEST)
+ .setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(name1))
+ .build(), callbackWeaker)
+ callbackWeaker.expectAvailableCallbacks(agent1.network!!)
+
+ // Connect the second agent with a score better than agent1. Verify the callback for
+ // agent1 sees the linger expiry while the callback for both sees the winner.
+ // Record linger start timestamp prior to send score to prevent possible race, the actual
+ // timestamp should be slightly late than this since the service handles update
+ // network score asynchronously.
+ val lingerStart = SystemClock.elapsedRealtime()
+ val agent2 = createNetworkAgent(name = name2)
+ agent2.register()
+ agent2.markConnected()
+ callback.expectAvailableCallbacks(agent2.network!!)
+ callbackWeaker.expectCallback<Losing>(agent1.network!!)
+ val expectedRemainingLingerDuration = lingerStart +
+ NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - SystemClock.elapsedRealtime()
+ // If the available callback is too late. The remaining duration will be reduced.
+ assertTrue(expectedRemainingLingerDuration > 0,
+ "expected remaining linger duration is $expectedRemainingLingerDuration")
+ callbackWeaker.assertNoCallback(expectedRemainingLingerDuration)
+ callbackWeaker.expectCallback<Lost>(agent1.network!!)
+ }
}
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 7ba415b..40da20b 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -2683,25 +2683,6 @@
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- // Bring up wifi with a score of 70.
- // Cell is lingered because it would not satisfy any request, even if it validated.
- mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- mWiFiNetworkAgent.adjustScore(50);
- mWiFiNetworkAgent.connect(false); // Score: 70
- callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
- defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
-
- // Tear down wifi.
- mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
- defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
- defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
- assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
-
// Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
// it's arguably correct to linger it, since it was the default network before it validated.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -3017,11 +2998,11 @@
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- // BUG: the network will no longer linger, even though it's validated and outscored.
- // TODO: fix this.
mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
- callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
+ callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
+ callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback();
@@ -4580,9 +4561,8 @@
expectNoRequestChanged(testFactory);
testFactory.assertRequestCountEquals(0);
assertFalse(testFactory.getMyStartRequested());
- // ... and cell data to be torn down after nascent network timeout.
- cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
- mService.mNascentDelayMs + TEST_CALLBACK_TIMEOUT_MS);
+ // ... and cell data to be torn down immediately since it is no longer nascent.
+ cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
waitForIdle();
assertLength(1, mCm.getAllNetworks());
} finally {
@@ -9846,7 +9826,8 @@
return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
nc, new NetworkScore.Builder().setLegacyInt(0).build(),
mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
- INVALID_UID, mQosCallbackTracker, new ConnectivityService.Dependencies());
+ INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
+ new ConnectivityService.Dependencies());
}
@Test
@@ -11887,6 +11868,11 @@
internetFactory.expectRequestRemove();
internetFactory.assertRequestCountEquals(0);
+ // Create a request that holds the upcoming wifi network.
+ final TestNetworkCallback wifiCallback = new TestNetworkCallback();
+ mCm.requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
+ wifiCallback);
+
// Now WiFi connects and it's unmetered, but it's weaker than cell.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
@@ -11895,7 +11881,7 @@
mWiFiNetworkAgent.connect(true);
// The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so
- // the oemPaidFactory can't beat this no matter how high its score.
+ // the oemPaidFactory can't beat wifi no matter how high its score.
oemPaidFactory.expectRequestRemove();
expectNoRequestChanged(internetFactory);
@@ -11906,6 +11892,7 @@
// unmetered network, so the oemPaidNetworkFactory still can't beat this.
expectNoRequestChanged(oemPaidFactory);
internetFactory.expectRequestAdd();
+ mCm.unregisterNetworkCallback(wifiCallback);
}
/**
diff --git a/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt b/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt
index f0d7d86..45b575a 100644
--- a/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt
@@ -56,7 +56,7 @@
if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN)
if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}.build()
- return mixInScore(nc, nac, false /* avoidBadWifi */)
+ return mixInScore(nc, nac, validated, false /* yieldToBadWifi */)
}
@Test
diff --git a/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java
index 116d755..36e229d 100644
--- a/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -71,6 +71,8 @@
static final int LOW_DAILY_LIMIT = 2;
static final int HIGH_DAILY_LIMIT = 1000;
+ private static final int TEST_LINGER_DELAY_MS = 400;
+
LingerMonitor mMonitor;
@Mock ConnectivityService mConnService;
@@ -366,7 +368,7 @@
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(),
mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd,
- mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(),
+ mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), TEST_LINGER_DELAY_MS,
mQosCallbackTracker, new ConnectivityService.Dependencies());
nai.everValidated = true;
return nai;
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
index 1348c6a..551b94c 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
@@ -16,7 +16,9 @@
package com.android.server.connectivity
+import android.net.NetworkCapabilities
import android.net.NetworkRequest
+import android.net.NetworkScore.KEEP_CONNECTED_NONE
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import org.junit.Test
@@ -32,10 +34,14 @@
class NetworkRankerTest {
private val ranker = NetworkRanker()
- private fun makeNai(satisfy: Boolean, score: Int) = mock(NetworkAgentInfo::class.java).also {
- doReturn(satisfy).`when`(it).satisfies(any())
- doReturn(score).`when`(it).currentScore
- }
+ private fun makeNai(satisfy: Boolean, legacyScore: Int) =
+ mock(NetworkAgentInfo::class.java).also {
+ doReturn(satisfy).`when`(it).satisfies(any())
+ val fs = FullScore(legacyScore, 0 /* policies */, KEEP_CONNECTED_NONE)
+ doReturn(fs).`when`(it).getScore()
+ val nc = NetworkCapabilities.Builder().build()
+ doReturn(nc).`when`(it).getCapsNoCopy()
+ }
@Test
fun testGetBestNetwork() {