Add a NET_CAPABILITY_FOREGROUND capability. am: 0f04220ffe am: aaec66110d

am: aabaa907de

Change-Id: I08ca73666668ddc6c9bfe002844a9d2e0ecb28e4
This commit is contained in:
Lorenzo Colitti
2016-09-14 19:22:54 +00:00
committed by android-build-merger
3 changed files with 124 additions and 32 deletions

View File

@@ -182,8 +182,15 @@ public final class NetworkCapabilities implements Parcelable {
*/
public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17;
/**
* Indicates that this network is available for use by apps, and not a network that is being
* kept up in the background to facilitate fast network switching.
* @hide
*/
public static final int NET_CAPABILITY_FOREGROUND = 18;
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_CAPTIVE_PORTAL;
private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND;
/**
* Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -194,7 +201,8 @@ public final class NetworkCapabilities implements Parcelable {
// http://b/18206275
(1 << NET_CAPABILITY_TRUSTED) |
(1 << NET_CAPABILITY_VALIDATED) |
(1 << NET_CAPABILITY_CAPTIVE_PORTAL);
(1 << NET_CAPABILITY_CAPTIVE_PORTAL) |
(1 << NET_CAPABILITY_FOREGROUND);
/**
* Network specifier for factories which want to match any network specifier
@@ -217,8 +225,7 @@ public final class NetworkCapabilities implements Parcelable {
* get immediately torn down because they do not have the requested capability.
*/
private static final long NON_REQUESTABLE_CAPABILITIES =
(1 << NET_CAPABILITY_VALIDATED) |
(1 << NET_CAPABILITY_CAPTIVE_PORTAL);
MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_TRUSTED);
/**
* Capabilities that are set by default when the object is constructed.
@@ -325,6 +332,7 @@ public final class NetworkCapabilities implements Parcelable {
public String describeFirstNonRequestableCapability() {
if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED";
if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL";
if (hasCapability(NET_CAPABILITY_FOREGROUND)) return "NET_CAPABILITY_FOREGROUND";
// This cannot happen unless the preceding checks are incomplete.
if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) {
return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities);
@@ -352,6 +360,11 @@ public final class NetworkCapabilities implements Parcelable {
(that.mNetworkCapabilities & ~MUTABLE_CAPABILITIES));
}
private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) {
return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
(that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
}
/**
* Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
* typically provided by restricted networks.
@@ -756,6 +769,19 @@ public final class NetworkCapabilities implements Parcelable {
equalsSpecifier(nc));
}
/**
* Checks that our requestable capabilities are the same as those of the given
* {@code NetworkCapabilities}.
*
* @hide
*/
public boolean equalRequestableCapabilities(NetworkCapabilities nc) {
if (nc == null) return false;
return (equalsNetCapabilitiesRequestable(nc) &&
equalsTransportTypes(nc) &&
equalsSpecifier(nc));
}
@Override
public boolean equals(Object obj) {
if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
@@ -840,6 +866,7 @@ public final class NetworkCapabilities implements Parcelable {
case NET_CAPABILITY_NOT_VPN: capabilities += "NOT_VPN"; break;
case NET_CAPABILITY_VALIDATED: capabilities += "VALIDATED"; break;
case NET_CAPABILITY_CAPTIVE_PORTAL: capabilities += "CAPTIVE_PORTAL"; break;
case NET_CAPABILITY_FOREGROUND: capabilities += "FOREGROUND"; break;
}
if (++i < types.length) capabilities += "&";
}

View File

@@ -24,6 +24,7 @@ import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
@@ -2133,14 +2134,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) ||
networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
}
if (nai.everConnected && !nai.networkCapabilities.equalImmutableCapabilities(
networkCapabilities)) {
Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities: "
+ nai.networkCapabilities + " -> " + networkCapabilities);
}
updateCapabilities(nai, networkCapabilities);
break;
}
@@ -2612,6 +2609,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
boolean wasKept = false;
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
if (nai != null) {
boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
nai.removeRequest(nri.request.requestId);
if (VDBG) {
log(" Removing from current network " + nai.name() +
@@ -2627,6 +2625,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
wasKept = true;
}
mNetworkForRequestId.remove(nri.request.requestId);
if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
// Went from foreground to background.
updateCapabilities(nai, nai.networkCapabilities);
}
}
// TODO: remove this code once we know that the Slog.wtf is never hit.
@@ -4505,6 +4507,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
* @param networkCapabilities the new network capabilities.
*/
private void updateCapabilities(NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
if (nai.everConnected && !nai.networkCapabilities.equalImmutableCapabilities(
networkCapabilities)) {
Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities: "
+ nai.networkCapabilities + " -> " + networkCapabilities);
}
// Don't modify caller's NetworkCapabilities.
networkCapabilities = new NetworkCapabilities(networkCapabilities);
if (nai.lastValidated) {
@@ -4517,21 +4525,40 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else {
networkCapabilities.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
}
if (!Objects.equals(nai.networkCapabilities, networkCapabilities)) {
final int oldScore = nai.getCurrentScore();
if (nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) !=
networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
try {
mNetd.setNetworkPermission(nai.network.netId,
networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) ?
null : NetworkManagementService.PERMISSION_SYSTEM);
} catch (RemoteException e) {
loge("Exception in setNetworkPermission: " + e);
}
}
synchronized (nai) {
nai.networkCapabilities = networkCapabilities;
if (nai.isBackgroundNetwork()) {
networkCapabilities.removeCapability(NET_CAPABILITY_FOREGROUND);
} else {
networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
}
if (Objects.equals(nai.networkCapabilities, networkCapabilities)) return;
if (nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) !=
networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
try {
mNetd.setNetworkPermission(nai.network.netId,
networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) ?
null : NetworkManagementService.PERMISSION_SYSTEM);
} catch (RemoteException e) {
loge("Exception in setNetworkPermission: " + e);
}
}
final int oldScore = nai.getCurrentScore();
final NetworkCapabilities prevNc = nai.networkCapabilities;
synchronized (nai) {
nai.networkCapabilities = networkCapabilities;
}
if (nai.getCurrentScore() == oldScore &&
networkCapabilities.equalRequestableCapabilities(prevNc)) {
// If the requestable capabilities haven't changed, and the score hasn't changed, then
// the change we're processing can't affect any requests, it can only affect the listens
// on this network. We might have been called by rematchNetworkAndRequests when a
// network changed foreground state.
processListenRequests(nai, true);
} else {
// If the requestable capabilities have changed or the score changed, we can't have been
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
rematchAllNetworksAndRequests(nai, oldScore);
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
@@ -4655,7 +4682,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
oldNetwork.clearLingerState();
if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) {
// Tear the network down.
teardownUnneededNetwork(oldNetwork);
} else {
// Put the network in the background.
updateCapabilities(oldNetwork, oldNetwork.networkCapabilities);
}
}
@@ -4673,7 +4704,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai) {
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
// For consistency with previous behaviour, send onLost callbacks before onAvailable.
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
NetworkRequest nr = nri.request;
@@ -4684,6 +4715,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
if (capabilitiesChanged) {
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
NetworkRequest nr = nri.request;
if (!nr.isListen()) continue;
@@ -4727,12 +4762,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
boolean keep = newNetwork.isVPN();
boolean isNewDefault = false;
NetworkAgentInfo oldDefaultNetwork = null;
final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
final int score = newNetwork.getCurrentScore();
if (VDBG) log("rematching " + newNetwork.name());
// Find and migrate to this Network any NetworkRequests for
// which this network is now the best.
ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<NetworkRequestInfo>();
if (VDBG) log(" network has: " + newNetwork.networkCapabilities);
NetworkCapabilities nc = newNetwork.networkCapabilities;
if (VDBG) log(" network has: " + nc);
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
// Process requests in the first pass and listens in the second pass. This allows us to
// change a network's capabilities depending on which requests it has. This is only
@@ -4759,10 +4800,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (VDBG) {
log("currentScore = " +
(currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
", newScore = " + newNetwork.getCurrentScore());
", newScore = " + score);
}
if (currentNetwork == null ||
currentNetwork.getCurrentScore() < newNetwork.getCurrentScore()) {
if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
if (VDBG) log("rematch for " + newNetwork.name());
if (currentNetwork != null) {
if (VDBG) log(" accepting network in place of " + currentNetwork.name());
@@ -4784,7 +4824,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// TODO - this could get expensive if we have alot of requests for this
// network. Think about if there is a way to reduce this. Push
// netid->request mapping to each factory?
sendUpdatedScoreToFactories(nri.request, newNetwork.getCurrentScore());
sendUpdatedScoreToFactories(nri.request, score);
if (isDefaultRequest(nri)) {
isNewDefault = true;
oldDefaultNetwork = currentNetwork;
@@ -4842,8 +4882,27 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {
Slog.wtf(TAG, String.format(
"BUG: %s changed requestable capabilities during rematch: %s -> %s",
nc, newNetwork.networkCapabilities));
}
if (newNetwork.getCurrentScore() != score) {
Slog.wtf(TAG, String.format(
"BUG: %s changed score during rematch: %d -> %d",
score, newNetwork.getCurrentScore()));
}
// Second pass: process all listens.
processListenRequests(newNetwork);
if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
// If the network went from background to foreground or vice versa, we need to update
// its foreground state. It is safe to do this after rematching the requests because
// NET_CAPABILITY_FOREGROUND does not affect requests, as is not a requestable
// capability and does not affect the network's score (see the Slog.wtf call above).
updateCapabilities(newNetwork, newNetwork.networkCapabilities);
} else {
processListenRequests(newNetwork, false);
}
// do this after the default net is switched, but
// before LegacyTypeTracker sends legacy broadcasts
@@ -5036,6 +5095,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!networkAgent.created
&& (state == NetworkInfo.State.CONNECTED
|| (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
// A network that has just connected has zero requests and is thus a foreground network.
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
try {
// This should never fail. Specifying an already in use NetID will cause failure.
if (networkAgent.isVPN()) {
@@ -5197,6 +5260,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequest nr = networkAgent.requestAt(i);
NetworkRequestInfo nri = mNetworkRequests.get(nr);
if (VDBG) log(" sending notification for " + nr);
// TODO: if we're in the middle of a rematch, can we send a CAP_CHANGED callback for
// a network that no longer satisfies the listen?
if (nri.mPendingIntent == null) {
callCallbackForRequest(nri, networkAgent, notifyType, arg1);
} else {

View File

@@ -380,7 +380,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
* it might satisfy a request if it validated).
*/
public boolean isBackgroundNetwork() {
return numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0;
return !isVPN() && numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0;
}
// Does this network satisfy request?