Merge "Pass whole TetheringConfiguration to IpServer"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 451abf7..41a0651 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -50,7 +50,7 @@
     ],
     libs: [
         "framework-connectivity",
-        "framework-connectivity-tiramisu.stubs.module_lib",
+        "framework-connectivity-t.stubs.module_lib",
         "framework-statsd.stubs.module_lib",
         "framework-tethering.impl",
         "framework-wifi",
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 85aec96..8459a2c 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -106,7 +106,7 @@
     name: "com.android.tethering-bootclasspath-fragment",
     contents: [
         "framework-connectivity",
-        "framework-connectivity-tiramisu",
+        "framework-connectivity-t",
         "framework-tethering",
     ],
     apex_available: ["com.android.tethering"],
diff --git a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index c1e7127..cc2422f 100644
--- a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -90,11 +90,8 @@
         mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS));
         mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));
 
-        mTetheringPrefixes = new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16")));
-        if (config.isSelectAllPrefixRangeEnabled()) {
-            mTetheringPrefixes.add(new IpPrefix("172.16.0.0/12"));
-            mTetheringPrefixes.add(new IpPrefix("10.0.0.0/8"));
-        }
+        mTetheringPrefixes = new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16"),
+            new IpPrefix("172.16.0.0/12"), new IpPrefix("10.0.0.0/8")));
     }
 
     /**
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 6c35b6b..eaf8589 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -99,13 +99,6 @@
             "use_legacy_wifi_p2p_dedicated_ip";
 
     /**
-     * Flag use to enable select all prefix ranges feature.
-     * TODO: Remove this flag if there are no problems after M-2020-12 rolls out.
-     */
-    public static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
-            "tether_enable_select_all_prefix_ranges";
-
-    /**
      * Experiment flag to force choosing upstreams automatically.
      *
      * This setting is intended to help force-enable the feature on OEM devices that disabled it
@@ -157,7 +150,6 @@
     private final boolean mEnableBpfOffload;
     private final boolean mEnableWifiP2pDedicatedIp;
 
-    private final boolean mEnableSelectAllPrefixRange;
     private final int mUsbTetheringFunction;
     protected final ContentResolver mContentResolver;
 
@@ -222,11 +214,6 @@
                 R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip,
                 false /* defaultValue */);
 
-        // Flags should normally not be booleans, but this is a kill-switch flag that is only used
-        // to turn off the feature, so binary rollback problems do not apply.
-        mEnableSelectAllPrefixRange = getDeviceConfigBoolean(
-                TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true /* defaultValue */);
-
         configLog.log(toString());
     }
 
@@ -323,9 +310,6 @@
         pw.print("enableWifiP2pDedicatedIp: ");
         pw.println(mEnableWifiP2pDedicatedIp);
 
-        pw.print("mEnableSelectAllPrefixRange: ");
-        pw.println(mEnableSelectAllPrefixRange);
-
         pw.print("mUsbTetheringFunction: ");
         pw.println(isUsingNcm() ? "NCM" : "RNDIS");
     }
@@ -389,10 +373,6 @@
         return mEnableBpfOffload;
     }
 
-    public boolean isSelectAllPrefixRangeEnabled() {
-        return mEnableSelectAllPrefixRange;
-    }
-
     private int getUsbTetheringFunction(Resources res) {
         final int valueFromRes = getResourceInteger(res, R.integer.config_tether_usb_functions,
                 TETHER_USB_RNDIS_FUNCTION /* defaultValue */);
diff --git a/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
index ef254ff..4525568 100644
--- a/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
+++ b/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
@@ -29,7 +29,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.app.UiAutomation;
 import android.content.Context;
@@ -81,12 +80,8 @@
         mUiAutomation.dropShellPermissionIdentity();
     }
 
-    private static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
-            "tether_enable_select_all_prefix_ranges";
     @Test
     public void testSwitchBasePrefixRangeWhenConflict() throws Exception {
-        assumeTrue(isFeatureEnabled(TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true));
-
         addressConflictTest(true);
     }
 
diff --git a/Tethering/tests/unit/Android.bp b/Tethering/tests/unit/Android.bp
index 224d87a..d1b8380 100644
--- a/Tethering/tests/unit/Android.bp
+++ b/Tethering/tests/unit/Android.bp
@@ -34,7 +34,7 @@
     libs: [
         "framework-minus-apex",
         "framework-connectivity.impl",
-        "framework-connectivity-tiramisu.impl",
+        "framework-connectivity-t.impl",
         "framework-tethering.impl",
     ],
     visibility: [
@@ -68,7 +68,7 @@
         "framework-minus-apex",
         "framework-res",
         "framework-connectivity.impl",
-        "framework-connectivity-tiramisu.impl",
+        "framework-connectivity-t.impl",
         "framework-tethering.impl",
         "framework-wifi.stubs.module_lib",
     ],
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
index 6c98f2f..55d9852 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -100,7 +100,6 @@
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr);
         when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
         when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
-        when(mConfig.isSelectAllPrefixRangeEnabled()).thenReturn(true);
         setUpIpServers();
         mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
     }
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index cd7505e..e8bb315 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -181,7 +181,6 @@
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
                 .thenReturn(false);
         initializeBpfOffloadConfiguration(true, null /* unset */);
-        initEnableSelectAllPrefixRangeFlag(null /* unset */);
 
         mHasTelephonyManager = true;
         mMockContext = new MockContext(mContext);
@@ -488,32 +487,6 @@
         assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp());
     }
 
-    private void initEnableSelectAllPrefixRangeFlag(final String value) {
-        doReturn(value).when(
-                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
-                eq(TetheringConfiguration.TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES)));
-    }
-
-    @Test
-    public void testSelectAllPrefixRangeFlag() throws Exception {
-        // Test default value.
-        final TetheringConfiguration defaultCfg = new TetheringConfiguration(
-                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
-        assertTrue(defaultCfg.isSelectAllPrefixRangeEnabled());
-
-        // Test disable flag.
-        initEnableSelectAllPrefixRangeFlag("false");
-        final TetheringConfiguration testDisable = new TetheringConfiguration(
-                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
-        assertFalse(testDisable.isSelectAllPrefixRangeEnabled());
-
-        // Test enable flag.
-        initEnableSelectAllPrefixRangeFlag("true");
-        final TetheringConfiguration testEnable = new TetheringConfiguration(
-                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
-        assertTrue(testEnable.isSelectAllPrefixRangeEnabled());
-    }
-
     @Test
     public void testChooseUpstreamAutomatically() throws Exception {
         when(mResources.getBoolean(R.bool.config_tether_upstream_automatic))
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index 6a911ab..2ab69b8 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -30,7 +30,7 @@
 // T, and were moved to the module in T. Other bootclasspath classes in connectivity should go to
 // framework-connectivity.
 java_defaults {
-    name: "framework-connectivity-tiramisu-defaults",
+    name: "framework-connectivity-t-defaults",
     sdk_version: "module_current",
     min_sdk_version: "Tiramisu",
     defaults: [
@@ -78,8 +78,8 @@
 }
 
 java_library {
-    name: "framework-connectivity-tiramisu-pre-jarjar",
-    defaults: ["framework-connectivity-tiramisu-defaults"],
+    name: "framework-connectivity-t-pre-jarjar",
+    defaults: ["framework-connectivity-t-defaults"],
     libs: [
         "framework-bluetooth",
         "framework-wifi",
@@ -92,9 +92,9 @@
 // T, and were moved to the module in T. Other bootclasspath classes in connectivity should go to
 // framework-connectivity.
 java_sdk_library {
-    name: "framework-connectivity-tiramisu",
+    name: "framework-connectivity-t",
     defaults: [
-        "framework-connectivity-tiramisu-defaults",
+        "framework-connectivity-t-defaults",
         "enable-framework-connectivity-t-targets",
     ],
     // Do not add static_libs to this library: put them in framework-connectivity instead.
diff --git a/framework-t/api/module-lib-current.txt b/framework-t/api/module-lib-current.txt
index 4304f6a..59ca730 100644
--- a/framework-t/api/module-lib-current.txt
+++ b/framework-t/api/module-lib-current.txt
@@ -10,7 +10,7 @@
     method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
     method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long);
     method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
-    method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}, conditional=true) public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long);
     method public void setPollForce(boolean);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean);
@@ -42,6 +42,7 @@
   public class NetworkIdentity {
     method public int getOemManaged();
     method public int getRatType();
+    method public int getSubId();
     method @Nullable public String getSubscriberId();
     method public int getType();
     method @Nullable public String getWifiNetworkKey();
@@ -60,6 +61,7 @@
     method @NonNull public android.net.NetworkIdentity.Builder setOemManaged(int);
     method @NonNull public android.net.NetworkIdentity.Builder setRatType(int);
     method @NonNull public android.net.NetworkIdentity.Builder setRoaming(boolean);
+    method @NonNull public android.net.NetworkIdentity.Builder setSubId(int);
     method @NonNull public android.net.NetworkIdentity.Builder setSubscriberId(@Nullable String);
     method @NonNull public android.net.NetworkIdentity.Builder setType(int);
     method @NonNull public android.net.NetworkIdentity.Builder setWifiNetworkKey(@Nullable String);
@@ -72,7 +74,8 @@
     method @NonNull public android.net.LinkProperties getLinkProperties();
     method @NonNull public android.net.Network getNetwork();
     method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
-    method @Nullable public String getSubscriberId();
+    method public int getSubId();
+    method @Deprecated @Nullable public String getSubscriberId();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStateSnapshot> CREATOR;
   }
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index bc9c1b4..4035e9b 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -2,8 +2,8 @@
 package android.app.usage {
 
   public class NetworkStatsManager {
-    method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getMobileUidStats();
-    method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getWifiUidStats();
+    method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getMobileUidStats();
+    method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getWifiUidStats();
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
   }
diff --git a/framework/Android.bp b/framework/Android.bp
index 481f375..66b662b 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -77,7 +77,7 @@
         ],
     },
     stub_only_libs: [
-        "framework-connectivity-tiramisu.stubs.module_lib",
+        "framework-connectivity-t.stubs.module_lib",
     ],
     impl_only_libs: [
         "framework-tethering.stubs.module_lib",
@@ -90,7 +90,7 @@
         "modules-utils-preconditions",
     ],
     libs: [
-        "framework-connectivity-tiramisu.stubs.module_lib",
+        "framework-connectivity-t.stubs.module_lib",
         "unsupportedappusage",
     ],
     apex_available: [
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 713d35a..b65c0ce 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -128,8 +128,8 @@
 
   public final class NetworkAgentConfig implements android.os.Parcelable {
     method @Nullable public String getSubscriberId();
-    method public boolean getVpnRequiresValidation();
     method public boolean isBypassableVpn();
+    method public boolean isVpnValidationRequired();
   }
 
   public static final class NetworkAgentConfig.Builder {
diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java
index 1991a58..b28c006 100644
--- a/framework/src/android/net/NetworkAgentConfig.java
+++ b/framework/src/android/net/NetworkAgentConfig.java
@@ -250,7 +250,7 @@
 
     /**
      * Whether network validation should be performed for this VPN network.
-     * {@see #getVpnRequiresValidation}
+     * {@see #isVpnValidationRequired}
      * @hide
      */
     private boolean mVpnRequiresValidation = false;
@@ -265,7 +265,7 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    public boolean getVpnRequiresValidation() {
+    public boolean isVpnValidationRequired() {
         return mVpnRequiresValidation;
     }
 
diff --git a/service-t/Android.bp b/service-t/Android.bp
index 6612318..159a870 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -19,10 +19,10 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-// This builds T+ services depending on framework-connectivity-tiramisu
+// This builds T+ services depending on framework-connectivity-t
 // hidden symbols separately from the S+ services, to ensure that S+
 // services cannot accidentally depend on T+ hidden symbols from
-// framework-connectivity-tiramisu.
+// framework-connectivity-t.
 java_library {
     name: "service-connectivity-tiramisu-pre-jarjar",
     sdk_version: "system_server_current",
@@ -35,7 +35,7 @@
     libs: [
         "framework-annotations-lib",
         "framework-connectivity-pre-jarjar",
-        "framework-connectivity-tiramisu-pre-jarjar",
+        "framework-connectivity-t-pre-jarjar",
         "framework-tethering.stubs.module_lib",
         "service-connectivity-pre-jarjar",
         "unsupportedappusage",
diff --git a/service/Android.bp b/service/Android.bp
index 2cfab1e..a4d8d64 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -100,7 +100,7 @@
     libs: [
         "framework-annotations-lib",
         "framework-connectivity-pre-jarjar",
-        "framework-connectivity-tiramisu.stubs.module_lib",
+        "framework-connectivity-t.stubs.module_lib",
         "framework-tethering.stubs.module_lib",
         "framework-wifi.stubs.module_lib",
         "unsupportedappusage",
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index c90fcd5..eabcd10 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -4242,7 +4242,7 @@
             mDnsManager.removeNetwork(nai.network);
 
             // clean up tc police filters on interface.
-            if (canNetworkBeRateLimited(nai) && mIngressRateLimit >= 0) {
+            if (nai.everConnected && canNetworkBeRateLimited(nai) && mIngressRateLimit >= 0) {
                 mDeps.disableIngressRateLimit(nai.linkProperties.getInterfaceName());
             }
         }
@@ -9011,19 +9011,6 @@
             // A network that has just connected has zero requests and is thus a foreground network.
             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
 
-            // If a rate limit has been configured and is applicable to this network (network
-            // provides internet connectivity), apply it.
-            // Note: in case of a system server crash, there is a very small chance that this
-            // leaves some interfaces rate limited (i.e. if the rate limit had been changed just
-            // before the crash and was never applied). One solution would be to delete all
-            // potential tc police filters every time this is called. Since this is an unlikely
-            // scenario in the first place (and worst case, the interface stays rate limited until
-            // the device is rebooted), this seems a little overkill.
-            if (canNetworkBeRateLimited(networkAgent) && mIngressRateLimit >= 0) {
-                mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
-                        mIngressRateLimit);
-            }
-
             if (!createNativeNetwork(networkAgent)) return;
             if (networkAgent.propagateUnderlyingCapabilities()) {
                 // Initialize the network's capabilities to their starting values according to the
@@ -9047,6 +9034,17 @@
             updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
                     null);
 
+            // If a rate limit has been configured and is applicable to this network (network
+            // provides internet connectivity), apply it. The tc police filter cannot be attached
+            // before the clsact qdisc is added which happens as part of updateLinkProperties ->
+            // updateInterfaces -> INetd#networkAddInterface.
+            // Note: in case of a system server crash, the NetworkController constructor in netd
+            // (called when netd starts up) deletes the clsact qdisc of all interfaces.
+            if (canNetworkBeRateLimited(networkAgent) && mIngressRateLimit >= 0) {
+                mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
+                        mIngressRateLimit);
+            }
+
             // Until parceled LinkProperties are sent directly to NetworkMonitor, the connect
             // command must be sent after updating LinkProperties to maximize chances of
             // NetworkMonitor seeing the correct LinkProperties when starting.
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index 8782684..b23074d 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -115,7 +115,7 @@
         // meaning @hide APIs in framework-connectivity are resolved before @SystemApi
         // stubs in framework
         "framework-connectivity.impl",
-        "framework-connectivity-tiramisu.impl",
+        "framework-connectivity-t.impl",
         "framework-tethering.impl",
         "framework",
 
diff --git a/tests/common/java/android/net/NetworkAgentConfigTest.kt b/tests/common/java/android/net/NetworkAgentConfigTest.kt
index e5db09f..c05cdbd 100644
--- a/tests/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/common/java/android/net/NetworkAgentConfigTest.kt
@@ -88,7 +88,7 @@
         assertEquals("TEST_NETWORK", config.getLegacyTypeName())
         if (isAtLeastT()) {
             assertTrue(config.areLocalRoutesExcludedForVpn())
-            assertTrue(config.getVpnRequiresValidation())
+            assertTrue(config.isVpnValidationRequired())
         }
         if (isAtLeastS()) {
             assertEquals(testExtraInfo, config.getLegacyExtraInfo())
diff --git a/tests/cts/net/src/android/net/cts/RateLimitTest.java b/tests/cts/net/src/android/net/cts/RateLimitTest.java
index ff779bd..423f213 100644
--- a/tests/cts/net/src/android/net/cts/RateLimitTest.java
+++ b/tests/cts/net/src/android/net/cts/RateLimitTest.java
@@ -83,7 +83,8 @@
 @RunWith(DevSdkIgnoreRunner.class)
 @DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
 public class RateLimitTest {
-    private static final HashSet<String> sKernelConfig;
+    // cannot be final as it gets initialized inside ensureKernelConfigLoaded().
+    private static HashSet<String> sKernelConfig;
 
     private static final String TAG = "RateLimitTest";
     private static final LinkAddress LOCAL_IP4_ADDR = new LinkAddress("10.0.0.1/8");
@@ -108,18 +109,21 @@
     private Network mNetwork;
     private DatagramSocket mSocket;
 
-    static {
+    // Note: exceptions thrown in @BeforeClass or @ClassRule methods are not reported correctly.
+    // This function is called from setUp and loads the kernel config options the first time it is
+    // invoked. This ensures proper error reporting.
+    private static synchronized void ensureKernelConfigLoaded() {
+        if (sKernelConfig != null) return;
         final String result = SystemUtil.runShellCommandOrThrow("gzip -cd /proc/config.gz");
         sKernelConfig = Arrays.stream(result.split("\\R")).collect(
                 Collectors.toCollection(HashSet::new));
 
         // make sure that if for some reason /proc/config.gz returns an empty string, this test
         // does not silently fail.
-        assertNotEquals(0, result.length());
+        assertNotEquals("gzip -cd /proc/config.gz returned an empty string", 0, result.length());
     }
 
     private static void assumeKernelSupport() {
-        // Note: assumptions that fail in @BeforeClass annotated methods are not handled correctly.
         assumeTrue(sKernelConfig.contains("CONFIG_NET_CLS_MATCHALL=y"));
         assumeTrue(sKernelConfig.contains("CONFIG_NET_ACT_POLICE=y"));
         assumeTrue(sKernelConfig.contains("CONFIG_NET_ACT_BPF=y"));
@@ -127,6 +131,8 @@
 
     @Before
     public void setUp() throws IOException {
+        ensureKernelConfigLoaded();
+
         mHandler = new Handler(Looper.getMainLooper());
 
         runAsShell(MANAGE_TEST_NETWORKS, () -> {
@@ -179,12 +185,14 @@
 
     @After
     public void tearDown() throws IOException {
-        // whatever happens, don't leave the device in rate limited state.
-        ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext, -1);
-        mSocket.close();
-        mNetworkAgent.unregister();
-        mTunInterface.getFileDescriptor().close();
-        mCm.unregisterNetworkCallback(mNetworkCallback);
+        if (mContext != null) {
+            // whatever happens, don't leave the device in rate limited state.
+            ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext, -1);
+        }
+        if (mSocket != null) mSocket.close();
+        if (mNetworkAgent != null) mNetworkAgent.unregister();
+        if (mTunInterface != null) mTunInterface.getFileDescriptor().close();
+        if (mCm != null) mCm.unregisterNetworkCallback(mNetworkCallback);
     }
 
     private void assertGreaterThan(final String msg, long lhs, long rhs) {
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index eaceb9a..1967e53 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -28,7 +28,6 @@
         "libbinder",
         "libbpf_bcc",
         "libc++",
-        "libcgrouprc",
         "libcrypto",
         "libcutils",
         "libdl_android",
@@ -43,7 +42,6 @@
         "libnetworkstatsfactorytestjni",
         "libpackagelistparser",
         "libpcre2",
-        "libprocessgroup",
         "libselinux",
         "libtinyxml2",
         "libui",
diff --git a/tests/unit/java/android/net/NetworkIdentityTest.kt b/tests/unit/java/android/net/NetworkIdentityTest.kt
index 4b2d874..bf5568d 100644
--- a/tests/unit/java/android/net/NetworkIdentityTest.kt
+++ b/tests/unit/java/android/net/NetworkIdentityTest.kt
@@ -22,6 +22,7 @@
 import android.net.ConnectivityManager.TYPE_MOBILE
 import android.net.ConnectivityManager.TYPE_NONE
 import android.net.ConnectivityManager.TYPE_WIFI
+import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
 import android.net.NetworkIdentity.OEM_NONE
 import android.net.NetworkIdentity.OEM_PAID
 import android.net.NetworkIdentity.OEM_PRIVATE
@@ -39,8 +40,11 @@
 import kotlin.test.assertFalse
 import kotlin.test.assertTrue
 
-private const val TEST_IMSI = "testimsi"
 private const val TEST_WIFI_KEY = "testwifikey"
+private const val TEST_IMSI1 = "testimsi1"
+private const val TEST_IMSI2 = "testimsi2"
+private const val TEST_SUBID1 = 1
+private const val TEST_SUBID2 = 2
 
 @RunWith(DevSdkIgnoreRunner::class)
 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
@@ -84,7 +88,7 @@
     fun testIsMetered() {
         // Verify network is metered.
         val netIdent1 = NetworkIdentity.buildNetworkIdentity(mockContext,
-                buildMobileNetworkStateSnapshot(NetworkCapabilities(), TEST_IMSI),
+                buildMobileNetworkStateSnapshot(NetworkCapabilities(), TEST_IMSI1),
                 false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
         assertTrue(netIdent1.isMetered())
 
@@ -93,7 +97,7 @@
             addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
         }.build()
         val netIdent2 = NetworkIdentity.buildNetworkIdentity(mockContext,
-                buildMobileNetworkStateSnapshot(capsNotMetered, TEST_IMSI),
+                buildMobileNetworkStateSnapshot(capsNotMetered, TEST_IMSI1),
                 false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
         assertFalse(netIdent2.isMetered())
 
@@ -103,33 +107,38 @@
             setCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED, true)
         }
         val netIdent3 = NetworkIdentity.buildNetworkIdentity(mockContext,
-                buildMobileNetworkStateSnapshot(capsTempNotMetered, TEST_IMSI),
+                buildMobileNetworkStateSnapshot(capsTempNotMetered, TEST_IMSI1),
                 false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
         assertFalse(netIdent3.isMetered())
     }
 
     @Test
     fun testBuilder() {
+        val specifier1 = TelephonyNetworkSpecifier(TEST_SUBID1)
         val oemPrivateRoamingNotMeteredCap = NetworkCapabilities().apply {
             addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)
             addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+            addTransportType(TRANSPORT_CELLULAR)
+            setNetworkSpecifier(specifier1)
         }
         val identFromSnapshot = NetworkIdentity.Builder().setNetworkStateSnapshot(
-                buildMobileNetworkStateSnapshot(oemPrivateRoamingNotMeteredCap, TEST_IMSI))
+                buildMobileNetworkStateSnapshot(oemPrivateRoamingNotMeteredCap, TEST_IMSI1))
                 .setDefaultNetwork(true)
                 .setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
+                .setSubId(TEST_SUBID1)
                 .build()
         val identFromLegacyBuild = NetworkIdentity.buildNetworkIdentity(mockContext,
-                buildMobileNetworkStateSnapshot(oemPrivateRoamingNotMeteredCap, TEST_IMSI),
+                buildMobileNetworkStateSnapshot(oemPrivateRoamingNotMeteredCap, TEST_IMSI1),
                 true /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
         val identFromConstructor = NetworkIdentity(TYPE_MOBILE,
                 TelephonyManager.NETWORK_TYPE_UMTS,
-                TEST_IMSI,
+                TEST_IMSI1,
                 null /* wifiNetworkKey */,
                 true /* roaming */,
                 false /* metered */,
                 true /* defaultNetwork */,
-                NetworkTemplate.OEM_MANAGED_PRIVATE)
+                NetworkTemplate.OEM_MANAGED_PRIVATE,
+                TEST_SUBID1)
         assertEquals(identFromLegacyBuild, identFromSnapshot)
         assertEquals(identFromConstructor, identFromSnapshot)
 
@@ -222,4 +231,28 @@
                             }
                 }
     }
+
+    @Test
+    fun testGetSubId() {
+        val specifier1 = TelephonyNetworkSpecifier(TEST_SUBID1)
+        val specifier2 = TelephonyNetworkSpecifier(TEST_SUBID2)
+        val capSUBID1 = NetworkCapabilities().apply {
+            addTransportType(TRANSPORT_CELLULAR)
+            setNetworkSpecifier(specifier1)
+        }
+        val capSUBID2 = NetworkCapabilities().apply {
+            addTransportType(TRANSPORT_CELLULAR)
+            setNetworkSpecifier(specifier2)
+        }
+
+        val netIdent1 = NetworkIdentity.buildNetworkIdentity(mockContext,
+                buildMobileNetworkStateSnapshot(capSUBID1, TEST_IMSI1),
+                false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+        assertEquals(TEST_SUBID1, netIdent1.getSubId())
+
+        val netIdent2 = NetworkIdentity.buildNetworkIdentity(mockContext,
+                buildMobileNetworkStateSnapshot(capSUBID2, TEST_IMSI2),
+                false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+        assertEquals(TEST_SUBID2, netIdent2.getSubId())
+    }
 }
diff --git a/tests/unit/java/android/net/NetworkStatsCollectionTest.java b/tests/unit/java/android/net/NetworkStatsCollectionTest.java
index c27ee93..32c106d 100644
--- a/tests/unit/java/android/net/NetworkStatsCollectionTest.java
+++ b/tests/unit/java/android/net/NetworkStatsCollectionTest.java
@@ -87,6 +87,7 @@
 
     private static final String TEST_FILE = "test.bin";
     private static final String TEST_IMSI = "310260000000000";
+    private static final int TEST_SUBID = 1;
 
     private static final long TIME_A = 1326088800000L; // UTC: Monday 9th January 2012 06:00:00 AM
     private static final long TIME_B = 1326110400000L; // UTC: Monday 9th January 2012 12:00:00 PM
@@ -213,7 +214,7 @@
         final NetworkStats.Entry entry = new NetworkStats.Entry();
         final NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                TEST_IMSI, null, false, true, true, OEM_NONE));
+                TEST_IMSI, null, false, true, true, OEM_NONE, TEST_SUBID));
 
         int myUid = Process.myUid();
         int otherUidInSameUser = Process.myUid() + 1;
@@ -475,7 +476,7 @@
         final NetworkStatsCollection large = new NetworkStatsCollection(HOUR_IN_MILLIS);
         final NetworkIdentitySet ident = new NetworkIdentitySet();
         ident.add(new NetworkIdentity(ConnectivityManager.TYPE_MOBILE, -1, TEST_IMSI, null,
-                false, true, true, OEM_NONE));
+                false, true, true, OEM_NONE, TEST_SUBID));
         large.recordData(ident, UID_ALL, SET_ALL, TAG_NONE, TIME_A, TIME_B,
                 new NetworkStats.Entry(12_730_893_164L, 1, 0, 0, 0));
 
diff --git a/tests/unit/java/android/net/netstats/NetworkStatsDataMigrationUtilsTest.kt b/tests/unit/java/android/net/netstats/NetworkStatsDataMigrationUtilsTest.kt
index e4943ea..743d39e 100644
--- a/tests/unit/java/android/net/netstats/NetworkStatsDataMigrationUtilsTest.kt
+++ b/tests/unit/java/android/net/netstats/NetworkStatsDataMigrationUtilsTest.kt
@@ -46,7 +46,7 @@
 
     @Test
     fun testReadPlatformCollection() {
-        // Verify the method throws for wrong file version.
+        // Verify the method throws for wrong file format.
         assertFailsWith<ProtocolException> {
             NetworkStatsDataMigrationUtils.readPlatformCollection(
                     NetworkStatsCollection.Builder(BUCKET_DURATION_MS),
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 098d48a..777da17 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -1998,6 +1998,13 @@
             // updated. Check that this happened.
             assertEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
             mActiveRateLimit.put(iface, rateInBytesPerSecond);
+            // verify that clsact qdisc has already been created, otherwise attaching a tc police
+            // filter will fail.
+            try {
+                verify(mMockNetd).networkAddInterface(anyInt(), eq(iface));
+            } catch (RemoteException e) {
+                fail(e.getMessage());
+            }
         }
 
         @Override
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
index 66dcf6d..5f9d1ff 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -36,6 +36,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 
+import android.content.Context;
 import android.net.DataUsageRequest;
 import android.net.NetworkIdentity;
 import android.net.NetworkIdentitySet;
@@ -78,6 +79,7 @@
 
     private static final String IMSI_1 = "310004";
     private static final String IMSI_2 = "310260";
+    private static final int SUBID_1 = 1;
     private static final String TEST_SSID = "AndroidAP";
 
     private static NetworkTemplate sTemplateWifi = buildTemplateWifiWildcard();
@@ -101,6 +103,7 @@
 
     @Mock private IBinder mUsageCallbackBinder;
     private TestableUsageCallback mUsageCallback;
+    @Mock private Context mContext;
 
     @Before
     public void setUp() throws Exception {
@@ -127,14 +130,14 @@
         final DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, thresholdTooLowBytes);
 
-        final DataUsageRequest requestByApp = mStatsObservers.register(inputRequest, mUsageCallback,
-                UID_RED, NetworkStatsAccess.Level.DEVICE);
+        final DataUsageRequest requestByApp = mStatsObservers.register(mContext, inputRequest,
+                mUsageCallback, UID_RED, NetworkStatsAccess.Level.DEVICE);
         assertTrue(requestByApp.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, requestByApp.template));
-        assertEquals(THRESHOLD_BYTES, requestByApp.thresholdInBytes);
+        assertEquals(thresholdTooLowBytes, requestByApp.thresholdInBytes);
 
         // Verify the threshold requested by system uid won't be overridden.
-        final DataUsageRequest requestBySystem = mStatsObservers.register(inputRequest,
+        final DataUsageRequest requestBySystem = mStatsObservers.register(mContext, inputRequest,
                 mUsageCallback, Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(requestBySystem.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, requestBySystem.template));
@@ -147,7 +150,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, highThresholdBytes);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, request.template));
@@ -159,13 +162,13 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, THRESHOLD_BYTES);
 
-        DataUsageRequest request1 = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request1 = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request1.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, request1.template));
         assertEquals(THRESHOLD_BYTES, request1.thresholdInBytes);
 
-        DataUsageRequest request2 = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request2 = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request2.requestId > request1.requestId);
         assertTrue(Objects.equals(sTemplateWifi, request2.template));
@@ -185,7 +188,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -205,7 +208,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 UID_RED, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -224,7 +227,7 @@
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
                 IMSI_1, null /* networkId */, false /* roaming */, true /* metered */,
-                true /* defaultNetwork */, OEM_NONE));
+                true /* defaultNetwork */, OEM_NONE, SUBID_1));
         return identSet;
     }
 
@@ -233,7 +236,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -257,7 +260,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -287,7 +290,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -318,7 +321,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 UID_RED, NetworkStatsAccess.Level.DEFAULT);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -351,7 +354,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 UID_BLUE, NetworkStatsAccess.Level.DEFAULT);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -383,7 +386,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 UID_BLUE, NetworkStatsAccess.Level.USER);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -416,7 +419,7 @@
         DataUsageRequest inputRequest = new DataUsageRequest(
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
-        DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+        DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
                 UID_RED, NetworkStatsAccess.Level.USER);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));