Merge "Process all responses if the network is null in MdnsServiceTypeClient"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 83ca2b7..b88ec7f 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -119,7 +119,6 @@
     name: "libcom_android_networkstack_tethering_util_jni",
     sdk_version: "30",
     apex_available: [
-        "//apex_available:platform", // Used by InProcessTethering
         "com.android.tethering",
     ],
     min_sdk_version: "30",
@@ -188,24 +187,6 @@
     lint: { strict_updatability_linting: true },
 }
 
-// Non-updatable tethering running in the system server process for devices not using the module
-android_app {
-    name: "InProcessTethering",
-    defaults: [
-        "TetheringAppDefaults",
-        "TetheringApiLevel",
-        "ConnectivityNextEnableDefaults",
-        "TetheringReleaseTargetSdk"
-    ],
-    static_libs: ["TetheringApiCurrentLib"],
-    certificate: "platform",
-    manifest: "AndroidManifest_InProcess.xml",
-    // InProcessTethering is a replacement for Tethering
-    overrides: ["Tethering"],
-    apex_available: ["com.android.tethering"],
-    lint: { strict_updatability_linting: true },
-}
-
 // Updatable tethering packaged for finalized API
 android_app {
     name: "Tethering",
diff --git a/Tethering/AndroidManifest_InProcess.xml b/Tethering/AndroidManifest_InProcess.xml
deleted file mode 100644
index b1f1240..0000000
--- a/Tethering/AndroidManifest_InProcess.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2019 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.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.networkstack.tethering.inprocess"
-          android:sharedUserId="android.uid.system"
-          android:process="system">
-    <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
-    <application>
-        <service android:name="com.android.networkstack.tethering.TetheringService"
-                 android:process="system"
-                 android:permission="android.permission.MAINLINE_NETWORK_STACK"
-                 android:exported="true">
-            <intent-filter>
-                <action android:name="android.net.ITetheringConnector.InProcess"/>
-            </intent-filter>
-        </service>
-    </application>
-</manifest>
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index d84fef3..4506e5a 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -19,13 +19,6 @@
 }
 
 prebuilt_etc {
-    name: "TetheringInProcessFlag",
-    src: "in-process",
-    filename_from_src: true,
-    sub_dir: "flag",
-}
-
-prebuilt_etc {
     name: "TetheringOutOfProcessFlag",
     src: "out-of-process",
     filename_from_src: true,
@@ -254,27 +247,3 @@
     standalone_contents: ["service-connectivity"],
     apex_available: ["com.android.tethering"],
 }
-
-override_apex {
-    name: "com.android.tethering.inprocess",
-    base: "com.android.tethering",
-    package_name: "com.android.tethering.inprocess",
-    enabled: enable_tethering_next_apex,
-    bpfs: [
-        "block.o",
-        "clatd.o",
-        "dscpPolicy.o",
-        "netd.o",
-        "offload@inprocess.o",
-        "test@inprocess.o",
-    ],
-    apps: [
-        "ServiceConnectivityResources",
-        "InProcessTethering",
-    ],
-    prebuilts: [
-        "current_sdkinfo",
-        "privapp_allowlist_com.android.tethering",
-        "TetheringInProcessFlag",
-    ],
-}
diff --git a/Tethering/tests/integration/base/android/net/TetheringTester.java b/Tethering/tests/integration/base/android/net/TetheringTester.java
index ae39b24..1c0803e 100644
--- a/Tethering/tests/integration/base/android/net/TetheringTester.java
+++ b/Tethering/tests/integration/base/android/net/TetheringTester.java
@@ -628,7 +628,7 @@
         return false;
     }
 
-    private void sendUploadPacket(ByteBuffer packet) throws Exception {
+    public void sendUploadPacket(ByteBuffer packet) throws Exception {
         mDownstreamReader.sendResponse(packet);
     }
 
@@ -680,4 +680,12 @@
 
         return verifyPacketNotNull("Download fail", getDownloadPacket(filter));
     }
+
+    // Send DHCPDISCOVER to DHCP server to see if DHCP server is still alive to handle
+    // the upcoming DHCP packets. This method should be only used when we know the DHCP
+    // server has been created successfully before.
+    public boolean testDhcpServerAlive(final MacAddress mac) throws Exception {
+        sendDhcpDiscover(mac.toByteArray());
+        return getNextDhcpPacket() != null;
+    }
 }
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 55854e2..21927df 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -39,6 +39,7 @@
 import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET;
 
 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;
@@ -839,4 +840,41 @@
                 REMOTE_NAT64_ADDR /* downloadSrcIp */, clatIp6 /* downloadDstIp */,
                 tester, true /* isClat */);
     }
+
+    private static final byte[] ZeroLengthDhcpPacket = new byte[] {
+            // scapy.Ether(
+            //   dst="ff:ff:ff:ff:ff:ff")
+            // scapy.IP(
+            //   dst="255.255.255.255")
+            // scapy.UDP(sport=68, dport=67)
+            /* Ethernet Header */
+            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+            (byte) 0xe0, (byte) 0x4f, (byte) 0x43, (byte) 0xe6, (byte) 0xfb, (byte) 0xd2,
+            (byte) 0x08, (byte) 0x00,
+            /* Ip header */
+            (byte) 0x45, (byte) 0x00, (byte) 0x00, (byte) 0x1c, (byte) 0x00, (byte) 0x01,
+            (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x11, (byte) 0xb6, (byte) 0x58,
+            (byte) 0x64, (byte) 0x4f, (byte) 0x60, (byte) 0x29, (byte) 0xff, (byte) 0xff,
+            (byte) 0xff, (byte) 0xff,
+            /* UDP header */
+            (byte) 0x00, (byte) 0x44, (byte) 0x00, (byte) 0x43,
+            (byte) 0x00, (byte) 0x08, (byte) 0x3a, (byte) 0xdf
+    };
+
+    @Test
+    public void testTetherZeroLengthDhcpPacket() throws Exception {
+        final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
+                toList(TEST_IP4_DNS));
+        tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
+
+        // Send a zero-length DHCP packet to upstream DHCP server.
+        final ByteBuffer packet = ByteBuffer.wrap(ZeroLengthDhcpPacket);
+        tester.sendUploadPacket(packet);
+
+        // Send DHCPDISCOVER packet from another downstream tethered device to verify that upstream
+        // DHCP server has closed the listening socket and stopped reading, then we will not receive
+        // any DHCPOFFER in this case.
+        final MacAddress macAddress = MacAddress.fromString("11:22:33:44:55:66");
+        assertFalse(tester.testDhcpServerAlive(macAddress));
+    }
 }
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
index b3fb3e4..81d4fbe 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
@@ -106,6 +106,7 @@
                 ConntrackMessage.Tuple tuple = ctmsg.tupleOrig;
 
                 if (nlmsghdr.nlmsg_type == (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW)
+                        && tuple != null
                         && tuple.protoNum == IPPROTO_TCP
                         && tuple.srcIp.equals(local.getAddress())
                         && tuple.dstIp.equals(remote.getAddress())
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 229dce3..b3f8ed6 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -103,18 +103,6 @@
 }
 
 bpf {
-    name: "offload@inprocess.o",
-    srcs: ["offload@inprocess.c"],
-    btf: true,
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-DBTF",
-        "-DINPROCESS",
-    ],
-}
-
-bpf {
     name: "test.o",
     srcs: ["test.c"],
     cflags: [
@@ -135,18 +123,6 @@
 }
 
 bpf {
-    name: "test@inprocess.o",
-    srcs: ["test@inprocess.c"],
-    btf: true,
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-DBTF",
-        "-DINPROCESS",
-    ],
-}
-
-bpf {
     name: "clatd.o",
     srcs: ["clatd.c"],
     btf: true,
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index f4d4254..80d1a41 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -38,13 +38,7 @@
 // Warning: values other than AID_ROOT don't work for map uid on BpfLoader < v0.21
 #define TETHERING_UID AID_ROOT
 
-#ifdef INPROCESS
-#define DEFAULT_BPF_MAP_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define DEFAULT_BPF_PROG_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define TETHERING_GID AID_SYSTEM
-#else
 #define TETHERING_GID AID_NETWORK_STACK
-#endif
 
 #include "bpf_helpers.h"
 #include "bpf_net_helpers.h"
diff --git a/bpf_progs/offload@inprocess.c b/bpf_progs/offload@inprocess.c
deleted file mode 120000
index 4092e0d..0000000
--- a/bpf_progs/offload@inprocess.c
+++ /dev/null
@@ -1 +0,0 @@
-offload.c
\ No newline at end of file
diff --git a/bpf_progs/test.c b/bpf_progs/test.c
index d1f780f..091743c 100644
--- a/bpf_progs/test.c
+++ b/bpf_progs/test.c
@@ -32,13 +32,7 @@
 // Warning: values other than AID_ROOT don't work for map uid on BpfLoader < v0.21
 #define TETHERING_UID AID_ROOT
 
-#ifdef INPROCESS
-#define DEFAULT_BPF_MAP_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define DEFAULT_BPF_PROG_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define TETHERING_GID AID_SYSTEM
-#else
 #define TETHERING_GID AID_NETWORK_STACK
-#endif
 
 // This is non production code, only used for testing
 // Needed because the bitmap array definition is non-kosher for pre-T OS devices.
diff --git a/bpf_progs/test@inprocess.c b/bpf_progs/test@inprocess.c
deleted file mode 120000
index aeebb26..0000000
--- a/bpf_progs/test@inprocess.c
+++ /dev/null
@@ -1 +0,0 @@
-test.c
\ No newline at end of file
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 3cc9c65..92e9599 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -1348,6 +1348,18 @@
     }
 
     /**
+     * Gets the transports as an int. Internal callers only.
+     *
+     * Prefer getTransportTypes/hasTransportType if not immediately collapsing back into a scalar.
+     *
+     * @return a long integer representing the transport types.
+     * @hide
+     */
+    public long getTransportTypesInternal() {
+        return mTransportTypes;
+    }
+
+    /**
      * Sets all the transports set on this {@code NetworkCapability} instance.
      * This overwrites any existing transports.
      *
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index a62ee7f..f30f120 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -19,10 +19,10 @@
 import static android.net.ConnectivityManager.NETID_UNSET;
 import static android.net.nsd.NsdManager.MDNS_DISCOVERY_MANAGER_EVENT;
 import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
 import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
 
 import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
+import static com.android.server.connectivity.mdns.MdnsRecord.MAX_LABEL_LENGTH;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -73,6 +73,7 @@
 import com.android.server.connectivity.mdns.MdnsServiceInfo;
 import com.android.server.connectivity.mdns.MdnsSocketClientBase;
 import com.android.server.connectivity.mdns.MdnsSocketProvider;
+import com.android.server.connectivity.mdns.util.MdnsUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -81,11 +82,6 @@
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -108,8 +104,6 @@
      */
     private static final String MDNS_DISCOVERY_MANAGER_VERSION = "mdns_discovery_manager_version";
     private static final String LOCAL_DOMAIN_NAME = "local";
-    // Max label length as per RFC 1034/1035
-    private static final int MAX_LABEL_LENGTH = 63;
 
     /**
      * Enable advertising using the Java MdnsAdvertiser, instead of the legacy mdnsresponder
@@ -570,18 +564,7 @@
              */
             @NonNull
             private String truncateServiceName(@NonNull String originalName) {
-                // UTF-8 is at most 4 bytes per character; return early in the common case where
-                // the name can't possibly be over the limit given its string length.
-                if (originalName.length() <= MAX_LABEL_LENGTH / 4) return originalName;
-
-                final Charset utf8 = StandardCharsets.UTF_8;
-                final CharsetEncoder encoder = utf8.newEncoder();
-                final ByteBuffer out = ByteBuffer.allocate(MAX_LABEL_LENGTH);
-                // encode will write as many characters as possible to the out buffer, and just
-                // return an overflow code if there were too many characters (no need to check the
-                // return code here, this method truncates the name on purpose).
-                encoder.encode(CharBuffer.wrap(originalName), out, true /* endOfInput */);
-                return new String(out.array(), 0, out.position(), utf8);
+                return MdnsUtils.truncateServiceName(originalName, MAX_LABEL_LENGTH);
             }
 
             private void stopDiscoveryManagerRequest(ClientRequest request, int clientId, int id,
@@ -1368,8 +1351,8 @@
          * @return true if the MdnsDiscoveryManager feature is enabled.
          */
         public boolean isMdnsDiscoveryManagerEnabled(Context context) {
-            return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
-                    NAMESPACE_CONNECTIVITY, MDNS_DISCOVERY_MANAGER_VERSION,
+            return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING,
+                    MDNS_DISCOVERY_MANAGER_VERSION, DeviceConfigUtils.TETHERING_MODULE_NAME,
                     false /* defaultEnabled */);
         }
 
@@ -1380,8 +1363,9 @@
          * @return true if the MdnsAdvertiser feature is enabled.
          */
         public boolean isMdnsAdvertiserEnabled(Context context) {
-            return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
-                    NAMESPACE_CONNECTIVITY, MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
+            return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING,
+                    MDNS_ADVERTISER_VERSION, DeviceConfigUtils.TETHERING_MODULE_NAME,
+                    false /* defaultEnabled */);
         }
 
         /**
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
index 33fef9d..a332da7 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
@@ -16,6 +16,8 @@
 
 package com.android.server.connectivity.mdns;
 
+import static com.android.server.connectivity.mdns.MdnsRecord.MAX_LABEL_LENGTH;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.LinkAddress;
@@ -29,6 +31,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.net.module.util.SharedLog;
+import com.android.server.connectivity.mdns.util.MdnsUtils;
 
 import java.io.PrintWriter;
 import java.util.List;
@@ -359,7 +362,7 @@
             // "Name (2)", then "Name (3)" etc.
             // TODO: use a hidden method in NsdServiceInfo once MdnsAdvertiser is moved to service-t
             final NsdServiceInfo newInfo = new NsdServiceInfo();
-            newInfo.setServiceName(mOriginalName + " (" + (mConflictCount + renameCount + 1) + ")");
+            newInfo.setServiceName(getUpdatedServiceName(renameCount));
             newInfo.setServiceType(mServiceInfo.getServiceType());
             for (Map.Entry<String, byte[]> attr : mServiceInfo.getAttributes().entrySet()) {
                 newInfo.setAttribute(attr.getKey(),
@@ -372,6 +375,13 @@
             return newInfo;
         }
 
+        private String getUpdatedServiceName(int renameCount) {
+            final String suffix = " (" + (mConflictCount + renameCount + 1) + ")";
+            final String truncatedServiceName = MdnsUtils.truncateServiceName(mOriginalName,
+                    MAX_LABEL_LENGTH - suffix.length());
+            return truncatedServiceName + suffix;
+        }
+
         @NonNull
         public NsdServiceInfo getServiceInfo() {
             return mServiceInfo;
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
index bcee9d1..19630e3 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
@@ -46,6 +46,8 @@
 
     public static final long RECEIPT_TIME_NOT_SENT = 0L;
     public static final int CLASS_ANY = 0x00ff;
+    /** Max label length as per RFC 1034/1035 */
+    public static final int MAX_LABEL_LENGTH = 63;
 
     /** Status indicating that the record is current. */
     public static final int STATUS_OK = 0;
diff --git a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java
index 4b9759d..5cc789f 100644
--- a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java
+++ b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java
@@ -21,6 +21,12 @@
 import android.net.Network;
 import android.os.Handler;
 
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
+
 /**
  * Mdns utility functions.
  */
@@ -73,4 +79,22 @@
             @Nullable Network currentNetwork) {
         return targetNetwork == null || targetNetwork.equals(currentNetwork);
     }
-}
+
+    /**
+     * Truncate a service name to up to maxLength UTF-8 bytes.
+     */
+    public static String truncateServiceName(@NonNull String originalName, int maxLength) {
+        // UTF-8 is at most 4 bytes per character; return early in the common case where
+        // the name can't possibly be over the limit given its string length.
+        if (originalName.length() <= maxLength / 4) return originalName;
+
+        final Charset utf8 = StandardCharsets.UTF_8;
+        final CharsetEncoder encoder = utf8.newEncoder();
+        final ByteBuffer out = ByteBuffer.allocate(maxLength);
+        // encode will write as many characters as possible to the out buffer, and just
+        // return an overflow code if there were too many characters (no need to check the
+        // return code here, this method truncates the name on purpose).
+        encoder.encode(CharBuffer.wrap(originalName), out, true /* endOfInput */);
+        return new String(out.array(), 0, out.position(), utf8);
+    }
+}
\ No newline at end of file
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index 77cffda..9ced44e 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -54,6 +54,10 @@
   if (!isOk(status)) {
     uid_t uid = getuid();
     ALOGE("BpfNetMaps jni init failure as uid=%d", uid);
+    // We probably only ever get called from system_server (ie. AID_SYSTEM)
+    // or from tests, and never from network_stack (ie. AID_NETWORK_STACK).
+    // However, if we ever do add calls from production network_stack code
+    // we do want to make sure this initializes correctly.
     // TODO: Fix tests to not use this jni lib, so we can unconditionally abort()
     if (uid == AID_SYSTEM || uid == AID_NETWORK_STACK) abort();
   }
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 8d909ed..d966070 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -90,11 +90,6 @@
 
 #undef ALOGF
 
-bool isGsiImage() {
-    // this implementation matches 2 other places in the codebase (same function name too)
-    return !access("/system/system_ext/etc/init/init.gsi.rc", F_OK);
-}
-
 static const char* kClatdDir = "/apex/com.android.tethering/bin/for-system";
 static const char* kClatdBin = "/apex/com.android.tethering/bin/for-system/clatd";
 
@@ -135,14 +130,6 @@
 
 #undef V2
 
-    // HACK: Some old vendor kernels lack ~5.10 backport of 'bpffs selinux genfscon' support.
-    // This is *NOT* supported, but let's allow, at least for now, U+ GSI to boot on them.
-    // (without this hack pixel5 R vendor + U gsi breaks)
-    if (isGsiImage() && !bpf::isAtLeastKernelVersion(5, 10, 0)) {
-        ALOGE("GSI with *BAD* pre-5.10 kernel lacking bpffs selinux genfscon support.");
-        return;
-    }
-
     if (fatal) abort();
 }
 
diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp
index 4bbaae6..ed74430 100644
--- a/service/jni/onload.cpp
+++ b/service/jni/onload.cpp
@@ -38,11 +38,11 @@
         return JNI_ERR;
     }
 
-    if (register_com_android_server_BpfNetMaps(env) < 0) {
-        return JNI_ERR;
-    }
-
     if (android::modules::sdklevel::IsAtLeastT()) {
+        if (register_com_android_server_BpfNetMaps(env) < 0) {
+            return JNI_ERR;
+        }
+
         if (register_com_android_server_connectivity_ClatCoordinator(env) < 0) {
             return JNI_ERR;
         }
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index b4fce37..84e581e 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -281,8 +281,8 @@
         if (sEnableJavaBpfMap == null) {
             sEnableJavaBpfMap = SdkLevel.isAtLeastU() ||
                     DeviceConfigUtils.isFeatureEnabled(context,
-                    DeviceConfig.NAMESPACE_TETHERING, BPF_NET_MAPS_ENABLE_JAVA_BPF_MAP,
-                    false /* defaultValue */);
+                            DeviceConfig.NAMESPACE_TETHERING, BPF_NET_MAPS_ENABLE_JAVA_BPF_MAP,
+                            DeviceConfigUtils.TETHERING_MODULE_NAME, false /* defaultValue */);
         }
         Log.d(TAG, "BpfNetMaps is initialized with sEnableJavaBpfMap=" + sEnableJavaBpfMap);
 
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index c080c59..fa770a9 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -91,7 +91,7 @@
 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
 import static android.os.Process.INVALID_UID;
 import static android.os.Process.VPN_UID;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
 import static android.system.OsConstants.ETH_P_ALL;
 import static android.system.OsConstants.IPPROTO_TCP;
 import static android.system.OsConstants.IPPROTO_UDP;
@@ -1393,9 +1393,9 @@
         /**
          * @see DeviceConfigUtils#isFeatureEnabled
          */
-        public boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled) {
-            return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name,
-                    TETHERING_MODULE_NAME, defaultEnabled);
+        public boolean isFeatureEnabled(Context context, String name) {
+            return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING, name,
+                    TETHERING_MODULE_NAME, false /* defaultValue */);
         }
 
         /**
diff --git a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
index ee8ab68..7c23816 100644
--- a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -842,7 +842,7 @@
          */
         public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
             return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
-                    defaultEnabled);
+                    DeviceConfigUtils.TETHERING_MODULE_NAME, defaultEnabled);
         }
 
         /**
diff --git a/service/src/com/android/server/connectivity/ConnectivityFlags.java b/service/src/com/android/server/connectivity/ConnectivityFlags.java
index 122ea1c..9039a14 100644
--- a/service/src/com/android/server/connectivity/ConnectivityFlags.java
+++ b/service/src/com/android/server/connectivity/ConnectivityFlags.java
@@ -61,6 +61,6 @@
      */
     public void loadFlags(ConnectivityService.Dependencies deps, Context ctx) {
         mNoRematchAllRequestsOnRegister = deps.isFeatureEnabled(
-                ctx, NO_REMATCH_ALL_REQUESTS_ON_REGISTER, false /* defaultEnabled */);
+                ctx, NO_REMATCH_ALL_REQUESTS_ON_REGISTER);
     }
 }
diff --git a/service/src/com/android/server/connectivity/NetworkDiagnostics.java b/service/src/com/android/server/connectivity/NetworkDiagnostics.java
index 4eba74b..15d0925 100644
--- a/service/src/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/service/src/com/android/server/connectivity/NetworkDiagnostics.java
@@ -19,6 +19,9 @@
 import static android.system.OsConstants.*;
 
 import static com.android.net.module.util.NetworkStackConstants.ICMP_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -35,6 +38,7 @@
 import android.system.Os;
 import android.system.StructTimeval;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Pair;
 
 import com.android.internal.util.IndentingPrintWriter;
@@ -174,7 +178,7 @@
         }
     }
 
-    private final Map<InetAddress, Measurement> mIcmpChecks = new HashMap<>();
+    private final Map<Pair<InetAddress, Integer>, Measurement> mIcmpChecks = new HashMap<>();
     private final Map<Pair<InetAddress, InetAddress>, Measurement> mExplicitSourceIcmpChecks =
             new HashMap<>();
     private final Map<InetAddress, Measurement> mDnsUdpChecks = new HashMap<>();
@@ -207,17 +211,21 @@
             mLinkProperties.addDnsServer(TEST_DNS6);
         }
 
+        final int mtu = mLinkProperties.getMtu();
         for (RouteInfo route : mLinkProperties.getRoutes()) {
             if (route.getType() == RouteInfo.RTN_UNICAST && route.hasGateway()) {
                 InetAddress gateway = route.getGateway();
-                prepareIcmpMeasurement(gateway);
+                // Use mtu in the route if exists. Otherwise, use the one in the link property.
+                final int routeMtu = route.getMtu();
+                prepareIcmpMeasurements(gateway, (routeMtu > 0) ? routeMtu : mtu);
                 if (route.isIPv6Default()) {
                     prepareExplicitSourceIcmpMeasurements(gateway);
                 }
             }
         }
+
         for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
-            prepareIcmpMeasurement(nameserver);
+            prepareIcmpMeasurements(nameserver, mtu);
             prepareDnsMeasurement(nameserver);
 
             // Unlike the DnsResolver which doesn't do certificate validation in opportunistic mode,
@@ -263,11 +271,50 @@
                 localAddr.getHostAddress(), inetSockAddr.getPort());
     }
 
-    private void prepareIcmpMeasurement(InetAddress target) {
-        if (!mIcmpChecks.containsKey(target)) {
-            Measurement measurement = new Measurement();
-            measurement.thread = new Thread(new IcmpCheck(target, 0, measurement));
-            mIcmpChecks.put(target, measurement);
+    private static int getHeaderLen(@NonNull InetAddress target) {
+        // Convert IPv4 mapped v6 address to v4 if any.
+        try {
+            final InetAddress addr = InetAddress.getByAddress(target.getAddress());
+            // An ICMPv6 header is technically 4 bytes, but the implementation in IcmpCheck#run()
+            // will always fill in another 4 bytes padding in the v6 diagnostic packets, so the size
+            // before icmp data is always 8 bytes in the implementation of ICMP diagnostics for both
+            // v4 and v6 packets. Thus, it's fine to use the v4 header size in the length
+            // calculation.
+            if (addr instanceof Inet6Address) {
+                return IPV6_HEADER_LEN + ICMP_HEADER_LEN;
+            }
+        } catch (UnknownHostException e) {
+            Log.e(TAG, "Create InetAddress fail(" + target + "): " + e);
+        }
+
+        return IPV4_HEADER_MIN_LEN + ICMP_HEADER_LEN;
+    }
+
+    private void prepareIcmpMeasurements(@NonNull InetAddress target, int targetNetworkMtu) {
+        // Test with different size payload ICMP.
+        // 1. Test with 0 payload.
+        addPayloadIcmpMeasurement(target, 0);
+        final int header = getHeaderLen(target);
+        // 2. Test with full size MTU.
+        addPayloadIcmpMeasurement(target, targetNetworkMtu - header);
+        // 3. If v6, make another measurement with the full v6 min MTU, unless that's what
+        //    was done above.
+        if ((target instanceof Inet6Address) && (targetNetworkMtu != IPV6_MIN_MTU)) {
+            addPayloadIcmpMeasurement(target, IPV6_MIN_MTU - header);
+        }
+    }
+
+    private void addPayloadIcmpMeasurement(@NonNull InetAddress target, int payloadLen) {
+        // This can happen if the there is no mtu filled(which is 0) in the link property.
+        // The value becomes negative after minus header length.
+        if (payloadLen < 0) return;
+
+        final Pair<InetAddress, Integer> lenTarget =
+                new Pair<>(target, Integer.valueOf(payloadLen));
+        if (!mIcmpChecks.containsKey(lenTarget)) {
+            final Measurement measurement = new Measurement();
+            measurement.thread = new Thread(new IcmpCheck(target, payloadLen, measurement));
+            mIcmpChecks.put(lenTarget, measurement);
         }
     }
 
@@ -336,8 +383,8 @@
         ArrayList<Measurement> measurements = new ArrayList(totalMeasurementCount());
 
         // Sort measurements IPv4 first.
-        for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
-            if (entry.getKey() instanceof Inet4Address) {
+        for (Map.Entry<Pair<InetAddress, Integer>, Measurement> entry : mIcmpChecks.entrySet()) {
+            if (entry.getKey().first instanceof Inet4Address) {
                 measurements.add(entry.getValue());
             }
         }
@@ -359,8 +406,8 @@
         }
 
         // IPv6 measurements second.
-        for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
-            if (entry.getKey() instanceof Inet6Address) {
+        for (Map.Entry<Pair<InetAddress, Integer>, Measurement> entry : mIcmpChecks.entrySet()) {
+            if (entry.getKey().first instanceof Inet6Address) {
                 measurements.add(entry.getValue());
             }
         }
diff --git a/tests/cts/hostside/app/Android.bp b/tests/cts/hostside/app/Android.bp
index 12e7d33..2245382 100644
--- a/tests/cts/hostside/app/Android.bp
+++ b/tests/cts/hostside/app/Android.bp
@@ -30,7 +30,6 @@
         "cts-net-utils",
         "ctstestrunner-axt",
         "modules-utils-build",
-        "ub-uiautomator",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
index b2e81ff..13bbab6 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
@@ -19,18 +19,18 @@
 import static com.android.cts.net.hostside.NetworkPolicyTestUtils.clearSnoozeTimestamps;
 
 import android.content.pm.PackageManager;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
 
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Direction;
 import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
 
 import com.android.compatibility.common.util.SystemUtil;
-import com.android.compatibility.common.util.UiAutomatorUtils;
+import com.android.compatibility.common.util.UiAutomatorUtils2;
 
 import org.junit.After;
 import org.junit.Assume;
@@ -84,7 +84,7 @@
             final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation);
             uiDevice.openNotification();
             try {
-                final UiObject2 uiObject = UiAutomatorUtils.waitFindObject(
+                final UiObject2 uiObject = UiAutomatorUtils2.waitFindObject(
                         By.text("Data warning"));
                 Assume.assumeNotNull(uiObject);
                 uiObject.wait(Until.clickable(true), 10_000L);
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index 624acd3..73a6502 100755
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -100,9 +100,6 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -114,6 +111,9 @@
 import android.util.Range;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
 
 import com.android.compatibility.common.util.BlockingBroadcastReceiver;
 import com.android.modules.utils.build.SdkLevel;
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 423b2bd..8b059e3 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -1901,6 +1901,9 @@
      */
     @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
     @Test
+    // getSupportedKeepalives is available in updatable ConnectivityManager (S+)
+    // Also, this feature is not mainlined before S, and it's fine to skip on R- devices.
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
     @RequiresDevice // Keepalive is not supported on virtual hardware
     public void testSocketKeepaliveLimitWifi() throws Exception {
         assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
@@ -1951,6 +1954,9 @@
      */
     @AppModeFull(reason = "Cannot request network in instant app mode")
     @Test
+    // getSupportedKeepalives is available in updatable ConnectivityManager (S+)
+    // Also, this feature is not mainlined before S, and it's fine to skip on R- devices.
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
     @RequiresDevice // Keepalive is not supported on virtual hardware
     public void testSocketKeepaliveLimitTelephony() throws Exception {
         if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) {
@@ -1997,6 +2003,9 @@
      */
     @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
     @Test
+    // getSupportedKeepalives is available in updatable ConnectivityManager (S+)
+    // Also, this feature is not mainlined before S, and it's fine to skip on R- devices.
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
     @RequiresDevice // Keepalive is not supported on virtual hardware
     public void testSocketKeepaliveUnprivileged() throws Exception {
         assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
@@ -2564,6 +2573,14 @@
                 tetherUtils.registerTetheringEventCallback();
         try {
             tetherEventCallback.assumeWifiTetheringSupported(mContext);
+            // To prevent WiFi-to-WiFi interruption while entering APM:
+            //  - If WiFi is retained while entering APM, hotspot will also remain enabled.
+            //  - If WiFi is off before APM or disabled while entering APM, hotspot will be
+            //    disabled.
+            //
+            // To ensure hotspot always be disabled after enabling APM, disable wifi before
+            // enabling the hotspot.
+            mCtsNetUtils.disableWifi();
 
             tetherUtils.startWifiTethering(tetherEventCallback);
             // Update setting to verify the behavior.
@@ -2597,6 +2614,7 @@
             ConnectivitySettingsManager.setPrivateDnsMode(mContext, curPrivateDnsMode);
             tetherUtils.unregisterTetheringEventCallback(tetherEventCallback);
             tetherUtils.stopAllTethering();
+            mCtsNetUtils.ensureWifiConnected();
         }
     }
 
@@ -2960,13 +2978,13 @@
 
         allowBadWifi();
 
-        final Network cellNetwork = mCtsNetUtils.connectToCell();
-        final Network wifiNetwork = prepareValidatedNetwork();
-
-        registerDefaultNetworkCallback(defaultCb);
-        registerNetworkCallback(makeWifiNetworkRequest(), wifiCb);
-
         try {
+            final Network cellNetwork = mCtsNetUtils.connectToCell();
+            final Network wifiNetwork = prepareValidatedNetwork();
+
+            registerDefaultNetworkCallback(defaultCb);
+            registerNetworkCallback(makeWifiNetworkRequest(), wifiCb);
+
             // Verify wifi is the default network.
             defaultCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
                     entry -> wifiNetwork.equals(entry.getNetwork()));
diff --git a/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt b/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
index fcfecad..2704dd3 100644
--- a/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
@@ -30,6 +30,7 @@
 import android.os.Build
 import android.os.Handler
 import android.os.HandlerThread
+import android.util.Log
 import androidx.test.InstrumentationRegistry
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
@@ -41,6 +42,7 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import java.util.Collections
 
 // This test doesn't really have a constraint on how fast the methods should return. If it's
 // going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio
@@ -64,10 +66,11 @@
 @IgnoreUpTo(Build.VERSION_CODES.R)
 @RunWith(DevSdkIgnoreRunner::class)
 class NetworkScoreTest {
+    private val TAG = javaClass.simpleName
     private val mCm = testContext.getSystemService(ConnectivityManager::class.java)
-    private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread")
+    private val mHandlerThread = HandlerThread("$TAG handler thread")
     private val mHandler by lazy { Handler(mHandlerThread.looper) }
-    private val agentsToCleanUp = mutableListOf<NetworkAgent>()
+    private val agentsToCleanUp = Collections.synchronizedList(mutableListOf<NetworkAgent>())
     private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
 
     @Before
@@ -83,15 +86,18 @@
                     .addTransportType(NetworkCapabilities.TRANSPORT_TEST).build(), cb, mHandler
             )
         }
+        Log.i(TAG, "Teardown on thread ${System.identityHashCode(Thread.currentThread())} " +
+                "cleaning up ${agentsToCleanUp.size} agents")
         agentsToCleanUp.forEach {
+            Log.i(TAG, "Unregister agent for net ${it.network}")
             it.unregister()
             agentCleanUpCb.eventuallyExpect<CallbackEntry.Lost> { cb -> cb.network == it.network }
         }
         mCm.unregisterNetworkCallback(agentCleanUpCb)
 
+        callbacksToCleanUp.forEach { mCm.unregisterNetworkCallback(it) }
         mHandlerThread.quitSafely()
         mHandlerThread.join()
-        callbacksToCleanUp.forEach { mCm.unregisterNetworkCallback(it) }
     }
 
     // Returns a networkCallback that sends onAvailable on the best network with TRANSPORT_TEST.
@@ -145,6 +151,8 @@
         val agent = object : NetworkAgent(context, looper, "NetworkScore test agent", nc,
                 LinkProperties(), score, config, NetworkProvider(context, looper,
                 "NetworkScore test provider")) {}.also {
+            Log.i(TAG, "Add on thread ${System.identityHashCode(Thread.currentThread())} " +
+                    "agent to clean up $it")
             agentsToCleanUp.add(it)
         }
         runWithShellPermissionIdentity({ agent.register() }, MANAGE_TEST_NETWORKS)
diff --git a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
index f86c5cd..d8a0b07 100644
--- a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
@@ -210,7 +210,6 @@
     private long mStartTime;
     private long mEndTime;
 
-    private long mBytesRead;
     private String mWriteSettingsMode;
     private String mUsageStatsMode;
 
@@ -229,6 +228,7 @@
             TrafficStats.setThreadStatsTag(NETWORK_TAG);
             urlc = (HttpURLConnection) network.openConnection(url);
             urlc.setConnectTimeout(TIMEOUT_MILLIS);
+            urlc.setReadTimeout(TIMEOUT_MILLIS);
             urlc.setUseCaches(false);
             // Disable compression so we generate enough traffic that assertWithinPercentage will
             // not be affected by the small amount of traffic (5-10kB) sent by the test harness.
@@ -236,11 +236,10 @@
             urlc.connect();
             boolean ping = urlc.getResponseCode() == 200;
             if (ping) {
-                in = new InputStreamReader(
-                        (InputStream) urlc.getContent());
-
-                mBytesRead = 0;
-                while (in.read() != -1) ++mBytesRead;
+                in = new InputStreamReader((InputStream) urlc.getContent());
+                // Since the test doesn't really care about the precise amount of data, instead
+                // of reading all contents, just read few bytes at the beginning.
+                in.read();
             }
         } catch (Exception e) {
             Log.i(LOG_TAG, "Badness during exercising remote server: " + e);
@@ -379,7 +378,7 @@
                 .build(), callback);
         synchronized (this) {
             try {
-                wait((int) (TIMEOUT_MILLIS * 1.2));
+                wait((int) (TIMEOUT_MILLIS * 2.4));
             } catch (InterruptedException e) {
             }
         }
@@ -394,7 +393,7 @@
         assertFalse(mNetworkInterfacesToTest[networkTypeIndex].getSystemFeature()
                 + " is a reported system feature, "
                 + "however no corresponding connected network interface was found or the attempt "
-                + "to connect has timed out (timeout = " + TIMEOUT_MILLIS + "ms)."
+                + "to connect and read has timed out (timeout = " + (TIMEOUT_MILLIS * 2) + "ms)."
                 + mNetworkInterfacesToTest[networkTypeIndex].getErrorMessage(), hasFeature);
         return false;
     }
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 877df98..d186920 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -2077,12 +2077,12 @@
         }
 
         @Override
-        public boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled) {
+        public boolean isFeatureEnabled(Context context, String name) {
             switch (name) {
                 case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER:
                     return true;
                 default:
-                    return super.isFeatureEnabled(context, name, defaultEnabled);
+                    return super.isFeatureEnabled(context, name);
             }
         }
 
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
index a917361..4b495cd 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
@@ -47,6 +47,8 @@
 
 private const val SERVICE_ID_1 = 1
 private const val SERVICE_ID_2 = 2
+private const val LONG_SERVICE_ID_1 = 3
+private const val LONG_SERVICE_ID_2 = 4
 private const val TIMEOUT_MS = 10_000L
 private val TEST_ADDR = parseNumericAddress("2001:db8::123")
 private val TEST_LINKADDR = LinkAddress(TEST_ADDR, 64 /* prefixLength */)
@@ -56,16 +58,30 @@
 
 private val SERVICE_1 = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply {
     port = 12345
-    host = TEST_ADDR
+    hostAddresses = listOf(TEST_ADDR)
     network = TEST_NETWORK_1
 }
 
+private val LONG_SERVICE_1 =
+    NsdServiceInfo("a".repeat(48) + "TestServiceName", "_longadvertisertest._tcp").apply {
+    port = 12345
+    hostAddresses = listOf(TEST_ADDR)
+    network = TEST_NETWORK_1
+    }
+
 private val ALL_NETWORKS_SERVICE = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply {
     port = 12345
-    host = TEST_ADDR
+    hostAddresses = listOf(TEST_ADDR)
     network = null
 }
 
+private val LONG_ALL_NETWORKS_SERVICE =
+    NsdServiceInfo("a".repeat(48) + "TestServiceName", "_longadvertisertest._tcp").apply {
+        port = 12345
+        hostAddresses = listOf(TEST_ADDR)
+        network = null
+    }
+
 @RunWith(DevSdkIgnoreRunner::class)
 @IgnoreUpTo(Build.VERSION_CODES.S_V2)
 class MdnsAdvertiserTest {
@@ -191,6 +207,9 @@
         verify(socketProvider).requestSocket(eq(null), allNetSocketCbCaptor.capture())
         val allNetSocketCb = allNetSocketCbCaptor.value
 
+        postSync { advertiser.addService(LONG_SERVICE_ID_1, LONG_SERVICE_1) }
+        postSync { advertiser.addService(LONG_SERVICE_ID_2, LONG_ALL_NETWORKS_SERVICE) }
+
         // Callbacks for matching network and all networks both get the socket
         postSync {
             oneNetSocketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR))
@@ -200,10 +219,18 @@
         val expectedRenamed = NsdServiceInfo(
                 "${ALL_NETWORKS_SERVICE.serviceName} (2)", ALL_NETWORKS_SERVICE.serviceType).apply {
             port = ALL_NETWORKS_SERVICE.port
-            host = ALL_NETWORKS_SERVICE.host
+            hostAddresses = ALL_NETWORKS_SERVICE.hostAddresses
             network = ALL_NETWORKS_SERVICE.network
         }
 
+        val expectedLongRenamed = NsdServiceInfo(
+            "${LONG_ALL_NETWORKS_SERVICE.serviceName.dropLast(4)} (2)",
+            LONG_ALL_NETWORKS_SERVICE.serviceType).apply {
+            port = LONG_ALL_NETWORKS_SERVICE.port
+            hostAddresses = LONG_ALL_NETWORKS_SERVICE.hostAddresses
+            network = LONG_ALL_NETWORKS_SERVICE.network
+        }
+
         val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
         verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
                 eq(thread.looper), any(), intAdvCbCaptor.capture(), eq(TEST_HOSTNAME)
@@ -212,6 +239,10 @@
                 argThat { it.matches(SERVICE_1) })
         verify(mockInterfaceAdvertiser1).addService(eq(SERVICE_ID_2),
                 argThat { it.matches(expectedRenamed) })
+        verify(mockInterfaceAdvertiser1).addService(eq(LONG_SERVICE_ID_1),
+                argThat { it.matches(LONG_SERVICE_1) })
+        verify(mockInterfaceAdvertiser1).addService(eq(LONG_SERVICE_ID_2),
+            argThat { it.matches(expectedLongRenamed) })
 
         doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
         postSync { intAdvCbCaptor.value.onRegisterServiceSucceeded(
@@ -251,7 +282,7 @@
     return Objects.equals(serviceName, other.serviceName) &&
             Objects.equals(serviceType, other.serviceType) &&
             Objects.equals(attributes, other.attributes) &&
-            Objects.equals(host, other.host) &&
+            Objects.equals(hostAddresses, other.hostAddresses) &&
             port == other.port &&
             Objects.equals(network, other.network)
 }
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt
index f584ed5..61c3a70 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt
@@ -19,6 +19,7 @@
 import android.os.Build
 import com.android.server.connectivity.mdns.util.MdnsUtils.equalsIgnoreDnsCase
 import com.android.server.connectivity.mdns.util.MdnsUtils.toDnsLowerCase
+import com.android.server.connectivity.mdns.util.MdnsUtils.truncateServiceName
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRunner
 import org.junit.Assert.assertEquals
@@ -65,4 +66,10 @@
                 "Test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" +
                         "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<"))
     }
+
+    @Test
+    fun testTruncateServiceName() {
+        assertEquals(truncateServiceName("测试abcde", 7), "测试a")
+        assertEquals(truncateServiceName("测试abcde", 100), "测试abcde")
+    }
 }