diff options
| author | 2018-03-03 00:15:11 +0000 | |
|---|---|---|
| committer | 2018-03-03 00:15:11 +0000 | |
| commit | c1b46229eeec6559bd6cfc49c44cdcbce1d1580c (patch) | |
| tree | 3178871f7199b9580d0a6964fe0894bf765d3400 | |
| parent | b0ebe11b747e64329198f75eb5bb7e96ed978da2 (diff) | |
| parent | 2d8067ed3ddc3a227cd5fdf6309c4961ad41e75f (diff) | |
Merge "Merge "Extend network request to query networks w/o capabilites" am: d846adac83 am: a3be78b5e7 am: f5312f3538"
| -rw-r--r-- | core/java/android/net/NetworkCapabilities.java | 142 | ||||
| -rw-r--r-- | core/java/android/net/NetworkRequest.java | 24 | ||||
| -rw-r--r-- | tests/net/java/android/net/NetworkCapabilitiesTest.java | 120 |
3 files changed, 257 insertions, 29 deletions
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 17b46c68ebe1..ef58f94e70cf 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.annotation.SystemApi; import android.net.ConnectivityManager.NetworkCallback; import android.os.Parcel; import android.os.Parcelable; @@ -69,6 +70,7 @@ public final class NetworkCapabilities implements Parcelable { mSignalStrength = nc.mSignalStrength; mUids = nc.mUids; mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid; + mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; } } @@ -78,7 +80,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void clearAll() { - mNetworkCapabilities = mTransportTypes = 0; + mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; mNetworkSpecifier = null; mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; @@ -92,6 +94,11 @@ public final class NetworkCapabilities implements Parcelable { */ private long mNetworkCapabilities; + /** + * If any capabilities specified here they must not exist in the matching Network. + */ + private long mUnwantedNetworkCapabilities; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "NET_CAPABILITY_" }, value = { @@ -339,31 +346,55 @@ public final class NetworkCapabilities implements Parcelable { * Adds the given capability to this {@code NetworkCapability} instance. * Multiple capabilities may be applied sequentially. Note that when searching * for a network to satisfy a request, all capabilities requested must be satisfied. + * <p> + * If the given capability was previously added to the list of unwanted capabilities + * then the capability will also be removed from the list of unwanted capabilities. * * @param capability the capability to be added. * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ public NetworkCapabilities addCapability(@NetCapability int capability) { - if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) { - throw new IllegalArgumentException("NetworkCapability out of range"); - } + checkValidCapability(capability); mNetworkCapabilities |= 1 << capability; + mUnwantedNetworkCapabilities &= ~(1 << capability); // remove from unwanted capability list return this; } /** + * Adds the given capability to the list of unwanted capabilities of this + * {@code NetworkCapability} instance. Multiple unwanted capabilities may be applied + * sequentially. Note that when searching for a network to satisfy a request, the network + * must not contain any capability from unwanted capability list. + * <p> + * If the capability was previously added to the list of required capabilities (for + * example, it was there by default or added using {@link #addCapability(int)} method), then + * it will be removed from the list of required capabilities as well. + * + * @see #addCapability(int) + * @hide + */ + public void addUnwantedCapability(@NetCapability int capability) { + checkValidCapability(capability); + mUnwantedNetworkCapabilities |= 1 << capability; + mNetworkCapabilities &= ~(1 << capability); // remove from requested capabilities + } + + /** * Removes (if found) the given capability from this {@code NetworkCapability} instance. + * <p> + * Note that this method removes capabilities that was added via {@link #addCapability(int)}, + * {@link #addUnwantedCapability(int)} or {@link #setCapabilities(int[], int[])} . * * @param capability the capability to be removed. * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ public NetworkCapabilities removeCapability(@NetCapability int capability) { - if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) { - throw new IllegalArgumentException("NetworkCapability out of range"); - } - mNetworkCapabilities &= ~(1 << capability); + checkValidCapability(capability); + final long mask = ~(1 << capability); + mNetworkCapabilities &= mask; + mUnwantedNetworkCapabilities &= mask; return this; } @@ -393,30 +424,57 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Gets all the unwanted capabilities set on this {@code NetworkCapability} instance. + * + * @return an array of unwanted capability values for this instance. + * @hide + */ + public @NetCapability int[] getUnwantedCapabilities() { + return BitUtils.unpackBits(mUnwantedNetworkCapabilities); + } + + + /** * Sets all the capabilities set on this {@code NetworkCapability} instance. * This overwrites any existing capabilities. * * @hide */ - public void setCapabilities(@NetCapability int[] capabilities) { + public void setCapabilities(@NetCapability int[] capabilities, + @NetCapability int[] unwantedCapabilities) { mNetworkCapabilities = BitUtils.packBits(capabilities); + mUnwantedNetworkCapabilities = BitUtils.packBits(unwantedCapabilities); + } + + /** + * @deprecated use {@link #setCapabilities(int[], int[])} + * @hide + */ + @Deprecated + public void setCapabilities(@NetCapability int[] capabilities) { + setCapabilities(capabilities, new int[] {}); } /** - * Tests for the presence of a capabilitity on this instance. + * Tests for the presence of a capability on this instance. * * @param capability the capabilities to be tested for. * @return {@code true} if set on this instance. */ public boolean hasCapability(@NetCapability int capability) { - if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) { - return false; - } - return ((mNetworkCapabilities & (1 << capability)) != 0); + return isValidCapability(capability) + && ((mNetworkCapabilities & (1 << capability)) != 0); + } + + /** @hide */ + public boolean hasUnwantedCapability(@NetCapability int capability) { + return isValidCapability(capability) + && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0); } private void combineNetCapabilities(NetworkCapabilities nc) { this.mNetworkCapabilities |= nc.mNetworkCapabilities; + this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities; } /** @@ -427,7 +485,9 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public String describeFirstNonRequestableCapability() { - final long nonRequestable = (mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES); + final long nonRequestable = (mNetworkCapabilities | mUnwantedNetworkCapabilities) + & NON_REQUESTABLE_CAPABILITIES; + if (nonRequestable != 0) { return capabilityNameOf(BitUtils.unpackBits(nonRequestable)[0]); } @@ -437,21 +497,29 @@ public final class NetworkCapabilities implements Parcelable { } private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) { - long networkCapabilities = this.mNetworkCapabilities; + long requestedCapabilities = mNetworkCapabilities; + long requestedUnwantedCapabilities = mUnwantedNetworkCapabilities; + long providedCapabilities = nc.mNetworkCapabilities; + if (onlyImmutable) { - networkCapabilities = networkCapabilities & ~MUTABLE_CAPABILITIES; + requestedCapabilities &= ~MUTABLE_CAPABILITIES; + requestedUnwantedCapabilities &= ~MUTABLE_CAPABILITIES; } - return ((nc.mNetworkCapabilities & networkCapabilities) == networkCapabilities); + return ((providedCapabilities & requestedCapabilities) == requestedCapabilities) + && ((requestedUnwantedCapabilities & providedCapabilities) == 0); } /** @hide */ public boolean equalsNetCapabilities(NetworkCapabilities nc) { - return (nc.mNetworkCapabilities == this.mNetworkCapabilities); + return (nc.mNetworkCapabilities == this.mNetworkCapabilities) + && (nc.mUnwantedNetworkCapabilities == this.mUnwantedNetworkCapabilities); } private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) { return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) == - (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)); + (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)) + && ((this.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) == + (that.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)); } /** @@ -1185,15 +1253,17 @@ public final class NetworkCapabilities implements Parcelable { @Override public int hashCode() { - return ((int) (mNetworkCapabilities & 0xFFFFFFFF) + return (int) (mNetworkCapabilities & 0xFFFFFFFF) + ((int) (mNetworkCapabilities >> 32) * 3) - + ((int) (mTransportTypes & 0xFFFFFFFF) * 5) - + ((int) (mTransportTypes >> 32) * 7) - + (mLinkUpBandwidthKbps * 11) - + (mLinkDownBandwidthKbps * 13) - + Objects.hashCode(mNetworkSpecifier) * 17 - + (mSignalStrength * 19) - + Objects.hashCode(mUids) * 23); + + ((int) (mUnwantedNetworkCapabilities & 0xFFFFFFFF) * 5) + + ((int) (mUnwantedNetworkCapabilities >> 32) * 7) + + ((int) (mTransportTypes & 0xFFFFFFFF) * 11) + + ((int) (mTransportTypes >> 32) * 13) + + (mLinkUpBandwidthKbps * 17) + + (mLinkDownBandwidthKbps * 19) + + Objects.hashCode(mNetworkSpecifier) * 23 + + (mSignalStrength * 29) + + Objects.hashCode(mUids) * 31; } @Override @@ -1203,6 +1273,7 @@ public final class NetworkCapabilities implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(mNetworkCapabilities); + dest.writeLong(mUnwantedNetworkCapabilities); dest.writeLong(mTransportTypes); dest.writeInt(mLinkUpBandwidthKbps); dest.writeInt(mLinkDownBandwidthKbps); @@ -1218,6 +1289,7 @@ public final class NetworkCapabilities implements Parcelable { NetworkCapabilities netCap = new NetworkCapabilities(); netCap.mNetworkCapabilities = in.readLong(); + netCap.mUnwantedNetworkCapabilities = in.readLong(); netCap.mTransportTypes = in.readLong(); netCap.mLinkUpBandwidthKbps = in.readInt(); netCap.mLinkDownBandwidthKbps = in.readInt(); @@ -1246,6 +1318,11 @@ public final class NetworkCapabilities implements Parcelable { appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities, NetworkCapabilities::capabilityNameOf, "&"); } + if (0 != mNetworkCapabilities) { + sb.append(" Unwanted: "); + appendStringRepresentationOfBitMaskToStringBuilder(sb, mUnwantedNetworkCapabilities, + NetworkCapabilities::capabilityNameOf, "&"); + } if (mLinkUpBandwidthKbps > 0) { sb.append(" LinkUpBandwidth>=").append(mLinkUpBandwidthKbps).append("Kbps"); } @@ -1396,4 +1473,13 @@ public final class NetworkCapabilities implements Parcelable { Preconditions.checkArgument( isValidTransport(transport), "Invalid TransportType " + transport); } + + private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) { + return capability >= MIN_NET_CAPABILITY && capability <= MAX_NET_CAPABILITY; + } + + private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) { + Preconditions.checkArgument(isValidCapability(capability), + "NetworkCapability " + capability + "out of range"); + } } diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 61199f906e4a..fdcc304e1d2e 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -165,6 +165,9 @@ public class NetworkRequest implements Parcelable { * the requested network's required capabilities. Note that when searching * for a network to satisfy a request, all capabilities requested must be * satisfied. + * <p> + * If the given capability was previously added to the list of unwanted capabilities + * then the capability will also be removed from the list of unwanted capabilities. * * @param capability The capability to add. * @return The builder to facilitate chaining @@ -176,7 +179,8 @@ public class NetworkRequest implements Parcelable { } /** - * Removes (if found) the given capability from this builder instance. + * Removes (if found) the given capability from this builder instance from both required + * and unwanted capabilities lists. * * @param capability The capability to remove. * @return The builder to facilitate chaining. @@ -201,6 +205,24 @@ public class NetworkRequest implements Parcelable { } /** + * Add a capability that must not exist in the requested network. + * <p> + * If the capability was previously added to the list of required capabilities (for + * example, it was there by default or added using {@link #addCapability(int)} method), then + * it will be removed from the list of required capabilities as well. + * + * @see #addCapability(int) + * + * @param capability The capability to add to unwanted capability list. + * @return The builder to facilitate chaining. + * @hide + */ + public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) { + mNetworkCapabilities.addUnwantedCapability(capability); + return this; + } + + /** * Completely clears all the {@code NetworkCapabilities} from this builder instance, * removing even the capabilities that are set by default when the object is constructed. * diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java index ec6a5ecbbd02..c86637186342 100644 --- a/tests/net/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java @@ -17,18 +17,24 @@ package android.net; import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; 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_OEM_PAID; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; 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.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -268,6 +274,120 @@ public class NetworkCapabilitiesTest { assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); } + @Test + public void testUnwantedCapabilities() { + NetworkCapabilities network = new NetworkCapabilities(); + + NetworkCapabilities request = new NetworkCapabilities(); + assertTrue("Request: " + request + ", Network:" + network, + request.satisfiedByNetworkCapabilities(network)); + + // Adding capabilities that doesn't exist in the network anyway + request.addUnwantedCapability(NET_CAPABILITY_WIFI_P2P); + request.addUnwantedCapability(NET_CAPABILITY_NOT_METERED); + assertTrue(request.satisfiedByNetworkCapabilities(network)); + assertArrayEquals(new int[] {NET_CAPABILITY_WIFI_P2P, NET_CAPABILITY_NOT_METERED}, + request.getUnwantedCapabilities()); + + // This is a default capability, just want to make sure its there because we use it below. + assertTrue(network.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + // Verify that adding unwanted capability will effectively remove it from capability list. + request.addUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED); + assertTrue(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED)); + assertFalse(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + + // Now this request won't be satisfied because network contains NOT_RESTRICTED. + assertFalse(request.satisfiedByNetworkCapabilities(network)); + network.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + assertTrue(request.satisfiedByNetworkCapabilities(network)); + + // Verify that adding capability will effectively remove it from unwanted list + request.addCapability(NET_CAPABILITY_NOT_RESTRICTED); + assertTrue(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + assertFalse(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + assertFalse(request.satisfiedByNetworkCapabilities(network)); + network.addCapability(NET_CAPABILITY_NOT_RESTRICTED); + assertTrue(request.satisfiedByNetworkCapabilities(network)); + } + + @Test + public void testEqualsNetCapabilities() { + int CAPABILITY = NET_CAPABILITY_MMS; // An arbitrary not mutable capability. + + NetworkCapabilities nc1 = new NetworkCapabilities(); + NetworkCapabilities nc2 = new NetworkCapabilities(); + assertTrue(nc1.equalsNetCapabilities(nc2)); + assertEquals(nc1, nc2); + + nc1.addCapability(CAPABILITY); + assertFalse(nc1.equalsNetCapabilities(nc2)); + assertNotEquals(nc1, nc2); + nc2.addCapability(CAPABILITY); + assertTrue(nc1.equalsNetCapabilities(nc2)); + assertEquals(nc1, nc2); + + nc1.addUnwantedCapability(CAPABILITY); + assertFalse(nc1.equalsNetCapabilities(nc2)); + nc2.addUnwantedCapability(CAPABILITY); + assertTrue(nc1.equalsNetCapabilities(nc2)); + + nc1.removeCapability(CAPABILITY); + assertFalse(nc1.equalsNetCapabilities(nc2)); + nc2.removeCapability(CAPABILITY); + assertTrue(nc1.equalsNetCapabilities(nc2)); + } + + @Test + public void testCombineCapabilities() { + NetworkCapabilities nc1 = new NetworkCapabilities(); + NetworkCapabilities nc2 = new NetworkCapabilities(); + + nc1.addUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL); + nc1.addCapability(NET_CAPABILITY_NOT_ROAMING); + assertNotEquals(nc1, nc2); + nc2.combineCapabilities(nc1); + assertEquals(nc1, nc2); + assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); + assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL)); + + // This will effectively move NOT_ROAMING capability from required to unwanted for nc1. + nc1.addUnwantedCapability(NET_CAPABILITY_NOT_ROAMING); + + nc2.combineCapabilities(nc1); + // We will get this capability in both requested and unwanted lists thus this request + // will never be satisfied. + assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); + assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING)); + } + + @Test + public void testSetCapabilities() { + final int[] REQUIRED_CAPABILITIES = new int[] { + NET_CAPABILITY_INTERNET, NET_CAPABILITY_NOT_VPN }; + final int[] UNWANTED_CAPABILITIES = new int[] { + NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_METERED + }; + + NetworkCapabilities nc1 = new NetworkCapabilities(); + NetworkCapabilities nc2 = new NetworkCapabilities(); + + nc1.setCapabilities(REQUIRED_CAPABILITIES, UNWANTED_CAPABILITIES); + assertArrayEquals(REQUIRED_CAPABILITIES, nc1.getCapabilities()); + + // Verify that setting and adding capabilities leads to the same object state. + nc2.clearAll(); + for (int cap : REQUIRED_CAPABILITIES) { + nc2.addCapability(cap); + } + for (int cap : UNWANTED_CAPABILITIES) { + nc2.addUnwantedCapability(cap); + } + assertEquals(nc1, nc2); + } + private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) { Parcel p = Parcel.obtain(); netCap.writeToParcel(p, /* flags */ 0); |