Snap for 12761221 from ce792537c3fc95e8837c78ad52cf37bc4d68ecc7 to mainline-appsearch-release

Change-Id: Ifbe5f385c224c9bb831f236b8697b553613351a9
diff --git a/src/android/net/apf/ApfCounterTracker.java b/src/android/net/apf/ApfCounterTracker.java
index 9700b5b..5bd9877 100644
--- a/src/android/net/apf/ApfCounterTracker.java
+++ b/src/android/net/apf/ApfCounterTracker.java
@@ -102,6 +102,10 @@
         DROPPED_ARP_REQUEST_REPLIED,
         DROPPED_ARP_UNKNOWN,
         DROPPED_ARP_V6_ONLY,
+        DROPPED_IGMP_V2_GENERAL_QUERY_REPLIED,
+        DROPPED_IGMP_V3_GENERAL_QUERY_REPLIED,
+        DROPPED_IGMP_INVALID,
+        DROPPED_IGMP_REPORT,
         DROPPED_GARP_REPLY;  // see also MAX_DROP_COUNTER below
 
         /**
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index 93443e2..7447fc5 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -51,11 +51,13 @@
 import static android.net.ip.IpClient.IpClientCommands.EVENT_NUD_FAILURE_QUERY_FAILURE;
 import static android.net.ip.IpClient.IpClientCommands.EVENT_NUD_FAILURE_QUERY_SUCCESS;
 import static android.net.ip.IpClient.IpClientCommands.EVENT_NUD_FAILURE_QUERY_TIMEOUT;
+import static android.net.ip.IpClient.IpClientCommands.EVENT_PIO_PREFIX_UPDATE;
 import static android.net.ip.IpClient.IpClientCommands.EVENT_PRE_DHCP_ACTION_COMPLETE;
 import static android.net.ip.IpClient.IpClientCommands.EVENT_PROVISIONING_TIMEOUT;
 import static android.net.ip.IpClient.IpClientCommands.EVENT_READ_PACKET_FILTER_COMPLETE;
 import static android.net.ip.IpClientLinkObserver.IpClientNetlinkMonitor;
 import static android.net.ip.IpClientLinkObserver.IpClientNetlinkMonitor.INetlinkMessageProcessor;
+import static android.net.ip.IpClientLinkObserver.PrefixInfo;
 import static android.net.ip.IpReachabilityMonitor.INVALID_REACHABILITY_LOSS_TYPE;
 import static android.net.ip.IpReachabilityMonitor.nudEventTypeToInt;
 import static android.net.util.SocketUtils.makePacketSocketAddress;
@@ -83,6 +85,7 @@
 import static com.android.networkstack.util.NetworkStackUtils.APF_HANDLE_ND_OFFLOAD;
 import static com.android.networkstack.util.NetworkStackUtils.APF_NEW_RA_FILTER_VERSION;
 import static com.android.networkstack.util.NetworkStackUtils.APF_POLLING_COUNTERS_VERSION;
+import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_DHCPV6_PD_PREFERRED_FLAG_VERSION;
 import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_DHCPV6_PREFIX_DELEGATION_VERSION;
 import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_GARP_NA_ROAMING_VERSION;
 import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_IGNORE_LOW_RA_LIFETIME_VERSION;
@@ -607,6 +610,7 @@
         static final int EVENT_NUD_FAILURE_QUERY_TIMEOUT = 21;
         static final int EVENT_NUD_FAILURE_QUERY_SUCCESS = 22;
         static final int EVENT_NUD_FAILURE_QUERY_FAILURE = 23;
+        static final int EVENT_PIO_PREFIX_UPDATE = 24;
         // Internal commands to use instead of trying to call transitionTo() inside
         // a given State's enter() method. Calling transitionTo() from enter/exit
         // encounters a Log.wtf() that can cause trouble on eng builds.
@@ -809,6 +813,7 @@
     private final boolean mApfShouldHandleNdOffload;
     private final boolean mApfShouldHandleMdnsOffload;
     private final boolean mIgnoreNudFailureEnabled;
+    private final boolean mDhcp6PdPreferredFlagEnabled;
 
     private InterfaceParams mInterfaceParams;
 
@@ -1088,6 +1093,8 @@
         mNudFailureCountWeeklyThreshold = mDependencies.getDeviceConfigPropertyInt(
                 CONFIG_NUD_FAILURE_COUNT_WEEKLY_THRESHOLD,
                 DEFAULT_NUD_FAILURE_COUNT_WEEKLY_THRESHOLD);
+        mDhcp6PdPreferredFlagEnabled =
+                mDependencies.isFeatureEnabled(mContext, IPCLIENT_DHCPV6_PD_PREFERRED_FLAG_VERSION);
 
         IpClientLinkObserver.Configuration config = new IpClientLinkObserver.Configuration(
                 mAcceptRaMinLft, mPopulateLinkAddressLifetime);
@@ -1137,6 +1144,12 @@
                             }
                         });
                     }
+
+                    @Override
+                    public void onNewPrefix(PrefixInfo info) {
+                        if (!mDhcp6PdPreferredFlagEnabled) return;
+                        sendMessage(EVENT_PIO_PREFIX_UPDATE, info);
+                    }
                 },
                 config, mLog, mDependencies
         );
diff --git a/src/android/net/ip/IpClientLinkObserver.java b/src/android/net/ip/IpClientLinkObserver.java
index 8f2856f..718f588 100644
--- a/src/android/net/ip/IpClientLinkObserver.java
+++ b/src/android/net/ip/IpClientLinkObserver.java
@@ -20,6 +20,7 @@
 import static android.system.OsConstants.AF_UNSPEC;
 import static android.system.OsConstants.IFF_LOOPBACK;
 
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_PIO;
 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
 import static com.android.net.module.util.NetworkStackConstants.INFINITE_LEASE;
 import static com.android.net.module.util.netlink.NetlinkConstants.IFF_LOWER_UP;
@@ -55,12 +56,14 @@
 import com.android.net.module.util.netlink.NetlinkMessage;
 import com.android.net.module.util.netlink.RtNetlinkAddressMessage;
 import com.android.net.module.util.netlink.RtNetlinkLinkMessage;
+import com.android.net.module.util.netlink.RtNetlinkPrefixMessage;
 import com.android.net.module.util.netlink.RtNetlinkRouteMessage;
 import com.android.net.module.util.netlink.StructIfacacheInfo;
 import com.android.net.module.util.netlink.StructIfaddrMsg;
 import com.android.net.module.util.netlink.StructIfinfoMsg;
 import com.android.net.module.util.netlink.StructNdOptPref64;
 import com.android.net.module.util.netlink.StructNdOptRdnss;
+import com.android.net.module.util.netlink.StructPrefixMsg;
 import com.android.networkstack.apishim.NetworkInformationShimImpl;
 import com.android.networkstack.apishim.common.NetworkInformationShim;
 
@@ -131,6 +134,13 @@
          *            False: clat interface was removed.
          */
         void onClatInterfaceStateUpdate(boolean add);
+
+        /**
+         * Called when the prefix information was updated via RTM_NEWPREFIX netlink message.
+         *
+         * @param info prefix information.
+         */
+        void onNewPrefix(PrefixInfo info);
     }
 
     /** Configuration parameters for IpClientLinkObserver. */
@@ -144,6 +154,21 @@
         }
     }
 
+    /** Prefix information received from RTM_NEWPREFIX netlink message. */
+    public static class PrefixInfo {
+        public final IpPrefix prefix;
+        public short flags;
+        public long preferred;
+        public long valid;
+
+        public PrefixInfo(@NonNull final IpPrefix prefix, short flags, long preferred, long valid) {
+            this.prefix = prefix;
+            this.flags = flags;
+            this.preferred = preferred;
+            this.valid = valid;
+        }
+    }
+
     private final Context mContext;
     private final String mInterfaceName;
     private final Callback mCallback;
@@ -389,7 +414,8 @@
                             | NetlinkConstants.RTMGRP_LINK
                             | NetlinkConstants.RTMGRP_IPV4_IFADDR
                             | NetlinkConstants.RTMGRP_IPV6_IFADDR
-                            | NetlinkConstants.RTMGRP_IPV6_ROUTE),
+                            | NetlinkConstants.RTMGRP_IPV6_ROUTE
+                            | NetlinkConstants.RTMGRP_IPV6_PREFIX),
                     sockRcvbufSize);
             mHandler = h;
             mNetlinkMessageProcessor = p;
@@ -630,6 +656,18 @@
         }
     }
 
+    private void processRtNetlinkPrefixMessage(RtNetlinkPrefixMessage msg) {
+        final StructPrefixMsg prefixmsg = msg.getPrefixMsg();
+        if (prefixmsg.prefix_family != AF_INET6) return;
+        if (prefixmsg.prefix_ifindex != mIfindex) return;
+        if (prefixmsg.prefix_type != ICMPV6_ND_OPTION_PIO) return;
+        final PrefixInfo info = new PrefixInfo(msg.getPrefix(),
+                prefixmsg.prefix_flags,
+                msg.getPreferredLifetime(),
+                msg.getValidLifetime());
+        mCallback.onNewPrefix(info);
+    }
+
     private void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) {
         if (nlMsg instanceof NduseroptMessage) {
             processNduseroptMessage((NduseroptMessage) nlMsg, whenMs);
@@ -639,6 +677,8 @@
             processRtNetlinkAddressMessage((RtNetlinkAddressMessage) nlMsg);
         } else if (nlMsg instanceof RtNetlinkRouteMessage) {
             processRtNetlinkRouteMessage((RtNetlinkRouteMessage) nlMsg);
+        } else if (nlMsg instanceof RtNetlinkPrefixMessage) {
+            processRtNetlinkPrefixMessage((RtNetlinkPrefixMessage) nlMsg);
         } else {
             Log.e(mTag, "Unknown netlink message: " + nlMsg);
         }
diff --git a/tests/unit/src/android/net/apf/ApfGeneratorTest.kt b/tests/unit/src/android/net/apf/ApfGeneratorTest.kt
index aec5b6d..85182d4 100644
--- a/tests/unit/src/android/net/apf/ApfGeneratorTest.kt
+++ b/tests/unit/src/android/net/apf/ApfGeneratorTest.kt
@@ -568,14 +568,14 @@
                 byteArrayOf(
                         encodeInstruction(opcode = 14, immLength = 2, register = 1), 1, 0
                 ) + largeByteArray + byteArrayOf(
-                        encodeInstruction(opcode = 21, immLength = 1, register = 0), 48, 6, 9
+                        encodeInstruction(opcode = 21, immLength = 1, register = 0), 48, 5, -7
                 ),
                 program
         )
         assertContentEquals(
                 listOf(
                         "0: data        256, " + "01".repeat(256),
-                        "259: debugbuf    size=1545"
+                        "259: debugbuf    size=1529"
                 ),
                 ApfJniUtils.disassembleApf(program).map { it.trim() }
         )
@@ -863,7 +863,7 @@
                 .generate()
         assertContentEquals(listOf(
                 "0: data        9, 112233445566778899",
-                "12: debugbuf    size=1772",
+                "12: debugbuf    size=1756",
                 "16: allocate    18",
                 "20: datacopy    src=3, len=6",
                 "23: datacopy    src=4, len=3",
diff --git a/tests/unit/src/android/net/apf/ApfJniUtils.java b/tests/unit/src/android/net/apf/ApfJniUtils.java
index 2cd606a..f61bd4c 100644
--- a/tests/unit/src/android/net/apf/ApfJniUtils.java
+++ b/tests/unit/src/android/net/apf/ApfJniUtils.java
@@ -63,11 +63,6 @@
     public static native String[] disassembleApf(byte[] program);
 
     /**
-     * Get the transmitted packet.
-     */
-    public static native byte[] getTransmittedPacket();
-
-    /**
      * Get all transmitted packets.
      */
     public static native List<byte[]> getAllTransmittedPackets();
diff --git a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
index 4273d95..37b157b 100644
--- a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -208,7 +208,6 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.reflect.Constructor;
 import java.net.HttpURLConnection;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -2519,9 +2518,9 @@
         verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                 .notifyPrivateDnsConfigResolved(any());
 
-        // Change the mode to opportunistic mode. Verify the callback.
+        // Change the mode to opportunistic mode. Verify the callback is fired a second time.
         wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig(true));
-        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyPrivateDnsConfigResolved(
+        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(2)).notifyPrivateDnsConfigResolved(
                 matchPrivateDnsConfigParcelWithDohOnly("some.doh.name" /* dohName */,
                         new String[0] /* dohIps */, "/dns-query{?dns}" /* dohPath */,
                         443 /* dohPort */));