diff --git a/common/TrunkStable.bp b/common/TrunkStable.bp index 772f79e8e0..56938fcf61 100644 --- a/common/TrunkStable.bp +++ b/common/TrunkStable.bp @@ -19,3 +19,8 @@ aconfig_declarations { package: "com.android.net.flags", srcs: ["flags.aconfig"], } + +java_aconfig_library { + name: "connectivity_flags_aconfig_lib", + aconfig_declarations: "com.android.net.flags-aconfig", +} diff --git a/common/flags.aconfig b/common/flags.aconfig index 4926503e08..cadc44f174 100644 --- a/common/flags.aconfig +++ b/common/flags.aconfig @@ -6,3 +6,10 @@ flag { description: "NetworkActivityTracker tracks multiple networks including non default networks" bug: "267870186" } + +flag { + name: "forbidden_capability" + namespace: "android_core_networking" + description: "This flag controls the forbidden capability API" + bug: "302997505" +} diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 5d70857aa6..74d50f8fd0 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -29,6 +29,9 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; +// Can't be imported because aconfig tooling doesn't exist on udc-mainline-prod yet +// See inner class Flags which mimics this for the time being +// import android.net.flags.Flags; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -121,6 +124,14 @@ import java.util.StringJoiner; public final class NetworkCapabilities implements Parcelable { private static final String TAG = "NetworkCapabilities"; + // TODO : remove this class when udc-mainline-prod is abandoned and android.net.flags.Flags is + // available here + /** @hide */ + public static class Flags { + static final String FLAG_FORBIDDEN_CAPABILITY = + "com.android.net.flags.forbidden_capability"; + } + /** * Mechanism to support redaction of fields in NetworkCapabilities that are guarded by specific * app permissions. @@ -793,6 +804,10 @@ public final class NetworkCapabilities implements Parcelable { * Adds the given capability to this {@code NetworkCapability} instance. * Note that when searching for a network to satisfy a request, all capabilities * requested must be satisfied. + *

+ * If the capability was previously added to the list of forbidden capabilities (either + * by default or added using {@link #addForbiddenCapability(int)}), then it will be removed + * from the list of forbidden capabilities as well. * * @param capability the capability to be added. * @return This NetworkCapabilities instance, to facilitate chaining. @@ -801,8 +816,7 @@ public final class NetworkCapabilities implements Parcelable { public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) { // If the given capability was previously added to the list of forbidden capabilities // then the capability will also be removed from the list of forbidden capabilities. - // TODO: Consider adding forbidden capabilities to the public API and mention this - // in the documentation. + // TODO: Add forbidden capabilities to the public API checkValidCapability(capability); mNetworkCapabilities |= 1L << capability; // remove from forbidden capability list @@ -901,6 +915,8 @@ public final class NetworkCapabilities implements Parcelable { * @return an array of forbidden capability values for this instance. * @hide */ + @NonNull + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public public @NetCapability int[] getForbiddenCapabilities() { return BitUtils.unpackBits(mForbiddenNetworkCapabilities); } @@ -1000,7 +1016,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Tests for the presence of a capability on this instance. * - * @param capability the capabilities to be tested for. + * @param capability the capability to be tested for. * @return {@code true} if set on this instance. */ public boolean hasCapability(@NetCapability int capability) { @@ -1008,8 +1024,15 @@ public final class NetworkCapabilities implements Parcelable { && ((mNetworkCapabilities & (1L << capability)) != 0); } - /** @hide */ + /** + * Tests for the presence of a forbidden capability on this instance. + * + * @param capability the capability to be tested for. + * @return {@code true} if this capability is set forbidden on this instance. + * @hide + */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public public boolean hasForbiddenCapability(@NetCapability int capability) { return isValidCapability(capability) && ((mForbiddenNetworkCapabilities & (1L << capability)) != 0); @@ -2888,6 +2911,44 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Adds the given capability to the list of forbidden capabilities. + * + * A network with a capability will not match a {@link NetworkCapabilities} or + * {@link NetworkRequest} which has said capability set as forbidden. For example, if + * a request has NET_CAPABILITY_INTERNET in the list of forbidden capabilities, networks + * with NET_CAPABILITY_INTERNET will not match the request. + * + * 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. + * + * @param capability the capability + * @return this builder + * @hide + */ + @NonNull + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public + public Builder addForbiddenCapability(@NetCapability final int capability) { + mCaps.addForbiddenCapability(capability); + return this; + } + + /** + * Removes the given capability from the list of forbidden capabilities. + * + * @see #addForbiddenCapability(int) + * @param capability the capability + * @return this builder + * @hide + */ + @NonNull + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public + public Builder removeForbiddenCapability(@NetCapability final int capability) { + mCaps.removeForbiddenCapability(capability); + return this; + } + /** * Adds the given enterprise capability identifier. * Note that when searching for a network to satisfy a request, all capabilities identifier diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 6c351d0548..5cc9f1b605 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -39,6 +39,8 @@ import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; +// TODO : replace with android.net.flags.Flags when aconfig is supported on udc-mainline-prod +// import android.net.NetworkCapabilities.Flags; import android.net.NetworkCapabilities.NetCapability; import android.net.NetworkCapabilities.Transport; import android.os.Build; @@ -408,6 +410,7 @@ public class NetworkRequest implements Parcelable { @NonNull @SuppressLint("MissingGetterMatchingBuilder") @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public public Builder addForbiddenCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addForbiddenCapability(capability); return this; @@ -424,6 +427,7 @@ public class NetworkRequest implements Parcelable { @NonNull @SuppressLint("BuilderSetStyle") @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public public Builder removeForbiddenCapability( @NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.removeForbiddenCapability(capability); @@ -433,6 +437,7 @@ public class NetworkRequest implements Parcelable { /** * Completely clears all the {@code NetworkCapabilities} from this builder instance, * removing even the capabilities that are set by default when the object is constructed. + * Also removes any set forbidden capabilities. * * @return The builder to facilitate chaining. */ @@ -721,6 +726,7 @@ public class NetworkRequest implements Parcelable { * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public instead of @SystemApi public boolean hasForbiddenCapability(@NetCapability int capability) { return networkCapabilities.hasForbiddenCapability(capability); } @@ -843,6 +849,7 @@ public class NetworkRequest implements Parcelable { */ @NonNull @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + // TODO : @FlaggedApi(Flags.FLAG_FORBIDDEN_CAPABILITY) and public instead of @SystemApi public @NetCapability int[] getForbiddenCapabilities() { // No need to make a defensive copy here as NC#getForbiddenCapabilities() already returns // a new array. diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java index 637ed26747..718ca6dea4 100644 --- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java +++ b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java @@ -104,6 +104,23 @@ public class NetworkRequestTest { verifyNoCapabilities(nr); } + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + public void testForbiddenCapabilities() { + final NetworkRequest.Builder builder = new NetworkRequest.Builder(); + builder.addForbiddenCapability(NET_CAPABILITY_MMS); + assertTrue(builder.build().hasForbiddenCapability(NET_CAPABILITY_MMS)); + builder.removeForbiddenCapability(NET_CAPABILITY_MMS); + assertFalse(builder.build().hasCapability(NET_CAPABILITY_MMS)); + builder.addCapability(NET_CAPABILITY_MMS); + assertFalse(builder.build().hasForbiddenCapability(NET_CAPABILITY_MMS)); + assertTrue(builder.build().hasCapability(NET_CAPABILITY_MMS)); + builder.addForbiddenCapability(NET_CAPABILITY_MMS); + assertTrue(builder.build().hasForbiddenCapability(NET_CAPABILITY_MMS)); + assertFalse(builder.build().hasCapability(NET_CAPABILITY_MMS)); + builder.clearCapabilities(); + verifyNoCapabilities(builder.build()); + } + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testTemporarilyNotMeteredCapability() { assertTrue(new NetworkRequest.Builder()