Merge "Fix some typos in comments"
diff --git a/OWNERS_core_networking_xts b/OWNERS_core_networking_xts
new file mode 100644
index 0000000..a6627fe
--- /dev/null
+++ b/OWNERS_core_networking_xts
@@ -0,0 +1,2 @@
+lorenzo@google.com
+satk@google.com
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 2921e78..041a3ae 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -110,6 +110,7 @@
     static_libs: [
         "libnet_utils_device_common_bpfjni",
         "libnetjniutils",
+        "libtcutils",
     ],
 
     // We cannot use plain "libc++" here to link libc++ dynamically because it results in:
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index ee1c5fe..c72d3a6 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -58,6 +58,10 @@
             jni_libs: ["libframework-connectivity-jni"],
         },
     },
+    binaries: [
+        "clatd",
+    ],
+    canned_fs_config: "canned_fs_config",
     bpfs: [
         "offload.o",
         "test.o",
@@ -91,6 +95,7 @@
     name: "com.android.tethering-bootclasspath-fragment",
     contents: [
         "framework-connectivity",
+        "framework-connectivity-tiramisu",
         "framework-tethering",
     ],
     apex_available: ["com.android.tethering"],
@@ -112,6 +117,7 @@
     // Additional hidden API flag files to override the defaults. This must only be
     // modified by the Soong or platform compat team.
     hidden_api: {
+        max_target_r_low_priority: ["hiddenapi/hiddenapi-max-target-r-loprio.txt"],
         max_target_o_low_priority: ["hiddenapi/hiddenapi-max-target-o-low-priority.txt"],
         unsupported: ["hiddenapi/hiddenapi-unsupported.txt"],
     },
diff --git a/Tethering/apex/canned_fs_config b/Tethering/apex/canned_fs_config
new file mode 100644
index 0000000..44c57ab
--- /dev/null
+++ b/Tethering/apex/canned_fs_config
@@ -0,0 +1,2 @@
+/bin/for-system 0 1000 0550
+/bin/for-system/clatd 1029 1029 06555
diff --git a/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt b/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
index 1f49d1b..ea0f61a 100644
--- a/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
+++ b/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
@@ -1163,6 +1163,93 @@
 Landroid/net/NetworkWatchlistManager;->reportWatchlistIfNecessary()V
 Landroid/net/NetworkWatchlistManager;->SHARED_MEMORY_TAG:Ljava/lang/String;
 Landroid/net/NetworkWatchlistManager;->TAG:Ljava/lang/String;
+Landroid/net/nsd/DnsSdTxtRecord;-><init>()V
+Landroid/net/nsd/DnsSdTxtRecord;-><init>(Landroid/net/nsd/DnsSdTxtRecord;)V
+Landroid/net/nsd/DnsSdTxtRecord;-><init>([B)V
+Landroid/net/nsd/DnsSdTxtRecord;->contains(Ljava/lang/String;)Z
+Landroid/net/nsd/DnsSdTxtRecord;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/nsd/DnsSdTxtRecord;->get(Ljava/lang/String;)Ljava/lang/String;
+Landroid/net/nsd/DnsSdTxtRecord;->getKey(I)Ljava/lang/String;
+Landroid/net/nsd/DnsSdTxtRecord;->getRawData()[B
+Landroid/net/nsd/DnsSdTxtRecord;->getValue(I)[B
+Landroid/net/nsd/DnsSdTxtRecord;->getValue(Ljava/lang/String;)[B
+Landroid/net/nsd/DnsSdTxtRecord;->getValueAsString(I)Ljava/lang/String;
+Landroid/net/nsd/DnsSdTxtRecord;->insert([B[BI)V
+Landroid/net/nsd/DnsSdTxtRecord;->keyCount()I
+Landroid/net/nsd/DnsSdTxtRecord;->mData:[B
+Landroid/net/nsd/DnsSdTxtRecord;->mSeperator:B
+Landroid/net/nsd/DnsSdTxtRecord;->remove(Ljava/lang/String;)I
+Landroid/net/nsd/DnsSdTxtRecord;->set(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/net/nsd/DnsSdTxtRecord;->size()I
+Landroid/net/nsd/INsdManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/net/nsd/INsdManager$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
+Landroid/net/nsd/INsdManager$Stub$Proxy;->getMessenger()Landroid/os/Messenger;
+Landroid/net/nsd/INsdManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/net/nsd/INsdManager$Stub$Proxy;->setEnabled(Z)V
+Landroid/net/nsd/INsdManager$Stub;-><init>()V
+Landroid/net/nsd/INsdManager$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/net/nsd/INsdManager$Stub;->TRANSACTION_getMessenger:I
+Landroid/net/nsd/INsdManager$Stub;->TRANSACTION_setEnabled:I
+Landroid/net/nsd/INsdManager;->setEnabled(Z)V
+Landroid/net/nsd/NsdManager;-><init>(Landroid/content/Context;Landroid/net/nsd/INsdManager;)V
+Landroid/net/nsd/NsdManager;->BASE:I
+Landroid/net/nsd/NsdManager;->checkListener(Ljava/lang/Object;)V
+Landroid/net/nsd/NsdManager;->checkProtocol(I)V
+Landroid/net/nsd/NsdManager;->checkServiceInfo(Landroid/net/nsd/NsdServiceInfo;)V
+Landroid/net/nsd/NsdManager;->DBG:Z
+Landroid/net/nsd/NsdManager;->DISABLE:I
+Landroid/net/nsd/NsdManager;->disconnect()V
+Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES:I
+Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES_FAILED:I
+Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES_STARTED:I
+Landroid/net/nsd/NsdManager;->ENABLE:I
+Landroid/net/nsd/NsdManager;->EVENT_NAMES:Landroid/util/SparseArray;
+Landroid/net/nsd/NsdManager;->fatal(Ljava/lang/String;)V
+Landroid/net/nsd/NsdManager;->FIRST_LISTENER_KEY:I
+Landroid/net/nsd/NsdManager;->getListenerKey(Ljava/lang/Object;)I
+Landroid/net/nsd/NsdManager;->getMessenger()Landroid/os/Messenger;
+Landroid/net/nsd/NsdManager;->getNsdServiceInfoType(Landroid/net/nsd/NsdServiceInfo;)Ljava/lang/String;
+Landroid/net/nsd/NsdManager;->init()V
+Landroid/net/nsd/NsdManager;->mAsyncChannel:Lcom/android/internal/util/AsyncChannel;
+Landroid/net/nsd/NsdManager;->mConnected:Ljava/util/concurrent/CountDownLatch;
+Landroid/net/nsd/NsdManager;->mContext:Landroid/content/Context;
+Landroid/net/nsd/NsdManager;->mHandler:Landroid/net/nsd/NsdManager$ServiceHandler;
+Landroid/net/nsd/NsdManager;->mListenerKey:I
+Landroid/net/nsd/NsdManager;->mListenerMap:Landroid/util/SparseArray;
+Landroid/net/nsd/NsdManager;->mMapLock:Ljava/lang/Object;
+Landroid/net/nsd/NsdManager;->mService:Landroid/net/nsd/INsdManager;
+Landroid/net/nsd/NsdManager;->mServiceMap:Landroid/util/SparseArray;
+Landroid/net/nsd/NsdManager;->nameOf(I)Ljava/lang/String;
+Landroid/net/nsd/NsdManager;->NATIVE_DAEMON_EVENT:I
+Landroid/net/nsd/NsdManager;->nextListenerKey()I
+Landroid/net/nsd/NsdManager;->putListener(Ljava/lang/Object;Landroid/net/nsd/NsdServiceInfo;)I
+Landroid/net/nsd/NsdManager;->REGISTER_SERVICE:I
+Landroid/net/nsd/NsdManager;->REGISTER_SERVICE_FAILED:I
+Landroid/net/nsd/NsdManager;->REGISTER_SERVICE_SUCCEEDED:I
+Landroid/net/nsd/NsdManager;->removeListener(I)V
+Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE:I
+Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE_FAILED:I
+Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE_SUCCEEDED:I
+Landroid/net/nsd/NsdManager;->SERVICE_FOUND:I
+Landroid/net/nsd/NsdManager;->SERVICE_LOST:I
+Landroid/net/nsd/NsdManager;->setEnabled(Z)V
+Landroid/net/nsd/NsdManager;->STOP_DISCOVERY:I
+Landroid/net/nsd/NsdManager;->STOP_DISCOVERY_FAILED:I
+Landroid/net/nsd/NsdManager;->STOP_DISCOVERY_SUCCEEDED:I
+Landroid/net/nsd/NsdManager;->TAG:Ljava/lang/String;
+Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE:I
+Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE_FAILED:I
+Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE_SUCCEEDED:I
+Landroid/net/nsd/NsdServiceInfo;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Landroid/net/nsd/NsdServiceInfo;->getTxtRecord()[B
+Landroid/net/nsd/NsdServiceInfo;->getTxtRecordSize()I
+Landroid/net/nsd/NsdServiceInfo;->mHost:Ljava/net/InetAddress;
+Landroid/net/nsd/NsdServiceInfo;->mPort:I
+Landroid/net/nsd/NsdServiceInfo;->mServiceName:Ljava/lang/String;
+Landroid/net/nsd/NsdServiceInfo;->mServiceType:Ljava/lang/String;
+Landroid/net/nsd/NsdServiceInfo;->mTxtRecord:Landroid/util/ArrayMap;
+Landroid/net/nsd/NsdServiceInfo;->setTxtRecords(Ljava/lang/String;)V
+Landroid/net/nsd/NsdServiceInfo;->TAG:Ljava/lang/String;
 Landroid/net/ProxyInfo;-><init>(Landroid/net/ProxyInfo;)V
 Landroid/net/ProxyInfo;-><init>(Landroid/net/Uri;)V
 Landroid/net/ProxyInfo;-><init>(Landroid/net/Uri;I)V
diff --git a/Tethering/apex/hiddenapi/hiddenapi-max-target-r-loprio.txt b/Tethering/apex/hiddenapi/hiddenapi-max-target-r-loprio.txt
new file mode 100644
index 0000000..211b847
--- /dev/null
+++ b/Tethering/apex/hiddenapi/hiddenapi-max-target-r-loprio.txt
@@ -0,0 +1 @@
+Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
diff --git a/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp b/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp
deleted file mode 100644
index f9e4824..0000000
--- a/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-#include <arpa/inet.h>
-#include <jni.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/netlink.h>
-#include <linux/pkt_cls.h>
-#include <linux/pkt_sched.h>
-#include <linux/rtnetlink.h>
-#include <nativehelper/JNIHelp.h>
-#include <net/if.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/utsname.h>
-
-// TODO: use unique_fd.
-#define BPF_FD_JUST_USE_INT
-#include "BpfSyscallWrappers.h"
-#include "bpf_tethering.h"
-#include "nativehelper/scoped_utf_chars.h"
-
-// The maximum length of TCA_BPF_NAME. Sync from net/sched/cls_bpf.c.
-#define CLS_BPF_NAME_LEN 256
-
-// Classifier name. See cls_bpf_ops in net/sched/cls_bpf.c.
-#define CLS_BPF_KIND_NAME "bpf"
-
-namespace android {
-// Sync from system/netd/server/NetlinkCommands.h
-const uint16_t NETLINK_REQUEST_FLAGS = NLM_F_REQUEST | NLM_F_ACK;
-const sockaddr_nl KERNEL_NLADDR = {AF_NETLINK, 0, 0, 0};
-
-static void throwIOException(JNIEnv *env, const char* msg, int error) {
-    jniThrowExceptionFmt(env, "java/io/IOException", "%s: %s", msg, strerror(error));
-}
-
-// TODO: move to frameworks/libs/net/common/native for sharing with
-// system/netd/server/OffloadUtils.{c, h}.
-static void sendAndProcessNetlinkResponse(JNIEnv* env, const void* req, int len) {
-    int fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);  // TODO: use unique_fd
-    if (fd == -1) {
-        throwIOException(env, "socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)", errno);
-        return;
-    }
-
-    static constexpr int on = 1;
-    if (setsockopt(fd, SOL_NETLINK, NETLINK_CAP_ACK, &on, sizeof(on))) {
-        throwIOException(env, "setsockopt(fd, SOL_NETLINK, NETLINK_CAP_ACK, 1)", errno);
-        close(fd);
-        return;
-    }
-
-    // this is needed to get valid strace netlink parsing, it allocates the pid
-    if (bind(fd, (const struct sockaddr*)&KERNEL_NLADDR, sizeof(KERNEL_NLADDR))) {
-        throwIOException(env, "bind(fd, {AF_NETLINK, 0, 0})", errno);
-        close(fd);
-        return;
-    }
-
-    // we do not want to receive messages from anyone besides the kernel
-    if (connect(fd, (const struct sockaddr*)&KERNEL_NLADDR, sizeof(KERNEL_NLADDR))) {
-        throwIOException(env, "connect(fd, {AF_NETLINK, 0, 0})", errno);
-        close(fd);
-        return;
-    }
-
-    int rv = send(fd, req, len, 0);
-
-    if (rv == -1) {
-        throwIOException(env, "send(fd, req, len, 0)", errno);
-        close(fd);
-        return;
-    }
-
-    if (rv != len) {
-        throwIOException(env, "send(fd, req, len, 0)", EMSGSIZE);
-        close(fd);
-        return;
-    }
-
-    struct {
-        nlmsghdr h;
-        nlmsgerr e;
-        char buf[256];
-    } resp = {};
-
-    rv = recv(fd, &resp, sizeof(resp), MSG_TRUNC);
-
-    if (rv == -1) {
-        throwIOException(env, "recv() failed", errno);
-        close(fd);
-        return;
-    }
-
-    if (rv < (int)NLMSG_SPACE(sizeof(struct nlmsgerr))) {
-        jniThrowExceptionFmt(env, "java/io/IOException", "recv() returned short packet: %d", rv);
-        close(fd);
-        return;
-    }
-
-    if (resp.h.nlmsg_len != (unsigned)rv) {
-        jniThrowExceptionFmt(env, "java/io/IOException",
-                             "recv() returned invalid header length: %d != %d", resp.h.nlmsg_len,
-                             rv);
-        close(fd);
-        return;
-    }
-
-    if (resp.h.nlmsg_type != NLMSG_ERROR) {
-        jniThrowExceptionFmt(env, "java/io/IOException",
-                             "recv() did not return NLMSG_ERROR message: %d", resp.h.nlmsg_type);
-        close(fd);
-        return;
-    }
-
-    if (resp.e.error) {  // returns 0 on success
-        throwIOException(env, "NLMSG_ERROR message return error", -resp.e.error);
-    }
-    close(fd);
-    return;
-}
-
-static int hardwareAddressType(const char* interface) {
-    int fd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-    if (fd < 0) return -errno;
-
-    struct ifreq ifr = {};
-    // We use strncpy() instead of strlcpy() since kernel has to be able
-    // to handle non-zero terminated junk passed in by userspace anyway,
-    // and this way too long interface names (more than IFNAMSIZ-1 = 15
-    // characters plus terminating NULL) will not get truncated to 15
-    // characters and zero-terminated and thus potentially erroneously
-    // match a truncated interface if one were to exist.
-    strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
-
-    int rv;
-    if (ioctl(fd, SIOCGIFHWADDR, &ifr, sizeof(ifr))) {
-        rv = -errno;
-    } else {
-        rv = ifr.ifr_hwaddr.sa_family;
-    }
-
-    close(fd);
-    return rv;
-}
-
-// -----------------------------------------------------------------------------
-// TODO - just use BpfUtils.h once that is available in sc-mainline-prod and has kernelVersion()
-//
-// In the mean time copying verbatim from:
-//   system/bpf/libbpf_android/include/bpf/BpfUtils.h
-// and
-//   system/bpf/libbpf_android/BpfUtils.cpp
-
-#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
-
-static unsigned kernelVersion() {
-    struct utsname buf;
-    int ret = uname(&buf);
-    if (ret) return 0;
-
-    unsigned kver_major;
-    unsigned kver_minor;
-    unsigned kver_sub;
-    char discard;
-    ret = sscanf(buf.release, "%u.%u.%u%c", &kver_major, &kver_minor, &kver_sub, &discard);
-    // Check the device kernel version
-    if (ret < 3) return 0;
-
-    return KVER(kver_major, kver_minor, kver_sub);
-}
-
-static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) {
-    return kernelVersion() >= KVER(major, minor, sub);
-}
-// -----------------------------------------------------------------------------
-
-static jboolean com_android_networkstack_tethering_BpfUtils_isEthernet(JNIEnv* env, jobject clazz,
-                                                                       jstring iface) {
-    ScopedUtfChars interface(env, iface);
-
-    int rv = hardwareAddressType(interface.c_str());
-    if (rv < 0) {
-        jniThrowExceptionFmt(env, "java/io/IOException",
-                             "Get hardware address type of interface %s failed: %s",
-                             interface.c_str(), strerror(-rv));
-        return false;
-    }
-
-    // Backwards compatibility with pre-GKI kernels that use various custom
-    // ARPHRD_* for their cellular interface
-    switch (rv) {
-        // ARPHRD_PUREIP on at least some Mediatek Android kernels
-        // example: wembley with 4.19 kernel
-        case 520:
-        // in Linux 4.14+ rmnet support was upstreamed and ARHRD_RAWIP became 519,
-        // but it is 530 on at least some Qualcomm Android 4.9 kernels with rmnet
-        // example: Pixel 3 family
-        case 530:
-            // >5.4 kernels are GKI2.0 and thus upstream compatible, however 5.10
-            // shipped with Android S, so (for safety) let's limit ourselves to
-            // >5.10, ie. 5.11+ as a guarantee we're on Android T+ and thus no
-            // longer need this non-upstream compatibility logic
-            static bool is_pre_5_11_kernel = !isAtLeastKernelVersion(5, 11, 0);
-            if (is_pre_5_11_kernel) return false;
-    }
-
-    switch (rv) {
-        case ARPHRD_ETHER:
-            return true;
-        case ARPHRD_NONE:
-        case ARPHRD_PPP:
-        case ARPHRD_RAWIP:
-            return false;
-        default:
-            jniThrowExceptionFmt(env, "java/io/IOException",
-                                 "Unknown hardware address type %d on interface %s", rv,
-                                 interface.c_str());
-            return false;
-    }
-}
-
-// tc filter add dev .. in/egress prio 1 protocol ipv6/ip bpf object-pinned /sys/fs/bpf/...
-// direct-action
-static void com_android_networkstack_tethering_BpfUtils_tcFilterAddDevBpf(
-        JNIEnv* env, jobject clazz, jint ifIndex, jboolean ingress, jshort prio, jshort proto,
-        jstring bpfProgPath) {
-    ScopedUtfChars pathname(env, bpfProgPath);
-
-    const int bpfFd = bpf::retrieveProgram(pathname.c_str());
-    if (bpfFd == -1) {
-        throwIOException(env, "retrieveProgram failed", errno);
-        return;
-    }
-
-    struct {
-        nlmsghdr n;
-        tcmsg t;
-        struct {
-            nlattr attr;
-            // The maximum classifier name length is defined in
-            // tcf_proto_ops in include/net/sch_generic.h.
-            char str[NLMSG_ALIGN(sizeof(CLS_BPF_KIND_NAME))];
-        } kind;
-        struct {
-            nlattr attr;
-            struct {
-                nlattr attr;
-                __u32 u32;
-            } fd;
-            struct {
-                nlattr attr;
-                char str[NLMSG_ALIGN(CLS_BPF_NAME_LEN)];
-            } name;
-            struct {
-                nlattr attr;
-                __u32 u32;
-            } flags;
-        } options;
-    } req = {
-            .n =
-                    {
-                            .nlmsg_len = sizeof(req),
-                            .nlmsg_type = RTM_NEWTFILTER,
-                            .nlmsg_flags = NETLINK_REQUEST_FLAGS | NLM_F_EXCL | NLM_F_CREATE,
-                    },
-            .t =
-                    {
-                            .tcm_family = AF_UNSPEC,
-                            .tcm_ifindex = ifIndex,
-                            .tcm_handle = TC_H_UNSPEC,
-                            .tcm_parent = TC_H_MAKE(TC_H_CLSACT,
-                                                    ingress ? TC_H_MIN_INGRESS : TC_H_MIN_EGRESS),
-                            .tcm_info = static_cast<__u32>((static_cast<uint16_t>(prio) << 16) |
-                                                           htons(static_cast<uint16_t>(proto))),
-                    },
-            .kind =
-                    {
-                            .attr =
-                                    {
-                                            .nla_len = sizeof(req.kind),
-                                            .nla_type = TCA_KIND,
-                                    },
-                            .str = CLS_BPF_KIND_NAME,
-                    },
-            .options =
-                    {
-                            .attr =
-                                    {
-                                            .nla_len = sizeof(req.options),
-                                            .nla_type = NLA_F_NESTED | TCA_OPTIONS,
-                                    },
-                            .fd =
-                                    {
-                                            .attr =
-                                                    {
-                                                            .nla_len = sizeof(req.options.fd),
-                                                            .nla_type = TCA_BPF_FD,
-                                                    },
-                                            .u32 = static_cast<__u32>(bpfFd),
-                                    },
-                            .name =
-                                    {
-                                            .attr =
-                                                    {
-                                                            .nla_len = sizeof(req.options.name),
-                                                            .nla_type = TCA_BPF_NAME,
-                                                    },
-                                            // Visible via 'tc filter show', but
-                                            // is overwritten by strncpy below
-                                            .str = "placeholder",
-                                    },
-                            .flags =
-                                    {
-                                            .attr =
-                                                    {
-                                                            .nla_len = sizeof(req.options.flags),
-                                                            .nla_type = TCA_BPF_FLAGS,
-                                                    },
-                                            .u32 = TCA_BPF_FLAG_ACT_DIRECT,
-                                    },
-                    },
-    };
-
-    snprintf(req.options.name.str, sizeof(req.options.name.str), "%s:[*fsobj]",
-            basename(pathname.c_str()));
-
-    // The exception may be thrown from sendAndProcessNetlinkResponse. Close the file descriptor of
-    // BPF program before returning the function in any case.
-    sendAndProcessNetlinkResponse(env, &req, sizeof(req));
-    close(bpfFd);
-}
-
-// tc filter del dev .. in/egress prio .. protocol ..
-static void com_android_networkstack_tethering_BpfUtils_tcFilterDelDev(JNIEnv* env, jobject clazz,
-                                                                       jint ifIndex,
-                                                                       jboolean ingress,
-                                                                       jshort prio, jshort proto) {
-    const struct {
-        nlmsghdr n;
-        tcmsg t;
-    } req = {
-            .n =
-                    {
-                            .nlmsg_len = sizeof(req),
-                            .nlmsg_type = RTM_DELTFILTER,
-                            .nlmsg_flags = NETLINK_REQUEST_FLAGS,
-                    },
-            .t =
-                    {
-                            .tcm_family = AF_UNSPEC,
-                            .tcm_ifindex = ifIndex,
-                            .tcm_handle = TC_H_UNSPEC,
-                            .tcm_parent = TC_H_MAKE(TC_H_CLSACT,
-                                                    ingress ? TC_H_MIN_INGRESS : TC_H_MIN_EGRESS),
-                            .tcm_info = static_cast<__u32>((static_cast<uint16_t>(prio) << 16) |
-                                                           htons(static_cast<uint16_t>(proto))),
-                    },
-    };
-
-    sendAndProcessNetlinkResponse(env, &req, sizeof(req));
-}
-
-/*
- * JNI registration.
- */
-static const JNINativeMethod gMethods[] = {
-        /* name, signature, funcPtr */
-        {"isEthernet", "(Ljava/lang/String;)Z",
-         (void*)com_android_networkstack_tethering_BpfUtils_isEthernet},
-        {"tcFilterAddDevBpf", "(IZSSLjava/lang/String;)V",
-         (void*)com_android_networkstack_tethering_BpfUtils_tcFilterAddDevBpf},
-        {"tcFilterDelDev", "(IZSS)V",
-         (void*)com_android_networkstack_tethering_BpfUtils_tcFilterDelDev},
-};
-
-int register_com_android_networkstack_tethering_BpfUtils(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "com/android/networkstack/tethering/BpfUtils", gMethods,
-                                    NELEM(gMethods));
-}
-
-};  // namespace android
diff --git a/Tethering/jni/onload.cpp b/Tethering/jni/onload.cpp
index 72895f1..ed80128 100644
--- a/Tethering/jni/onload.cpp
+++ b/Tethering/jni/onload.cpp
@@ -23,6 +23,7 @@
 namespace android {
 
 int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
+int register_com_android_net_module_util_TcUtils(JNIEnv* env, char const* class_name);
 int register_com_android_networkstack_tethering_BpfCoordinator(JNIEnv* env);
 int register_com_android_networkstack_tethering_BpfUtils(JNIEnv* env);
 int register_com_android_networkstack_tethering_util_TetheringUtils(JNIEnv* env);
@@ -39,9 +40,10 @@
     if (register_com_android_net_module_util_BpfMap(env,
             "com/android/networkstack/tethering/util/BpfMap") < 0) return JNI_ERR;
 
-    if (register_com_android_networkstack_tethering_BpfCoordinator(env) < 0) return JNI_ERR;
+    if (register_com_android_net_module_util_TcUtils(env,
+            "com/android/networkstack/tethering/util/TcUtils") < 0) return JNI_ERR;
 
-    if (register_com_android_networkstack_tethering_BpfUtils(env) < 0) return JNI_ERR;
+    if (register_com_android_networkstack_tethering_BpfCoordinator(env) < 0) return JNI_ERR;
 
     return JNI_VERSION_1_6;
 }
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfUtils.java b/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
index 4f095cf..ad410eb 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
@@ -24,6 +24,8 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.net.module.util.TcUtils;
+
 import java.io.IOException;
 
 /**
@@ -82,7 +84,7 @@
 
         boolean ether;
         try {
-            ether = isEthernet(iface);
+            ether = TcUtils.isEthernet(iface);
         } catch (IOException e) {
             throw new IOException("isEthernet(" + params.index + "[" + iface + "]) failure: " + e);
         }
@@ -90,7 +92,7 @@
         try {
             // tc filter add dev .. ingress prio 1 protocol ipv6 bpf object-pinned /sys/fs/bpf/...
             // direct-action
-            tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6,
+            TcUtils.tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6,
                     makeProgPath(downstream, 6, ether));
         } catch (IOException e) {
             throw new IOException("tc filter add dev (" + params.index + "[" + iface
@@ -100,7 +102,7 @@
         try {
             // tc filter add dev .. ingress prio 2 protocol ip bpf object-pinned /sys/fs/bpf/...
             // direct-action
-            tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP,
+            TcUtils.tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP,
                     makeProgPath(downstream, 4, ether));
         } catch (IOException e) {
             throw new IOException("tc filter add dev (" + params.index + "[" + iface
@@ -121,7 +123,7 @@
 
         try {
             // tc filter del dev .. ingress prio 1 protocol ipv6
-            tcFilterDelDev(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6);
+            TcUtils.tcFilterDelDev(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6);
         } catch (IOException e) {
             throw new IOException("tc filter del dev (" + params.index + "[" + iface
                     + "]) ingress prio PRIO_TETHER6 protocol ipv6 failure: " + e);
@@ -129,18 +131,10 @@
 
         try {
             // tc filter del dev .. ingress prio 2 protocol ip
-            tcFilterDelDev(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP);
+            TcUtils.tcFilterDelDev(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP);
         } catch (IOException e) {
             throw new IOException("tc filter del dev (" + params.index + "[" + iface
                     + "]) ingress prio PRIO_TETHER4 protocol ip failure: " + e);
         }
     }
-
-    private static native boolean isEthernet(String iface) throws IOException;
-
-    private static native void tcFilterAddDevBpf(int ifIndex, boolean ingress, short prio,
-            short proto, String bpfProgPath) throws IOException;
-
-    private static native void tcFilterDelDev(int ifIndex, boolean ingress, short prio,
-            short proto) throws IOException;
 }
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
new file mode 100644
index 0000000..79bb128
--- /dev/null
+++ b/framework-t/Android.bp
@@ -0,0 +1,60 @@
+//
+// Copyright (C) 2021 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_sdk_library {
+    name: "framework-connectivity-tiramisu",
+    sdk_version: "module_current",
+    min_sdk_version: "Tiramisu",
+    defaults: ["framework-module-defaults"],
+    srcs: [
+        ":framework-connectivity-tiramisu-updatable-sources",
+    ],
+    libs: [
+        "unsupportedappusage",
+        "app-compat-annotations",
+    ],
+    permitted_packages: [
+        "android.net",
+        "android.net.nsd",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+    impl_library_visibility: [
+        "//packages/modules/Connectivity/Tethering/apex",
+        // In preparation for future move
+        "//packages/modules/Connectivity/apex",
+        "//packages/modules/Connectivity/service-t",
+        "//frameworks/base",
+
+        // Tests using hidden APIs
+        "//cts/tests/netlegacy22.api",
+        "//external/sl4a:__subpackages__",
+        "//frameworks/libs/net/common/testutils",
+        "//frameworks/libs/net/common/tests:__subpackages__",
+        "//frameworks/opt/telephony/tests/telephonytests",
+        "//packages/modules/CaptivePortalLogin/tests",
+        "//packages/modules/Connectivity/Tethering/tests:__subpackages__",
+        "//packages/modules/Connectivity/tests:__subpackages__",
+        "//packages/modules/NetworkStack/tests:__subpackages__",
+        "//packages/modules/Wifi/service/tests/wifitests",
+    ],
+}
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
new file mode 100644
index 0000000..0443456
--- /dev/null
+++ b/framework-t/api/current.txt
@@ -0,0 +1,60 @@
+// Signature format: 2.0
+package android.net.nsd {
+
+  public final class NsdManager {
+    method public void discoverServices(String, int, android.net.nsd.NsdManager.DiscoveryListener);
+    method public void registerService(android.net.nsd.NsdServiceInfo, int, android.net.nsd.NsdManager.RegistrationListener);
+    method public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener);
+    method public void stopServiceDiscovery(android.net.nsd.NsdManager.DiscoveryListener);
+    method public void unregisterService(android.net.nsd.NsdManager.RegistrationListener);
+    field public static final String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
+    field public static final String EXTRA_NSD_STATE = "nsd_state";
+    field public static final int FAILURE_ALREADY_ACTIVE = 3; // 0x3
+    field public static final int FAILURE_INTERNAL_ERROR = 0; // 0x0
+    field public static final int FAILURE_MAX_LIMIT = 4; // 0x4
+    field public static final int NSD_STATE_DISABLED = 1; // 0x1
+    field public static final int NSD_STATE_ENABLED = 2; // 0x2
+    field public static final int PROTOCOL_DNS_SD = 1; // 0x1
+  }
+
+  public static interface NsdManager.DiscoveryListener {
+    method public void onDiscoveryStarted(String);
+    method public void onDiscoveryStopped(String);
+    method public void onServiceFound(android.net.nsd.NsdServiceInfo);
+    method public void onServiceLost(android.net.nsd.NsdServiceInfo);
+    method public void onStartDiscoveryFailed(String, int);
+    method public void onStopDiscoveryFailed(String, int);
+  }
+
+  public static interface NsdManager.RegistrationListener {
+    method public void onRegistrationFailed(android.net.nsd.NsdServiceInfo, int);
+    method public void onServiceRegistered(android.net.nsd.NsdServiceInfo);
+    method public void onServiceUnregistered(android.net.nsd.NsdServiceInfo);
+    method public void onUnregistrationFailed(android.net.nsd.NsdServiceInfo, int);
+  }
+
+  public static interface NsdManager.ResolveListener {
+    method public void onResolveFailed(android.net.nsd.NsdServiceInfo, int);
+    method public void onServiceResolved(android.net.nsd.NsdServiceInfo);
+  }
+
+  public final class NsdServiceInfo implements android.os.Parcelable {
+    ctor public NsdServiceInfo();
+    method public int describeContents();
+    method public java.util.Map<java.lang.String,byte[]> getAttributes();
+    method public java.net.InetAddress getHost();
+    method public int getPort();
+    method public String getServiceName();
+    method public String getServiceType();
+    method public void removeAttribute(String);
+    method public void setAttribute(String, String);
+    method public void setHost(java.net.InetAddress);
+    method public void setPort(int);
+    method public void setServiceName(String);
+    method public void setServiceType(String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.nsd.NsdServiceInfo> CREATOR;
+  }
+
+}
+
diff --git a/framework-t/api/module-lib-current.txt b/framework-t/api/module-lib-current.txt
new file mode 100644
index 0000000..81d89c6
--- /dev/null
+++ b/framework-t/api/module-lib-current.txt
@@ -0,0 +1,9 @@
+// Signature format: 2.0
+package android.net {
+
+  public final class ConnectivityFrameworkInitializerTiramisu {
+    method public static void registerServiceWrappers();
+  }
+
+}
+
diff --git a/framework-t/api/module-lib-removed.txt b/framework-t/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/framework-t/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/framework-t/api/removed.txt b/framework-t/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/framework-t/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/framework-t/api/system-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/framework-t/api/system-removed.txt b/framework-t/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/framework-t/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/framework/Android.bp b/framework/Android.bp
index 028701a..de505c7 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -94,6 +94,7 @@
         // In preparation for future move
         "//packages/modules/Connectivity/apex",
         "//packages/modules/Connectivity/service",
+        "//packages/modules/Connectivity/service-t",
         "//frameworks/base/packages/Connectivity/service",
         "//frameworks/base",
 
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index eab798a..415b3e5 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -51,6 +51,7 @@
     field public static final int FIREWALL_CHAIN_STANDBY = 2; // 0x2
     field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0
     field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1
+    field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK = 2; // 0x2
   }
 
   public static class ConnectivityManager.NetworkCallback {
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index a94db27..009890c 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -1120,7 +1120,8 @@
     }
 
     /**
-     * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}.
+     * Preference for {@link ProfileNetworkPreference#setPreference(int)}.
+     * {@see #setProfileNetworkPreferences(UserHandle, List, Executor, Runnable)}
      * Specify that the traffic for this user should by follow the default rules.
      * @hide
      */
@@ -1128,7 +1129,8 @@
     public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0;
 
     /**
-     * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}.
+     * Preference for {@link ProfileNetworkPreference#setPreference(int)}.
+     * {@see #setProfileNetworkPreferences(UserHandle, List, Executor, Runnable)}
      * Specify that the traffic for this user should by default go on a network with
      * {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE}, and on the system default network
      * if no such network is available.
@@ -1137,11 +1139,23 @@
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1;
 
+    /**
+     * Preference for {@link ProfileNetworkPreference#setPreference(int)}.
+     * {@see #setProfileNetworkPreferences(UserHandle, List, Executor, Runnable)}
+     * Specify that the traffic for this user should by default go on a network with
+     * {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE} and if no such network is available
+     * should not go on the system default network
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK = 2;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
             PROFILE_NETWORK_PREFERENCE_DEFAULT,
-            PROFILE_NETWORK_PREFERENCE_ENTERPRISE
+            PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+            PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK
     })
     public @interface ProfileNetworkPreferencePolicy {
     }
diff --git a/framework/src/android/net/ProfileNetworkPreference.java b/framework/src/android/net/ProfileNetworkPreference.java
index d580209..2ce1698 100644
--- a/framework/src/android/net/ProfileNetworkPreference.java
+++ b/framework/src/android/net/ProfileNetworkPreference.java
@@ -63,7 +63,7 @@
 
     @Override
     public int hashCode() {
-        return (mPreference);
+        return mPreference;
     }
 
     /**
@@ -91,6 +91,7 @@
             mPreference = preference;
             return this;
         }
+
         /**
          * Returns an instance of {@link ProfileNetworkPreference} created from the
          * fields set on this builder.
diff --git a/service-t/Android.bp b/service-t/Android.bp
new file mode 100644
index 0000000..48c74c6
--- /dev/null
+++ b/service-t/Android.bp
@@ -0,0 +1,56 @@
+//
+// Copyright (C) 2021 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// This builds T+ services depending on framework-connectivity-tiramisu
+// hidden symbols separately from the S+ services, to ensure that S+
+// services cannot accidentally depend on T+ hidden symbols from
+// framework-connectivity-tiramisu.
+java_library {
+    name: "service-connectivity-tiramisu-pre-jarjar",
+    sdk_version: "system_server_current",
+    // TODO(b/210962470): Bump this to at least S, and then T.
+    min_sdk_version: "30",
+    srcs: [
+        "src/**/*.java",
+        // TODO: This is necessary just for LocalLog, remove after removing NativeDaemonConnector.
+        ":framework-connectivity-shared-srcs",
+        ":services.connectivity-tiramisu-updatable-sources",
+    ],
+    libs: [
+        "framework-annotations-lib",
+        "framework-connectivity.impl",
+        "framework-connectivity-tiramisu.impl",
+        "service-connectivity-pre-jarjar",
+        "unsupportedappusage",
+    ],
+    static_libs: [
+        "modules-utils-build",
+        "modules-utils-statemachine",
+        "net-utils-framework-common",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+    visibility: [
+        "//packages/modules/Connectivity/service",
+        "//packages/modules/Connectivity/tests:__subpackages__",
+    ],
+}
diff --git a/service/src/com/android/server/ConnectivityServiceInitializer.java b/service-t/src/com/android/server/ConnectivityServiceInitializer.java
similarity index 68%
rename from service/src/com/android/server/ConnectivityServiceInitializer.java
rename to service-t/src/com/android/server/ConnectivityServiceInitializer.java
index b1a56ae..23d8bdc 100644
--- a/service/src/com/android/server/ConnectivityServiceInitializer.java
+++ b/service-t/src/com/android/server/ConnectivityServiceInitializer.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.util.Log;
 
+import com.android.modules.utils.build.SdkLevel;
+
 /**
  * Connectivity service initializer for core networking. This is called by system server to create
  * a new instance of ConnectivityService.
@@ -26,12 +28,14 @@
 public final class ConnectivityServiceInitializer extends SystemService {
     private static final String TAG = ConnectivityServiceInitializer.class.getSimpleName();
     private final ConnectivityService mConnectivity;
+    private final NsdService mNsdService;
 
     public ConnectivityServiceInitializer(Context context) {
         super(context);
         // Load JNI libraries used by ConnectivityService and its dependencies
         System.loadLibrary("service-connectivity");
         mConnectivity = new ConnectivityService(context);
+        mNsdService = createNsdService(context);
     }
 
     @Override
@@ -39,5 +43,20 @@
         Log.i(TAG, "Registering " + Context.CONNECTIVITY_SERVICE);
         publishBinderService(Context.CONNECTIVITY_SERVICE, mConnectivity,
                 /* allowIsolated= */ false);
+        if (mNsdService != null) {
+            Log.i(TAG, "Registering " + Context.NSD_SERVICE);
+            publishBinderService(Context.NSD_SERVICE, mNsdService, /* allowIsolated= */ false);
+        }
+    }
+
+    /** Return NsdService instance or null if current SDK is lower than T */
+    private NsdService createNsdService(final Context context) {
+        if (!SdkLevel.isAtLeastT()) return null;
+        try {
+            return NsdService.create(context);
+        } catch (InterruptedException e) {
+            Log.d(TAG, "Unable to get NSD service", e);
+            return null;
+        }
     }
 }
diff --git a/service/Android.bp b/service/Android.bp
index 1ec7daa..76f9153 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -108,6 +108,10 @@
         "com.android.tethering",
     ],
     lint: { strict_updatability_linting: true },
+    visibility: [
+        "//packages/modules/Connectivity/service-t",
+        "//packages/modules/Connectivity/tests:__subpackages__",
+    ],
 }
 
 java_library {
@@ -132,8 +136,13 @@
     sdk_version: "system_server_current",
     min_sdk_version: "30",
     installable: true,
+    // This library combines system server jars that have access to different bootclasspath jars.
+    // Lower SDK service jars must not depend on higher SDK jars as that would let them
+    // transitively depend on the wrong bootclasspath jars. Sources also cannot be added here as
+    // they would transitively depend on bootclasspath jars that may not be available.
     static_libs: [
         "service-connectivity-pre-jarjar",
+        "service-connectivity-tiramisu-pre-jarjar",
     ],
     jarjar_rules: "jarjar-rules.txt",
     apex_available: [
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index bb0b126..d625d1b 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -5674,7 +5674,7 @@
         mPermissionMonitor.onUserRemoved(user);
         // If there was a network preference for this user, remove it.
         handleSetProfileNetworkPreference(
-                List.of(new ProfileNetworkPreferenceList.Preference(user, null)),
+                List.of(new ProfileNetworkPreferenceList.Preference(user, null, true)),
                 null /* listener */);
         if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
@@ -10139,12 +10139,16 @@
 
         final List<ProfileNetworkPreferenceList.Preference> preferenceList =
                 new ArrayList<ProfileNetworkPreferenceList.Preference>();
+        boolean allowFallback = true;
         for (final ProfileNetworkPreference preference : preferences) {
             final NetworkCapabilities nc;
             switch (preference.getPreference()) {
                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT:
                     nc = null;
                     break;
+                case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK:
+                    allowFallback = false;
+                    // continue to process the enterprise preference.
                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE:
                     final UidRange uids = UidRange.createForUser(profile);
                     nc = createDefaultNetworkCapabilitiesForUidRange(uids);
@@ -10155,8 +10159,8 @@
                     throw new IllegalArgumentException(
                             "Invalid preference in setProfileNetworkPreferences");
             }
-            preferenceList.add(
-                    new ProfileNetworkPreferenceList.Preference(profile, nc));
+            preferenceList.add(new ProfileNetworkPreferenceList.Preference(
+                    profile, nc, allowFallback));
         }
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_PROFILE_NETWORK_PREFERENCE,
                 new Pair<>(preferenceList, listener)));
@@ -10172,17 +10176,17 @@
             @NonNull final ProfileNetworkPreferenceList prefs) {
         final ArraySet<NetworkRequestInfo> result = new ArraySet<>();
         for (final ProfileNetworkPreferenceList.Preference pref : prefs.preferences) {
-            // The NRI for a user should be comprised of two layers:
-            // - The request for the capabilities
-            // - The request for the default network, for fallback. Create an image of it to
-            //   have the correct UIDs in it (also a request can only be part of one NRI, because
-            //   of lookups in 1:1 associations like mNetworkRequests).
-            // Note that denying a fallback can be implemented simply by not adding the second
-            // request.
+            // The NRI for a user should contain the request for capabilities.
+            // If fallback to default network is needed then NRI should include
+            // the request for the default network. Create an image of it to
+            // have the correct UIDs in it (also a request can only be part of one NRI, because
+            // of lookups in 1:1 associations like mNetworkRequests).
             final ArrayList<NetworkRequest> nrs = new ArrayList<>();
             nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities));
-            nrs.add(createDefaultInternetRequestForTransport(
-                    TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
+            if (pref.allowFallback) {
+                nrs.add(createDefaultInternetRequestForTransport(
+                        TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
+            }
             setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids()));
             final NetworkRequestInfo nri = new NetworkRequestInfo(Process.myUid(), nrs,
                     PREFERENCE_ORDER_PROFILE);
diff --git a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java
index b345ede..71f342d 100644
--- a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java
+++ b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java
@@ -38,16 +38,22 @@
         @NonNull public final UserHandle user;
         // Capabilities are only null when sending an object to remove the setting for a user
         @Nullable public final NetworkCapabilities capabilities;
+        public final boolean allowFallback;
 
         public Preference(@NonNull final UserHandle user,
-                @Nullable final NetworkCapabilities capabilities) {
+                @Nullable final NetworkCapabilities capabilities,
+                final boolean allowFallback) {
             this.user = user;
             this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities);
+            this.allowFallback = allowFallback;
         }
 
         /** toString */
         public String toString() {
-            return "[ProfileNetworkPreference user=" + user + " caps=" + capabilities + "]";
+            return "[ProfileNetworkPreference user=" + user
+                    + " caps=" + capabilities
+                    + " allowFallback=" + allowFallback
+                    + "]";
         }
     }
 
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index c533dab..f1897f5 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -114,6 +114,7 @@
         // meaning @hide APIs in framework-connectivity are resolved before @SystemApi
         // stubs in framework
         "framework-connectivity.impl",
+        "framework-connectivity-tiramisu.impl",
         "framework-tethering.impl",
         "framework",
 
diff --git a/tests/common/java/ParseExceptionTest.kt b/tests/common/java/ParseExceptionTest.kt
index b702d61..ca01c76 100644
--- a/tests/common/java/ParseExceptionTest.kt
+++ b/tests/common/java/ParseExceptionTest.kt
@@ -18,6 +18,7 @@
 import android.os.Build
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertNull
@@ -27,6 +28,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@ConnectivityModuleTest
 class ParseExceptionTest {
     @get:Rule
     val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.R)
diff --git a/tests/common/java/android/net/CaptivePortalDataTest.kt b/tests/common/java/android/net/CaptivePortalDataTest.kt
index 18a9331..f927380 100644
--- a/tests/common/java/android/net/CaptivePortalDataTest.kt
+++ b/tests/common/java/android/net/CaptivePortalDataTest.kt
@@ -19,7 +19,6 @@
 import android.os.Build
 import androidx.test.filters.SmallTest
 import com.android.modules.utils.build.SdkLevel
-import com.android.testutils.assertParcelSane
 import com.android.testutils.assertParcelingIsLossless
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
@@ -71,9 +70,8 @@
 
     @Test
     fun testParcelUnparcel() {
-        val fieldCount = if (SdkLevel.isAtLeastS()) 10 else 7
-        assertParcelSane(data, fieldCount)
-        assertParcelSane(dataFromPasspoint, fieldCount)
+        assertParcelingIsLossless(data)
+        assertParcelingIsLossless(dataFromPasspoint)
 
         assertParcelingIsLossless(makeBuilder().setUserPortalUrl(null).build())
         assertParcelingIsLossless(makeBuilder().setVenueInfoUrl(null).build())
diff --git a/tests/common/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/common/java/android/net/ConnectivityDiagnosticsManagerTest.java
index 294ed10..03a9a80 100644
--- a/tests/common/java/android/net/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/common/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -21,7 +21,7 @@
 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
 import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
 
-import static com.android.testutils.ParcelUtils.assertParcelSane;
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -202,7 +202,7 @@
 
     @Test
     public void testConnectivityReportParcelUnparcel() {
-        assertParcelSane(createSampleConnectivityReport(), 5);
+        assertParcelingIsLossless(createSampleConnectivityReport());
     }
 
     private DataStallReport createSampleDataStallReport() {
@@ -303,7 +303,7 @@
 
     @Test
     public void testDataStallReportParcelUnparcel() {
-        assertParcelSane(createSampleDataStallReport(), 6);
+        assertParcelingIsLossless(createSampleDataStallReport());
     }
 
     @Test
diff --git a/tests/common/java/android/net/DhcpInfoTest.java b/tests/common/java/android/net/DhcpInfoTest.java
index ab4726b..b42e183 100644
--- a/tests/common/java/android/net/DhcpInfoTest.java
+++ b/tests/common/java/android/net/DhcpInfoTest.java
@@ -17,7 +17,6 @@
 package android.net;
 
 import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTL;
-import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
 import static com.android.testutils.ParcelUtils.parcelingRoundTrip;
 
 import static org.junit.Assert.assertEquals;
@@ -101,7 +100,6 @@
         // Cannot use assertParcelSane() here because this requires .equals() to work as
         // defined, but DhcpInfo has a different legacy behavior that we cannot change.
         final DhcpInfo dhcpInfo = createDhcpInfoObject();
-        assertFieldCountEquals(7, DhcpInfo.class);
 
         final DhcpInfo dhcpInfoRoundTrip = parcelingRoundTrip(dhcpInfo);
         assertTrue(dhcpInfoEquals(null, null));
diff --git a/tests/common/java/android/net/IpPrefixTest.java b/tests/common/java/android/net/IpPrefixTest.java
index f61c8c3..fef6416 100644
--- a/tests/common/java/android/net/IpPrefixTest.java
+++ b/tests/common/java/android/net/IpPrefixTest.java
@@ -17,7 +17,6 @@
 package android.net;
 
 import static com.android.testutils.MiscAsserts.assertEqualBothWays;
-import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
 import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay;
 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
@@ -31,6 +30,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.ConnectivityModuleTest;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -39,6 +40,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@ConnectivityModuleTest
 public class IpPrefixTest {
 
     private static InetAddress address(String addr) {
@@ -371,7 +373,5 @@
         p = new IpPrefix("192.0.2.0/25");
         assertParcelingIsLossless(p);
         assertTrue(p.isIPv4());
-
-        assertFieldCountEquals(2, IpPrefix.class);
     }
 }
diff --git a/tests/common/java/android/net/LinkAddressTest.java b/tests/common/java/android/net/LinkAddressTest.java
index 2cf3cf9..6b04fee 100644
--- a/tests/common/java/android/net/LinkAddressTest.java
+++ b/tests/common/java/android/net/LinkAddressTest.java
@@ -28,7 +28,6 @@
 import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
 
 import static com.android.testutils.MiscAsserts.assertEqualBothWays;
-import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
 import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay;
 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
@@ -44,8 +43,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule;
-import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 
 import org.junit.Rule;
@@ -63,6 +62,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@ConnectivityModuleTest
 public class LinkAddressTest {
     @Rule
     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
@@ -352,17 +352,6 @@
         assertParcelingIsLossless(l);
     }
 
-    @Test @IgnoreAfter(Build.VERSION_CODES.Q)
-    public void testFieldCount_Q() {
-        assertFieldCountEquals(4, LinkAddress.class);
-    }
-
-    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
-    public void testFieldCount() {
-        // Make sure any new field is covered by the above parceling tests when changing this number
-        assertFieldCountEquals(6, LinkAddress.class);
-    }
-
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testDeprecationTime() {
         try {
diff --git a/tests/common/java/android/net/LinkPropertiesTest.java b/tests/common/java/android/net/LinkPropertiesTest.java
index 550953d..4d85a57 100644
--- a/tests/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/common/java/android/net/LinkPropertiesTest.java
@@ -20,7 +20,6 @@
 import static android.net.RouteInfo.RTN_UNICAST;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 
-import static com.android.testutils.ParcelUtils.assertParcelSane;
 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 import static com.android.testutils.ParcelUtils.parcelingRoundTrip;
 
@@ -41,6 +40,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
+import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -60,6 +60,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@ConnectivityModuleTest
 public class LinkPropertiesTest {
     @Rule
     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
@@ -1006,7 +1007,7 @@
     @Test @IgnoreAfter(Build.VERSION_CODES.Q)
     public void testLinkPropertiesParcelable_Q() throws Exception {
         final LinkProperties source = makeLinkPropertiesForParceling();
-        assertParcelSane(source, 14 /* fieldCount */);
+        assertParcelingIsLossless(source);
     }
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
@@ -1017,8 +1018,7 @@
         source.setCaptivePortalApiUrl(CAPPORT_API_URL);
         source.setCaptivePortalData((CaptivePortalData) getCaptivePortalData());
         source.setDhcpServerAddress((Inet4Address) GATEWAY1);
-        assertParcelSane(new LinkProperties(source, true /* parcelSensitiveFields */),
-                18 /* fieldCount */);
+        assertParcelingIsLossless(new LinkProperties(source, true /* parcelSensitiveFields */));
 
         // Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared.
         final LinkProperties sanitized = new LinkProperties(source);
diff --git a/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt
index a5e44d5..4a4859d 100644
--- a/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt
+++ b/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt
@@ -22,14 +22,11 @@
 import android.os.Build
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-
-import com.android.testutils.assertParcelSane
+import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
-
-import java.lang.IllegalStateException
-
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertFalse
 import org.junit.Rule
 import org.junit.Test
@@ -38,6 +35,7 @@
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
+@ConnectivityModuleTest
 class MatchAllNetworkSpecifierTest {
     @Rule @JvmField
     val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule()
@@ -50,7 +48,7 @@
 
     @Test
     fun testParcel() {
-        assertParcelSane(MatchAllNetworkSpecifier(), 0)
+        assertParcelingIsLossless(MatchAllNetworkSpecifier())
     }
 
     @Test
diff --git a/tests/common/java/android/net/NattKeepalivePacketDataTest.kt b/tests/common/java/android/net/NattKeepalivePacketDataTest.kt
index 46f39dd..ad7a526 100644
--- a/tests/common/java/android/net/NattKeepalivePacketDataTest.kt
+++ b/tests/common/java/android/net/NattKeepalivePacketDataTest.kt
@@ -23,10 +23,9 @@
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
 import com.android.testutils.assertEqualBothWays
-import com.android.testutils.assertFieldCountEquals
-import com.android.testutils.assertParcelSane
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.assertParcelingIsLossless
 import com.android.testutils.parcelingRoundTrip
 import java.net.InetAddress
 import org.junit.Assert.assertEquals
@@ -93,7 +92,7 @@
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     fun testParcel() {
-        assertParcelSane(nattKeepalivePacket(), 0)
+        assertParcelingIsLossless(nattKeepalivePacket())
     }
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
@@ -103,8 +102,6 @@
         assertNotEquals(nattKeepalivePacket(srcAddress = TEST_DST_ADDRV4), nattKeepalivePacket())
         // Test src port only because dst port have to be NATT_PORT
         assertNotEquals(nattKeepalivePacket(srcPort = TEST_PORT2), nattKeepalivePacket())
-        // Make sure the parceling test is updated if fields are added in the base class.
-        assertFieldCountEquals(5, KeepalivePacketData::class.java)
     }
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
diff --git a/tests/common/java/android/net/NetworkAgentConfigTest.kt b/tests/common/java/android/net/NetworkAgentConfigTest.kt
index ed9995c..b339a27 100644
--- a/tests/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/common/java/android/net/NetworkAgentConfigTest.kt
@@ -20,9 +20,10 @@
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
 import com.android.modules.utils.build.SdkLevel.isAtLeastS
+import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -32,6 +33,7 @@
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
+@ConnectivityModuleTest
 class NetworkAgentConfigTest {
     @Rule @JvmField
     val ignoreRule = DevSdkIgnoreRule()
@@ -48,20 +50,7 @@
                 setBypassableVpn(true)
             }
         }.build()
-        // This test can be run as unit test against the latest system image, as CTS to verify
-        // an Android release that is as recent as the test, or as MTS to verify the
-        // Connectivity module. In the first two cases NetworkAgentConfig will be as recent
-        // as the test. In the last case, starting from S NetworkAgentConfig is updated as part
-        // of Connectivity, so it is also as recent as the test. For MTS on Q and R,
-        // NetworkAgentConfig is not updatable, so it may have a different number of fields.
-        if (isAtLeastS()) {
-            // When this test is run on S+, NetworkAgentConfig is as recent as the test,
-            // so this should be the most recent known number of fields.
-            assertParcelSane(config, 13)
-        } else {
-            // For R or below, the config will have 10 items
-            assertParcelSane(config, 10)
-        }
+        assertParcelingIsLossless(config)
     }
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
diff --git a/tests/common/java/android/net/NetworkCapabilitiesTest.java b/tests/common/java/android/net/NetworkCapabilitiesTest.java
index 2a4df7a..9cc001d 100644
--- a/tests/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/common/java/android/net/NetworkCapabilitiesTest.java
@@ -59,7 +59,6 @@
 import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
 import static com.android.testutils.MiscAsserts.assertEmpty;
 import static com.android.testutils.MiscAsserts.assertThrows;
-import static com.android.testutils.ParcelUtils.assertParcelSane;
 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -344,21 +343,7 @@
     }
 
     private void testParcelSane(NetworkCapabilities cap) {
-        // This test can be run as unit test against the latest system image, as CTS to verify
-        // an Android release that is as recent as the test, or as MTS to verify the
-        // Connectivity module. In the first two cases NetworkCapabilities will be as recent
-        // as the test. In the last case, starting from S NetworkCapabilities is updated as part
-        // of Connectivity, so it is also as recent as the test. For MTS on Q and R,
-        // NetworkCapabilities is not updatable, so it may have a different number of fields.
-        if (isAtLeastS()) {
-            // When this test is run on S+, NetworkCapabilities is as recent as the test,
-            // so this should be the most recent known number of fields.
-            assertParcelSane(cap, 18);
-        } else if (isAtLeastR()) {
-            assertParcelSane(cap, 15);
-        } else {
-            assertParcelSane(cap, 11);
-        }
+        assertParcelingIsLossless(cap);
     }
 
     private static NetworkCapabilities createNetworkCapabilitiesWithTransportInfo() {
diff --git a/tests/common/java/android/net/NetworkProviderTest.kt b/tests/common/java/android/net/NetworkProviderTest.kt
index ff5de1d..3ceacf8 100644
--- a/tests/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/common/java/android/net/NetworkProviderTest.kt
@@ -32,6 +32,7 @@
 import androidx.test.InstrumentationRegistry
 import com.android.net.module.util.ArrayTrackRecord
 import com.android.testutils.CompatUtil
+import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
@@ -62,6 +63,7 @@
 
 @RunWith(DevSdkIgnoreRunner::class)
 @IgnoreUpTo(Build.VERSION_CODES.Q)
+@ConnectivityModuleTest
 class NetworkProviderTest {
     @Rule @JvmField
     val mIgnoreRule = DevSdkIgnoreRule()
diff --git a/tests/common/java/android/net/NetworkSpecifierTest.kt b/tests/common/java/android/net/NetworkSpecifierTest.kt
index f3409f5..b960417 100644
--- a/tests/common/java/android/net/NetworkSpecifierTest.kt
+++ b/tests/common/java/android/net/NetworkSpecifierTest.kt
@@ -17,18 +17,20 @@
 
 import android.os.Build
 import androidx.test.filters.SmallTest
+import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
 import com.android.testutils.DevSdkIgnoreRunner
-import kotlin.test.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
-import org.junit.Test
-import org.junit.runner.RunWith
+import kotlin.test.assertTrue
 
 @SmallTest
 @RunWith(DevSdkIgnoreRunner::class)
 @IgnoreUpTo(Build.VERSION_CODES.Q)
+@ConnectivityModuleTest
 class NetworkSpecifierTest {
     private class TestNetworkSpecifier(
         val intData: Int = 123,
diff --git a/tests/common/java/android/net/NetworkStateSnapshotTest.kt b/tests/common/java/android/net/NetworkStateSnapshotTest.kt
index 0ca4d95..0dad6a8 100644
--- a/tests/common/java/android/net/NetworkStateSnapshotTest.kt
+++ b/tests/common/java/android/net/NetworkStateSnapshotTest.kt
@@ -22,9 +22,10 @@
 import android.net.NetworkCapabilities.TRANSPORT_WIFI
 import android.os.Build
 import androidx.test.filters.SmallTest
+import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRunner
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Test
 import org.junit.runner.RunWith
 import java.net.Inet4Address
@@ -59,6 +60,7 @@
 @SmallTest
 @RunWith(DevSdkIgnoreRunner::class)
 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@ConnectivityModuleTest
 class NetworkStateSnapshotTest {
 
     @Test
@@ -67,7 +69,7 @@
                 LinkProperties(), null, TYPE_NONE)
         val snapshot = NetworkStateSnapshot(
                 Network(TEST_NETID), TEST_CAPABILITIES, TEST_LINK_PROPERTIES, TEST_IMSI, TYPE_WIFI)
-        assertParcelSane(emptySnapshot, 5)
-        assertParcelSane(snapshot, 5)
+        assertParcelingIsLossless(emptySnapshot)
+        assertParcelingIsLossless(snapshot)
     }
 }
diff --git a/tests/common/java/android/net/NetworkTest.java b/tests/common/java/android/net/NetworkTest.java
index 7423c73..c102cb3 100644
--- a/tests/common/java/android/net/NetworkTest.java
+++ b/tests/common/java/android/net/NetworkTest.java
@@ -28,6 +28,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -46,6 +47,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@ConnectivityModuleTest
 public class NetworkTest {
     final Network mNetwork = new Network(99);
 
diff --git a/tests/common/java/android/net/OemNetworkPreferencesTest.java b/tests/common/java/android/net/OemNetworkPreferencesTest.java
index fd29a95..d96f80c 100644
--- a/tests/common/java/android/net/OemNetworkPreferencesTest.java
+++ b/tests/common/java/android/net/OemNetworkPreferencesTest.java
@@ -17,7 +17,7 @@
 package android.net;
 
 import static com.android.testutils.MiscAsserts.assertThrows;
-import static com.android.testutils.ParcelUtils.assertParcelSane;
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -27,6 +27,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 import com.android.testutils.DevSdkIgnoreRunner;
 
@@ -38,6 +39,7 @@
 @IgnoreUpTo(Build.VERSION_CODES.R)
 @RunWith(DevSdkIgnoreRunner.class)
 @SmallTest
+@ConnectivityModuleTest
 public class OemNetworkPreferencesTest {
 
     private static final int TEST_PREF = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
@@ -101,7 +103,7 @@
 
         final OemNetworkPreferences prefs = mBuilder.build();
 
-        assertParcelSane(prefs, 1 /* fieldCount */);
+        assertParcelingIsLossless(prefs);
     }
 
     @Test
diff --git a/tests/common/java/android/net/RouteInfoTest.java b/tests/common/java/android/net/RouteInfoTest.java
index b69b045..5b28b84 100644
--- a/tests/common/java/android/net/RouteInfoTest.java
+++ b/tests/common/java/android/net/RouteInfoTest.java
@@ -21,7 +21,6 @@
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 
 import static com.android.testutils.MiscAsserts.assertEqualBothWays;
-import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
 import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay;
 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
@@ -38,8 +37,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule;
-import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 
 import org.junit.Rule;
@@ -52,6 +51,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@ConnectivityModuleTest
 public class RouteInfoTest {
     @Rule
     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
@@ -383,17 +383,6 @@
         assertParcelingIsLossless(r);
     }
 
-    @Test @IgnoreAfter(Build.VERSION_CODES.Q)
-    public void testFieldCount_Q() {
-        assertFieldCountEquals(6, RouteInfo.class);
-    }
-
-    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
-    public void testFieldCount() {
-        // Make sure any new field is covered by the above parceling tests when changing this number
-        assertFieldCountEquals(7, RouteInfo.class);
-    }
-
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testMtu() {
         RouteInfo r;
diff --git a/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt b/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt
index 7a18bb0..063ea23 100644
--- a/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt
+++ b/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt
@@ -20,8 +20,7 @@
 import android.os.Build
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRunner
-import com.android.testutils.assertFieldCountEquals
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Test
 import org.junit.runner.RunWith
 import java.net.InetAddress
@@ -68,15 +67,11 @@
         assertNotEquals(makeData(tcpWndScale = 3), makeData())
         assertNotEquals(makeData(ipTos = 0x14), makeData())
         assertNotEquals(makeData(ipTtl = 11), makeData())
-
-        // Update above assertions if field is added
-        assertFieldCountEquals(5, KeepalivePacketData::class.java)
-        assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
     }
 
     @Test
     fun testParcelUnparcel() {
-        assertParcelSane(makeData(), fieldCount = 6) { a, b ->
+        assertParcelingIsLossless(makeData()) { a, b ->
             // .equals() does not verify .packet
             a == b && a.packet contentEquals b.packet
         }
@@ -98,9 +93,5 @@
         assertTrue(str.contains(data.getTcpWindowScale().toString()))
         assertTrue(str.contains(data.getIpTos().toString()))
         assertTrue(str.contains(data.getIpTtl().toString()))
-
-        // Update above assertions if field is added
-        assertFieldCountEquals(5, KeepalivePacketData::class.java)
-        assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
     }
 }
\ No newline at end of file
diff --git a/tests/common/java/android/net/UidRangeTest.java b/tests/common/java/android/net/UidRangeTest.java
index a435119..d46fdc9 100644
--- a/tests/common/java/android/net/UidRangeTest.java
+++ b/tests/common/java/android/net/UidRangeTest.java
@@ -35,6 +35,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 
@@ -46,6 +47,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@ConnectivityModuleTest
 public class UidRangeTest {
 
     /*
diff --git a/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt b/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
index f23ba26..a041c4e 100644
--- a/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
+++ b/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
@@ -18,9 +18,10 @@
 
 import android.os.Build
 import androidx.test.filters.SmallTest
+import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRunner
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Test
 import org.junit.runner.RunWith
 import kotlin.test.assertEquals
@@ -32,6 +33,7 @@
 @SmallTest
 @RunWith(DevSdkIgnoreRunner::class)
 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@ConnectivityModuleTest
 class UnderlyingNetworkInfoTest {
     @Test
     fun testParcelUnparcel() {
@@ -39,12 +41,12 @@
         assertEquals(TEST_OWNER_UID, testInfo.getOwnerUid())
         assertEquals(TEST_IFACE, testInfo.getInterface())
         assertEquals(TEST_IFACE_LIST, testInfo.getUnderlyingInterfaces())
-        assertParcelSane(testInfo, 3)
+        assertParcelingIsLossless(testInfo)
 
         val emptyInfo = UnderlyingNetworkInfo(0, String(), listOf())
         assertEquals(0, emptyInfo.getOwnerUid())
         assertEquals(String(), emptyInfo.getInterface())
         assertEquals(listOf(), emptyInfo.getUnderlyingInterfaces())
-        assertParcelSane(emptyInfo, 3)
+        assertParcelingIsLossless(emptyInfo)
     }
 }
\ No newline at end of file
diff --git a/tests/common/java/android/net/apf/ApfCapabilitiesTest.java b/tests/common/java/android/net/apf/ApfCapabilitiesTest.java
index 88996d9..fa4adcb 100644
--- a/tests/common/java/android/net/apf/ApfCapabilitiesTest.java
+++ b/tests/common/java/android/net/apf/ApfCapabilitiesTest.java
@@ -16,7 +16,7 @@
 
 package android.net.apf;
 
-import static com.android.testutils.ParcelUtils.assertParcelSane;
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -62,7 +62,7 @@
         assertEquals(456, caps.maximumApfProgramSize);
         assertEquals(789, caps.apfPacketFormat);
 
-        assertParcelSane(caps, 3);
+        assertParcelingIsLossless(caps);
     }
 
     @Test
diff --git a/tests/common/java/android/net/metrics/ApfProgramEventTest.kt b/tests/common/java/android/net/metrics/ApfProgramEventTest.kt
index 0b7b740..1c175da 100644
--- a/tests/common/java/android/net/metrics/ApfProgramEventTest.kt
+++ b/tests/common/java/android/net/metrics/ApfProgramEventTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -48,7 +48,7 @@
         assertEquals(5, apfProgramEvent.programLength)
         assertEquals(ApfProgramEvent.flagsFor(true, true), apfProgramEvent.flags)
 
-        assertParcelSane(apfProgramEvent, 6)
+        assertParcelingIsLossless(apfProgramEvent)
     }
 
     @Test
diff --git a/tests/common/java/android/net/metrics/ApfStatsTest.kt b/tests/common/java/android/net/metrics/ApfStatsTest.kt
index 46a8c8e..610e674 100644
--- a/tests/common/java/android/net/metrics/ApfStatsTest.kt
+++ b/tests/common/java/android/net/metrics/ApfStatsTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -52,6 +52,6 @@
         assertEquals(8, apfStats.programUpdatesAllowingMulticast)
         assertEquals(9, apfStats.maxProgramSize)
 
-        assertParcelSane(apfStats, 10)
+        assertParcelingIsLossless(apfStats)
     }
 }
diff --git a/tests/common/java/android/net/metrics/DhcpClientEventTest.kt b/tests/common/java/android/net/metrics/DhcpClientEventTest.kt
index 8d7a9c4..4c70e11 100644
--- a/tests/common/java/android/net/metrics/DhcpClientEventTest.kt
+++ b/tests/common/java/android/net/metrics/DhcpClientEventTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -38,6 +38,6 @@
         assertEquals(FAKE_MESSAGE, dhcpClientEvent.msg)
         assertEquals(Integer.MAX_VALUE, dhcpClientEvent.durationMs)
 
-        assertParcelSane(dhcpClientEvent, 2)
+        assertParcelingIsLossless(dhcpClientEvent)
     }
 }
diff --git a/tests/common/java/android/net/metrics/IpManagerEventTest.kt b/tests/common/java/android/net/metrics/IpManagerEventTest.kt
index 64be508..bb21dca 100644
--- a/tests/common/java/android/net/metrics/IpManagerEventTest.kt
+++ b/tests/common/java/android/net/metrics/IpManagerEventTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -33,7 +33,7 @@
             assertEquals(it, ipManagerEvent.eventType)
             assertEquals(Long.MAX_VALUE, ipManagerEvent.durationMs)
 
-            assertParcelSane(ipManagerEvent, 2)
+            assertParcelingIsLossless(ipManagerEvent)
         }
     }
 }
diff --git a/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt b/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt
index 55b5e49..3d21b81 100644
--- a/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt
+++ b/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -32,7 +32,7 @@
             val ipReachabilityEvent = IpReachabilityEvent(it)
             assertEquals(it, ipReachabilityEvent.eventType)
 
-            assertParcelSane(ipReachabilityEvent, 1)
+            assertParcelingIsLossless(ipReachabilityEvent)
         }
     }
 }
diff --git a/tests/common/java/android/net/metrics/NetworkEventTest.kt b/tests/common/java/android/net/metrics/NetworkEventTest.kt
index 41430b0..17b5e2d 100644
--- a/tests/common/java/android/net/metrics/NetworkEventTest.kt
+++ b/tests/common/java/android/net/metrics/NetworkEventTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -37,7 +37,7 @@
             assertEquals(it, networkEvent.eventType)
             assertEquals(Long.MAX_VALUE, networkEvent.durationMs)
 
-            assertParcelSane(networkEvent, 2)
+            assertParcelingIsLossless(networkEvent)
         }
     }
 }
diff --git a/tests/common/java/android/net/metrics/RaEventTest.kt b/tests/common/java/android/net/metrics/RaEventTest.kt
index d9b7203..e9daa0f 100644
--- a/tests/common/java/android/net/metrics/RaEventTest.kt
+++ b/tests/common/java/android/net/metrics/RaEventTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -67,6 +67,6 @@
         assertEquals(5, raEvent.rdnssLifetime)
         assertEquals(6, raEvent.dnsslLifetime)
 
-        assertParcelSane(raEvent, 6)
+        assertParcelingIsLossless(raEvent)
     }
 }
diff --git a/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt b/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt
index 51c0d41..7dfa7e1 100644
--- a/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt
+++ b/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
 import java.lang.reflect.Modifier
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
@@ -51,7 +51,7 @@
         assertTrue(validationProbeEvent.probeType hasType FIRST_VALIDATION)
         assertEquals(ValidationProbeEvent.DNS_SUCCESS, validationProbeEvent.returnCode)
 
-        assertParcelSane(validationProbeEvent, 3)
+        assertParcelingIsLossless(validationProbeEvent)
     }
 
     @Test
diff --git a/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt b/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt
index 7b22e45..c90b1aa 100644
--- a/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt
+++ b/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt
@@ -31,7 +31,6 @@
 import android.os.Build
 import androidx.test.filters.SmallTest
 import com.android.testutils.DevSdkIgnoreRule
-import com.android.testutils.assertFieldCountEquals
 import com.android.testutils.assertNetworkStatsEquals
 import com.android.testutils.assertParcelingIsLossless
 import org.junit.Before
@@ -176,7 +175,6 @@
         assertParcelingIsLossless(testStatsEmpty)
         assertParcelingIsLossless(testStats1)
         assertParcelingIsLossless(testStats2)
-        assertFieldCountEquals(15, NetworkStats::class.java)
     }
 
     @Test
diff --git a/tests/cts/OWNERS b/tests/cts/OWNERS
index 4264345..8dfa455 100644
--- a/tests/cts/OWNERS
+++ b/tests/cts/OWNERS
@@ -1,4 +1,3 @@
 # Bug component: 31808
 set noparent
-lorenzo@google.com
-satk@google.com
\ No newline at end of file
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking_xts
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 708d600..916b566 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
@@ -893,7 +893,7 @@
 
     @Test
     public void testDefault() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
         if (!SdkLevel.isAtLeastS() && (
                 SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
                         || SystemProperties.getInt("service.adb.tcp.port", -1) > -1)) {
@@ -986,7 +986,7 @@
 
     @Test
     public void testAppAllowed() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
 
         FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
 
@@ -1007,7 +1007,7 @@
 
     @Test
     public void testAppDisallowed() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
 
         FileDescriptor localFd = openSocketFd(TEST_HOST, 80, TIMEOUT_MS);
         FileDescriptor remoteFd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
@@ -1041,8 +1041,8 @@
 
     @Test
     public void testExcludedRoutes() throws Exception {
-        if (!supportedHardware()) return;
-        if (!SdkLevel.isAtLeastT()) return;
+        assumeTrue(supportedHardware());
+        assumeTrue(SdkLevel.isAtLeastT());
 
         // Shell app must not be put in here or it would kill the ADB-over-network use case
         String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
@@ -1062,7 +1062,7 @@
 
     @Test
     public void testIncludedRoutes() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
 
         // Shell app must not be put in here or it would kill the ADB-over-network use case
         String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
@@ -1081,8 +1081,8 @@
 
     @Test
     public void testInterleavedRoutes() throws Exception {
-        if (!supportedHardware()) return;
-        if (!SdkLevel.isAtLeastT()) return;
+        assumeTrue(supportedHardware());
+        assumeTrue(SdkLevel.isAtLeastT());
 
         // Shell app must not be put in here or it would kill the ADB-over-network use case
         String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
@@ -1109,7 +1109,7 @@
 
     @Test
     public void testGetConnectionOwnerUidSecurity() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
 
         DatagramSocket s;
         InetAddress address = InetAddress.getByName("localhost");
@@ -1131,7 +1131,7 @@
 
     @Test
     public void testSetProxy() throws  Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
         ProxyInfo initialProxy = mCM.getDefaultProxy();
         // Receiver for the proxy change broadcast.
         BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
@@ -1171,7 +1171,7 @@
 
     @Test
     public void testSetProxyDisallowedApps() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
         ProxyInfo initialProxy = mCM.getDefaultProxy();
 
         String disallowedApps = mPackageName;
@@ -1197,7 +1197,7 @@
 
     @Test
     public void testNoProxy() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
         ProxyInfo initialProxy = mCM.getDefaultProxy();
         BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
         proxyBroadcastReceiver.register();
@@ -1232,7 +1232,7 @@
 
     @Test
     public void testBindToNetworkWithProxy() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
         String allowedApps = mPackageName;
         Network initialNetwork = mCM.getActiveNetwork();
         ProxyInfo initialProxy = mCM.getDefaultProxy();
@@ -1474,7 +1474,7 @@
     }
 
     private void maybeExpectVpnTransportInfo(Network network) {
-        if (!SdkLevel.isAtLeastS()) return;
+        assumeTrue(SdkLevel.isAtLeastS());
         final NetworkCapabilities vpnNc = mCM.getNetworkCapabilities(network);
         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
         final TransportInfo ti = vpnNc.getTransportInfo();
@@ -1526,7 +1526,7 @@
      */
     @Test
     public void testDownloadWithDownloadManagerDisallowed() throws Exception {
-        if (!supportedHardware()) return;
+        assumeTrue(supportedHardware());
 
         // Start a VPN with DownloadManager package in disallowed list.
         startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
diff --git a/tests/cts/net/src/android/net/cts/IpConfigurationTest.java b/tests/cts/net/src/android/net/cts/IpConfigurationTest.java
index 56ab2a7..385bf9e 100644
--- a/tests/cts/net/src/android/net/cts/IpConfigurationTest.java
+++ b/tests/cts/net/src/android/net/cts/IpConfigurationTest.java
@@ -16,7 +16,7 @@
 
 package android.net.cts;
 
-import static com.android.testutils.ParcelUtils.assertParcelSane;
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
@@ -118,6 +118,6 @@
     @Test
     public void testParcel() {
         final IpConfiguration config = new IpConfiguration();
-        assertParcelSane(config, 4);
+        assertParcelingIsLossless(config);
     }
 }
diff --git a/tests/cts/net/src/android/net/cts/LocalSocketTest.java b/tests/cts/net/src/android/net/cts/LocalSocketTest.java
deleted file mode 100644
index 6e61705..0000000
--- a/tests/cts/net/src/android/net/cts/LocalSocketTest.java
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 2008 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.cts;
-
-import junit.framework.TestCase;
-
-import android.net.Credentials;
-import android.net.LocalServerSocket;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.system.Os;
-import android.system.OsConstants;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-public class LocalSocketTest extends TestCase {
-    private final static String ADDRESS_PREFIX = "com.android.net.LocalSocketTest";
-
-    public void testLocalConnections() throws IOException {
-        String address = ADDRESS_PREFIX + "_testLocalConnections";
-        // create client and server socket
-        LocalServerSocket localServerSocket = new LocalServerSocket(address);
-        LocalSocket clientSocket = new LocalSocket();
-
-        // establish connection between client and server
-        LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
-        assertFalse(clientSocket.isConnected());
-        clientSocket.connect(locSockAddr);
-        assertTrue(clientSocket.isConnected());
-
-        LocalSocket serverSocket = localServerSocket.accept();
-        assertTrue(serverSocket.isConnected());
-        assertTrue(serverSocket.isBound());
-        try {
-            serverSocket.bind(localServerSocket.getLocalSocketAddress());
-            fail("Cannot bind a LocalSocket from accept()");
-        } catch (IOException expected) {
-        }
-        try {
-            serverSocket.connect(locSockAddr);
-            fail("Cannot connect a LocalSocket from accept()");
-        } catch (IOException expected) {
-        }
-
-        Credentials credent = clientSocket.getPeerCredentials();
-        assertTrue(0 != credent.getPid());
-
-        // send data from client to server
-        OutputStream clientOutStream = clientSocket.getOutputStream();
-        clientOutStream.write(12);
-        InputStream serverInStream = serverSocket.getInputStream();
-        assertEquals(12, serverInStream.read());
-
-        //send data from server to client
-        OutputStream serverOutStream = serverSocket.getOutputStream();
-        serverOutStream.write(3);
-        InputStream clientInStream = clientSocket.getInputStream();
-        assertEquals(3, clientInStream.read());
-
-        // Test sending and receiving file descriptors
-        clientSocket.setFileDescriptorsForSend(new FileDescriptor[]{FileDescriptor.in});
-        clientOutStream.write(32);
-        assertEquals(32, serverInStream.read());
-
-        FileDescriptor[] out = serverSocket.getAncillaryFileDescriptors();
-        assertEquals(1, out.length);
-        FileDescriptor fd = clientSocket.getFileDescriptor();
-        assertTrue(fd.valid());
-
-        //shutdown input stream of client
-        clientSocket.shutdownInput();
-        assertEquals(-1, clientInStream.read());
-
-        //shutdown output stream of client
-        clientSocket.shutdownOutput();
-        try {
-            clientOutStream.write(10);
-            fail("testLocalSocket shouldn't come to here");
-        } catch (IOException e) {
-            // expected
-        }
-
-        //shutdown input stream of server
-        serverSocket.shutdownInput();
-        assertEquals(-1, serverInStream.read());
-
-        //shutdown output stream of server
-        serverSocket.shutdownOutput();
-        try {
-            serverOutStream.write(10);
-            fail("testLocalSocket shouldn't come to here");
-        } catch (IOException e) {
-            // expected
-        }
-
-        //close client socket
-        clientSocket.close();
-        try {
-            clientInStream.read();
-            fail("testLocalSocket shouldn't come to here");
-        } catch (IOException e) {
-            // expected
-        }
-
-        //close server socket
-        serverSocket.close();
-        try {
-            serverInStream.read();
-            fail("testLocalSocket shouldn't come to here");
-        } catch (IOException e) {
-            // expected
-        }
-    }
-
-    public void testAccessors() throws IOException {
-        String address = ADDRESS_PREFIX + "_testAccessors";
-        LocalSocket socket = new LocalSocket();
-        LocalSocketAddress addr = new LocalSocketAddress(address);
-
-        assertFalse(socket.isBound());
-        socket.bind(addr);
-        assertTrue(socket.isBound());
-        assertEquals(addr, socket.getLocalSocketAddress());
-
-        String str = socket.toString();
-        assertTrue(str.contains("impl:android.net.LocalSocketImpl"));
-
-        socket.setReceiveBufferSize(1999);
-        assertEquals(1999 << 1, socket.getReceiveBufferSize());
-
-        socket.setSendBufferSize(3998);
-        assertEquals(3998 << 1, socket.getSendBufferSize());
-
-        assertEquals(0, socket.getSoTimeout());
-        socket.setSoTimeout(1996);
-        assertTrue(socket.getSoTimeout() > 0);
-
-        try {
-            socket.getRemoteSocketAddress();
-            fail("testLocalSocketSecondary shouldn't come to here");
-        } catch (UnsupportedOperationException e) {
-            // expected
-        }
-
-        try {
-            socket.isClosed();
-            fail("testLocalSocketSecondary shouldn't come to here");
-        } catch (UnsupportedOperationException e) {
-            // expected
-        }
-
-        try {
-            socket.isInputShutdown();
-            fail("testLocalSocketSecondary shouldn't come to here");
-        } catch (UnsupportedOperationException e) {
-            // expected
-        }
-
-        try {
-            socket.isOutputShutdown();
-            fail("testLocalSocketSecondary shouldn't come to here");
-        } catch (UnsupportedOperationException e) {
-            // expected
-        }
-
-        try {
-            socket.connect(addr, 2005);
-            fail("testLocalSocketSecondary shouldn't come to here");
-        } catch (UnsupportedOperationException e) {
-            // expected
-        }
-
-        socket.close();
-    }
-
-    // http://b/31205169
-    public void testSetSoTimeout_readTimeout() throws Exception {
-        String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout";
-
-        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
-            final LocalSocket clientSocket = socketPair.clientSocket;
-
-            // Set the timeout in millis.
-            int timeoutMillis = 1000;
-            clientSocket.setSoTimeout(timeoutMillis);
-
-            // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
-            Callable<Result> reader = () -> {
-                try {
-                    clientSocket.getInputStream().read();
-                    return Result.noException("Did not block");
-                } catch (IOException e) {
-                    return Result.exception(e);
-                }
-            };
-            // Allow the configured timeout, plus some slop.
-            int allowedTime = timeoutMillis + 2000;
-            Result result = runInSeparateThread(allowedTime, reader);
-
-            // Check the message was a timeout, it's all we have to go on.
-            String expectedMessage = Os.strerror(OsConstants.EAGAIN);
-            result.assertThrewIOException(expectedMessage);
-        }
-    }
-
-    // http://b/31205169
-    public void testSetSoTimeout_writeTimeout() throws Exception {
-        String address = ADDRESS_PREFIX + "_testSetSoTimeout_writeTimeout";
-
-        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
-            final LocalSocket clientSocket = socketPair.clientSocket;
-
-            // Set the timeout in millis.
-            int timeoutMillis = 1000;
-            clientSocket.setSoTimeout(timeoutMillis);
-
-            // Set a small buffer size so we know we can flood it.
-            clientSocket.setSendBufferSize(100);
-            final int bufferSize = clientSocket.getSendBufferSize();
-
-            // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
-            Callable<Result> writer = () -> {
-                try {
-                    byte[] toWrite = new byte[bufferSize * 2];
-                    clientSocket.getOutputStream().write(toWrite);
-                    return Result.noException("Did not block");
-                } catch (IOException e) {
-                    return Result.exception(e);
-                }
-            };
-            // Allow the configured timeout, plus some slop.
-            int allowedTime = timeoutMillis + 2000;
-
-            Result result = runInSeparateThread(allowedTime, writer);
-
-            // Check the message was a timeout, it's all we have to go on.
-            String expectedMessage = Os.strerror(OsConstants.EAGAIN);
-            result.assertThrewIOException(expectedMessage);
-        }
-    }
-
-    public void testAvailable() throws Exception {
-        String address = ADDRESS_PREFIX + "_testAvailable";
-
-        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
-            LocalSocket clientSocket = socketPair.clientSocket;
-            LocalSocket serverSocket = socketPair.serverSocket.accept();
-
-            OutputStream clientOutputStream = clientSocket.getOutputStream();
-            InputStream serverInputStream = serverSocket.getInputStream();
-            assertEquals(0, serverInputStream.available());
-
-            byte[] buffer = new byte[50];
-            clientOutputStream.write(buffer);
-            assertEquals(50, serverInputStream.available());
-
-            InputStream clientInputStream = clientSocket.getInputStream();
-            OutputStream serverOutputStream = serverSocket.getOutputStream();
-            assertEquals(0, clientInputStream.available());
-            serverOutputStream.write(buffer);
-            assertEquals(50, serverInputStream.available());
-
-            serverSocket.close();
-        }
-    }
-
-    // http://b/34095140
-    public void testLocalSocketCreatedFromFileDescriptor() throws Exception {
-        String address = ADDRESS_PREFIX + "_testLocalSocketCreatedFromFileDescriptor";
-
-        // Establish connection between a local client and server to get a valid client socket file
-        // descriptor.
-        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
-            // Extract the client FileDescriptor we can use.
-            FileDescriptor fileDescriptor = socketPair.clientSocket.getFileDescriptor();
-            assertTrue(fileDescriptor.valid());
-
-            // Create the LocalSocket we want to test.
-            LocalSocket clientSocketCreatedFromFileDescriptor =
-                    LocalSocket.createConnectedLocalSocket(fileDescriptor);
-            assertTrue(clientSocketCreatedFromFileDescriptor.isConnected());
-            assertTrue(clientSocketCreatedFromFileDescriptor.isBound());
-
-            // Test the LocalSocket can be used for communication.
-            LocalSocket serverSocket = socketPair.serverSocket.accept();
-            OutputStream clientOutputStream =
-                    clientSocketCreatedFromFileDescriptor.getOutputStream();
-            InputStream serverInputStream = serverSocket.getInputStream();
-
-            clientOutputStream.write(12);
-            assertEquals(12, serverInputStream.read());
-
-            // Closing clientSocketCreatedFromFileDescriptor does not close the file descriptor.
-            clientSocketCreatedFromFileDescriptor.close();
-            assertTrue(fileDescriptor.valid());
-
-            // .. while closing the LocalSocket that owned the file descriptor does.
-            socketPair.clientSocket.close();
-            assertFalse(fileDescriptor.valid());
-        }
-    }
-
-    public void testFlush() throws Exception {
-        String address = ADDRESS_PREFIX + "_testFlush";
-
-        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
-            LocalSocket clientSocket = socketPair.clientSocket;
-            LocalSocket serverSocket = socketPair.serverSocket.accept();
-
-            OutputStream clientOutputStream = clientSocket.getOutputStream();
-            InputStream serverInputStream = serverSocket.getInputStream();
-            testFlushWorks(clientOutputStream, serverInputStream);
-
-            OutputStream serverOutputStream = serverSocket.getOutputStream();
-            InputStream clientInputStream = clientSocket.getInputStream();
-            testFlushWorks(serverOutputStream, clientInputStream);
-
-            serverSocket.close();
-        }
-    }
-
-    private void testFlushWorks(OutputStream outputStream, InputStream inputStream)
-            throws Exception {
-        final int bytesToTransfer = 50;
-        StreamReader inputStreamReader = new StreamReader(inputStream, bytesToTransfer);
-
-        byte[] buffer = new byte[bytesToTransfer];
-        outputStream.write(buffer);
-        assertEquals(bytesToTransfer, inputStream.available());
-
-        // Start consuming the data.
-        inputStreamReader.start();
-
-        // This doesn't actually flush any buffers, it just polls until the reader has read all the
-        // bytes.
-        outputStream.flush();
-
-        inputStreamReader.waitForCompletion(5000);
-        inputStreamReader.assertBytesRead(bytesToTransfer);
-        assertEquals(0, inputStream.available());
-    }
-
-    private static class StreamReader extends Thread {
-        private final InputStream is;
-        private final int expectedByteCount;
-        private final CountDownLatch completeLatch = new CountDownLatch(1);
-
-        private volatile Exception exception;
-        private int bytesRead;
-
-        private StreamReader(InputStream is, int expectedByteCount) {
-            this.is = is;
-            this.expectedByteCount = expectedByteCount;
-        }
-
-        @Override
-        public void run() {
-            try {
-                byte[] buffer = new byte[10];
-                int readCount;
-                while ((readCount = is.read(buffer)) >= 0) {
-                    bytesRead += readCount;
-                    if (bytesRead >= expectedByteCount) {
-                        break;
-                    }
-                }
-            } catch (IOException e) {
-                exception = e;
-            } finally {
-                completeLatch.countDown();
-            }
-        }
-
-        public void waitForCompletion(long waitMillis) throws Exception {
-            if (!completeLatch.await(waitMillis, TimeUnit.MILLISECONDS)) {
-                fail("Timeout waiting for completion");
-            }
-            if (exception != null) {
-                throw new Exception("Read failed", exception);
-            }
-        }
-
-        public void assertBytesRead(int expected) {
-            assertEquals(expected, bytesRead);
-        }
-    }
-
-    private static class Result {
-        private final String type;
-        private final Exception e;
-
-        private Result(String type, Exception e) {
-            this.type = type;
-            this.e = e;
-        }
-
-        static Result noException(String description) {
-            return new Result(description, null);
-        }
-
-        static Result exception(Exception e) {
-            return new Result(e.getClass().getName(), e);
-        }
-
-        void assertThrewIOException(String expectedMessage) {
-            assertEquals("Unexpected result type", IOException.class.getName(), type);
-            assertEquals("Unexpected exception message", expectedMessage, e.getMessage());
-        }
-    }
-
-    private static Result runInSeparateThread(int allowedTime, final Callable<Result> callable)
-            throws Exception {
-        ExecutorService service = Executors.newSingleThreadScheduledExecutor();
-        Future<Result> future = service.submit(callable);
-        Result result = future.get(allowedTime, TimeUnit.MILLISECONDS);
-        if (!future.isDone()) {
-            fail("Worker thread appears blocked");
-        }
-        return result;
-    }
-
-    private static class LocalSocketPair implements AutoCloseable {
-        static LocalSocketPair createConnectedSocketPair(String address) throws Exception {
-            LocalServerSocket localServerSocket = new LocalServerSocket(address);
-            final LocalSocket clientSocket = new LocalSocket();
-
-            // Establish connection between client and server
-            LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
-            clientSocket.connect(locSockAddr);
-            assertTrue(clientSocket.isConnected());
-            return new LocalSocketPair(localServerSocket, clientSocket);
-        }
-
-        final LocalServerSocket serverSocket;
-        final LocalSocket clientSocket;
-
-        LocalSocketPair(LocalServerSocket serverSocket, LocalSocket clientSocket) {
-            this.serverSocket = serverSocket;
-            this.clientSocket = clientSocket;
-        }
-
-        public void close() throws Exception {
-            serverSocket.close();
-            clientSocket.close();
-        }
-    }
-}
diff --git a/tests/cts/net/src/android/net/cts/MacAddressTest.java b/tests/cts/net/src/android/net/cts/MacAddressTest.java
index 3fd3bba..e47155b 100644
--- a/tests/cts/net/src/android/net/cts/MacAddressTest.java
+++ b/tests/cts/net/src/android/net/cts/MacAddressTest.java
@@ -20,7 +20,7 @@
 import static android.net.MacAddress.TYPE_MULTICAST;
 import static android.net.MacAddress.TYPE_UNICAST;
 
-import static com.android.testutils.ParcelUtils.assertParcelSane;
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertFalse;
@@ -218,6 +218,6 @@
     public void testParcelMacAddress() {
         final MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
 
-        assertParcelSane(mac, 1);
+        assertParcelingIsLossless(mac);
     }
 }
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index 5e3df57..142e013 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -13,72 +13,92 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
- * bpf_existence_test.cpp - checks that the device runs expected BPF programs
+ * bpf_existence_test.cpp - checks that the device has expected BPF programs and maps
  */
 
 #include <cstdint>
+#include <set>
 #include <string>
-#include <vector>
 
-#include <android-base/strings.h>
+#include <android/api-level.h>
 #include <android-base/properties.h>
 #include <android-modules-utils/sdk_level.h>
 
 #include <gtest/gtest.h>
 
 using std::find;
+using std::set;
 using std::string;
-using std::vector;
 
 using android::modules::sdklevel::IsAtLeastR;
 using android::modules::sdklevel::IsAtLeastS;
 using android::modules::sdklevel::IsAtLeastT;
 
+// Mainline development branches lack the constant for the current development OS.
+#ifndef __ANDROID_API_T__
+#define __ANDROID_API_T__ 33
+#endif
+
+#define PLATFORM "/sys/fs/bpf/"
+#define TETHERING "/sys/fs/bpf/tethering/"
+
 class BpfExistenceTest : public ::testing::Test {
 };
 
-static const vector<string> INTRODUCED_R = {
-    "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_ether",
-    "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_rawip",
+static const set<string> INTRODUCED_R = {
+    PLATFORM "map_offload_tether_ingress_map",
+    PLATFORM "map_offload_tether_limit_map",
+    PLATFORM "map_offload_tether_stats_map",
+    PLATFORM "prog_offload_schedcls_ingress_tether_ether",
+    PLATFORM "prog_offload_schedcls_ingress_tether_rawip",
 };
 
-static const vector<string> INTRODUCED_S = {
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream4_ether",
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream4_rawip",
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream6_ether",
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream6_rawip",
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream4_ether",
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream4_rawip",
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream6_ether",
-    "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream6_rawip",
+static const set<string> INTRODUCED_S = {
+    TETHERING "map_offload_tether_dev_map",
+    TETHERING "map_offload_tether_downstream4_map",
+    TETHERING "map_offload_tether_downstream64_map",
+    TETHERING "map_offload_tether_downstream6_map",
+    TETHERING "map_offload_tether_error_map",
+    TETHERING "map_offload_tether_limit_map",
+    TETHERING "map_offload_tether_stats_map",
+    TETHERING "map_offload_tether_upstream4_map",
+    TETHERING "map_offload_tether_upstream6_map",
+    TETHERING "map_test_tether_downstream6_map",
+    TETHERING "prog_offload_schedcls_tether_downstream4_ether",
+    TETHERING "prog_offload_schedcls_tether_downstream4_rawip",
+    TETHERING "prog_offload_schedcls_tether_downstream6_ether",
+    TETHERING "prog_offload_schedcls_tether_downstream6_rawip",
+    TETHERING "prog_offload_schedcls_tether_upstream4_ether",
+    TETHERING "prog_offload_schedcls_tether_upstream4_rawip",
+    TETHERING "prog_offload_schedcls_tether_upstream6_ether",
+    TETHERING "prog_offload_schedcls_tether_upstream6_rawip",
 };
 
-static const vector<string> REMOVED_S = {
-    "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_ether",
-    "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_rawip",
+static const set<string> REMOVED_S = {
+    PLATFORM "map_offload_tether_ingress_map",
+    PLATFORM "map_offload_tether_limit_map",
+    PLATFORM "map_offload_tether_stats_map",
+    PLATFORM "prog_offload_schedcls_ingress_tether_ether",
+    PLATFORM "prog_offload_schedcls_ingress_tether_rawip",
 };
 
-static const vector<string> INTRODUCED_T = {
+static const set<string> INTRODUCED_T = {
 };
 
-static const vector<string> REMOVED_T = {
+static const set<string> REMOVED_T = {
 };
 
-void addAll(vector<string>* a, const vector<string>& b) {
-    a->insert(a->end(), b.begin(), b.end());
+void addAll(set<string>* a, const set<string>& b) {
+    a->insert(b.begin(), b.end());
 }
 
-void removeAll(vector<string>* a, const vector<string> b) {
+void removeAll(set<string>* a, const set<string>& b) {
     for (const auto& toRemove : b) {
-        auto iter = find(a->begin(), a->end(), toRemove);
-        while (iter != a->end()) {
-            a->erase(iter);
-            iter = find(a->begin(), a->end(), toRemove);
-        }
+        a->erase(toRemove);
     }
 }
 
-void getFileLists(vector<string>* expected, vector<string>* unexpected) {
+void getFileLists(set<string>* expected, set<string>* unexpected) {
     unexpected->clear();
     expected->clear();
 
@@ -112,8 +132,8 @@
 }
 
 void checkFiles() {
-    vector<string> mustExist;
-    vector<string> mustNotExist;
+    set<string> mustExist;
+    set<string> mustNotExist;
 
     getFileLists(&mustExist, &mustNotExist);
 
@@ -132,9 +152,9 @@
 
 TEST_F(BpfExistenceTest, TestPrograms) {
     // Pre-flight check to ensure test has been updated.
-    uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
+    uint64_t buildVersionSdk = android_get_device_api_level();
     ASSERT_NE(0, buildVersionSdk) << "Unable to determine device SDK version";
-    if (buildVersionSdk > 33 && buildVersionSdk != 10000) {
+    if (buildVersionSdk > __ANDROID_API_T__ && buildVersionSdk != __ANDROID_API_FUTURE__) {
             FAIL() << "Unknown OS version " << buildVersionSdk << ", please update this test";
     }
 
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 3735ca4..48751f4 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -130,6 +130,7 @@
         "platform-compat-test-rules",
         "platform-test-annotations",
         "service-connectivity-pre-jarjar",
+        "service-connectivity-tiramisu-pre-jarjar",
         "services.core-vpn",
     ],
     libs: [
diff --git a/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java b/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
index 08a3007..6e51069 100644
--- a/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
+++ b/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
@@ -220,6 +220,26 @@
                         TEST_SUBSCRIBER_ID));
     }
 
+    @Test
+    public void testQueryTaggedSummary() throws Exception {
+        final long startTime = 1;
+        final long endTime = 100;
+
+        reset(mStatsSession);
+        when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession);
+        when(mStatsSession.getTaggedSummaryForAllUid(any(NetworkTemplate.class),
+                anyLong(), anyLong()))
+                .thenReturn(new android.net.NetworkStats(0, 0));
+        final NetworkTemplate template = new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
+                .setMeteredness(NetworkStats.Bucket.METERED_YES).build();
+        NetworkStats stats = mManager.queryTaggedSummary(template, startTime, endTime);
+
+        verify(mStatsSession, times(1)).getTaggedSummaryForAllUid(
+                eq(template), eq(startTime), eq(endTime));
+
+        assertFalse(stats.hasNextBucket());
+    }
+
     private void assertBucketMatches(Entry expected, NetworkStats.Bucket actual) {
         assertEquals(expected.uid, actual.getUid());
         assertEquals(expected.rxBytes, actual.getRxBytes());
diff --git a/tests/unit/java/android/net/Ikev2VpnProfileTest.java b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
index 83de40e..a151f03 100644
--- a/tests/unit/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
@@ -35,6 +35,7 @@
 import com.android.testutils.DevSdkIgnoreRunner;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -64,6 +65,9 @@
     private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
     private static final int TEST_MTU = 1300;
 
+    @Rule
+    public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
     private final MockContext mMockContext =
             new MockContext() {
                 @Override
diff --git a/tests/unit/java/android/net/NetworkStatsTest.java b/tests/unit/java/android/net/NetworkStatsTest.java
index c971da1..b0cc16c 100644
--- a/tests/unit/java/android/net/NetworkStatsTest.java
+++ b/tests/unit/java/android/net/NetworkStatsTest.java
@@ -37,6 +37,7 @@
 import static android.net.NetworkStats.UID_ALL;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.os.Build;
@@ -53,8 +54,10 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Iterator;
 
 @RunWith(DevSdkIgnoreRunner.class)
 @SmallTest
@@ -1037,6 +1040,29 @@
         assertEquals(secondEntry, stats.getValues(1, null));
     }
 
+    @Test
+    public void testIterator() {
+        final NetworkStats emptyStats = new NetworkStats(0, 0);
+        final Iterator emptyIterator = emptyStats.iterator();
+        assertFalse(emptyIterator.hasNext());
+
+        final int numEntries = 10;
+        final ArrayList<NetworkStats.Entry> entries = new ArrayList<>();
+        final NetworkStats stats = new NetworkStats(TEST_START, 1);
+        for (int i = 0; i < numEntries; ++i) {
+            NetworkStats.Entry entry = new NetworkStats.Entry("test1", 10100, SET_DEFAULT,
+                    TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
+                    i * 10L /* rxBytes */, i * 3L /* rxPackets */,
+                    i * 15L /* txBytes */, i * 2L /* txPackets */, 0L /* operations */);
+            stats.insertEntry(entry);
+            entries.add(entry);
+        }
+
+        for (NetworkStats.Entry e : stats) {
+            assertEquals(e, entries.remove(0));
+        }
+    }
+
     private static void assertContains(NetworkStats stats,  String iface, int uid, int set,
             int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
             long txBytes, long txPackets, long operations) {
@@ -1057,22 +1083,22 @@
     private static void assertValues(
             NetworkStats.Entry entry, String iface, int uid, int set, int tag, int metered,
             int roaming, int defaultNetwork) {
-        assertEquals(iface, entry.iface);
-        assertEquals(uid, entry.uid);
-        assertEquals(set, entry.set);
-        assertEquals(tag, entry.tag);
-        assertEquals(metered, entry.metered);
-        assertEquals(roaming, entry.roaming);
-        assertEquals(defaultNetwork, entry.defaultNetwork);
+        assertEquals(iface, entry.getIface());
+        assertEquals(uid, entry.getUid());
+        assertEquals(set, entry.getSet());
+        assertEquals(tag, entry.getTag());
+        assertEquals(metered, entry.getMetered());
+        assertEquals(roaming, entry.getRoaming());
+        assertEquals(defaultNetwork, entry.getDefaultNetwork());
     }
 
     private static void assertValues(NetworkStats.Entry entry, long rxBytes, long rxPackets,
             long txBytes, long txPackets, long operations) {
-        assertEquals(rxBytes, entry.rxBytes);
-        assertEquals(rxPackets, entry.rxPackets);
-        assertEquals(txBytes, entry.txBytes);
-        assertEquals(txPackets, entry.txPackets);
-        assertEquals(operations, entry.operations);
+        assertEquals(rxBytes, entry.getRxBytes());
+        assertEquals(rxPackets, entry.getRxPackets());
+        assertEquals(txBytes, entry.getTxBytes());
+        assertEquals(txPackets, entry.getTxPackets());
+        assertEquals(operations, entry.getOperations());
     }
 
 }
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 8d91552..abb34dc 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -51,6 +51,7 @@
 import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
@@ -250,6 +251,7 @@
 import android.net.NetworkTestResultParcelable;
 import android.net.OemNetworkPreferences;
 import android.net.PacProxyManager;
+import android.net.ProfileNetworkPreference;
 import android.net.Proxy;
 import android.net.ProxyInfo;
 import android.net.QosCallbackException;
@@ -13755,12 +13757,12 @@
     }
 
     /**
-     * Make sure per-profile networking preference behaves as expected when the enterprise network
-     * goes up and down while the preference is active. Make sure they behave as expected whether
-     * there is a general default network or not.
+     * Make sure per profile network preferences behave as expected for a given
+     * profile network preference.
      */
-    @Test
-    public void testPreferenceForUserNetworkUpDown() throws Exception {
+    public void testPreferenceForUserNetworkUpDownForGivenPreference(
+            ProfileNetworkPreference profileNetworkPreference,
+            boolean connectWorkProfileAgentAhead) throws Exception {
         final InOrder inOrder = inOrder(mMockNetd);
         final UserHandle testHandle = setupEnterpriseNetwork();
         registerDefaultNetworkCallbacks();
@@ -13774,29 +13776,45 @@
         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
 
+        final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
+        if (connectWorkProfileAgentAhead) {
+            workAgent.connect(false);
+        }
 
         final TestOnCompleteListener listener = new TestOnCompleteListener();
-        mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+        mCm.setProfileNetworkPreferences(testHandle, List.of(profileNetworkPreference),
                 r -> r.run(), listener);
         listener.expectOnComplete();
-
-        // Setting a network preference for this user will create a new set of routing rules for
-        // the UID range that corresponds to this user, so as to define the default network
-        // for these apps separately. This is true because the multi-layer request relevant to
-        // this UID range contains a TRACK_DEFAULT, so the range will be moved through UID-specific
-        // rules to the correct network – in this case the system default network. The case where
-        // the default network for the profile happens to be the same as the system default
-        // is not handled specially, the rules are always active as long as a preference is set.
-        inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
-                PREFERENCE_ORDER_PROFILE));
+        boolean allowFallback = true;
+        if (profileNetworkPreference.getPreference()
+                == PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) {
+            allowFallback = false;
+        }
+        if (allowFallback) {
+            // Setting a network preference for this user will create a new set of routing rules for
+            // the UID range that corresponds to this user, inorder to define the default network
+            // for these apps separately. This is true because the multi-layer request relevant to
+            // this UID range contains a TRACK_DEFAULT, so the range will be moved through
+            // UID-specific rules to the correct network – in this case the system default network.
+            // The case where the default network for the profile happens to be the same as the
+            // system default is not handled specially, the rules are always active as long as
+            // a preference is set.
+            inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                    mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
+                    PREFERENCE_ORDER_PROFILE));
+        }
 
         // The enterprise network is not ready yet.
-        assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
-                mProfileDefaultNetworkCallback);
+        assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+        if (allowFallback) {
+            assertNoCallbacks(mProfileDefaultNetworkCallback);
+        } else if (!connectWorkProfileAgentAhead) {
+            mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        }
 
-        final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
-        workAgent.connect(false);
+        if (!connectWorkProfileAgentAhead) {
+            workAgent.connect(false);
+        }
 
         mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
         mSystemDefaultNetworkCallback.assertNoCallback();
@@ -13805,9 +13823,12 @@
                 nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
-        inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
-                PREFERENCE_ORDER_PROFILE));
+
+        if (allowFallback) {
+            inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
+                    mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
+                    PREFERENCE_ORDER_PROFILE));
+        }
 
         // Make sure changes to the work agent send callbacks to the app in the work profile, but
         // not to the other apps.
@@ -13853,17 +13874,23 @@
         // default network.
         workAgent.disconnect();
         mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent);
-        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        if (allowFallback) {
+            mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        }
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
-        inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
-                PREFERENCE_ORDER_PROFILE));
+        if (allowFallback) {
+            inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                    mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
+                    PREFERENCE_ORDER_PROFILE));
+        }
         inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
 
         mCellNetworkAgent.disconnect();
         mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
-        mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        if (allowFallback) {
+            mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        }
 
         // Waiting for the handler to be idle before checking for networkDestroy is necessary
         // here because ConnectivityService calls onLost before the network is fully torn down.
@@ -13891,7 +13918,7 @@
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
         inOrder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
 
-        // When the agent disconnects, test that the app on the work profile falls back to the
+        // When the agent disconnects, test that the app on the work profile fall back to the
         // default network.
         workAgent2.disconnect();
         mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent2);
@@ -13905,6 +13932,52 @@
     }
 
     /**
+     * Make sure per-profile networking preference behaves as expected when the enterprise network
+     * goes up and down while the preference is active. Make sure they behave as expected whether
+     * there is a general default network or not.
+     */
+    @Test
+    public void testPreferenceForUserNetworkUpDown() throws Exception {
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+        testPreferenceForUserNetworkUpDownForGivenPreference(
+                profileNetworkPreferenceBuilder.build(), false);
+    }
+
+    /**
+     * Make sure per-profile networking preference behaves as expected when the enterprise network
+     * goes up and down while the preference is active. Make sure they behave as expected whether
+     * there is a general default network or not when configured to not fallback to default network.
+     */
+    @Test
+    public void testPreferenceForUserNetworkUpDownWithNoFallback() throws Exception {
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder.setPreference(
+                PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
+        testPreferenceForUserNetworkUpDownForGivenPreference(
+                profileNetworkPreferenceBuilder.build(), false);
+    }
+
+    /**
+     * Make sure per-profile networking preference behaves as expected when the enterprise network
+     * goes up and down while the preference is active. Make sure they behave as expected whether
+     * there is a general default network or not when configured to not fallback to default network
+     * along with already connected enterprise work agent
+     */
+    @Test
+    public void testPreferenceForUserNetworkUpDownWithNoFallbackWithAlreadyConnectedWorkAgent()
+            throws Exception {
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder.setPreference(
+                PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
+        testPreferenceForUserNetworkUpDownForGivenPreference(
+                profileNetworkPreferenceBuilder.build(), true);
+    }
+
+    /**
      * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
      * defaults on then off works as expected.
      */
@@ -14057,7 +14130,8 @@
         assertThrows("Should not be able to set an illegal preference",
                 IllegalArgumentException.class,
                 () -> mCm.setProfileNetworkPreference(testHandle,
-                        PROFILE_NETWORK_PREFERENCE_ENTERPRISE + 1, null, null));
+                        PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK + 1,
+                        null, null));
     }
 
     /**