Merge "Move checkAnyPermissionOf to PermissionUtils"
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index 1fe6c2c..904e8c6 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -328,6 +328,38 @@
     lint: { strict_updatability_linting: true },
 }
 
+// Limited set of utilities for use by service-connectivity-mdns-standalone-build-test, to make sure
+// the mDNS code can build with only system APIs.
+// The mDNS code is platform code so it should use framework-annotations-lib, contrary to apps that
+// should use sdk_version: "system_current" and only androidx.annotation_annotation. But this build
+// rule verifies that the mDNS code can be built into apps, if code transformations are applied to
+// the annotations.
+// When using "system_current", framework annotations are not available; they would appear as
+// package-private as they are marked as such in the system_current stubs. So build against
+// core_platform and add the stubs manually in "libs". See http://b/147773144#comment7.
+java_library {
+    name: "net-utils-device-common-mdns-standalone-build-test",
+    // Build against core_platform and add the stub libraries manually in "libs", as annotations
+    // are already included in android_system_stubs_current but package-private, so
+    // "framework-annotations-lib" needs to be manually included before
+    // "android_system_stubs_current" (b/272392042)
+    sdk_version: "core_platform",
+    srcs: [
+        "device/com/android/net/module/util/FdEventsReader.java",
+        "device/com/android/net/module/util/HexDump.java",
+        "device/com/android/net/module/util/SharedLog.java",
+        "framework/com/android/net/module/util/ByteUtils.java",
+        "framework/com/android/net/module/util/CollectionUtils.java",
+        "framework/com/android/net/module/util/LinkPropertiesUtils.java",
+    ],
+    libs: [
+        "framework-annotations-lib",
+        "android_system_stubs_current",
+        "androidx.annotation_annotation",
+    ],
+    visibility: ["//packages/modules/Connectivity/service-t"],
+}
+
 // Use a filegroup and not a library for telephony sources, as framework-annotations cannot be
 // included either (some annotations would be duplicated on the bootclasspath).
 filegroup {
diff --git a/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java b/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java
index 5a180e7..0a2f50d 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java
@@ -58,8 +58,8 @@
     private static final int TIMEOUT_MS = 500;
 
     /**
-     * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException}
-     * if local and remote are not both null or both non-null.
+     * Construct an inet_diag_req_v2 message. This method will throw
+     * {@link IllegalArgumentException} if local and remote are not both null or both non-null.
      */
     public static byte[] inetDiagReqV2(int protocol, InetSocketAddress local,
             InetSocketAddress remote, int family, short flags) {
@@ -68,16 +68,16 @@
     }
 
     /**
-     * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException}
-     * if local and remote are not both null or both non-null.
+     * Construct an inet_diag_req_v2 message. This method will throw
+     * {@code IllegalArgumentException} if local and remote are not both null or both non-null.
      *
      * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
      *                 IPPROTO_UDP, or IPPROTO_UDPLITE.
      * @param local local socket address of the target socket. This will be packed into a
-     *              {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
+     *              {@link StructInetDiagSockId}. Request to diagnose for all sockets if both of
      *              local or remote address is null.
      * @param remote remote socket address of the target socket. This will be packed into a
-     *              {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
+     *              {@link StructInetDiagSockId}. Request to diagnose for all sockets if both of
      *              local or remote address is null.
      * @param family the ip family of the request message. This should be set to either AF_INET or
      *               AF_INET6 for IPv4 or IPv6 sockets respectively.
@@ -90,18 +90,47 @@
      */
     public static byte[] inetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
             @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt,
-            int state) throws NullPointerException {
+            int state) throws IllegalArgumentException {
+        // Request for all sockets if no specific socket is requested. Specify the local and remote
+        // socket address information for target request socket.
+        if ((local == null) != (remote == null)) {
+            throw new IllegalArgumentException(
+                    "Local and remote must be both null or both non-null");
+        }
+        final StructInetDiagSockId id = ((local != null && remote != null)
+                ? new StructInetDiagSockId(local, remote) : null);
+        return inetDiagReqV2(protocol, id, family,
+                SOCK_DIAG_BY_FAMILY, flags, pad, idiagExt, state);
+    }
+
+    /**
+     * Construct an inet_diag_req_v2 message.
+     *
+     * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
+     *                 IPPROTO_UDP, or IPPROTO_UDPLITE.
+     * @param id inet_diag_sockid. See {@link StructInetDiagSockId}
+     * @param family the ip family of the request message. This should be set to either AF_INET or
+     *               AF_INET6 for IPv4 or IPv6 sockets respectively.
+     * @param type message types.
+     * @param flags message flags. See <linux_src>/include/uapi/linux/netlink.h.
+     * @param pad for raw socket protocol specification.
+     * @param idiagExt a set of flags defining what kind of extended information to report.
+     * @param state a bit mask that defines a filter of socket states.
+     * @return bytes array representation of the message
+     */
+    public static byte[] inetDiagReqV2(int protocol, @Nullable StructInetDiagSockId id, int family,
+            short type, short flags, int pad, int idiagExt, int state) {
         final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
         final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
         byteBuffer.order(ByteOrder.nativeOrder());
 
         final StructNlMsgHdr nlMsgHdr = new StructNlMsgHdr();
         nlMsgHdr.nlmsg_len = bytes.length;
-        nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY;
+        nlMsgHdr.nlmsg_type = type;
         nlMsgHdr.nlmsg_flags = flags;
         nlMsgHdr.pack(byteBuffer);
         final StructInetDiagReqV2 inetDiagReqV2 =
-                new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state);
+                new StructInetDiagReqV2(protocol, id, family, pad, idiagExt, state);
 
         inetDiagReqV2.pack(byteBuffer);
         return bytes;
diff --git a/staticlibs/device/com/android/net/module/util/netlink/NetlinkConstants.java b/staticlibs/device/com/android/net/module/util/netlink/NetlinkConstants.java
index c44a5b4..44c51d8 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/NetlinkConstants.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/NetlinkConstants.java
@@ -141,6 +141,7 @@
 
     /* see include/uapi/linux/sock_diag.h */
     public static final short SOCK_DIAG_BY_FAMILY = 20;
+    public static final short SOCK_DESTROY = 21;
 
     // Netlink groups.
     public static final int RTMGRP_LINK = 1;
diff --git a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
index ae16cf8..d4bf14a 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -81,6 +82,54 @@
     }
 
     /**
+     * Parse netlink error message
+     *
+     * @param bytes byteBuffer to parse netlink error message
+     * @return NetlinkErrorMessage if bytes contains valid NetlinkErrorMessage, else {@code null}
+     */
+    @Nullable
+    private static NetlinkErrorMessage parseNetlinkErrorMessage(ByteBuffer bytes) {
+        final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(bytes);
+        if (nlmsghdr == null || nlmsghdr.nlmsg_type != NetlinkConstants.NLMSG_ERROR) {
+            return null;
+        }
+        return NetlinkErrorMessage.parse(nlmsghdr, bytes);
+    }
+
+    /**
+     * Receive netlink ack message and check error
+     *
+     * @param fd fd to read netlink message
+     */
+    public static void receiveNetlinkAck(final FileDescriptor fd)
+            throws InterruptedIOException, ErrnoException {
+        final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
+        // recvMessage() guaranteed to not return null if it did not throw.
+        final NetlinkErrorMessage response = parseNetlinkErrorMessage(bytes);
+        if (response != null && response.getNlMsgError() != null) {
+            final int errno = response.getNlMsgError().error;
+            if (errno != 0) {
+                // TODO: consider ignoring EINVAL (-22), which appears to be
+                // normal when probing a neighbor for which the kernel does
+                // not already have / no longer has a link layer address.
+                Log.e(TAG, "receiveNetlinkAck, errmsg=" + response.toString());
+                // Note: convert kernel errnos (negative) into userspace errnos (positive).
+                throw new ErrnoException(response.toString(), Math.abs(errno));
+            }
+        } else {
+            final String errmsg;
+            if (response == null) {
+                bytes.position(0);
+                errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
+            } else {
+                errmsg = response.toString();
+            }
+            Log.e(TAG, "receiveNetlinkAck, errmsg=" + errmsg);
+            throw new ErrnoException(errmsg, EPROTO);
+        }
+    }
+
+    /**
      * Send one netlink message to kernel via netlink socket.
      *
      * @param nlProto netlink protocol type.
@@ -93,31 +142,7 @@
         try {
             connectSocketToNetlink(fd);
             sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT_MS);
-            final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
-            // recvMessage() guaranteed to not return null if it did not throw.
-            final NetlinkMessage response = NetlinkMessage.parse(bytes, nlProto);
-            if (response != null && response instanceof NetlinkErrorMessage
-                    && (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
-                final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
-                if (errno != 0) {
-                    // TODO: consider ignoring EINVAL (-22), which appears to be
-                    // normal when probing a neighbor for which the kernel does
-                    // not already have / no longer has a link layer address.
-                    Log.e(TAG, errPrefix + ", errmsg=" + response.toString());
-                    // Note: convert kernel errnos (negative) into userspace errnos (positive).
-                    throw new ErrnoException(response.toString(), Math.abs(errno));
-                }
-            } else {
-                final String errmsg;
-                if (response == null) {
-                    bytes.position(0);
-                    errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
-                } else {
-                    errmsg = response.toString();
-                }
-                Log.e(TAG, errPrefix + ", errmsg=" + errmsg);
-                throw new ErrnoException(errmsg, EPROTO);
-            }
+            receiveNetlinkAck(fd);
         } catch (InterruptedIOException e) {
             Log.e(TAG, errPrefix, e);
             throw new ErrnoException(errPrefix, ETIMEDOUT, e);
diff --git a/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagMsg.java b/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagMsg.java
index e7fc02f..cbd895d 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagMsg.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagMsg.java
@@ -43,14 +43,22 @@
  */
 public class StructInetDiagMsg {
     public static final int STRUCT_SIZE = 4 + StructInetDiagSockId.STRUCT_SIZE + 20;
-    // Offset to the id field from the beginning of inet_diag_msg struct
-    private static final int IDIAG_SOCK_ID_OFFSET = 4;
-    // Offset to the idiag_uid field from the beginning of inet_diag_msg struct
-    private static final int IDIAG_UID_OFFSET =
-            IDIAG_SOCK_ID_OFFSET + StructInetDiagSockId.STRUCT_SIZE + 12;
-    public int idiag_uid;
+    public short idiag_family;
+    public short idiag_state;
+    public short idiag_timer;
+    public short idiag_retrans;
     @NonNull
     public StructInetDiagSockId id;
+    public long idiag_expires;
+    public long idiag_rqueue;
+    public long idiag_wqueue;
+    // Use int for uid since other code use int for uid and uid fits to int
+    public int idiag_uid;
+    public long idiag_inode;
+
+    private static short unsignedByte(byte b) {
+        return (short) (b & 0xFF);
+    }
 
     /**
      * Parse inet diag netlink message from buffer.
@@ -60,26 +68,36 @@
         if (byteBuffer.remaining() < STRUCT_SIZE) {
             return null;
         }
-        final int baseOffset = byteBuffer.position();
         StructInetDiagMsg struct = new StructInetDiagMsg();
-        final byte family = byteBuffer.get();
-        byteBuffer.position(baseOffset + IDIAG_SOCK_ID_OFFSET);
-        struct.id = StructInetDiagSockId.parse(byteBuffer, family);
+        struct.idiag_family = unsignedByte(byteBuffer.get());
+        struct.idiag_state = unsignedByte(byteBuffer.get());
+        struct.idiag_timer = unsignedByte(byteBuffer.get());
+        struct.idiag_retrans = unsignedByte(byteBuffer.get());
+        struct.id = StructInetDiagSockId.parse(byteBuffer, struct.idiag_family);
         if (struct.id == null) {
             return null;
         }
-        struct.idiag_uid = byteBuffer.getInt(baseOffset + IDIAG_UID_OFFSET);
-
-        // Move position to the end of the inet_diag_msg
-        byteBuffer.position(baseOffset + STRUCT_SIZE);
+        struct.idiag_expires = Integer.toUnsignedLong(byteBuffer.getInt());
+        struct.idiag_rqueue = Integer.toUnsignedLong(byteBuffer.getInt());
+        struct.idiag_wqueue = Integer.toUnsignedLong(byteBuffer.getInt());
+        struct.idiag_uid = byteBuffer.getInt();
+        struct.idiag_inode = Integer.toUnsignedLong(byteBuffer.getInt());
         return struct;
     }
 
     @Override
     public String toString() {
         return "StructInetDiagMsg{ "
-                + "idiag_uid{" + idiag_uid + "}, "
+                + "idiag_family{" + idiag_family + "}, "
+                + "idiag_state{" + idiag_state + "}, "
+                + "idiag_timer{" + idiag_timer + "}, "
+                + "idiag_retrans{" + idiag_retrans + "}, "
                 + "id{" + id + "}, "
+                + "idiag_expires{" + idiag_expires + "}, "
+                + "idiag_rqueue{" + idiag_rqueue + "}, "
+                + "idiag_wqueue{" + idiag_wqueue + "}, "
+                + "idiag_uid{" + idiag_uid + "}, "
+                + "idiag_inode{" + idiag_inode + "}, "
                 + "}";
     }
 }
diff --git a/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java b/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java
index 6eef865..3b47008 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagReqV2.java
@@ -18,7 +18,6 @@
 
 import androidx.annotation.Nullable;
 
-import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 
 /**
@@ -48,23 +47,11 @@
     private final int mState;
     public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
 
-    public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote,
-            int family) {
-        this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */,
-                INET_DIAG_REQ_V2_ALL_STATES);
-    }
-
-    public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
-            @Nullable InetSocketAddress remote, int family, int pad, int extension, int state)
-            throws NullPointerException {
+    public StructInetDiagReqV2(int protocol, @Nullable StructInetDiagSockId id, int family, int pad,
+            int extension, int state) {
         mSdiagFamily = (byte) family;
         mSdiagProtocol = (byte) protocol;
-        // Request for all sockets if no specific socket is requested. Specify the local and remote
-        // socket address information for target request socket.
-        if ((local == null) != (remote == null)) {
-            throw new NullPointerException("Local and remote must be both null or both non-null");
-        }
-        mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null);
+        mId = id;
         mPad = (byte) pad;
         mIdiagExt = (byte) extension;
         mState = state;
diff --git a/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagSockId.java b/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagSockId.java
index 648a020..dd85934 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagSockId.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/StructInetDiagSockId.java
@@ -29,6 +29,7 @@
 import androidx.annotation.Nullable;
 
 import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
@@ -80,7 +81,7 @@
      * Parse inet diag socket id from buffer.
      */
     @Nullable
-    public static StructInetDiagSockId parse(final ByteBuffer byteBuffer, final byte family) {
+    public static StructInetDiagSockId parse(final ByteBuffer byteBuffer, final short family) {
         if (byteBuffer.remaining() < STRUCT_SIZE) {
             return null;
         }
@@ -89,43 +90,53 @@
         final int srcPort = Short.toUnsignedInt(byteBuffer.getShort());
         final int dstPort = Short.toUnsignedInt(byteBuffer.getShort());
 
-        final byte[] srcAddrByte;
-        final byte[] dstAddrByte;
+        final InetAddress srcAddr;
+        final InetAddress dstAddr;
         if (family == AF_INET) {
-            srcAddrByte = new byte[IPV4_ADDR_LEN];
-            dstAddrByte = new byte[IPV4_ADDR_LEN];
+            final byte[] srcAddrByte = new byte[IPV4_ADDR_LEN];
+            final byte[] dstAddrByte = new byte[IPV4_ADDR_LEN];
             byteBuffer.get(srcAddrByte);
             // Address always uses IPV6_ADDR_LEN in the buffer. So if the address is IPv4, position
             // needs to be advanced to the next field.
             byteBuffer.position(byteBuffer.position() + (IPV6_ADDR_LEN - IPV4_ADDR_LEN));
             byteBuffer.get(dstAddrByte);
             byteBuffer.position(byteBuffer.position() + (IPV6_ADDR_LEN - IPV4_ADDR_LEN));
+            try {
+                srcAddr = Inet4Address.getByAddress(srcAddrByte);
+                dstAddr = Inet4Address.getByAddress(dstAddrByte);
+            } catch (UnknownHostException e) {
+                Log.wtf(TAG, "Failed to parse address: " + e);
+                return null;
+            }
         } else if (family == AF_INET6) {
-            srcAddrByte = new byte[IPV6_ADDR_LEN];
-            dstAddrByte = new byte[IPV6_ADDR_LEN];
+            final byte[] srcAddrByte = new byte[IPV6_ADDR_LEN];
+            final byte[] dstAddrByte = new byte[IPV6_ADDR_LEN];
             byteBuffer.get(srcAddrByte);
             byteBuffer.get(dstAddrByte);
+            try {
+                // Using Inet6Address.getByAddress to be consistent with idiag_family field since
+                // InetAddress.getByAddress returns Inet4Address if the address is v4-mapped v6
+                // address.
+                srcAddr = Inet6Address.getByAddress(
+                        null /* host */, srcAddrByte, -1 /* scope_id */);
+                dstAddr = Inet6Address.getByAddress(
+                        null /* host */, dstAddrByte, -1 /* scope_id */);
+            } catch (UnknownHostException e) {
+                Log.wtf(TAG, "Failed to parse address: " + e);
+                return null;
+            }
         } else {
             Log.wtf(TAG, "Invalid address family: " + family);
             return null;
         }
 
-        final InetSocketAddress srcAddr;
-        final InetSocketAddress dstAddr;
-        try {
-            srcAddr = new InetSocketAddress(InetAddress.getByAddress(srcAddrByte), srcPort);
-            dstAddr = new InetSocketAddress(InetAddress.getByAddress(dstAddrByte), dstPort);
-        } catch (UnknownHostException e) {
-            // Should not happen. UnknownHostException is thrown only if addr byte array is of
-            // illegal length.
-            Log.wtf(TAG, "Failed to parse address: " + e);
-            return null;
-        }
+        final InetSocketAddress srcSocketAddr = new InetSocketAddress(srcAddr, srcPort);
+        final InetSocketAddress dstSocketAddr = new InetSocketAddress(dstAddr, dstPort);
 
         byteBuffer.order(ByteOrder.nativeOrder());
         final int ifIndex = byteBuffer.getInt();
         final long cookie = byteBuffer.getLong();
-        return new StructInetDiagSockId(srcAddr, dstAddr, ifIndex, cookie);
+        return new StructInetDiagSockId(srcSocketAddr, dstSocketAddr, ifIndex, cookie);
     }
 
     /**
diff --git a/staticlibs/framework/com/android/net/module/util/LinkPropertiesUtils.java b/staticlibs/framework/com/android/net/module/util/LinkPropertiesUtils.java
index 1565f2b..e271f64 100644
--- a/staticlibs/framework/com/android/net/module/util/LinkPropertiesUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/LinkPropertiesUtils.java
@@ -146,6 +146,24 @@
                 right != null ? right.getLinkAddresses() : null);
     }
 
+    /**
+     * Compares {@code left} {@code LinkProperties} allLinkAddresses against the {@code right}.
+     *
+     * @param left A LinkProperties or null
+     * @param right A LinkProperties or null
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     * @see LinkProperties#getAllLinkAddresses()
+     */
+    public static boolean isIdenticalAllLinkAddresses(@Nullable LinkProperties left,
+            @Nullable LinkProperties right) {
+        if (left == right) return true;
+        if (left == null || right == null) return false;
+        final List<LinkAddress> leftAddresses = left.getAllLinkAddresses();
+        final List<LinkAddress> rightAddresses = right.getAllLinkAddresses();
+        if (leftAddresses.size() != rightAddresses.size()) return false;
+        return leftAddresses.containsAll(rightAddresses);
+    }
+
    /**
      * Compares {@code left} {@code LinkProperties} interface addresses against the {@code right}.
      *
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
index 1d88d6e..aa2dd4c 100644
--- a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
+++ b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
@@ -208,6 +208,9 @@
      */
     public static final int INFINITE_LEASE = 0xffffffff;
     public static final int DHCP4_CLIENT_PORT = 68;
+    // The maximum length of a DHCP packet that can be constructed.
+    public static final int DHCP_MAX_LENGTH = 1500;
+    public static final int DHCP_MAX_OPTION_LEN = 255;
 
     /**
      * DHCPv6 constants.
diff --git a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
index 206acba..99c7a91 100644
--- a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
@@ -63,8 +63,9 @@
     // 4.9 kernels. The kernel code of socket release on pf_key socket will
     // explicitly call synchronize_rcu() which is exactly what we need.
     //
-    // Linux 4.14/4.19/5.4/5.10/5.15 (and 5.18) still have this same behaviour.
+    // Linux 4.14/4.19/5.4/5.10/5.15/6.1 (and 6.3-rc5) still have this same behaviour.
     // see net/key/af_key.c: pfkey_release() -> synchronize_rcu()
+    // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/key/af_key.c?h=v6.3-rc5#n185
     const int pfSocket = socket(AF_KEY, SOCK_RAW | SOCK_CLOEXEC, PF_KEY_V2);
 
     if (pfSocket < 0) {
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java
index 09f0490..80ab618 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java
@@ -94,6 +94,9 @@
         assertTrue(LinkPropertiesUtils.isIdenticalAddresses(source, target));
         assertTrue(LinkPropertiesUtils.isIdenticalAddresses(target, source));
 
+        assertTrue(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target));
+        assertTrue(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source));
+
         assertTrue(LinkPropertiesUtils.isIdenticalDnses(source, target));
         assertTrue(LinkPropertiesUtils.isIdenticalDnses(target, source));
 
@@ -116,12 +119,17 @@
         assertFalse(LinkPropertiesUtils.isIdenticalAddresses(source, target));
         assertFalse(LinkPropertiesUtils.isIdenticalAddresses(target, source));
 
+        assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target));
+        assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source));
+
         // Currently, target contains V4_LINKADDR, V6_LINKADDR and testLinkAddr.
         // Compare addresses.size() equals but contains different address.
         target.removeLinkAddress(V4_LINKADDR);
         assertEquals(source.getAddresses().size(), target.getAddresses().size());
         assertFalse(LinkPropertiesUtils.isIdenticalAddresses(source, target));
         assertFalse(LinkPropertiesUtils.isIdenticalAddresses(target, source));
+        assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target));
+        assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source));
         // Restore link address
         target.addLinkAddress(V4_LINKADDR);
         target.removeLinkAddress(testLinkAddr);
@@ -169,6 +177,13 @@
         target.setHttpProxy(null);
         assertFalse(LinkPropertiesUtils.isIdenticalHttpProxy(source, target));
         assertFalse(LinkPropertiesUtils.isIdenticalHttpProxy(target, source));
+
+        final LinkProperties stacked = new LinkProperties();
+        stacked.setInterfaceName("v4-" + target.getInterfaceName());
+        stacked.addLinkAddress(testLinkAddr);
+        target.addStackedLink(stacked);
+        assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target));
+        assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source));
     }
 
     private <T> void compareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved,
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java
index d81422f..30796d2 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java
@@ -22,6 +22,8 @@
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.NETLINK_INET_DIAG;
 
+import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DESTROY;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
 
@@ -41,6 +43,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
@@ -49,6 +52,21 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class InetDiagSocketTest {
+    // ::FFFF:192.0.2.1
+    private static final byte[] SRC_V4_MAPPED_V6_ADDRESS_BYTES = {
+            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+            (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff,
+            (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01,
+    };
+    // ::FFFF:192.0.2.2
+    private static final byte[] DST_V4_MAPPED_V6_ADDRESS_BYTES = {
+            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+            (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff,
+            (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02,
+    };
+
     // Hexadecimal representation of InetDiagReqV2 request.
     private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX =
             // struct nlmsghdr
@@ -205,14 +223,14 @@
             msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6,
                     NLM_F_REQUEST);
             fail("Both remote and local should be null, expected UnknownHostException");
-        } catch (NullPointerException e) {
+        } catch (IllegalArgumentException e) {
         }
 
         try {
             msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6,
                     NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
             fail("Both remote and local should be null, expected UnknownHostException");
-        } catch (NullPointerException e) {
+        } catch (IllegalArgumentException e) {
         }
 
         msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
@@ -221,6 +239,85 @@
         assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_BYTES, msgExt);
     }
 
+    // Hexadecimal representation of InetDiagReqV2 request with v4-mapped v6 address
+    private static final String INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_HEX =
+            // struct nlmsghdr
+            "48000000" +     // length = 72
+            "1400" +         // type = SOCK_DIAG_BY_FAMILY
+            "0100" +         // flags = NLM_F_REQUEST
+            "00000000" +     // seqno
+            "00000000" +     // pid (0 == kernel)
+            // struct inet_diag_req_v2
+            "0a" +           // family = AF_INET6
+            "06" +           // protcol = IPPROTO_TCP
+            "00" +           // idiag_ext
+            "00" +           // pad
+            "ffffffff" +     // idiag_states
+            // inet_diag_sockid
+            "a817" +     // idiag_sport = 43031
+            "960f" +     // idiag_dport = 38415
+            "00000000000000000000ffffc0000201" + // idiag_src = ::FFFF:192.0.2.1
+            "00000000000000000000ffffc0000202" + // idiag_dst = ::FFFF:192.0.2.2
+            "00000000" +     // idiag_if
+            "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
+
+    private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_BYTES =
+            HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_HEX.toCharArray(), false);
+
+    @Test
+    public void testInetDiagReqV2TcpInet6V4Mapped() throws Exception {
+        final Inet6Address srcAddr = Inet6Address.getByAddress(
+                null /* host */, SRC_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */);
+        final Inet6Address dstAddr = Inet6Address.getByAddress(
+                null /* host */, DST_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */);
+        final byte[] msg = InetDiagMessage.inetDiagReqV2(
+                IPPROTO_TCP,
+                new InetSocketAddress(srcAddr, 43031),
+                new InetSocketAddress(dstAddr, 38415),
+                AF_INET6,
+                NLM_F_REQUEST);
+        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_BYTES, msg);
+    }
+
+    // Hexadecimal representation of InetDiagReqV2 request with SOCK_DESTROY
+    private static final String INET_DIAG_REQ_V2_TCP_INET6_DESTROY_HEX =
+            // struct nlmsghdr
+            "48000000" +     // length = 72
+            "1500" +         // type = SOCK_DESTROY
+            "0500" +         // flags = NLM_F_REQUEST | NLM_F_ACK
+            "00000000" +     // seqno
+            "00000000" +     // pid (0 == kernel)
+            // struct inet_diag_req_v2
+            "0a" +           // family = AF_INET6
+            "06" +           // protcol = IPPROTO_TCP
+            "00" +           // idiag_ext
+            "00" +           // pad
+            "ffffffff" +     // idiag_states = TCP_ALL_STATES
+            // inet_diag_sockid
+            "a817" +     // idiag_sport = 43031
+            "960f" +     // idiag_dport = 38415
+            "20010db8000000000000000000000001" + // idiag_src = 2001:db8::1
+            "20010db8000000000000000000000002" + // idiag_dst = 2001:db8::2
+            "07000000" + // idiag_if = 7
+            "5800000000000000"; // idiag_cookie = 88
+
+    private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_DESTROY_BYTES =
+            HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_DESTROY_HEX.toCharArray(), false);
+
+    @Test
+    public void testInetDiagReqV2TcpInet6Destroy() throws Exception {
+        final StructInetDiagSockId sockId = new StructInetDiagSockId(
+                new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::1"), 43031),
+                new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::2"), 38415),
+                7  /* ifIndex */,
+                88 /* cookie */);
+        final byte[] msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, sockId, AF_INET6,
+                SOCK_DESTROY, (short) (NLM_F_REQUEST | NLM_F_ACK), 0 /* pad */, 0 /* idiagExt */,
+                TCP_ALL_STATES);
+
+        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_DESTROY_BYTES, msg);
+    }
+
     private void assertNlMsgHdr(StructNlMsgHdr hdr, short type, short flags, int seq, int pid) {
         assertNotNull(hdr);
         assertEquals(type, hdr.nlmsg_type);
@@ -248,9 +345,9 @@
             "f5220000" +     // pid
             // struct inet_diag_msg
             "0a" +           // family = AF_INET6
-            "01" +           // idiag_state
-            "00" +           // idiag_timer
-            "00" +           // idiag_retrans
+            "01" +           // idiag_state = 1
+            "02" +           // idiag_timer = 2
+            "ff" +           // idiag_retrans = 255
                 // inet_diag_sockid
                 "a817" +     // idiag_sport = 43031
                 "960f" +     // idiag_dport = 38415
@@ -258,11 +355,11 @@
                 "20010db8000000000000000000000002" + // idiag_dst = 2001:db8::2
                 "07000000" + // idiag_if = 7
                 "5800000000000000" + // idiag_cookie = 88
-            "00000000" +     // idiag_expires
-            "00000000" +     // idiag_rqueue
-            "00000000" +     // idiag_wqueue
+            "04000000" +     // idiag_expires = 4
+            "05000000" +     // idiag_rqueue = 5
+            "06000000" +     // idiag_wqueue = 6
             "a3270000" +     // idiag_uid = 10147
-            "A57E1900";      // idiag_inode
+            "a57e19f0";      // idiag_inode = 4028202661
 
     private void assertInetDiagMsg1(final NetlinkMessage msg) {
         assertNotNull(msg);
@@ -276,12 +373,20 @@
                 0    /* seq */,
                 8949 /* pid */);
 
-        assertEquals(10147, inetDiagMsg.inetDiagMsg.idiag_uid);
+        assertEquals(AF_INET6, inetDiagMsg.inetDiagMsg.idiag_family);
+        assertEquals(1, inetDiagMsg.inetDiagMsg.idiag_state);
+        assertEquals(2, inetDiagMsg.inetDiagMsg.idiag_timer);
+        assertEquals(255, inetDiagMsg.inetDiagMsg.idiag_retrans);
         assertInetDiagSockId(inetDiagMsg.inetDiagMsg.id,
                 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::1"), 43031),
                 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::2"), 38415),
                 7  /* ifIndex */,
                 88 /* cookie */);
+        assertEquals(4, inetDiagMsg.inetDiagMsg.idiag_expires);
+        assertEquals(5, inetDiagMsg.inetDiagMsg.idiag_rqueue);
+        assertEquals(6, inetDiagMsg.inetDiagMsg.idiag_wqueue);
+        assertEquals(10147, inetDiagMsg.inetDiagMsg.idiag_uid);
+        assertEquals(4028202661L, inetDiagMsg.inetDiagMsg.idiag_inode);
     }
 
     // Hexadecimal representation of InetDiagMessage
@@ -294,9 +399,9 @@
             "f5220000" +     // pid
             // struct inet_diag_msg
             "0a" +           // family = AF_INET6
-            "01" +           // idiag_state
-            "00" +           // idiag_timer
-            "00" +           // idiag_retrans
+            "02" +           // idiag_state = 2
+            "10" +           // idiag_timer = 16
+            "20" +           // idiag_retrans = 32
                 // inet_diag_sockid
                 "a845" +     // idiag_sport = 43077
                 "01bb" +     // idiag_dport = 443
@@ -304,11 +409,11 @@
                 "20010db8000000000000000000000004" + // idiag_dst = 2001:db8::4
                 "08000000" + // idiag_if = 8
                 "6300000000000000" + // idiag_cookie = 99
-            "00000000" +     // idiag_expires
-            "00000000" +     // idiag_rqueue
-            "00000000" +     // idiag_wqueue
+            "30000000" +     // idiag_expires = 48
+            "40000000" +     // idiag_rqueue = 64
+            "50000000" +     // idiag_wqueue = 80
             "39300000" +     // idiag_uid = 12345
-            "A57E1900";      // idiag_inode
+            "851a0000";      // idiag_inode = 6789
 
     private void assertInetDiagMsg2(final NetlinkMessage msg) {
         assertNotNull(msg);
@@ -322,12 +427,20 @@
                 0    /* seq */,
                 8949 /* pid */);
 
-        assertEquals(12345, inetDiagMsg.inetDiagMsg.idiag_uid);
+        assertEquals(AF_INET6, inetDiagMsg.inetDiagMsg.idiag_family);
+        assertEquals(2, inetDiagMsg.inetDiagMsg.idiag_state);
+        assertEquals(16, inetDiagMsg.inetDiagMsg.idiag_timer);
+        assertEquals(32, inetDiagMsg.inetDiagMsg.idiag_retrans);
         assertInetDiagSockId(inetDiagMsg.inetDiagMsg.id,
                 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::3"), 43077),
                 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::4"), 443),
                 8  /* ifIndex */,
                 99 /* cookie */);
+        assertEquals(48, inetDiagMsg.inetDiagMsg.idiag_expires);
+        assertEquals(64, inetDiagMsg.inetDiagMsg.idiag_rqueue);
+        assertEquals(80, inetDiagMsg.inetDiagMsg.idiag_wqueue);
+        assertEquals(12345, inetDiagMsg.inetDiagMsg.idiag_uid);
+        assertEquals(6789, inetDiagMsg.inetDiagMsg.idiag_inode);
     }
 
     private static final byte[] INET_DIAG_MSG_BYTES =
@@ -336,7 +449,7 @@
     @Test
     public void testParseInetDiagResponse() throws Exception {
         final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES);
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
+        byteBuffer.order(ByteOrder.nativeOrder());
         assertInetDiagMsg1(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG));
     }
 
@@ -347,8 +460,87 @@
     @Test
     public void testParseInetDiagResponseMultiple() {
         final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES_MULTIPLE);
-        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
+        byteBuffer.order(ByteOrder.nativeOrder());
         assertInetDiagMsg1(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG));
         assertInetDiagMsg2(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG));
     }
+
+    private static final String INET_DIAG_SOCK_ID_V4_MAPPED_V6_HEX =
+            "a845" +     // idiag_sport = 43077
+            "01bb" +     // idiag_dport = 443
+            "00000000000000000000ffffc0000201" + // idiag_src = ::FFFF:192.0.2.1
+            "00000000000000000000ffffc0000202" + // idiag_dst = ::FFFF:192.0.2.2
+            "08000000" + // idiag_if = 8
+            "6300000000000000"; // idiag_cookie = 99
+
+    private static final byte[] INET_DIAG_SOCK_ID_V4_MAPPED_V6_BYTES =
+            HexEncoding.decode(INET_DIAG_SOCK_ID_V4_MAPPED_V6_HEX.toCharArray(), false);
+
+    @Test
+    public void testParseAndPackInetDiagSockIdV4MappedV6() {
+        final ByteBuffer parseByteBuffer = ByteBuffer.wrap(INET_DIAG_SOCK_ID_V4_MAPPED_V6_BYTES);
+        parseByteBuffer.order(ByteOrder.nativeOrder());
+        final StructInetDiagSockId diagSockId =
+                StructInetDiagSockId.parse(parseByteBuffer, (short) AF_INET6);
+        assertNotNull(diagSockId);
+
+        final ByteBuffer packByteBuffer =
+                ByteBuffer.allocate(INET_DIAG_SOCK_ID_V4_MAPPED_V6_BYTES.length);
+        diagSockId.pack(packByteBuffer);
+
+        // Move position to the head since ByteBuffer#equals compares the values from the current
+        // position.
+        parseByteBuffer.position(0);
+        packByteBuffer.position(0);
+        assertEquals(parseByteBuffer, packByteBuffer);
+    }
+
+    // Hexadecimal representation of InetDiagMessage with v4-mapped v6 address
+    private static final String INET_DIAG_MSG_V4_MAPPED_V6_HEX =
+            // struct nlmsghdr
+            "58000000" +     // length = 88
+            "1400" +         // type = SOCK_DIAG_BY_FAMILY
+            "0200" +         // flags = NLM_F_MULTI
+            "00000000" +     // seqno
+            "f5220000" +     // pid
+            // struct inet_diag_msg
+            "0a" +           // family = AF_INET6
+            "01" +           // idiag_state = 1
+            "02" +           // idiag_timer = 2
+            "03" +           // idiag_retrans = 3
+                // inet_diag_sockid
+                "a817" +     // idiag_sport = 43031
+                "960f" +     // idiag_dport = 38415
+                "00000000000000000000ffffc0000201" + // idiag_src = ::FFFF:192.0.2.1
+                "00000000000000000000ffffc0000202" + // idiag_dst = ::FFFF:192.0.2.2
+                "07000000" + // idiag_if = 7
+                "5800000000000000" + // idiag_cookie = 88
+            "04000000" +     // idiag_expires = 4
+            "05000000" +     // idiag_rqueue = 5
+            "06000000" +     // idiag_wqueue = 6
+            "a3270000" +     // idiag_uid = 10147
+            "A57E1900";      // idiag_inode = 1670821
+
+    private static final byte[] INET_DIAG_MSG_V4_MAPPED_V6_BYTES =
+            HexEncoding.decode(INET_DIAG_MSG_V4_MAPPED_V6_HEX.toCharArray(), false);
+
+    @Test
+    public void testParseInetDiagResponseV4MappedV6() throws Exception {
+        final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_V4_MAPPED_V6_BYTES);
+        byteBuffer.order(ByteOrder.nativeOrder());
+        final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG);
+
+        assertNotNull(msg);
+        assertTrue(msg instanceof InetDiagMessage);
+        final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg;
+        final Inet6Address srcAddr = Inet6Address.getByAddress(
+                null /* host */, SRC_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */);
+        final Inet6Address dstAddr = Inet6Address.getByAddress(
+                null /* host */, DST_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */);
+        assertInetDiagSockId(inetDiagMsg.inetDiagMsg.id,
+                new InetSocketAddress(srcAddr, 43031),
+                new InetSocketAddress(dstAddr, 38415),
+                7  /* ifIndex */,
+                88 /* cookie */);
+    }
 }
diff --git a/staticlibs/tests/unit/src/com/android/testutils/TestableNetworkCallbackTest.kt b/staticlibs/tests/unit/src/com/android/testutils/TestableNetworkCallbackTest.kt
index ec7cdbd..4ed881a 100644
--- a/staticlibs/tests/unit/src/com/android/testutils/TestableNetworkCallbackTest.kt
+++ b/staticlibs/tests/unit/src/com/android/testutils/TestableNetworkCallbackTest.kt
@@ -366,18 +366,6 @@
     }
 
     @Test
-    fun testPollOrThrow() {
-        assertFails { mCallback.pollOrThrow(SHORT_TIMEOUT_MS) }
-        TNCInterpreter.interpretTestSpec(initial = mCallback, lineShift = 1,
-                threadTransform = { cb -> cb.createLinkedCopy() }, spec = """
-            sleep; onAvailable(133)    | pollOrThrow(2) = Available(133) time 1..4
-                                       | pollOrThrow(1) fails
-            onCapabilitiesChanged(108) | pollOrThrow(1) = CapabilitiesChanged(108) time 0..3
-            onBlockedStatus(199)       | pollOrThrow(1) = BlockedStatus(199) time 0..3
-        """)
-    }
-
-    @Test
     fun testEventuallyExpect() {
         // TODO: Current test does not verify the inline one. Also verify the behavior after
         // aligning two eventuallyExpect()
@@ -455,7 +443,6 @@
         }
     },
     Regex("""poll\((\d+)\)""") to { i, cb, t -> cb.poll(t.timeArg(1)) },
-    Regex("""pollOrThrow\((\d+)\)""") to { i, cb, t -> cb.pollOrThrow(t.timeArg(1)) },
     // Interpret "eventually(Available(xx), timeout)" as calling eventuallyExpect that expects
     // CallbackEntry.AVAILABLE with netId of xx within timeout*INTERPRET_TIME_UNIT timeout, and
     // likewise for all callback types.
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
index e7d86e0..0e73112 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
@@ -223,18 +223,6 @@
     fun poll(timeoutMs: Long = defaultTimeoutMs, predicate: (CallbackEntry) -> Boolean = { true }) =
             history.poll(timeoutMs, predicate)
 
-    /**
-     * Get the next callback or throw if timeout.
-     *
-     * With no argument, this method waits out the default timeout. To wait forever, pass
-     * Long.MAX_VALUE.
-     */
-    @JvmOverloads
-    fun pollOrThrow(
-        timeoutMs: Long = defaultTimeoutMs,
-        errorMsg: String = "Did not receive callback after $timeoutMs"
-    ): CallbackEntry = poll(timeoutMs) ?: fail(errorMsg)
-
     /*****
      * expect family of methods.
      * These methods fetch the next callback and assert it matches the conditions : type,
@@ -350,15 +338,16 @@
         timeoutMs: Long = defaultTimeoutMs,
         errorMsg: String? = null,
         test: (T) -> Boolean = { true }
-    ) = pollOrThrow(timeoutMs, "Did not receive ${T::class.simpleName} after ${timeoutMs}ms").also {
-        if (it !is T) fail("Expected callback ${T::class.simpleName}, got $it")
-        if (ANY_NETWORK !== network && it.network != network) {
-            fail("Expected network $network for callback : $it")
-        }
-        if (!test(it)) {
-            fail("${errorMsg ?: "Callback doesn't match predicate"} : $it")
-        }
-    } as T
+    ) = (poll(timeoutMs) ?: fail("Did not receive ${T::class.simpleName} after ${timeoutMs}ms"))
+            .also {
+                if (it !is T) fail("Expected callback ${T::class.simpleName}, got $it")
+                if (ANY_NETWORK !== network && it.network != network) {
+                    fail("Expected network $network for callback : $it")
+                }
+                if (!test(it)) {
+                    fail("${errorMsg ?: "Callback doesn't match predicate"} : $it")
+                }
+            } as T
 
     inline fun <reified T : CallbackEntry> expect(
         network: HasNetwork,
@@ -367,6 +356,12 @@
         test: (T) -> Boolean = { true }
     ) = expect(network.network, timeoutMs, errorMsg, test)
 
+    /*****
+     * assertNoCallback family of methods.
+     * These methods make sure that no callback that matches the predicate was received.
+     * If no predicate is given, they make sure that no callback at all was received.
+     * These methods run the waiter func given in the constructor if any.
+     */
     @JvmOverloads
     fun assertNoCallback(
         timeoutMs: Long = defaultNoCallbackTimeoutMs,
@@ -379,9 +374,12 @@
     fun assertNoCallback(valid: (CallbackEntry) -> Boolean) =
             assertNoCallback(defaultNoCallbackTimeoutMs, valid)
 
-    // Expects a callback of the specified type matching the predicate within the timeout.
-    // Any callback that doesn't match the predicate will be skipped. Fails only if
-    // no matching callback is received within the timeout.
+    /*****
+     * eventuallyExpect family of methods.
+     * These methods make sure a callback that matches the type/predicate is received eventually.
+     * Any callback of the wrong type, or doesn't match the optional predicate, is ignored.
+     * They fail if no callback matching the predicate is received within the timeout.
+     */
     inline fun <reified T : CallbackEntry> eventuallyExpect(
         timeoutMs: Long = defaultTimeoutMs,
         from: Int = mark,
@@ -408,13 +406,6 @@
         assertNotNull(it, "Callback ${type.java} not received within ${timeoutMs}ms")
     } as T
 
-    // TODO (b/157405399) remove this method when there are no longer any uses of it.
-    inline fun <reified T : CallbackEntry> eventuallyExpectOrNull(
-        timeoutMs: Long = defaultTimeoutMs,
-        from: Int = mark,
-        crossinline predicate: (T) -> Boolean = { true }
-    ) = history.poll(timeoutMs, from) { it is T && predicate(it) } as T?
-
     // Expects onAvailable and the callbacks that follow it. These are:
     // - onSuspended, iff the network was suspended when the callbacks fire.
     // - onCapabilitiesChanged.