Merge "Add enterpriseSpecifier"
diff --git a/framework/api/current.txt b/framework/api/current.txt
index ecb7024..827da6d 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -294,6 +294,7 @@
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 50dd2ad..81a1e5d 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -121,6 +121,11 @@
public final class NetworkCapabilities implements android.os.Parcelable {
method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> 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 5337b38..8d084e6 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -294,9 +294,11 @@
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 721a12d..84f7cbb 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 @@
*/
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 @@
mRequestorPackageName = null;
mSubIds = new ArraySet<>();
mUnderlyingNetworks = null;
+ mEnterpriseCapabilitySubLevel = 0;
}
/**
@@ -224,6 +291,7 @@
// mUnderlyingNetworks is an unmodifiable list if non-null, so a defensive copy is not
// necessary.
mUnderlyingNetworks = nc.mUnderlyingNetworks;
+ mEnterpriseCapabilitySubLevel = nc.mEnterpriseCapabilitySubLevel;
}
/**
@@ -716,6 +784,38 @@
}
/**
+ * 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.
*
* @param networks The underlying networks of this network.
@@ -815,6 +915,22 @@
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 @@
&& satisfiedByTransportTypes(nc)
&& (onlyImmutable || satisfiedByLinkBandwidths(nc))
&& satisfiedBySpecifier(nc)
+ && satisfiedByEnterpriseCapabilitiesSubLevel(nc)
&& (onlyImmutable || satisfiedBySignalStrength(nc))
&& (onlyImmutable || satisfiedByUids(nc))
&& (onlyImmutable || satisfiedBySSID(nc))
@@ -1822,7 +1939,8 @@
&& equalsRequestor(that)
&& equalsAdministratorUids(that)
&& equalsSubscriptionIds(that)
- && equalsUnderlyingNetworks(that);
+ && equalsUnderlyingNetworks(that)
+ && equalsEnterpriseCapabilitiesSubLevel(that);
}
@Override
@@ -1846,7 +1964,8 @@
+ 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 @@
dest.writeString(mRequestorPackageName);
dest.writeIntArray(CollectionUtils.toIntArray(mSubIds));
dest.writeTypedList(mUnderlyingNetworks);
+ dest.writeInt(mEnterpriseCapabilitySubLevel);
}
public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1911,6 +2031,7 @@
netCap.mSubIds.add(subIdInts[i]);
}
netCap.setUnderlyingNetworks(in.createTypedArrayList(Network.CREATOR));
+ netCap.mEnterpriseCapabilitySubLevel = in.readInt();
return netCap;
}
@Override
@@ -2002,6 +2123,12 @@
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 @@
}
}
+ private static @NonNull String enterpriseCapabilitySublevelNameOf(
+ @NetCapability int capability) {
+ return Integer.toString(capability);
+ }
+
/**
* @hide
*/
@@ -2141,6 +2273,20 @@
}
}
+ 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.
*
@@ -2467,6 +2613,37 @@
}
/**
+ * 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.
*
* The default value is {@link Process#INVALID_UID}. Pass this value to reset.
@@ -2724,6 +2901,12 @@
+ " 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 32f00a3..2a4df7a 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.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 @@
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 @@
} 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<IllegalArgumentException> illegalArgumentExceptionClass =
+ IllegalArgumentException.class;
+ assertThrows(illegalArgumentExceptionClass, () -> new NetworkCapabilities.Builder()
+ .addEnterpriseCapabilitySubLevel(6)
+ .build());
+ assertThrows(illegalArgumentExceptionClass, () -> new NetworkCapabilities.Builder()
+ .removeEnterpriseCapabilitySubLevel(6)
+ .build());
+
+ final Class<IllegalStateException> 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()