diff options
-rw-r--r-- | api/current.txt | 3 | ||||
-rw-r--r-- | api/system-current.txt | 3 | ||||
-rw-r--r-- | api/test-current.txt | 3 | ||||
-rw-r--r-- | core/java/android/net/NetworkCapabilities.java | 119 | ||||
-rw-r--r-- | core/java/android/net/NetworkIdentity.java | 4 | ||||
-rw-r--r-- | core/java/android/net/NetworkInfo.java | 13 | ||||
-rw-r--r-- | services/core/java/com/android/server/ConnectivityService.java | 38 | ||||
-rw-r--r-- | services/core/java/com/android/server/connectivity/Vpn.java | 63 | ||||
-rw-r--r-- | tests/net/java/android/net/NetworkCapabilitiesTest.java | 25 | ||||
-rw-r--r-- | tests/net/java/com/android/server/ConnectivityServiceTest.java | 83 | ||||
-rw-r--r-- | tests/net/java/com/android/server/connectivity/VpnTest.java | 101 | ||||
-rw-r--r-- | tests/net/java/com/android/server/net/NetworkStatsServiceTest.java | 9 |
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); } |