[NS06] Implement the don't-reap mechanism
This exposes a mechanism for network providers to tell
the network stack that a given network must be kept up
for some specific reason. This is meant to be easier
for them than to have to file a request, in particular
because there is no guaranteed way to make sure the
request will be best matched by any given network.
Test: new test for this
Bug: 167544279
Merged-In: I3c2563d4ae4e3715d0c6270344ba8f7ef067872f
Merged-In: I238a3ee5ee9262477a23b897e4141769dd1505d1
Change-Id: I238a3ee5ee9262477a23b897e4141769dd1505d1
(cherry-picked from ag/13929760)
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index f7d8aa0..9540e06 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -3974,6 +3974,12 @@
// then it should be lingered.
private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
ensureRunningOnConnectivityServiceThread();
+
+ if (!nai.everConnected || nai.isVPN() || nai.isInactive()
+ || nai.getScore().getKeepConnectedReason() != NetworkScore.KEEP_CONNECTED_NONE) {
+ return false;
+ }
+
final int numRequests;
switch (reason) {
case TEARDOWN:
@@ -3987,9 +3993,8 @@
return true;
}
- if (!nai.everConnected || nai.isVPN() || nai.isInactive() || numRequests > 0) {
- return false;
- }
+ if (numRequests > 0) return false;
+
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
if (reason == UnneededFor.LINGER
&& !nri.isMultilayerRequest()
diff --git a/service/src/com/android/server/connectivity/FullScore.java b/service/src/com/android/server/connectivity/FullScore.java
index 9326d69..375d005 100644
--- a/service/src/com/android/server/connectivity/FullScore.java
+++ b/service/src/com/android/server/connectivity/FullScore.java
@@ -19,12 +19,14 @@
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.KEEP_CONNECTED_NONE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkScore;
+import android.net.NetworkScore.KeepConnectedReason;
import com.android.internal.annotations.VisibleForTesting;
@@ -95,9 +97,13 @@
// Bitmask of all the policies applied to this score.
private final long mPolicies;
- FullScore(final int legacyInt, final long policies) {
+ private final int mKeepConnectedReason;
+
+ FullScore(final int legacyInt, final long policies,
+ @KeepConnectedReason final int keepConnectedReason) {
mLegacyInt = legacyInt;
mPolicies = policies;
+ mKeepConnectedReason = keepConnectedReason;
}
/**
@@ -110,14 +116,15 @@
*/
public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
@NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config) {
- return withPolicies(score.getLegacyInt(), caps.hasCapability(NET_CAPABILITY_VALIDATED),
+ return withPolicies(score.getLegacyInt(), score.getKeepConnectedReason(),
+ caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
config.explicitlySelected,
config.acceptUnvalidated);
}
/**
- * Given a score supplied by the NetworkAgent, produce a prospective score for an offer.
+ * Given a score supplied by a NetworkProvider, produce a prospective score for an offer.
*
* NetworkOffers have score filters that are compared to the scores of actual networks
* to see if they could possibly beat the current satisfier. Some things the agent can't
@@ -139,8 +146,8 @@
final boolean everUserSelected = false;
// Don't assume the user will accept unvalidated connectivity.
final boolean acceptUnvalidated = false;
- return withPolicies(score.getLegacyInt(), mayValidate, vpn, everUserSelected,
- acceptUnvalidated);
+ return withPolicies(score.getLegacyInt(), KEEP_CONNECTED_NONE,
+ mayValidate, vpn, everUserSelected, acceptUnvalidated);
}
/**
@@ -152,13 +159,15 @@
*/
public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
@NonNull final NetworkAgentConfig config) {
- return withPolicies(mLegacyInt, caps.hasCapability(NET_CAPABILITY_VALIDATED),
+ return withPolicies(mLegacyInt, mKeepConnectedReason,
+ caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
config.explicitlySelected,
config.acceptUnvalidated);
}
private static FullScore withPolicies(@NonNull final int legacyInt,
+ @KeepConnectedReason final int keepConnectedReason,
final boolean isValidated,
final boolean isVpn,
final boolean everUserSelected,
@@ -167,7 +176,8 @@
(isValidated ? 1L << POLICY_IS_VALIDATED : 0)
| (isVpn ? 1L << POLICY_IS_VPN : 0)
| (everUserSelected ? 1L << POLICY_EVER_USER_SELECTED : 0)
- | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0));
+ | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0),
+ keepConnectedReason);
}
/**
@@ -219,13 +229,21 @@
return 0 != (mPolicies & (1L << policy));
}
+ /**
+ * Returns the keep-connected reason, or KEEP_CONNECTED_NONE.
+ */
+ public int getKeepConnectedReason() {
+ return mKeepConnectedReason;
+ }
+
// Example output :
// Score(50 ; Policies : EVER_USER_SELECTED&IS_VALIDATED)
@Override
public String toString() {
final StringJoiner sj = new StringJoiner(
"&", // delimiter
- "Score(" + mLegacyInt + " ; Policies : ", // prefix
+ "Score(" + mLegacyInt + " ; KeepConnected : " + mKeepConnectedReason
+ + " ; Policies : ", // prefix
")"); // suffix
for (int i = NetworkScore.MIN_AGENT_MANAGED_POLICY;
i <= NetworkScore.MAX_AGENT_MANAGED_POLICY; ++i) {