diff --git a/common/flags.aconfig b/common/flags.aconfig index 6c3e89d3bc..bc4168b6cb 100644 --- a/common/flags.aconfig +++ b/common/flags.aconfig @@ -107,3 +107,11 @@ flag { description: "Flag for BLOCKED_REASON_NETWORK_RESTRICTED API" bug: "339559837" } + +flag { + name: "net_capability_not_bandwidth_constrained" + is_exported: true + namespace: "android_core_networking" + description: "Flag for NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED API" + bug: "343823469" +} diff --git a/framework/api/current.txt b/framework/api/current.txt index ef8415c693..7bc0cf308c 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -337,6 +337,7 @@ package android.net { field public static final int NET_CAPABILITY_MCX = 23; // 0x17 field public static final int NET_CAPABILITY_MMS = 0; // 0x0 field public static final int NET_CAPABILITY_MMTEL = 33; // 0x21 + field @FlaggedApi("com.android.net.flags.net_capability_not_bandwidth_constrained") public static final int NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED = 37; // 0x25 field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14 field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index a5a6723b03..6a14bdea48 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -40,6 +40,7 @@ import android.util.Log; import android.util.Range; import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.BitUtils; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkCapabilitiesUtils; @@ -135,6 +136,8 @@ public final class NetworkCapabilities implements Parcelable { "com.android.net.flags.request_restricted_wifi"; static final String SUPPORT_TRANSPORT_SATELLITE = "com.android.net.flags.support_transport_satellite"; + static final String NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED = + "com.android.net.flags.net_capability_not_bandwidth_constrained"; } /** @@ -459,6 +462,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_PRIORITIZE_LATENCY, NET_CAPABILITY_PRIORITIZE_BANDWIDTH, NET_CAPABILITY_LOCAL_NETWORK, + NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED, }) public @interface NetCapability { } @@ -741,7 +745,26 @@ public final class NetworkCapabilities implements Parcelable { @FlaggedApi(Flags.FLAG_NET_CAPABILITY_LOCAL_NETWORK) public static final int NET_CAPABILITY_LOCAL_NETWORK = 36; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_LOCAL_NETWORK; + /** + * Indicates that this is not a bandwidth-constrained network. + * + * Starting from {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, this capability is by default + * set in {@link NetworkRequest}s and true for most networks. + * + * If a network lacks this capability, it is bandwidth-constrained. Bandwidth constrained + * networks cannot support high-bandwidth data transfers and applications that request and use + * them must ensure that they limit bandwidth usage to below the values returned by + * {@link #getLinkDownstreamBandwidthKbps()} and {@link #getLinkUpstreamBandwidthKbps()} and + * limit the frequency of their network usage. If applications perform high-bandwidth data + * transfers on constrained networks or perform network access too frequently, the system may + * block the app's access to the network. The system may take other measures to reduce network + * usage on constrained networks, such as disabling network access to apps that are not in the + * foreground. + */ + @FlaggedApi(Flags.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED) + public static final int NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED = 37; + + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED; // Set all bits up to the MAX_NET_CAPABILITY-th bit private static final long ALL_VALID_CAPABILITIES = (2L << MAX_NET_CAPABILITY) - 1; @@ -785,10 +808,17 @@ public final class NetworkCapabilities implements Parcelable { /** * Capabilities that are set by default when the object is constructed. */ - private static final long DEFAULT_CAPABILITIES = - (1L << NET_CAPABILITY_NOT_RESTRICTED) | - (1L << NET_CAPABILITY_TRUSTED) | - (1L << NET_CAPABILITY_NOT_VPN); + private static final long DEFAULT_CAPABILITIES; + static { + long defaultCapabilities = + (1L << NET_CAPABILITY_NOT_RESTRICTED) + | (1L << NET_CAPABILITY_TRUSTED) + | (1L << NET_CAPABILITY_NOT_VPN); + if (SdkLevel.isAtLeastV()) { + defaultCapabilities |= (1L << NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED); + } + DEFAULT_CAPABILITIES = defaultCapabilities; + } /** * Capabilities that are managed by ConnectivityService. @@ -815,7 +845,9 @@ public final class NetworkCapabilities implements Parcelable { (1L << NET_CAPABILITY_NOT_ROAMING) | (1L << NET_CAPABILITY_NOT_CONGESTED) | (1L << NET_CAPABILITY_NOT_SUSPENDED) | - (1L << NET_CAPABILITY_NOT_VCN_MANAGED); + (1L << NET_CAPABILITY_NOT_VCN_MANAGED) | + (1L << NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED); + /** * Extra allowed capabilities for test networks that do not have TRANSPORT_CELLULAR. Test @@ -2603,6 +2635,7 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_PRIORITIZE_LATENCY: return "PRIORITIZE_LATENCY"; case NET_CAPABILITY_PRIORITIZE_BANDWIDTH: return "PRIORITIZE_BANDWIDTH"; case NET_CAPABILITY_LOCAL_NETWORK: return "LOCAL_NETWORK"; + case NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED: return "NOT_BANDWIDTH_CONSTRAINED"; default: return Integer.toString(capability); } } diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index f7600b269a..502ac6f4b3 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; @@ -286,7 +287,8 @@ public class NetworkRequest implements Parcelable { NET_CAPABILITY_PARTIAL_CONNECTIVITY, NET_CAPABILITY_TEMPORARILY_NOT_METERED, NET_CAPABILITY_TRUSTED, - NET_CAPABILITY_VALIDATED); + NET_CAPABILITY_VALIDATED, + NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED); private final NetworkCapabilities mNetworkCapabilities; diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index d3b7f793b1..ca2cb1548e 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -77,6 +77,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; @@ -13286,11 +13287,12 @@ public class ConnectivityService extends IConnectivityManager.Stub requests.add(createDefaultInternetRequestForTransport( TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT)); - // request: restricted Satellite internet + // request: Satellite internet, satellite network could be restricted or constrained final NetworkCapabilities cap = new NetworkCapabilities.Builder() .addCapability(NET_CAPABILITY_INTERNET) .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) + .removeCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED) .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE) .build(); requests.add(createNetworkRequest(NetworkRequest.Type.REQUEST, cap)); diff --git a/service/src/com/android/server/TestNetworkService.java b/service/src/com/android/server/TestNetworkService.java index 843b7b3f36..4d39d7d05a 100644 --- a/service/src/com/android/server/TestNetworkService.java +++ b/service/src/com/android/server/TestNetworkService.java @@ -267,6 +267,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED); nc.setNetworkSpecifier(new TestNetworkSpecifier(iface)); nc.setAdministratorUids(administratorUids); if (!isMetered) { diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java index 5b538399f1..ff10e1a441 100644 --- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java +++ b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java @@ -19,19 +19,19 @@ package android.net.cts; import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK; import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static com.android.testutils.DevSdkIgnoreRuleKt.VANILLA_ICE_CREAM; - import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.fail; @@ -66,9 +66,9 @@ import com.android.networkstack.apishim.common.NetworkRequestShim; import com.android.networkstack.apishim.common.UnsupportedApiLevelException; import com.android.testutils.ConnectivityModuleTest; import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -512,30 +512,20 @@ public class NetworkRequestTest { assertArrayEquals(netCapabilities, nr.getCapabilities()); } - @Test @IgnoreUpTo(VANILLA_ICE_CREAM) @Ignore("b/338200742") + // Default capabilities and default forbidden capabilities must not be changed on U- because + // this could cause the system server crash when there is a module rollback (b/313030307) + @Test + @IgnoreUpTo(Build.VERSION_CODES.R) @IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public void testDefaultCapabilities() { final NetworkRequest defaultNR = new NetworkRequest.Builder().build(); - assertTrue(defaultNR.hasForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK)); - assertFalse(defaultNR.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)); + + assertEquals(4, defaultNR.getCapabilities().length); + assertTrue(defaultNR.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + assertTrue(defaultNR.hasCapability(NET_CAPABILITY_TRUSTED)); assertTrue(defaultNR.hasCapability(NET_CAPABILITY_NOT_VPN)); + assertTrue(defaultNR.hasCapability(NET_CAPABILITY_NOT_VCN_MANAGED)); - final NetworkCapabilities emptyNC = - NetworkCapabilities.Builder.withoutDefaultCapabilities().build(); - assertFalse(defaultNR.canBeSatisfiedBy(emptyNC)); - - // defaultNC represent the capabilities of a network agent, so they must not contain - // forbidden capabilities by default. - final NetworkCapabilities defaultNC = new NetworkCapabilities.Builder().build(); - assertArrayEquals(new int[0], defaultNC.getForbiddenCapabilities()); - // A default NR can be satisfied by default NC. - assertTrue(defaultNR.canBeSatisfiedBy(defaultNC)); - - // Conversely, network requests have forbidden capabilities by default to manage - // backward compatibility, so test that these forbidden capabilities are in place. - // Starting in V, NET_CAPABILITY_LOCAL_NETWORK is introduced but is not seen by - // default, thanks to a default forbidden capability in NetworkRequest. - defaultNC.addCapability(NET_CAPABILITY_LOCAL_NETWORK); - assertFalse(defaultNR.canBeSatisfiedBy(defaultNC)); + assertEquals(0, defaultNR.getForbiddenCapabilities().length); } @Test diff --git a/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt index 45de4a7bde..88c27386d0 100644 --- a/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt +++ b/tests/unit/java/com/android/server/connectivityservice/CSSatelliteNetworkTest.kt @@ -24,6 +24,7 @@ import android.net.NativeNetworkConfig import android.net.NativeNetworkType import android.net.NetworkCapabilities import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET +import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED @@ -41,10 +42,13 @@ import android.os.UserHandle import android.util.ArraySet import com.android.net.module.util.CollectionUtils import com.android.server.ConnectivityService.PREFERENCE_ORDER_SATELLITE_FALLBACK +import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner +import com.android.testutils.TestableNetworkCallback import com.android.testutils.visibleOnHandlerThread import org.junit.Assert +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any @@ -62,6 +66,9 @@ private const val TEST_PACKAGE_UID2 = 321 @RunWith(DevSdkIgnoreRunner::class) @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) class CSSatelliteNetworkTest : CSTest() { + @get:Rule + val ignoreRule = DevSdkIgnoreRule() + /** * Test createMultiLayerNrisFromSatelliteNetworkPreferredUids returns correct * NetworkRequestInfo. @@ -80,54 +87,81 @@ class CSSatelliteNetworkTest : CSTest() { } /** - * Test that SATELLITE_NETWORK_PREFERENCE_UIDS changes will send correct net id and uid ranges - * to netd. + * Test that satellite network satisfies satellite fallback per-app default network request and + * send correct net id and uid ranges to netd. */ - @Test - fun testSatelliteNetworkPreferredUidsChanged() { + private fun doTestSatelliteNetworkFallbackUids(restricted: Boolean) { val netdInOrder = inOrder(netd) - val satelliteAgent = createSatelliteAgent("satellite0") + val satelliteAgent = createSatelliteAgent("satellite0", restricted) satelliteAgent.connect() val satelliteNetId = satelliteAgent.network.netId + val permission = if (restricted) {INetd.PERMISSION_SYSTEM} else {INetd.PERMISSION_NONE} netdInOrder.verify(netd).networkCreate( - nativeNetworkConfigPhysical(satelliteNetId, INetd.PERMISSION_SYSTEM)) + nativeNetworkConfigPhysical(satelliteNetId, permission)) val uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) val uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2) val uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) - // Initial satellite network preferred uids status. - setAndUpdateSatelliteNetworkPreferredUids(setOf()) + // Initial satellite network fallback uids status. + updateSatelliteNetworkFallbackUids(setOf()) netdInOrder.verify(netd, never()).networkAddUidRangesParcel(any()) netdInOrder.verify(netd, never()).networkRemoveUidRangesParcel(any()) - // Set SATELLITE_NETWORK_PREFERENCE_UIDS setting and verify that net id and uid ranges - // send to netd + // Update satellite network fallback uids and verify that net id and uid ranges send to netd var uids = mutableSetOf(uid1, uid2, uid3) val uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids)) val config1 = NativeUidRangeConfig( satelliteNetId, uidRanges1, PREFERENCE_ORDER_SATELLITE_FALLBACK ) - setAndUpdateSatelliteNetworkPreferredUids(uids) + updateSatelliteNetworkFallbackUids(uids) netdInOrder.verify(netd).networkAddUidRangesParcel(config1) netdInOrder.verify(netd, never()).networkRemoveUidRangesParcel(any()) - // Set SATELLITE_NETWORK_PREFERENCE_UIDS setting again and verify that old rules are removed - // and new rules are added. + // Update satellite network fallback uids and verify that net id and uid ranges send to netd uids = mutableSetOf(uid1) val uidRanges2: Array = toUidRangeStableParcels(uidRangesForUids(uids)) val config2 = NativeUidRangeConfig( satelliteNetId, uidRanges2, PREFERENCE_ORDER_SATELLITE_FALLBACK ) - setAndUpdateSatelliteNetworkPreferredUids(uids) + updateSatelliteNetworkFallbackUids(uids) netdInOrder.verify(netd).networkRemoveUidRangesParcel(config1) netdInOrder.verify(netd).networkAddUidRangesParcel(config2) } + @Test + fun testSatelliteNetworkFallbackUids_restricted() { + doTestSatelliteNetworkFallbackUids(restricted = true) + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + fun testSatelliteNetworkFallbackUids_nonRestricted() { + doTestSatelliteNetworkFallbackUids(restricted = false) + } + + private fun doTestSatelliteNeverBecomeDefaultNetwork(restricted: Boolean) { + val agent = createSatelliteAgent("satellite0", restricted) + agent.connect() + val defaultCb = TestableNetworkCallback() + cm.registerDefaultNetworkCallback(defaultCb) + // Satellite network must not become the default network + defaultCb.assertNoCallback() + } + + @Test + fun testSatelliteNeverBecomeDefaultNetwork_restricted() { + doTestSatelliteNeverBecomeDefaultNetwork(restricted = true) + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + fun testSatelliteNeverBecomeDefaultNetwork_notRestricted() { + doTestSatelliteNeverBecomeDefaultNetwork(restricted = false) + } + private fun assertCreateMultiLayerNrisFromSatelliteNetworkPreferredUids(uids: Set) { val nris: Set = service.createMultiLayerNrisFromSatelliteNetworkFallbackUids(uids) @@ -140,7 +174,7 @@ class CSSatelliteNetworkTest : CSTest() { assertEquals(PREFERENCE_ORDER_SATELLITE_FALLBACK, nri.mPreferenceOrder) } - private fun setAndUpdateSatelliteNetworkPreferredUids(uids: Set) { + private fun updateSatelliteNetworkFallbackUids(uids: Set) { visibleOnHandlerThread(csHandler) { deps.satelliteNetworkFallbackUidUpdate!!.accept(uids) } @@ -150,9 +184,9 @@ class CSSatelliteNetworkTest : CSTest() { NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission, false /* secure */, VpnManager.TYPE_VPN_NONE, false /* excludeLocalRoutes */) - private fun createSatelliteAgent(name: String): CSAgentWrapper { + private fun createSatelliteAgent(name: String, restricted: Boolean = true): CSAgentWrapper { return Agent(score = keepScore(), lp = lp(name), - nc = satelliteNc() + nc = satelliteNc(restricted) ) } @@ -176,7 +210,7 @@ class CSSatelliteNetworkTest : CSTest() { return uidRangesForUids(*CollectionUtils.toIntArray(uids)) } - private fun satelliteNc() = + private fun satelliteNc(restricted: Boolean) = NetworkCapabilities.Builder().apply { addTransportType(TRANSPORT_SATELLITE) @@ -184,7 +218,10 @@ class CSSatelliteNetworkTest : CSTest() { addCapability(NET_CAPABILITY_NOT_SUSPENDED) addCapability(NET_CAPABILITY_NOT_ROAMING) addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) - removeCapability(NET_CAPABILITY_NOT_RESTRICTED) + if (restricted) { + removeCapability(NET_CAPABILITY_NOT_RESTRICTED) + } + removeCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED) }.build() private fun lp(iface: String) = LinkProperties().apply {