summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@android.com> 2017-11-03 22:41:51 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2017-11-03 22:41:51 +0000
commit8f380ab29c8606bca861ba21eee52cedfbc99f46 (patch)
tree4bf5a25e001a1c8b9aa141744aac7a7c9486cce0
parent3ddf22e69cc329741b41b423a3b5d18d8c9e81aa (diff)
parent72f9c42b9e59761a28d6b32c42f65de57c98daed (diff)
Merge "Define NOT_ROAMING network capability."
-rw-r--r--api/current.txt3
-rw-r--r--api/system-current.txt3
-rw-r--r--api/test-current.txt3
-rw-r--r--core/java/android/net/NetworkCapabilities.java119
-rw-r--r--core/java/android/net/NetworkIdentity.java4
-rw-r--r--core/java/android/net/NetworkInfo.java13
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java38
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java63
-rw-r--r--tests/net/java/android/net/NetworkCapabilitiesTest.java25
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java83
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java101
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java9
12 files changed, 405 insertions, 59 deletions
diff --git a/api/current.txt b/api/current.txt
index 3bff61f290e7..a8250e256c97 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -25691,6 +25691,7 @@ package android.net {
field public static final int NET_CAPABILITY_MMS = 0; // 0x0
field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
+ field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
field public static final int NET_CAPABILITY_RCS = 8; // 0x8
field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
@@ -25721,7 +25722,7 @@ package android.net {
method public boolean isConnected();
method public boolean isConnectedOrConnecting();
method public boolean isFailover();
- method public boolean isRoaming();
+ method public deprecated boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index d2f919702217..3b0da5ee3438 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -27889,6 +27889,7 @@ package android.net {
field public static final int NET_CAPABILITY_MMS = 0; // 0x0
field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
+ field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
field public static final int NET_CAPABILITY_RCS = 8; // 0x8
field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
@@ -27919,7 +27920,7 @@ package android.net {
method public boolean isConnected();
method public boolean isConnectedOrConnecting();
method public boolean isFailover();
- method public boolean isRoaming();
+ method public deprecated boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
}
diff --git a/api/test-current.txt b/api/test-current.txt
index d8a71a53ef2d..97bc448ba1bf 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -25801,6 +25801,7 @@ package android.net {
field public static final int NET_CAPABILITY_MMS = 0; // 0x0
field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
+ field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
field public static final int NET_CAPABILITY_RCS = 8; // 0x8
field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
@@ -25831,7 +25832,7 @@ package android.net {
method public boolean isConnected();
method public boolean isConnectedOrConnecting();
method public boolean isFailover();
- method public boolean isRoaming();
+ method public deprecated boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index db12dd9724dc..ee75fd443052 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.IntDef;
+import android.net.ConnectivityManager.NetworkCallback;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,15 +31,24 @@ import java.util.Objects;
import java.util.StringJoiner;
/**
- * This class represents the capabilities of a network. This is used both to specify
- * needs to {@link ConnectivityManager} and when inspecting a network.
- *
- * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method
- * of network selection. Rather than indicate a need for Wi-Fi because an application
- * needs high bandwidth and risk obsolescence when a new, fast network appears (like LTE),
- * the application should specify it needs high bandwidth. Similarly if an application
- * needs an unmetered network for a bulk transfer it can specify that rather than assuming
- * all cellular based connections are metered and all Wi-Fi based connections are not.
+ * Representation of the capabilities of a network. This object serves two
+ * purposes:
+ * <ul>
+ * <li>An expression of the current capabilities of an active network, typically
+ * expressed through
+ * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)}
+ * or {@link ConnectivityManager#getNetworkCapabilities(Network)}.
+ * <li>An expression of the future capabilities of a desired network, typically
+ * expressed through {@link NetworkRequest}.
+ * </ul>
+ * <p>
+ * This replaces the old {@link ConnectivityManager#TYPE_MOBILE} method of
+ * network selection. Rather than indicate a need for Wi-Fi because an
+ * application needs high bandwidth and risk obsolescence when a new, fast
+ * network appears (like LTE), the application should specify it needs high
+ * bandwidth. Similarly if an application needs an unmetered network for a bulk
+ * transfer it can specify that rather than assuming all cellular based
+ * connections are metered and all Wi-Fi based connections are not.
*/
public final class NetworkCapabilities implements Parcelable {
private static final String TAG = "NetworkCapabilities";
@@ -101,6 +111,7 @@ public final class NetworkCapabilities implements Parcelable {
NET_CAPABILITY_NOT_VPN,
NET_CAPABILITY_VALIDATED,
NET_CAPABILITY_CAPTIVE_PORTAL,
+ NET_CAPABILITY_NOT_ROAMING,
NET_CAPABILITY_FOREGROUND,
})
public @interface NetCapability { }
@@ -218,11 +229,16 @@ public final class NetworkCapabilities implements Parcelable {
public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17;
/**
+ * Indicates that this network is not roaming.
+ */
+ public static final int NET_CAPABILITY_NOT_ROAMING = 18;
+
+ /**
* 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;
+ public static final int NET_CAPABILITY_FOREGROUND = 19;
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND;
@@ -237,6 +253,7 @@ public final class NetworkCapabilities implements Parcelable {
(1 << NET_CAPABILITY_TRUSTED) |
(1 << NET_CAPABILITY_VALIDATED) |
(1 << NET_CAPABILITY_CAPTIVE_PORTAL) |
+ (1 << NET_CAPABILITY_NOT_ROAMING) |
(1 << NET_CAPABILITY_FOREGROUND);
/**
@@ -316,6 +333,21 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
+ * Sets (or clears) the given capability on this {@link NetworkCapabilities}
+ * instance.
+ *
+ * @hide
+ */
+ public NetworkCapabilities setCapability(@NetCapability int capability, boolean value) {
+ if (value) {
+ addCapability(capability);
+ } else {
+ removeCapability(capability);
+ }
+ return this;
+ }
+
+ /**
* Gets all the capabilities set on this {@code NetworkCapability} instance.
*
* @return an array of capability values for this instance.
@@ -326,6 +358,15 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
+ * Sets all the capabilities set on this {@code NetworkCapability} instance.
+ *
+ * @hide
+ */
+ public void setCapabilities(@NetCapability int[] capabilities) {
+ mNetworkCapabilities = BitUtils.packBits(capabilities);
+ }
+
+ /**
* Tests for the presence of a capabilitity on this instance.
*
* @param capability the capabilities to be tested for.
@@ -515,6 +556,21 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
+ * Sets (or clears) the given transport on this {@link NetworkCapabilities}
+ * instance.
+ *
+ * @hide
+ */
+ public NetworkCapabilities setTransportType(@Transport int transportType, boolean value) {
+ if (value) {
+ addTransportType(transportType);
+ } else {
+ removeTransportType(transportType);
+ }
+ return this;
+ }
+
+ /**
* Gets all the transports set on this {@code NetworkCapability} instance.
*
* @return an array of transport type values for this instance.
@@ -525,6 +581,15 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
+ * Sets all the transports set on this {@code NetworkCapability} instance.
+ *
+ * @hide
+ */
+ public void setTransportTypes(@Transport int[] transportTypes) {
+ mTransportTypes = BitUtils.packBits(transportTypes);
+ }
+
+ /**
* Tests for the presence of a transport on this instance.
*
* @param transportType the transport type to be tested for.
@@ -549,12 +614,18 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
+ * Value indicating that link bandwidth is unspecified.
+ * @hide
+ */
+ public static final int LINK_BANDWIDTH_UNSPECIFIED = 0;
+
+ /**
* Passive link bandwidth. This is a rough guide of the expected peak bandwidth
* for the first hop on the given transport. It is not measured, but may take into account
* link parameters (Radio technology, allocated channels, etc).
*/
- private int mLinkUpBandwidthKbps;
- private int mLinkDownBandwidthKbps;
+ private int mLinkUpBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
+ private int mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
/**
* Sets the upstream bandwidth for this network in Kbps. This always only refers to
@@ -571,8 +642,9 @@ public final class NetworkCapabilities implements Parcelable {
* @param upKbps the estimated first hop upstream (device to network) bandwidth.
* @hide
*/
- public void setLinkUpstreamBandwidthKbps(int upKbps) {
+ public NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) {
mLinkUpBandwidthKbps = upKbps;
+ return this;
}
/**
@@ -600,8 +672,9 @@ public final class NetworkCapabilities implements Parcelable {
* @param downKbps the estimated first hop downstream (network to device) bandwidth.
* @hide
*/
- public void setLinkDownstreamBandwidthKbps(int downKbps) {
+ public NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) {
mLinkDownBandwidthKbps = downKbps;
+ return this;
}
/**
@@ -628,6 +701,20 @@ public final class NetworkCapabilities implements Parcelable {
return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
}
+ /** @hide */
+ public static int minBandwidth(int a, int b) {
+ if (a == LINK_BANDWIDTH_UNSPECIFIED) {
+ return b;
+ } else if (b == LINK_BANDWIDTH_UNSPECIFIED) {
+ return a;
+ } else {
+ return Math.min(a, b);
+ }
+ }
+ /** @hide */
+ public static int maxBandwidth(int a, int b) {
+ return Math.max(a, b);
+ }
private NetworkSpecifier mNetworkSpecifier = null;
@@ -708,8 +795,9 @@ public final class NetworkCapabilities implements Parcelable {
* @param signalStrength the bearer-specific signal strength.
* @hide
*/
- public void setSignalStrength(int signalStrength) {
+ public NetworkCapabilities setSignalStrength(int signalStrength) {
mSignalStrength = signalStrength;
+ return this;
}
/**
@@ -968,6 +1056,7 @@ public final class NetworkCapabilities implements Parcelable {
case NET_CAPABILITY_NOT_VPN: return "NOT_VPN";
case NET_CAPABILITY_VALIDATED: return "VALIDATED";
case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL";
+ case NET_CAPABILITY_NOT_ROAMING: return "NOT_ROAMING";
case NET_CAPABILITY_FOREGROUND: return "FOREGROUND";
default: return Integer.toString(capability);
}
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 0775bdaaf380..df404b7dce27 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -189,7 +189,8 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
String subscriberId = null;
String networkId = null;
- boolean roaming = false;
+ boolean roaming = !state.networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
boolean metered = !state.networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
@@ -203,7 +204,6 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
}
subscriberId = state.subscriberId;
- roaming = state.networkInfo.isRoaming();
} else if (type == TYPE_WIFI) {
if (state.networkId != null) {
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 84c32bec8ef7..d5549387755d 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -307,11 +307,17 @@ public class NetworkInfo implements Parcelable {
}
/**
- * Indicates whether the device is currently roaming on this network.
- * When {@code true}, it suggests that use of data on this network
- * may incur extra costs.
+ * Indicates whether the device is currently roaming on this network. When
+ * {@code true}, it suggests that use of data on this network may incur
+ * extra costs.
+ *
* @return {@code true} if roaming is in effect, {@code false} otherwise.
+ * @deprecated Callers should switch to checking
+ * {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING}
+ * instead, since that handles more complex situations, such as
+ * VPNs.
*/
+ @Deprecated
public boolean isRoaming() {
synchronized (this) {
return mIsRoaming;
@@ -320,6 +326,7 @@ public class NetworkInfo implements Parcelable {
/** {@hide} */
@VisibleForTesting
+ @Deprecated
public void setRoaming(boolean isRoaming) {
synchronized (this) {
mIsRoaming = isRoaming;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 25c96d14e9ad..708bcdde2c86 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -29,7 +29,10 @@ 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;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.Nullable;
@@ -71,6 +74,7 @@ import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.UidRange;
import android.net.Uri;
+import android.net.VpnService;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.util.MultinetworkPolicyTracker;
@@ -4664,10 +4668,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
- final NetworkCapabilities prevNc = nai.networkCapabilities;
+ final NetworkCapabilities prevNc;
synchronized (nai) {
+ prevNc = nai.networkCapabilities;
nai.networkCapabilities = networkCapabilities;
}
+
if (nai.getCurrentScore() == oldScore &&
networkCapabilities.equalRequestableCapabilities(prevNc)) {
// If the requestable capabilities haven't changed, and the score hasn't changed, then
@@ -4681,6 +4687,28 @@ public class ConnectivityService extends IConnectivityManager.Stub
rematchAllNetworksAndRequests(nai, oldScore);
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
+
+ // Report changes that are interesting for network statistics tracking.
+ if (prevNc != null) {
+ final boolean meteredChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_METERED) !=
+ networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED);
+ final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) !=
+ networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ if (meteredChanged || roamingChanged) {
+ notifyIfacesChangedForNetworkStats();
+ }
+ }
+
+ if (!networkCapabilities.hasTransport(TRANSPORT_VPN)) {
+ // Tell VPNs about updated capabilities, since they may need to
+ // bubble those changes through.
+ synchronized (mVpns) {
+ for (int i = 0; i < mVpns.size(); i++) {
+ final Vpn vpn = mVpns.valueAt(i);
+ vpn.updateCapabilities();
+ }
+ }
+ }
}
public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
@@ -5214,14 +5242,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
notifyLockdownVpn(networkAgent);
- if (oldInfo != null && oldInfo.getState() == state) {
- if (oldInfo.isRoaming() != newInfo.isRoaming()) {
- if (VDBG) log("roaming status changed, notifying NetworkStatsService");
- notifyIfacesChangedForNetworkStats();
- } else if (VDBG) log("ignoring duplicate network state non-change");
- // In either case, no further work should be needed.
- return;
- }
if (DBG) {
log(networkAgent.name() + " EVENT_NETWORK_INFO_CHANGED, going from " +
(oldInfo == null ? "null" : oldInfo.getState()) +
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a44b18dc2d8c..7715727f6d73 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -18,6 +18,8 @@ package com.android.server.connectivity;
import static android.Manifest.permission.BIND_VPN_SERVICE;
import static android.net.ConnectivityManager.NETID_UNSET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE;
@@ -90,6 +92,8 @@ import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.ConnectivityService;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.net.BaseNetworkObserver;
@@ -245,10 +249,10 @@ public class Vpn {
}
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, "");
- // TODO: Copy metered attribute and bandwidths from physical transport, b/16207332
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+ updateCapabilities();
loadAlwaysOnPackage();
}
@@ -275,6 +279,62 @@ public class Vpn {
updateAlwaysOnNotification(detailedState);
}
+ public void updateCapabilities() {
+ final Network[] underlyingNetworks = (mConfig != null) ? mConfig.underlyingNetworks : null;
+ updateCapabilities(mContext.getSystemService(ConnectivityManager.class), underlyingNetworks,
+ mNetworkCapabilities);
+
+ if (mNetworkAgent != null) {
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+ }
+
+ @VisibleForTesting
+ public static void updateCapabilities(ConnectivityManager cm, Network[] underlyingNetworks,
+ NetworkCapabilities caps) {
+ int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
+ int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+ int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+ boolean metered = false;
+ boolean roaming = false;
+
+ if (ArrayUtils.isEmpty(underlyingNetworks)) {
+ // No idea what the underlying networks are; assume sane defaults
+ metered = true;
+ roaming = false;
+ } else {
+ for (Network underlying : underlyingNetworks) {
+ final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
+ for (int underlyingType : underlyingCaps.getTransportTypes()) {
+ transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
+ }
+
+ // When we have multiple networks, we have to assume the
+ // worst-case link speed and restrictions.
+ downKbps = NetworkCapabilities.minBandwidth(downKbps,
+ underlyingCaps.getLinkDownstreamBandwidthKbps());
+ upKbps = NetworkCapabilities.minBandwidth(upKbps,
+ underlyingCaps.getLinkUpstreamBandwidthKbps());
+ metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
+ roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ }
+ }
+
+ caps.setTransportTypes(transportTypes);
+ caps.setLinkDownstreamBandwidthKbps(downKbps);
+ caps.setLinkUpstreamBandwidthKbps(upKbps);
+ if (metered) {
+ caps.removeCapability(NET_CAPABILITY_NOT_METERED);
+ } else {
+ caps.addCapability(NET_CAPABILITY_NOT_METERED);
+ }
+ if (roaming) {
+ caps.removeCapability(NET_CAPABILITY_NOT_ROAMING);
+ } else {
+ caps.addCapability(NET_CAPABILITY_NOT_ROAMING);
+ }
+ }
+
/**
* Chooses whether to force all connections to go though VPN.
*
@@ -1344,6 +1404,7 @@ public class Vpn {
}
}
}
+ updateCapabilities();
return true;
}
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index 7346f9f95041..cd2d0985c793 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -26,13 +27,12 @@ import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
-
-import android.net.NetworkCapabilities;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
@@ -159,4 +159,25 @@ public class NetworkCapabilitiesTest {
assertNotEquals("", nc1.describeImmutableDifferences(nc2));
assertEquals("", nc1.describeImmutableDifferences(nc1));
}
+
+ @Test
+ public void testLinkBandwidthUtils() {
+ assertEquals(LINK_BANDWIDTH_UNSPECIFIED, NetworkCapabilities
+ .minBandwidth(LINK_BANDWIDTH_UNSPECIFIED, LINK_BANDWIDTH_UNSPECIFIED));
+ assertEquals(10, NetworkCapabilities
+ .minBandwidth(LINK_BANDWIDTH_UNSPECIFIED, 10));
+ assertEquals(10, NetworkCapabilities
+ .minBandwidth(10, LINK_BANDWIDTH_UNSPECIFIED));
+ assertEquals(10, NetworkCapabilities
+ .minBandwidth(10, 20));
+
+ assertEquals(LINK_BANDWIDTH_UNSPECIFIED, NetworkCapabilities
+ .maxBandwidth(LINK_BANDWIDTH_UNSPECIFIED, LINK_BANDWIDTH_UNSPECIFIED));
+ assertEquals(10, NetworkCapabilities
+ .maxBandwidth(LINK_BANDWIDTH_UNSPECIFIED, 10));
+ assertEquals(10, NetworkCapabilities
+ .maxBandwidth(10, LINK_BANDWIDTH_UNSPECIFIED));
+ assertEquals(20, NetworkCapabilities
+ .maxBandwidth(10, 20));
+ }
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 27a29b68e12d..113cd37f1a27 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -23,21 +23,44 @@ import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.ConnectivityManager.getNetworkTypeName;
-import static android.net.NetworkCapabilities.*;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
+
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static com.android.internal.util.TestUtils.waitForIdleHandler;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
@@ -45,7 +68,6 @@ import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
@@ -64,7 +86,6 @@ import android.net.MatchAllNetworkSpecifier;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
-import android.net.NetworkConfig;
import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
@@ -79,13 +100,9 @@ import android.net.util.MultinetworkPolicyTracker;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
-import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
-import android.os.MessageQueue;
-import android.os.Messenger;
-import android.os.MessageQueue.IdleHandler;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
@@ -96,10 +113,8 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
-import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
-import android.util.LogPrinter;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
@@ -109,7 +124,6 @@ import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
-import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -160,6 +174,7 @@ public class ConnectivityServiceTest {
@Mock IpConnectivityMetrics.Logger mMetricsService;
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+ @Mock INetworkStatsService mStatsService;
// This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
// do not go through ConnectivityService but talk to netd directly, so they don't automatically
@@ -858,7 +873,7 @@ public class ConnectivityServiceTest {
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mService = new WrappedConnectivityService(mServiceContext,
mock(INetworkManagementService.class),
- mock(INetworkStatsService.class),
+ mStatsService,
mock(INetworkPolicyManager.class),
mock(IpConnectivityLog.class));
@@ -3440,6 +3455,40 @@ public class ConnectivityServiceTest {
mCm.unregisterNetworkCallback(networkCallback);
}
+ @Test
+ public void testStatsIfacesChanged() throws Exception {
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+
+ // Simple connection should have updated ifaces
+ mCellNetworkAgent.connect(false);
+ waitForIdle();
+ verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+ reset(mStatsService);
+
+ // Metered change should update ifaces
+ mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ waitForIdle();
+ verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+ reset(mStatsService);
+
+ mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ waitForIdle();
+ verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+ reset(mStatsService);
+
+ // Captive portal change shouldn't update ifaces
+ mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+ waitForIdle();
+ verify(mStatsService, never()).forceUpdateIfaces();
+ reset(mStatsService);
+
+ // Roaming change should update ifaces
+ mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
+ waitForIdle();
+ verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+ reset(mStatsService);
+ }
+
private void checkDirectlyConnectedRoutes(Object callbackObj,
Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
assertTrue(callbackObj instanceof LinkProperties);
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index fe396c3a5c40..c29363cd1a4f 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -20,11 +20,30 @@ import static android.content.pm.UserInfo.FLAG_ADMIN;
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
import static android.content.pm.UserInfo.FLAG_PRIMARY;
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
+import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+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_ROAMING;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.AdditionalMatchers.*;
-import static org.mockito.Mockito.*;
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
@@ -36,6 +55,9 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState;
import android.net.UidRange;
import android.net.VpnService;
@@ -45,17 +67,17 @@ import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
-import android.support.test.runner.AndroidJUnit4;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.R;
import com.android.internal.net.VpnConfig;
-import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.Mock;
@@ -64,6 +86,7 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -114,6 +137,7 @@ public class VpnTest {
@Mock private AppOpsManager mAppOps;
@Mock private NotificationManager mNotificationManager;
@Mock private Vpn.SystemServices mSystemServices;
+ @Mock private ConnectivityManager mConnectivityManager;
@Before
public void setUp() throws Exception {
@@ -127,6 +151,8 @@ public class VpnTest {
when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
.thenReturn(mNotificationManager);
+ when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE)))
+ .thenReturn(mConnectivityManager);
when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
.thenReturn(Resources.getSystem().getString(
R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
@@ -397,6 +423,66 @@ public class VpnTest {
order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
}
+ @Test
+ public void testCapabilities() {
+ final Vpn vpn = createVpn(primaryUser.id);
+ setMockedUsers(primaryUser);
+
+ final Network mobile = new Network(1);
+ final Network wifi = new Network(2);
+
+ final Map<Network, NetworkCapabilities> networks = new HashMap<>();
+ networks.put(mobile, new NetworkCapabilities()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .setLinkDownstreamBandwidthKbps(10));
+ networks.put(wifi, new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addCapability(NET_CAPABILITY_NOT_ROAMING)
+ .setLinkUpstreamBandwidthKbps(20));
+ setMockedNetworks(networks);
+
+ final NetworkCapabilities caps = new NetworkCapabilities();
+
+ Vpn.updateCapabilities(mConnectivityManager, new Network[] { }, caps);
+ assertTrue(caps.hasTransport(TRANSPORT_VPN));
+ assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
+ assertFalse(caps.hasTransport(TRANSPORT_WIFI));
+ assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
+ assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
+ assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+
+ Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile }, caps);
+ assertTrue(caps.hasTransport(TRANSPORT_VPN));
+ assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
+ assertFalse(caps.hasTransport(TRANSPORT_WIFI));
+ assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
+ assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
+ assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+
+ Vpn.updateCapabilities(mConnectivityManager, new Network[] { wifi }, caps);
+ assertTrue(caps.hasTransport(TRANSPORT_VPN));
+ assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
+ assertTrue(caps.hasTransport(TRANSPORT_WIFI));
+ assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
+ assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
+ assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+
+ Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile, wifi }, caps);
+ assertTrue(caps.hasTransport(TRANSPORT_VPN));
+ assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
+ assertTrue(caps.hasTransport(TRANSPORT_WIFI));
+ assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
+ assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
+ assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+ }
+
/**
* Mock some methods of vpn object.
*/
@@ -463,4 +549,11 @@ public class VpnTest {
} catch (Exception e) {
}
}
+
+ private void setMockedNetworks(final Map<Network, NetworkCapabilities> networks) {
+ doAnswer(invocation -> {
+ final Network network = (Network) invocation.getArguments()[0];
+ return networks.get(network);
+ }).when(mConnectivityManager).getNetworkCapabilities(any());
+ }
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index fa997958ba6d..375b418bead6 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -1169,9 +1169,8 @@ public class NetworkStatsServiceTest {
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(TEST_IFACE);
final NetworkCapabilities capabilities = new NetworkCapabilities();
- if (!isMetered) {
- capabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
- }
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !isMetered);
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
return new NetworkState(info, prop, capabilities, null, null, TEST_SSID);
}
@@ -1187,6 +1186,8 @@ public class NetworkStatsServiceTest {
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(TEST_IFACE);
final NetworkCapabilities capabilities = new NetworkCapabilities();
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
return new NetworkState(info, prop, capabilities, null, subscriberId, null);
}
@@ -1196,6 +1197,8 @@ public class NetworkStatsServiceTest {
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(iface);
final NetworkCapabilities capabilities = new NetworkCapabilities();
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
+ capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
return new NetworkState(info, prop, capabilities, null, null, null);
}