diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index bae373d756..74b52c9edb 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -117,6 +117,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_FOREGROUND, NET_CAPABILITY_NOT_CONGESTED, NET_CAPABILITY_NOT_SUSPENDED, + NET_CAPABILITY_OEM_PAID, }) public @interface NetCapability { } @@ -264,8 +265,15 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; + /** + * Indicates that traffic that goes through this network is paid by oem. For example, + * this network can be used by system apps to upload telemetry data. + * @hide + */ + public static final int NET_CAPABILITY_OEM_PAID = 22; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_SUSPENDED; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_OEM_PAID; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -313,7 +321,8 @@ public final class NetworkCapabilities implements Parcelable { (1 << NET_CAPABILITY_IA) | (1 << NET_CAPABILITY_IMS) | (1 << NET_CAPABILITY_RCS) | - (1 << NET_CAPABILITY_XCAP); + (1 << NET_CAPABILITY_XCAP) | + (1 << NET_CAPABILITY_OEM_PAID); /** * Capabilities that suggest that a network is unrestricted. @@ -1218,34 +1227,68 @@ public final class NetworkCapabilities implements Parcelable { @Override public String toString() { - // TODO: enumerate bits for transports and capabilities instead of creating arrays. - // TODO: use a StringBuilder instead of string concatenation. - int[] types = getTransportTypes(); - String transports = (types.length > 0) ? " Transports: " + transportNamesOf(types) : ""; - - types = getCapabilities(); - String capabilities = (types.length > 0 ? " Capabilities: " : ""); - for (int i = 0; i < types.length; ) { - capabilities += capabilityNameOf(types[i]); - if (++i < types.length) capabilities += "&"; + final StringBuilder sb = new StringBuilder("["); + if (0 != mTransportTypes) { + sb.append(" Transports: "); + appendStringRepresentationOfBitMaskToStringBuilder(sb, mTransportTypes, + NetworkCapabilities::transportNameOf, "|"); + } + if (0 != mNetworkCapabilities) { + sb.append(" Capabilities: "); + appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities, + NetworkCapabilities::capabilityNameOf, "&"); + } + if (mLinkUpBandwidthKbps > 0) { + sb.append(" LinkUpBandwidth>=").append(mLinkUpBandwidthKbps).append("Kbps"); + } + if (mLinkDownBandwidthKbps > 0) { + sb.append(" LinkDnBandwidth>=").append(mLinkDownBandwidthKbps).append("Kbps"); + } + if (mNetworkSpecifier != null) { + sb.append(" Specifier: <").append(mNetworkSpecifier).append(">"); + } + if (hasSignalStrength()) { + sb.append(" SignalStrength: ").append(mSignalStrength); } - String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" + - mLinkUpBandwidthKbps + "Kbps" : ""); - String dnBand = ((mLinkDownBandwidthKbps > 0) ? " LinkDnBandwidth>=" + - mLinkDownBandwidthKbps + "Kbps" : ""); + if (null != mUids) { + if ((1 == mUids.size()) && (mUids.valueAt(0).count() == 1)) { + sb.append(" Uid: ").append(mUids.valueAt(0).start); + } else { + sb.append(" Uids: <").append(mUids).append(">"); + } + } + if (mEstablishingVpnAppUid != INVALID_UID) { + sb.append(" EstablishingAppUid: ").append(mEstablishingVpnAppUid); + } - String specifier = (mNetworkSpecifier == null ? - "" : " Specifier: <" + mNetworkSpecifier + ">"); + sb.append("]"); + return sb.toString(); + } - String signalStrength = (hasSignalStrength() ? " SignalStrength: " + mSignalStrength : ""); - String uids = (null != mUids ? " Uids: <" + mUids + ">" : ""); - - String establishingAppUid = " EstablishingAppUid: " + mEstablishingVpnAppUid; - - return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength - + uids + establishingAppUid + "]"; + private interface NameOf { + String nameOf(int value); + } + /** + * @hide + */ + public static void appendStringRepresentationOfBitMaskToStringBuilder(StringBuilder sb, + long bitMask, NameOf nameFetcher, String separator) { + int bitPos = 0; + boolean firstElementAdded = false; + while (bitMask != 0) { + if ((bitMask & 1) != 0) { + if (firstElementAdded) { + sb.append(separator); + } else { + firstElementAdded = true; + } + sb.append(nameFetcher.nameOf(bitPos)); + } + bitMask >>= 1; + ++bitPos; + } } /** @hide */ @@ -1313,6 +1356,7 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_FOREGROUND: return "FOREGROUND"; case NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED"; case NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED"; + case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; default: return Integer.toString(capability); } } diff --git a/core/java/android/net/UidRange.java b/core/java/android/net/UidRange.java index fd465d95a9..3164929943 100644 --- a/core/java/android/net/UidRange.java +++ b/core/java/android/net/UidRange.java @@ -21,8 +21,6 @@ import static android.os.UserHandle.PER_USER_RANGE; import android.os.Parcel; import android.os.Parcelable; -import java.lang.IllegalArgumentException; - /** * An inclusive range of UIDs. * @@ -52,6 +50,13 @@ public final class UidRange implements Parcelable { return start <= uid && uid <= stop; } + /** + * Returns the count of UIDs in this range. + */ + public int count() { + return 1 + stop - start; + } + /** * @return {@code true} if this range contains every UID contained by the {@param other} range. */ diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java index 2e1519b871..4227da6c47 100644 --- a/tests/net/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java @@ -22,6 +22,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 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_VALIDATED; import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; @@ -252,6 +253,19 @@ public class NetworkCapabilitiesTest { assertEqualsThroughMarshalling(netCap); } + @Test + public void testOemPaid() { + NetworkCapabilities nc = new NetworkCapabilities(); + nc.maybeMarkCapabilitiesRestricted(); + assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PAID)); + assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + nc.addCapability(NET_CAPABILITY_OEM_PAID); + nc.maybeMarkCapabilitiesRestricted(); + assertTrue(nc.hasCapability(NET_CAPABILITY_OEM_PAID)); + assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + } + private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) { Parcel p = Parcel.obtain(); netCap.writeToParcel(p, /* flags */ 0);