Loading core/java/android/net/NetworkCapabilities.java +114 −28 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -68,6 +69,7 @@ public final class NetworkCapabilities implements Parcelable { mSignalStrength = nc.mSignalStrength; mUids = nc.mUids; mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; } } Loading @@ -77,7 +79,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; Loading @@ -91,6 +93,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 = { Loading Loading @@ -338,31 +345,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; } Loading Loading @@ -391,31 +422,58 @@ public final class NetworkCapabilities implements Parcelable { return BitUtils.unpackBits(mNetworkCapabilities); } /** * 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 isValidCapability(capability) && ((mNetworkCapabilities & (1 << capability)) != 0); } return ((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; } /** Loading @@ -426,7 +484,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]); } Loading @@ -436,21 +496,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)); } /** Loading Loading @@ -1186,15 +1254,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 Loading @@ -1204,6 +1274,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); Loading @@ -1219,6 +1290,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(); Loading Loading @@ -1247,6 +1319,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"); } Loading Loading @@ -1372,4 +1449,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"); } } core/java/android/net/NetworkRequest.java +23 −1 Original line number Diff line number Diff line Loading @@ -164,6 +164,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 Loading @@ -175,7 +178,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. Loading @@ -199,6 +203,24 @@ public class NetworkRequest implements Parcelable { return this; } /** * 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. Loading tests/net/java/android/net/NetworkCapabilitiesTest.java +120 −0 Original line number Diff line number Diff line Loading @@ -17,19 +17,25 @@ 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_DUN; 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; Loading Loading @@ -277,6 +283,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); Loading Loading
core/java/android/net/NetworkCapabilities.java +114 −28 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -68,6 +69,7 @@ public final class NetworkCapabilities implements Parcelable { mSignalStrength = nc.mSignalStrength; mUids = nc.mUids; mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; } } Loading @@ -77,7 +79,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; Loading @@ -91,6 +93,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 = { Loading Loading @@ -338,31 +345,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; } Loading Loading @@ -391,31 +422,58 @@ public final class NetworkCapabilities implements Parcelable { return BitUtils.unpackBits(mNetworkCapabilities); } /** * 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 isValidCapability(capability) && ((mNetworkCapabilities & (1 << capability)) != 0); } return ((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; } /** Loading @@ -426,7 +484,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]); } Loading @@ -436,21 +496,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)); } /** Loading Loading @@ -1186,15 +1254,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 Loading @@ -1204,6 +1274,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); Loading @@ -1219,6 +1290,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(); Loading Loading @@ -1247,6 +1319,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"); } Loading Loading @@ -1372,4 +1449,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"); } }
core/java/android/net/NetworkRequest.java +23 −1 Original line number Diff line number Diff line Loading @@ -164,6 +164,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 Loading @@ -175,7 +178,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. Loading @@ -199,6 +203,24 @@ public class NetworkRequest implements Parcelable { return this; } /** * 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. Loading
tests/net/java/android/net/NetworkCapabilitiesTest.java +120 −0 Original line number Diff line number Diff line Loading @@ -17,19 +17,25 @@ 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_DUN; 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; Loading Loading @@ -277,6 +283,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); Loading