Refactor staticlibs am: 9b0df36ea4

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/3157076

Change-Id: I3a3210caeadee99c4a1c7c4f8fcbc3865b14d283
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 47e5d5e..bcf5e8b 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,7 +1,7 @@
 {
   "captiveportal-networkstack-resolve-tethering-mainline-presubmit": [
     {
-      "name": "CtsNetTestCasesLatestSdk",
+      "name": "CtsNetTestCases",
       "options": [
         {
           "exclude-annotation": "com.android.testutils.SkipPresubmit"
@@ -89,7 +89,7 @@
     // Test with APK modules only, in cases where APEX is not supported, or the other modules
     // were simply not updated
     {
-      "name": "CtsNetTestCasesLatestSdk",
+      "name": "CtsNetTestCases",
       "options": [
         {
           "exclude-annotation": "com.android.testutils.SkipPresubmit"
@@ -115,7 +115,7 @@
     // really exist in the field, but there is no strong guarantee, and it is required by MTS
     // testing for module qualification, where modules are tested independently.
     {
-      "name": "CtsNetTestCasesLatestSdk",
+      "name": "CtsNetTestCases",
       "options": [
         {
           "exclude-annotation": "com.android.testutils.SkipPresubmit"
@@ -158,8 +158,6 @@
     },
     // Run in addition to mainline-presubmit as mainline-presubmit is not
     // supported in every branch.
-    // CtsNetTestCasesLatestSdk uses stable API shims, so does not exercise
-    // some latest APIs. Run CtsNetTestCases to get coverage of newer APIs.
     {
       "name": "CtsNetTestCases",
       "options": [
@@ -171,18 +169,6 @@
         }
       ]
     },
-    // Also run CtsNetTestCasesLatestSdk to ensure tests using older shims pass.
-    {
-      "name": "CtsNetTestCasesLatestSdk",
-      "options": [
-        {
-          "exclude-annotation": "com.android.testutils.SkipPresubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.RequiresDevice"
-        }
-      ]
-    },
     // CTS tests that target older SDKs.
     {
       "name": "CtsNetTestCasesMaxTargetSdk30",
@@ -275,7 +261,7 @@
   ],
   "mainline-presubmit": [
     {
-      "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+      "name": "CtsNetTestCases[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
       "options": [
         {
           "exclude-annotation": "com.android.testutils.SkipPresubmit"
@@ -333,7 +319,7 @@
     // Test with APK modules only, in cases where APEX is not supported, or the other modules
     // were simply not updated
     {
-      "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk]",
+      "name": "CtsNetTestCases[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk]",
       "options": [
         {
           "exclude-annotation": "com.android.testutils.SkipPresubmit"
@@ -357,7 +343,7 @@
     // really exist in the field, but there is no strong guarantee, and it is required by MTS
     // testing for module qualification, where modules are tested independently.
     {
-      "name": "CtsNetTestCasesLatestSdk[com.google.android.tethering.apex]",
+      "name": "CtsNetTestCases[com.google.android.tethering.apex]",
       "options": [
         {
           "exclude-annotation": "com.android.testutils.SkipPresubmit"
@@ -408,7 +394,7 @@
   "mainline-postsubmit": [
     // Tests on physical devices with SIM cards: postsubmit only for capacity constraints
     {
-      "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+      "name": "CtsNetTestCases[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
       "keywords": ["sim"]
     },
     {
@@ -422,7 +408,7 @@
     },
     // Postsubmit on virtual devices to monitor flakiness of @SkipMainlinePresubmit methods
     {
-      "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+      "name": "CtsNetTestCases[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
       "options": [
         {
           "exclude-annotation": "androidx.test.filters.RequiresDevice"
diff --git a/Tethering/common/TetheringLib/lint-baseline.xml b/Tethering/common/TetheringLib/lint-baseline.xml
index ed5fbb0..5171efb 100644
--- a/Tethering/common/TetheringLib/lint-baseline.xml
+++ b/Tethering/common/TetheringLib/lint-baseline.xml
@@ -12,4 +12,15 @@
             column="50"/>
     </issue>
 
+    <issue
+        id="FlaggedApi"
+        message="Method `TetheringRequest()` is a flagged API and should be inside an `if (Flags.tetheringRequestWithSoftApConfig())` check (or annotate the surrounding method `build` with `@FlaggedApi(Flags.TETHERING_REQUEST_WITH_SOFT_AP_CONFIG) to transfer requirement to caller`)"
+        errorLine1="                return new TetheringRequest(mBuilderParcel);"
+        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/Connectivity/Tethering/common/TetheringLib/src/android/net/TetheringManager.java"
+            line="814"
+            column="24"/>
+    </issue>
+
 </issues>
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 5c258b2..9cdba2f 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import static android.Manifest.permission.DUMP;
 import static android.net.InetAddresses.parseNumericAddress;
 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
 import static android.net.TetheringManager.TETHERING_ETHERNET;
@@ -26,36 +27,51 @@
 import static android.net.TetheringTester.isExpectedUdpDnsPacket;
 import static android.system.OsConstants.ICMP_ECHO;
 import static android.system.OsConstants.ICMP_ECHOREPLY;
+import static android.system.OsConstants.IPPROTO_UDP;
 
 import static com.android.net.module.util.ConnectivityUtils.isIPv6ULA;
 import static com.android.net.module.util.HexDump.dumpHexString;
 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REPLY_TYPE;
 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
+import static com.android.testutils.DeviceInfoUtils.KVersion;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
+import android.content.Context;
 import android.net.TetheringManager.TetheringRequest;
 import android.net.TetheringTester.TetheredDevice;
 import android.os.Build;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.VintfRuntimeInfo;
 import android.util.Log;
+import android.util.Pair;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.net.module.util.BpfDump;
 import com.android.net.module.util.Ipv6Utils;
 import com.android.net.module.util.Struct;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
+import com.android.net.module.util.bpf.TetherStatsKey;
+import com.android.net.module.util.bpf.TetherStatsValue;
 import com.android.net.module.util.structs.Ipv4Header;
 import com.android.net.module.util.structs.UdpHeader;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DeviceInfoUtils;
+import com.android.testutils.DumpTestUtils;
 import com.android.testutils.NetworkStackModuleTest;
 import com.android.testutils.TapPacketReader;
 
@@ -73,7 +89,9 @@
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.TimeoutException;
 
@@ -89,6 +107,26 @@
     private static final short ICMPECHO_ID = 0x0;
     private static final short ICMPECHO_SEQ = 0x0;
 
+    private static final int DUMP_POLLING_MAX_RETRY = 100;
+    private static final int DUMP_POLLING_INTERVAL_MS = 50;
+    // Kernel treats a confirmed UDP connection which active after two seconds as stream mode.
+    // See upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5.
+    private static final int UDP_STREAM_TS_MS = 2000;
+    // Give slack time for waiting UDP stream mode because handling conntrack event in user space
+    // may not in precise time. Used to reduce the flaky rate.
+    private static final int UDP_STREAM_SLACK_MS = 500;
+    // Per RX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
+    private static final int RX_UDP_PACKET_SIZE = 30;
+    private static final int RX_UDP_PACKET_COUNT = 456;
+    // Per TX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
+    private static final int TX_UDP_PACKET_SIZE = 30;
+    private static final int TX_UDP_PACKET_COUNT = 123;
+
+    private static final String DUMPSYS_TETHERING_RAWMAP_ARG = "bpfRawMap";
+    private static final String DUMPSYS_RAWMAP_ARG_STATS = "--stats";
+    private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
+    private static final String LINE_DELIMITER = "\\n";
+
     // TODO: use class DnsPacket to build DNS query and reply message once DnsPacket supports
     // building packet for given arguments.
     private static final ByteBuffer DNS_QUERY = ByteBuffer.wrap(new byte[] {
@@ -802,4 +840,217 @@
         final MacAddress macAddress = MacAddress.fromString("11:22:33:44:55:66");
         assertTrue(tester.testDhcpServerAlive(macAddress));
     }
+
+    private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
+        final KVersion current = DeviceInfoUtils.getMajorMinorSubminorVersion(kernelVersion);
+        return current.isInRange(new KVersion(4, 14, 222), new KVersion(4, 19, 0))
+                || current.isInRange(new KVersion(4, 19, 176), new KVersion(5, 4, 0))
+                || current.isAtLeast(new KVersion(5, 4, 98));
+    }
+
+    @Test
+    public void testIsUdpOffloadSupportedByKernel() throws Exception {
+        assertFalse(isUdpOffloadSupportedByKernel("4.14.221"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.14.222"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.16.0"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.18.0"));
+        assertFalse(isUdpOffloadSupportedByKernel("4.19.0"));
+
+        assertFalse(isUdpOffloadSupportedByKernel("4.19.175"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.19.176"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.2.0"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.3.0"));
+        assertFalse(isUdpOffloadSupportedByKernel("5.4.0"));
+
+        assertFalse(isUdpOffloadSupportedByKernel("5.4.97"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.4.98"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.10.0"));
+    }
+
+    private static void assumeKernelSupportBpfOffloadUdpV4() {
+        final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
+        assumeTrue("Kernel version " + kernelVersion + " doesn't support IPv4 UDP BPF offload",
+                isUdpOffloadSupportedByKernel(kernelVersion));
+    }
+
+    @Test
+    public void testKernelSupportBpfOffloadUdpV4() throws Exception {
+        assumeKernelSupportBpfOffloadUdpV4();
+    }
+
+    private boolean isTetherConfigBpfOffloadEnabled() throws Exception {
+        final String dumpStr = runAsShell(DUMP, () ->
+                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short"));
+
+        // BPF offload tether config can be overridden by "config_tether_enable_bpf_offload" in
+        // packages/modules/Connectivity/Tethering/res/values/config.xml. OEM may disable config by
+        // RRO to override the enabled default value. Get the tethering config via dumpsys.
+        // $ dumpsys tethering
+        //   mIsBpfEnabled: true
+        boolean enabled = dumpStr.contains("mIsBpfEnabled: true");
+        if (!enabled) {
+            Log.d(TAG, "BPF offload tether config not enabled: " + dumpStr);
+        }
+        return enabled;
+    }
+
+    @Test
+    public void testTetherConfigBpfOffloadEnabled() throws Exception {
+        assumeTrue(isTetherConfigBpfOffloadEnabled());
+    }
+
+    @NonNull
+    private <K extends Struct, V extends Struct> HashMap<K, V> dumpAndParseRawMap(
+            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
+            throws Exception {
+        final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
+        final String rawMapStr = runAsShell(DUMP, () ->
+                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args));
+        final HashMap<K, V> map = new HashMap<>();
+
+        for (final String line : rawMapStr.split(LINE_DELIMITER)) {
+            final Pair<K, V> rule =
+                    BpfDump.fromBase64EncodedString(keyClass, valueClass, line.trim());
+            map.put(rule.first, rule.second);
+        }
+        return map;
+    }
+
+    @Nullable
+    private <K extends Struct, V extends Struct> HashMap<K, V> pollRawMapFromDump(
+            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
+            throws Exception {
+        for (int retryCount = 0; retryCount < DUMP_POLLING_MAX_RETRY; retryCount++) {
+            final HashMap<K, V> map = dumpAndParseRawMap(keyClass, valueClass, mapArg);
+            if (!map.isEmpty()) return map;
+
+            Thread.sleep(DUMP_POLLING_INTERVAL_MS);
+        }
+
+        fail("Cannot get rules after " + DUMP_POLLING_MAX_RETRY * DUMP_POLLING_INTERVAL_MS + "ms");
+        return null;
+    }
+
+    // Test network topology:
+    //
+    //         public network (rawip)                 private network
+    //                   |                 UE                |
+    // +------------+    V    +------------+------------+    V    +------------+
+    // |   Sever    +---------+  Upstream  | Downstream +---------+   Client   |
+    // +------------+         +------------+------------+         +------------+
+    // remote ip              public ip                           private ip
+    // 8.8.8.8:443            <Upstream ip>:9876                  <TetheredDevice ip>:9876
+    //
+    private void runUdp4Test() throws Exception {
+        final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
+                toList(TEST_IP4_DNS));
+        final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
+
+        // TODO: remove the connectivity verification for upstream connected notification race.
+        // Because async upstream connected notification can't guarantee the tethering routing is
+        // ready to use. Need to test tethering connectivity before testing.
+        // For short term plan, consider using IPv6 RA to get MAC address because the prefix comes
+        // from upstream. That can guarantee that the routing is ready. Long term plan is that
+        // refactors upstream connected notification from async to sync.
+        probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
+
+        final MacAddress srcMac = tethered.macAddr;
+        final MacAddress dstMac = tethered.routerMacAddr;
+        final InetAddress remoteIp = REMOTE_IP4_ADDR;
+        final InetAddress tetheringUpstreamIp = TEST_IP4_ADDR.getAddress();
+        final InetAddress clientIp = tethered.ipv4Addr;
+        sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
+        sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
+
+        // Send second UDP packet in original direction.
+        // The BPF coordinator only offloads the ASSURED conntrack entry. The "request + reply"
+        // packets can make status IPS_SEEN_REPLY to be set. Need one more packet to make
+        // conntrack status IPS_ASSURED_BIT to be set. Note the third packet needs to delay
+        // 2 seconds because kernel monitors a UDP connection which still alive after 2 seconds
+        // and apply ASSURED flag.
+        // See kernel upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5 and
+        // nf_conntrack_udp_packet in net/netfilter/nf_conntrack_proto_udp.c
+        Thread.sleep(UDP_STREAM_TS_MS);
+        sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
+
+        // Give a slack time for handling conntrack event in user space.
+        Thread.sleep(UDP_STREAM_SLACK_MS);
+
+        // [1] Verify IPv4 upstream rule map.
+        final HashMap<Tether4Key, Tether4Value> upstreamMap = pollRawMapFromDump(
+                Tether4Key.class, Tether4Value.class, DUMPSYS_RAWMAP_ARG_UPSTREAM4);
+        assertNotNull(upstreamMap);
+        assertEquals(1, upstreamMap.size());
+
+        final Map.Entry<Tether4Key, Tether4Value> rule =
+                upstreamMap.entrySet().iterator().next();
+
+        final Tether4Key upstream4Key = rule.getKey();
+        assertEquals(IPPROTO_UDP, upstream4Key.l4proto);
+        assertTrue(Arrays.equals(tethered.ipv4Addr.getAddress(), upstream4Key.src4));
+        assertEquals(LOCAL_PORT, upstream4Key.srcPort);
+        assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(), upstream4Key.dst4));
+        assertEquals(REMOTE_PORT, upstream4Key.dstPort);
+
+        final Tether4Value upstream4Value = rule.getValue();
+        assertTrue(Arrays.equals(tetheringUpstreamIp.getAddress(),
+                InetAddress.getByAddress(upstream4Value.src46).getAddress()));
+        assertEquals(LOCAL_PORT, upstream4Value.srcPort);
+        assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(),
+                InetAddress.getByAddress(upstream4Value.dst46).getAddress()));
+        assertEquals(REMOTE_PORT, upstream4Value.dstPort);
+
+        // [2] Verify stats map.
+        // Transmit packets on both direction for verifying stats. Because we only care the
+        // packet count in stats test, we just reuse the existing packets to increaes
+        // the packet count on both direction.
+
+        // Send packets on original direction.
+        for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) {
+            sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester,
+                    false /* is4To6 */);
+        }
+
+        // Send packets on reply direction.
+        for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) {
+            sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
+        }
+
+        // Dump stats map to verify.
+        final HashMap<TetherStatsKey, TetherStatsValue> statsMap = pollRawMapFromDump(
+                TetherStatsKey.class, TetherStatsValue.class, DUMPSYS_RAWMAP_ARG_STATS);
+        assertNotNull(statsMap);
+        assertEquals(1, statsMap.size());
+
+        final Map.Entry<TetherStatsKey, TetherStatsValue> stats =
+                statsMap.entrySet().iterator().next();
+
+        // TODO: verify the upstream index in TetherStatsKey.
+
+        final TetherStatsValue statsValue = stats.getValue();
+        assertEquals(RX_UDP_PACKET_COUNT, statsValue.rxPackets);
+        assertEquals(RX_UDP_PACKET_COUNT * RX_UDP_PACKET_SIZE, statsValue.rxBytes);
+        assertEquals(0, statsValue.rxErrors);
+        assertEquals(TX_UDP_PACKET_COUNT, statsValue.txPackets);
+        assertEquals(TX_UDP_PACKET_COUNT * TX_UDP_PACKET_SIZE, statsValue.txBytes);
+        assertEquals(0, statsValue.txErrors);
+    }
+
+    /**
+     * BPF offload IPv4 UDP tethering test. Verify that UDP tethered packets are offloaded by BPF.
+     * Minimum test requirement:
+     * 1. S+ device.
+     * 2. Tethering config enables tethering BPF offload.
+     * 3. Kernel supports IPv4 UDP BPF offload. See #isUdpOffloadSupportedByKernel.
+     *
+     * TODO: consider enabling the test even tethering config disables BPF offload. See b/238288883
+     */
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testTetherBpfOffloadUdpV4() throws Exception {
+        assumeTrue("Tethering config disabled BPF offload", isTetherConfigBpfOffloadEnabled());
+        assumeKernelSupportBpfOffloadUdpV4();
+
+        runUdp4Test();
+    }
 }
diff --git a/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java b/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java
deleted file mode 100644
index c2bc812..0000000
--- a/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.Manifest.permission.DUMP;
-import static android.system.OsConstants.IPPROTO_UDP;
-
-import static com.android.testutils.DeviceInfoUtils.KVersion;
-import static com.android.testutils.TestPermissionUtil.runAsShell;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.Context;
-import android.net.TetheringTester.TetheredDevice;
-import android.os.Build;
-import android.os.VintfRuntimeInfo;
-import android.util.Log;
-import android.util.Pair;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.net.module.util.BpfDump;
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.bpf.Tether4Key;
-import com.android.net.module.util.bpf.Tether4Value;
-import com.android.net.module.util.bpf.TetherStatsKey;
-import com.android.net.module.util.bpf.TetherStatsValue;
-import com.android.testutils.DevSdkIgnoreRule;
-import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
-import com.android.testutils.DeviceInfoUtils;
-import com.android.testutils.DumpTestUtils;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.InetAddress;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(AndroidJUnit4.class)
-@MediumTest
-public class MtsEthernetTetheringTest extends EthernetTetheringTestBase {
-    @Rule
-    public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
-
-    private static final String TAG = MtsEthernetTetheringTest.class.getSimpleName();
-
-    private static final int DUMP_POLLING_MAX_RETRY = 100;
-    private static final int DUMP_POLLING_INTERVAL_MS = 50;
-    // Kernel treats a confirmed UDP connection which active after two seconds as stream mode.
-    // See upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5.
-    private static final int UDP_STREAM_TS_MS = 2000;
-    // Give slack time for waiting UDP stream mode because handling conntrack event in user space
-    // may not in precise time. Used to reduce the flaky rate.
-    private static final int UDP_STREAM_SLACK_MS = 500;
-    // Per RX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
-    private static final int RX_UDP_PACKET_SIZE = 30;
-    private static final int RX_UDP_PACKET_COUNT = 456;
-    // Per TX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
-    private static final int TX_UDP_PACKET_SIZE = 30;
-    private static final int TX_UDP_PACKET_COUNT = 123;
-
-    private static final String DUMPSYS_TETHERING_RAWMAP_ARG = "bpfRawMap";
-    private static final String DUMPSYS_RAWMAP_ARG_STATS = "--stats";
-    private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
-    private static final String LINE_DELIMITER = "\\n";
-
-    private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
-        final KVersion current = DeviceInfoUtils.getMajorMinorSubminorVersion(kernelVersion);
-        return current.isInRange(new KVersion(4, 14, 222), new KVersion(4, 19, 0))
-                || current.isInRange(new KVersion(4, 19, 176), new KVersion(5, 4, 0))
-                || current.isAtLeast(new KVersion(5, 4, 98));
-    }
-
-    @Test
-    public void testIsUdpOffloadSupportedByKernel() throws Exception {
-        assertFalse(isUdpOffloadSupportedByKernel("4.14.221"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.14.222"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.16.0"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.18.0"));
-        assertFalse(isUdpOffloadSupportedByKernel("4.19.0"));
-
-        assertFalse(isUdpOffloadSupportedByKernel("4.19.175"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.19.176"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.2.0"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.3.0"));
-        assertFalse(isUdpOffloadSupportedByKernel("5.4.0"));
-
-        assertFalse(isUdpOffloadSupportedByKernel("5.4.97"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.4.98"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.10.0"));
-    }
-
-    private static void assumeKernelSupportBpfOffloadUdpV4() {
-        final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
-        assumeTrue("Kernel version " + kernelVersion + " doesn't support IPv4 UDP BPF offload",
-                isUdpOffloadSupportedByKernel(kernelVersion));
-    }
-
-    @Test
-    public void testKernelSupportBpfOffloadUdpV4() throws Exception {
-        assumeKernelSupportBpfOffloadUdpV4();
-    }
-
-    private boolean isTetherConfigBpfOffloadEnabled() throws Exception {
-        final String dumpStr = runAsShell(DUMP, () ->
-                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short"));
-
-        // BPF offload tether config can be overridden by "config_tether_enable_bpf_offload" in
-        // packages/modules/Connectivity/Tethering/res/values/config.xml. OEM may disable config by
-        // RRO to override the enabled default value. Get the tethering config via dumpsys.
-        // $ dumpsys tethering
-        //   mIsBpfEnabled: true
-        boolean enabled = dumpStr.contains("mIsBpfEnabled: true");
-        if (!enabled) {
-            Log.d(TAG, "BPF offload tether config not enabled: " + dumpStr);
-        }
-        return enabled;
-    }
-
-    @Test
-    public void testTetherConfigBpfOffloadEnabled() throws Exception {
-        assumeTrue(isTetherConfigBpfOffloadEnabled());
-    }
-
-    @NonNull
-    private <K extends Struct, V extends Struct> HashMap<K, V> dumpAndParseRawMap(
-            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
-            throws Exception {
-        final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
-        final String rawMapStr = runAsShell(DUMP, () ->
-                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args));
-        final HashMap<K, V> map = new HashMap<>();
-
-        for (final String line : rawMapStr.split(LINE_DELIMITER)) {
-            final Pair<K, V> rule =
-                    BpfDump.fromBase64EncodedString(keyClass, valueClass, line.trim());
-            map.put(rule.first, rule.second);
-        }
-        return map;
-    }
-
-    @Nullable
-    private <K extends Struct, V extends Struct> HashMap<K, V> pollRawMapFromDump(
-            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
-            throws Exception {
-        for (int retryCount = 0; retryCount < DUMP_POLLING_MAX_RETRY; retryCount++) {
-            final HashMap<K, V> map = dumpAndParseRawMap(keyClass, valueClass, mapArg);
-            if (!map.isEmpty()) return map;
-
-            Thread.sleep(DUMP_POLLING_INTERVAL_MS);
-        }
-
-        fail("Cannot get rules after " + DUMP_POLLING_MAX_RETRY * DUMP_POLLING_INTERVAL_MS + "ms");
-        return null;
-    }
-
-    // Test network topology:
-    //
-    //         public network (rawip)                 private network
-    //                   |                 UE                |
-    // +------------+    V    +------------+------------+    V    +------------+
-    // |   Sever    +---------+  Upstream  | Downstream +---------+   Client   |
-    // +------------+         +------------+------------+         +------------+
-    // remote ip              public ip                           private ip
-    // 8.8.8.8:443            <Upstream ip>:9876                  <TetheredDevice ip>:9876
-    //
-    private void runUdp4Test() throws Exception {
-        final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
-                toList(TEST_IP4_DNS));
-        final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
-
-        // TODO: remove the connectivity verification for upstream connected notification race.
-        // Because async upstream connected notification can't guarantee the tethering routing is
-        // ready to use. Need to test tethering connectivity before testing.
-        // For short term plan, consider using IPv6 RA to get MAC address because the prefix comes
-        // from upstream. That can guarantee that the routing is ready. Long term plan is that
-        // refactors upstream connected notification from async to sync.
-        probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
-
-        final MacAddress srcMac = tethered.macAddr;
-        final MacAddress dstMac = tethered.routerMacAddr;
-        final InetAddress remoteIp = REMOTE_IP4_ADDR;
-        final InetAddress tetheringUpstreamIp = TEST_IP4_ADDR.getAddress();
-        final InetAddress clientIp = tethered.ipv4Addr;
-        sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
-        sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
-
-        // Send second UDP packet in original direction.
-        // The BPF coordinator only offloads the ASSURED conntrack entry. The "request + reply"
-        // packets can make status IPS_SEEN_REPLY to be set. Need one more packet to make
-        // conntrack status IPS_ASSURED_BIT to be set. Note the third packet needs to delay
-        // 2 seconds because kernel monitors a UDP connection which still alive after 2 seconds
-        // and apply ASSURED flag.
-        // See kernel upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5 and
-        // nf_conntrack_udp_packet in net/netfilter/nf_conntrack_proto_udp.c
-        Thread.sleep(UDP_STREAM_TS_MS);
-        sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
-
-        // Give a slack time for handling conntrack event in user space.
-        Thread.sleep(UDP_STREAM_SLACK_MS);
-
-        // [1] Verify IPv4 upstream rule map.
-        final HashMap<Tether4Key, Tether4Value> upstreamMap = pollRawMapFromDump(
-                Tether4Key.class, Tether4Value.class, DUMPSYS_RAWMAP_ARG_UPSTREAM4);
-        assertNotNull(upstreamMap);
-        assertEquals(1, upstreamMap.size());
-
-        final Map.Entry<Tether4Key, Tether4Value> rule =
-                upstreamMap.entrySet().iterator().next();
-
-        final Tether4Key upstream4Key = rule.getKey();
-        assertEquals(IPPROTO_UDP, upstream4Key.l4proto);
-        assertTrue(Arrays.equals(tethered.ipv4Addr.getAddress(), upstream4Key.src4));
-        assertEquals(LOCAL_PORT, upstream4Key.srcPort);
-        assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(), upstream4Key.dst4));
-        assertEquals(REMOTE_PORT, upstream4Key.dstPort);
-
-        final Tether4Value upstream4Value = rule.getValue();
-        assertTrue(Arrays.equals(tetheringUpstreamIp.getAddress(),
-                InetAddress.getByAddress(upstream4Value.src46).getAddress()));
-        assertEquals(LOCAL_PORT, upstream4Value.srcPort);
-        assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(),
-                InetAddress.getByAddress(upstream4Value.dst46).getAddress()));
-        assertEquals(REMOTE_PORT, upstream4Value.dstPort);
-
-        // [2] Verify stats map.
-        // Transmit packets on both direction for verifying stats. Because we only care the
-        // packet count in stats test, we just reuse the existing packets to increaes
-        // the packet count on both direction.
-
-        // Send packets on original direction.
-        for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) {
-            sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester,
-                    false /* is4To6 */);
-        }
-
-        // Send packets on reply direction.
-        for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) {
-            sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
-        }
-
-        // Dump stats map to verify.
-        final HashMap<TetherStatsKey, TetherStatsValue> statsMap = pollRawMapFromDump(
-                TetherStatsKey.class, TetherStatsValue.class, DUMPSYS_RAWMAP_ARG_STATS);
-        assertNotNull(statsMap);
-        assertEquals(1, statsMap.size());
-
-        final Map.Entry<TetherStatsKey, TetherStatsValue> stats =
-                statsMap.entrySet().iterator().next();
-
-        // TODO: verify the upstream index in TetherStatsKey.
-
-        final TetherStatsValue statsValue = stats.getValue();
-        assertEquals(RX_UDP_PACKET_COUNT, statsValue.rxPackets);
-        assertEquals(RX_UDP_PACKET_COUNT * RX_UDP_PACKET_SIZE, statsValue.rxBytes);
-        assertEquals(0, statsValue.rxErrors);
-        assertEquals(TX_UDP_PACKET_COUNT, statsValue.txPackets);
-        assertEquals(TX_UDP_PACKET_COUNT * TX_UDP_PACKET_SIZE, statsValue.txBytes);
-        assertEquals(0, statsValue.txErrors);
-    }
-
-    /**
-     * BPF offload IPv4 UDP tethering test. Verify that UDP tethered packets are offloaded by BPF.
-     * Minimum test requirement:
-     * 1. S+ device.
-     * 2. Tethering config enables tethering BPF offload.
-     * 3. Kernel supports IPv4 UDP BPF offload. See #isUdpOffloadSupportedByKernel.
-     *
-     * TODO: consider enabling the test even tethering config disables BPF offload. See b/238288883
-     */
-    @Test
-    @IgnoreUpTo(Build.VERSION_CODES.R)
-    public void testTetherBpfOffloadUdpV4() throws Exception {
-        assumeTrue("Tethering config disabled BPF offload", isTetherConfigBpfOffloadEnabled());
-        assumeKernelSupportBpfOffloadUdpV4();
-
-        runUdp4Test();
-    }
-}
diff --git a/service/ServiceConnectivityResources/res/values-ky/strings.xml b/service/ServiceConnectivityResources/res/values-ky/strings.xml
index 08ffd2a..398531a 100644
--- a/service/ServiceConnectivityResources/res/values-ky/strings.xml
+++ b/service/ServiceConnectivityResources/res/values-ky/strings.xml
@@ -26,7 +26,7 @@
     <string name="mobile_network_available_no_internet_detailed" msgid="5438738723127062816">"<xliff:g id="NETWORK_CARRIER">%1$s</xliff:g> трафиги түгөнгөн окшойт. Параметрлерди ачуу үчүн таптаңыз."</string>
     <string name="mobile_network_available_no_internet_detailed_unknown_carrier" msgid="5375681117265354337">"Трафик түгөнгөн окшойт. Параметрлерди ачуу үчүн таптаңыз."</string>
     <string name="wifi_no_internet" msgid="1326348603404555475">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> Интернетке туташуусу жок"</string>
-    <string name="wifi_no_internet_detailed" msgid="1746921096565304090">"Параметрлерди ачуу үчүн таптап коюңуз"</string>
+    <string name="wifi_no_internet_detailed" msgid="1746921096565304090">"Параметрлерди ачуу үчүн тийип коюңуз"</string>
     <string name="mobile_no_internet" msgid="4087718456753201450">"Мобилдик Интернет жок"</string>
     <string name="other_networks_no_internet" msgid="5693932964749676542">"Тармактын Интернет жок"</string>
     <string name="private_dns_broken_detailed" msgid="2677123850463207823">"Жеке DNS сервери жеткиликсиз"</string>
diff --git a/service/ServiceConnectivityResources/res/values-mn/strings.xml b/service/ServiceConnectivityResources/res/values-mn/strings.xml
index 2f13ef4..9af035b 100644
--- a/service/ServiceConnectivityResources/res/values-mn/strings.xml
+++ b/service/ServiceConnectivityResources/res/values-mn/strings.xml
@@ -27,7 +27,7 @@
     <string name="mobile_network_available_no_internet_detailed_unknown_carrier" msgid="5375681117265354337">"Таны дата дууссан байж магадгүй. Сонголтыг харахын тулд товшино уу."</string>
     <string name="wifi_no_internet" msgid="1326348603404555475">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-д интернэтийн хандалт алга"</string>
     <string name="wifi_no_internet_detailed" msgid="1746921096565304090">"Сонголт хийхийн тулд товшино уу"</string>
-    <string name="mobile_no_internet" msgid="4087718456753201450">"Мобайл сүлжээнд интернэт хандалт байхгүй байна"</string>
+    <string name="mobile_no_internet" msgid="4087718456753201450">"Хөдөлгөөнт холбооны сүлжээнд интернэт хандалт байхгүй байна"</string>
     <string name="other_networks_no_internet" msgid="5693932964749676542">"Сүлжээнд интернэт хандалт байхгүй байна"</string>
     <string name="private_dns_broken_detailed" msgid="2677123850463207823">"Хувийн DNS серверт хандах боломжгүй байна"</string>
     <string name="network_partial_connectivity" msgid="5549503845834993258">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> зарим үйлчилгээнд хандах боломжгүй байна"</string>
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
index 66362d4..ae43c15 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
@@ -44,13 +44,18 @@
 object ANY_NETWORK : Network(-2)
 fun anyNetwork() = ANY_NETWORK
 
-open class RecorderCallback private constructor(
-    private val backingRecord: ArrayTrackRecord<CallbackEntry>
-) : NetworkCallback() {
-    public constructor() : this(ArrayTrackRecord())
-    protected constructor(src: RecorderCallback?) : this(src?.backingRecord ?: ArrayTrackRecord())
+private val DEFAULT_TAG = RecorderCallback::class.simpleName
+    ?: fail("Could not determine class name")
 
-    private val TAG = this::class.simpleName
+open class RecorderCallback private constructor(
+    private val backingRecord: ArrayTrackRecord<CallbackEntry>,
+    val logTag: String
+) : NetworkCallback() {
+    public constructor(logTag: String = DEFAULT_TAG) : this(ArrayTrackRecord(), logTag)
+    protected constructor(src: RecorderCallback?, logTag: String) : this(
+        src?.backingRecord ?: ArrayTrackRecord(),
+        logTag
+    )
 
     sealed class CallbackEntry {
         // To get equals(), hashcode(), componentN() etc for free, the child classes of
@@ -123,7 +128,7 @@
     val mark get() = history.mark
 
     override fun onAvailable(network: Network) {
-        Log.d(TAG, "onAvailable $network")
+        Log.d(logTag, "onAvailable $network")
         history.add(Available(network))
     }
 
@@ -131,22 +136,22 @@
     // expect the callbacks not to record this, do not listen to PreCheck here.
 
     override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
-        Log.d(TAG, "onCapabilitiesChanged $network $caps")
+        Log.d(logTag, "onCapabilitiesChanged $network $caps")
         history.add(CapabilitiesChanged(network, caps))
     }
 
     override fun onLinkPropertiesChanged(network: Network, lp: LinkProperties) {
-        Log.d(TAG, "onLinkPropertiesChanged $network $lp")
+        Log.d(logTag, "onLinkPropertiesChanged $network $lp")
         history.add(LinkPropertiesChanged(network, lp))
     }
 
     override fun onLocalNetworkInfoChanged(network: Network, info: LocalNetworkInfo) {
-        Log.d(TAG, "onLocalNetworkInfoChanged $network $info")
+        Log.d(logTag, "onLocalNetworkInfoChanged $network $info")
         history.add(LocalInfoChanged(network, info))
     }
 
     override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
-        Log.d(TAG, "onBlockedStatusChanged $network $blocked")
+        Log.d(logTag, "onBlockedStatusChanged $network $blocked")
         history.add(BlockedStatus(network, blocked))
     }
 
@@ -154,27 +159,27 @@
     // fun onBlockedStatusChanged(network: Network, blocked: Int) {
     // because on S, that needs to be "override fun", and on R, that cannot be "override fun".
     override fun onNetworkSuspended(network: Network) {
-        Log.d(TAG, "onNetworkSuspended $network $network")
+        Log.d(logTag, "onNetworkSuspended $network $network")
         history.add(Suspended(network))
     }
 
     override fun onNetworkResumed(network: Network) {
-        Log.d(TAG, "$network onNetworkResumed $network")
+        Log.d(logTag, "$network onNetworkResumed $network")
         history.add(Resumed(network))
     }
 
     override fun onLosing(network: Network, maxMsToLive: Int) {
-        Log.d(TAG, "onLosing $network $maxMsToLive")
+        Log.d(logTag, "onLosing $network $maxMsToLive")
         history.add(Losing(network, maxMsToLive))
     }
 
     override fun onLost(network: Network) {
-        Log.d(TAG, "onLost $network")
+        Log.d(logTag, "onLost $network")
         history.add(Lost(network))
     }
 
     override fun onUnavailable() {
-        Log.d(TAG, "onUnavailable")
+        Log.d(logTag, "onUnavailable")
         history.add(Unavailable())
     }
 }
@@ -188,10 +193,11 @@
  */
 open class TestableNetworkCallback private constructor(
     src: TestableNetworkCallback?,
-    val defaultTimeoutMs: Long = DEFAULT_TIMEOUT,
-    val defaultNoCallbackTimeoutMs: Long = DEFAULT_NO_CALLBACK_TIMEOUT,
-    val waiterFunc: Runnable = NOOP // "() -> Unit" would forbid calling with a void func from Java
-) : RecorderCallback(src) {
+    val defaultTimeoutMs: Long,
+    val defaultNoCallbackTimeoutMs: Long,
+    val waiterFunc: Runnable,
+    logTag: String
+) : RecorderCallback(src, logTag) {
     /**
      * Construct a testable network callback.
      * @param timeoutMs the default timeout for expecting a callback. Default 30 seconds. This
@@ -213,14 +219,16 @@
     constructor(
         timeoutMs: Long = DEFAULT_TIMEOUT,
         noCallbackTimeoutMs: Long = DEFAULT_NO_CALLBACK_TIMEOUT,
-        waiterFunc: Runnable = NOOP
-    ) : this(null, timeoutMs, noCallbackTimeoutMs, waiterFunc)
+        waiterFunc: Runnable = NOOP, // "() -> Unit" would forbid calling with a void func from Java
+        logTag: String = DEFAULT_TAG
+    ) : this(null, timeoutMs, noCallbackTimeoutMs, waiterFunc, logTag)
 
     fun createLinkedCopy() = TestableNetworkCallback(
         this,
         defaultTimeoutMs,
         defaultNoCallbackTimeoutMs,
-        waiterFunc
+        waiterFunc,
+        logTag
     )
 
     // The last available network, or null if any network was lost since the last call to
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index ae85701..1cd8327 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -111,25 +111,6 @@
     min_sdk_version: "30",
 }
 
-// Networking CTS tests that target the latest released SDK. These tests can be installed on release
-// devices at any point in the Android release cycle and are useful for qualifying mainline modules
-// on release devices.
-android_test {
-    name: "CtsNetTestCasesLatestSdk",
-    defaults: [
-        "ConnectivityTestsLatestSdkDefaults",
-        "CtsNetTestCasesDefaults",
-        "CtsNetTestCasesApiStableDefaults",
-    ],
-    test_suites: [
-        "general-tests",
-        "mts-dnsresolver",
-        "mts-networking",
-        "mts-tethering",
-        "mts-wifi",
-    ],
-}
-
 java_defaults {
     name: "CtsNetTestCasesMaxTargetSdkDefaults",
     defaults: [
diff --git a/tests/cts/net/AndroidTestTemplate.xml b/tests/cts/net/AndroidTestTemplate.xml
index 077c3ef..024d3bf 100644
--- a/tests/cts/net/AndroidTestTemplate.xml
+++ b/tests/cts/net/AndroidTestTemplate.xml
@@ -48,8 +48,8 @@
              those tests with an annotation matching the name of the APK.
 
              This allows us to maintain one AndroidTestTemplate.xml for all CtsNetTestCases*.apk,
-             and have CtsNetTestCases and CtsNetTestCasesLatestSdk run all tests, but have
-             CtsNetTestCasesMaxTargetSdk31 run only tests that require target SDK 31.
+             and have CtsNetTestCases run all tests, but have CtsNetTestCasesMaxTargetSdk31 run only
+             tests that require target SDK 31.
 
              This relies on the fact that if the class specified in include-annotation exists, then
              the runner will only run the tests annotated with that annotation, but if it does not,