From 4196937bdda20ef09fdba47325abb7e497e635eb Mon Sep 17 00:00:00 2001 From: Sooraj Sasindran Date: Fri, 10 Dec 2021 11:31:19 -0800 Subject: [PATCH] Add enterpriseSpecifier Add enterpriseSpecifier to network capability Bug: 194332512 CTS-Coverage-Bug: 211133973 Test: CTS and unit test. Change-Id: If16c8e17cee71cc6788c43a8818bcca68a00bf99 --- framework/api/current.txt | 1 + framework/api/module-lib-current.txt | 5 + framework/api/system-current.txt | 2 + .../src/android/net/NetworkCapabilities.java | 187 +++++++++++++++++- .../android/net/NetworkCapabilitiesTest.java | 89 ++++++++- 5 files changed, 281 insertions(+), 3 deletions(-) diff --git a/framework/api/current.txt b/framework/api/current.txt index ad42ddeda8..b21b41e2ec 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -293,6 +293,7 @@ package android.net { ctor public NetworkCapabilities(android.net.NetworkCapabilities); method public int describeContents(); method @NonNull public int[] getCapabilities(); + method @NonNull public int[] getEnterpriseCapabilitySubLevels(); method public int getLinkDownstreamBandwidthKbps(); method public int getLinkUpstreamBandwidthKbps(); method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 50dd2ad5da..81a1e5dd62 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -121,6 +121,11 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { method @Nullable public java.util.Set> getUids(); method public boolean hasForbiddenCapability(int); + field public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1 = 1; // 0x1 + field public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2 = 2; // 0x2 + field public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_3 = 3; // 0x3 + field public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_4 = 4; // 0x4 + field public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_5 = 5; // 0x5 field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index cfab8724fd..bada3e20c2 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -295,9 +295,11 @@ package android.net { ctor public NetworkCapabilities.Builder(); ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder addEnterpriseCapabilitySubLevel(int); method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); method @NonNull public android.net.NetworkCapabilities build(); method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder removeEnterpriseCapabilitySubLevel(int); method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 721a12d0c6..84f7cbbd62 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -16,6 +16,8 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.annotation.IntDef; @@ -146,6 +148,70 @@ public final class NetworkCapabilities implements Parcelable { */ private String mRequestorPackageName; + /** + * enterprise capability sub level 1 + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1 = 1; + + /** + * enterprise capability sub level 2 + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2 = 2; + + /** + * enterprise capability sub level 3 + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_3 = 3; + + /** + * enterprise capability sub level 4 + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_4 = 4; + + /** + * enterprise capability sub level 5 + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_5 = 5; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "NET_CAPABILITY_ENTERPRISE_SUB_LEVEL" }, value = { + NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1, + NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2, + NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_3, + NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_4, + NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_5, + }) + + public @interface EnterpriseCapabilitySubLevel { + } + + /** + * Bitfield representing the network's enterprise capability sublevel. If any are specified + * they will be satisfied by any Network that matches all of them. + * {@see addEnterpriseCapabilitySubLevel} for details on how masks are added + */ + private int mEnterpriseCapabilitySubLevel; + + /** + * @return all the enteprise capabilities sub level set on this {@code NetworkCapability} + * instance. + * + */ + public @NonNull @EnterpriseCapabilitySubLevel int[] getEnterpriseCapabilitySubLevels() { + return NetworkCapabilitiesUtils.unpackBits(mEnterpriseCapabilitySubLevel); + } + public NetworkCapabilities() { clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; @@ -192,6 +258,7 @@ public final class NetworkCapabilities implements Parcelable { mRequestorPackageName = null; mSubIds = new ArraySet<>(); mUnderlyingNetworks = null; + mEnterpriseCapabilitySubLevel = 0; } /** @@ -224,6 +291,7 @@ public final class NetworkCapabilities implements Parcelable { // mUnderlyingNetworks is an unmodifiable list if non-null, so a defensive copy is not // necessary. mUnderlyingNetworks = nc.mUnderlyingNetworks; + mEnterpriseCapabilitySubLevel = nc.mEnterpriseCapabilitySubLevel; } /** @@ -715,6 +783,38 @@ public final class NetworkCapabilities implements Parcelable { setCapabilities(capabilities, new int[] {}); } + /** + * Adds the given enterprise capability sub level to this {@code NetworkCapability} instance. + * Note that when searching for a network to satisfy a request, all capabilities sub level + * requested must be satisfied. + * + * @param enterpriseCapabilitySubLevel the enterprise capability sub level to be added. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + private @NonNull NetworkCapabilities addEnterpriseCapabilitySubLevel( + @EnterpriseCapabilitySubLevel int enterpriseCapabilitySubLevel) { + checkValidEnterpriseCapabilitySublevel(enterpriseCapabilitySubLevel); + mEnterpriseCapabilitySubLevel |= 1 << enterpriseCapabilitySubLevel; + return this; + } + + /** + * Removes (if found) the given enterprise capability sublevel from this + * {@code NetworkCapability} instance that were added via addEnterpriseCapabilitySubLevel(int) + * + * @param enterpriseCapabilitySubLevel the enterprise capability sublevel to be removed. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + private @NonNull NetworkCapabilities removeEnterpriseCapabilitySubLevel( + @EnterpriseCapabilitySubLevel int enterpriseCapabilitySubLevel) { + checkValidEnterpriseCapabilitySublevel(enterpriseCapabilitySubLevel); + final int mask = ~(1 << enterpriseCapabilitySubLevel); + mEnterpriseCapabilitySubLevel &= mask; + return this; + } + /** * Set the underlying networks of this network. * @@ -815,6 +915,22 @@ public final class NetworkCapabilities implements Parcelable { return null; } + private boolean equalsEnterpriseCapabilitiesSubLevel(@NonNull NetworkCapabilities nc) { + return nc.mEnterpriseCapabilitySubLevel == this.mEnterpriseCapabilitySubLevel; + } + + private boolean satisfiedByEnterpriseCapabilitiesSubLevel(@NonNull NetworkCapabilities nc) { + final int requestedEnterpriseCapabilitiesSubLevel = mEnterpriseCapabilitySubLevel; + final int providedEnterpriseCapabailitiesSubLevel = nc.mEnterpriseCapabilitySubLevel; + + if ((providedEnterpriseCapabailitiesSubLevel & requestedEnterpriseCapabilitiesSubLevel) + == requestedEnterpriseCapabilitiesSubLevel) { + return true; + } else { + return false; + } + } + private boolean satisfiedByNetCapabilities(@NonNull NetworkCapabilities nc, boolean onlyImmutable) { long requestedCapabilities = mNetworkCapabilities; @@ -1720,6 +1836,7 @@ public final class NetworkCapabilities implements Parcelable { && satisfiedByTransportTypes(nc) && (onlyImmutable || satisfiedByLinkBandwidths(nc)) && satisfiedBySpecifier(nc) + && satisfiedByEnterpriseCapabilitiesSubLevel(nc) && (onlyImmutable || satisfiedBySignalStrength(nc)) && (onlyImmutable || satisfiedByUids(nc)) && (onlyImmutable || satisfiedBySSID(nc)) @@ -1822,7 +1939,8 @@ public final class NetworkCapabilities implements Parcelable { && equalsRequestor(that) && equalsAdministratorUids(that) && equalsSubscriptionIds(that) - && equalsUnderlyingNetworks(that); + && equalsUnderlyingNetworks(that) + && equalsEnterpriseCapabilitiesSubLevel(that); } @Override @@ -1846,7 +1964,8 @@ public final class NetworkCapabilities implements Parcelable { + Objects.hashCode(mRequestorPackageName) * 59 + Arrays.hashCode(mAdministratorUids) * 61 + Objects.hashCode(mSubIds) * 67 - + Objects.hashCode(mUnderlyingNetworks) * 71; + + Objects.hashCode(mUnderlyingNetworks) * 71 + + mEnterpriseCapabilitySubLevel * 73; } @Override @@ -1882,6 +2001,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeString(mRequestorPackageName); dest.writeIntArray(CollectionUtils.toIntArray(mSubIds)); dest.writeTypedList(mUnderlyingNetworks); + dest.writeInt(mEnterpriseCapabilitySubLevel); } public static final @android.annotation.NonNull Creator CREATOR = @@ -1911,6 +2031,7 @@ public final class NetworkCapabilities implements Parcelable { netCap.mSubIds.add(subIdInts[i]); } netCap.setUnderlyingNetworks(in.createTypedArrayList(Network.CREATOR)); + netCap.mEnterpriseCapabilitySubLevel = in.readInt(); return netCap; } @Override @@ -2002,6 +2123,12 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" SubscriptionIds: ").append(mSubIds); } + if (0 != mEnterpriseCapabilitySubLevel) { + sb.append(" EnterpriseCapabilitySublevel: "); + appendStringRepresentationOfBitMaskToStringBuilder(sb, mEnterpriseCapabilitySubLevel, + NetworkCapabilities::enterpriseCapabilitySublevelNameOf, "&"); + } + sb.append(" UnderlyingNetworks: "); if (mUnderlyingNetworks != null) { sb.append("["); @@ -2101,6 +2228,11 @@ public final class NetworkCapabilities implements Parcelable { } } + private static @NonNull String enterpriseCapabilitySublevelNameOf( + @NetCapability int capability) { + return Integer.toString(capability); + } + /** * @hide */ @@ -2141,6 +2273,20 @@ public final class NetworkCapabilities implements Parcelable { } } + private static boolean isValidEnterpriseCapabilitySubLevel( + @NetworkCapabilities.EnterpriseCapabilitySubLevel int enterpriseCapabilitySubLevel) { + return enterpriseCapabilitySubLevel >= NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1 + && enterpriseCapabilitySubLevel <= NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_5; + } + + private static void checkValidEnterpriseCapabilitySublevel( + @NetworkCapabilities.EnterpriseCapabilitySubLevel int enterpriseCapabilitySubLevel) { + if (!isValidEnterpriseCapabilitySubLevel(enterpriseCapabilitySubLevel)) { + throw new IllegalArgumentException("enterprise capability sublevel " + + enterpriseCapabilitySubLevel + " is out of range"); + } + } + /** * Check if this {@code NetworkCapability} instance is metered. * @@ -2466,6 +2612,37 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Adds the given enterprise capability sub level. + * Note that when searching for a network to satisfy a request, all capabilities sub level + * requested must be satisfied. Enterprise capability sub-level is applicable only + * for NET_CAPABILITY_ENTERPRISE capability + * + * @param enterpriseCapabilitySubLevel enterprise capability sub-level. + * + * @return this builder + */ + @NonNull + public Builder addEnterpriseCapabilitySubLevel( + @EnterpriseCapabilitySubLevel int enterpriseCapabilitySubLevel) { + mCaps.addEnterpriseCapabilitySubLevel(enterpriseCapabilitySubLevel); + return this; + } + + /** + * Removes the given enterprise capability sub level. Enterprise capability sub-level is + * applicable only for NET_CAPABILITY_ENTERPRISE capability + * + * @param enterpriseCapabilitySubLevel the enterprise capability subLevel + * @return this builder + */ + @NonNull + public Builder removeEnterpriseCapabilitySubLevel( + @EnterpriseCapabilitySubLevel int enterpriseCapabilitySubLevel) { + mCaps.removeEnterpriseCapabilitySubLevel(enterpriseCapabilitySubLevel); + return this; + } + /** * Sets the owner UID. * @@ -2724,6 +2901,12 @@ public final class NetworkCapabilities implements Parcelable { + " administrator UIDs."); } } + + if ((mCaps.getEnterpriseCapabilitySubLevels().length != 0) + && !mCaps.hasCapability(NET_CAPABILITY_ENTERPRISE)) { + throw new IllegalStateException("Enterprise capability sublevel is applicable only" + + " with ENTERPRISE capability."); + } return new NetworkCapabilities(mCaps); } } diff --git a/tests/common/java/android/net/NetworkCapabilitiesTest.java b/tests/common/java/android/net/NetworkCapabilitiesTest.java index 32f00a3cdc..2a4df7adea 100644 --- a/tests/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/common/java/android/net/NetworkCapabilitiesTest.java @@ -22,6 +22,12 @@ import static android.net.NetworkCapabilities.MIN_TRANSPORT; 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_ENTERPRISE; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_3; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_4; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_5; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; @@ -347,7 +353,7 @@ public class NetworkCapabilitiesTest { if (isAtLeastS()) { // When this test is run on S+, NetworkCapabilities is as recent as the test, // so this should be the most recent known number of fields. - assertParcelSane(cap, 17); + assertParcelSane(cap, 18); } else if (isAtLeastR()) { assertParcelSane(cap, 15); } else { @@ -797,6 +803,87 @@ public class NetworkCapabilitiesTest { } catch (IllegalStateException expected) { } } + @Test @IgnoreUpTo(Build.VERSION_CODES.S) + public void testEnterpriseCapabilitySubLevel() { + final NetworkCapabilities nc1 = new NetworkCapabilities.Builder() + .addCapability(NET_CAPABILITY_ENTERPRISE) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .build(); + assertEquals(1, nc1.getEnterpriseCapabilitySubLevels().length); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1, + nc1.getEnterpriseCapabilitySubLevels()[0]); + final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() + .addCapability(NET_CAPABILITY_ENTERPRISE) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2) + .build(); + assertEquals(2, nc2.getEnterpriseCapabilitySubLevels().length); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1, + nc2.getEnterpriseCapabilitySubLevels()[0]); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2, + nc2.getEnterpriseCapabilitySubLevels()[1]); + final NetworkCapabilities nc3 = new NetworkCapabilities.Builder() + .addCapability(NET_CAPABILITY_ENTERPRISE) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_3) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_4) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_5) + .build(); + assertEquals(5, nc3.getEnterpriseCapabilitySubLevels().length); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1, + nc3.getEnterpriseCapabilitySubLevels()[0]); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2, + nc3.getEnterpriseCapabilitySubLevels()[1]); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_3, + nc3.getEnterpriseCapabilitySubLevels()[2]); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_4, + nc3.getEnterpriseCapabilitySubLevels()[3]); + assertEquals(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_5, + nc3.getEnterpriseCapabilitySubLevels()[4]); + + final Class illegalArgumentExceptionClass = + IllegalArgumentException.class; + assertThrows(illegalArgumentExceptionClass, () -> new NetworkCapabilities.Builder() + .addEnterpriseCapabilitySubLevel(6) + .build()); + assertThrows(illegalArgumentExceptionClass, () -> new NetworkCapabilities.Builder() + .removeEnterpriseCapabilitySubLevel(6) + .build()); + + final Class illegalStateException = + IllegalStateException.class; + assertThrows(illegalStateException, () -> new NetworkCapabilities.Builder() + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .build()); + + final NetworkCapabilities nc4 = new NetworkCapabilities.Builder() + .addCapability(NET_CAPABILITY_ENTERPRISE) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2) + .removeEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .removeEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2) + .build(); + assertEquals(0, nc4.getEnterpriseCapabilitySubLevels().length); + + final NetworkCapabilities nc5 = new NetworkCapabilities.Builder() + .addCapability(NET_CAPABILITY_CBS) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .addEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2) + .removeEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_1) + .removeEnterpriseCapabilitySubLevel(NET_CAPABILITY_ENTERPRISE_SUB_LEVEL_2) + .build(); + + assertTrue(nc4.satisfiedByNetworkCapabilities(nc1)); + assertFalse(nc1.satisfiedByNetworkCapabilities(nc4)); + + assertFalse(nc3.satisfiedByNetworkCapabilities(nc2)); + assertTrue(nc2.satisfiedByNetworkCapabilities(nc3)); + + assertFalse(nc1.satisfiedByNetworkCapabilities(nc5)); + assertFalse(nc5.satisfiedByNetworkCapabilities(nc1)); + } + @Test public void testWifiAwareNetworkSpecifier() { final NetworkCapabilities nc = new NetworkCapabilities()