Merge changes from topic "deprecate_connectivity_action_in_tethering"

* changes:
  Tethering: deprecate CONNECTIVITY_ACTION on U+ device
  Test: add tests to testChooseDunUpstreamByAutomaticMode_*
  TetheringTest: separate setup func from chooseDunUpstreamTestCommon
diff --git a/Cronet/AndroidManifest.xml b/Cronet/AndroidManifest.xml
index f3b3c3e..c6471ed 100644
--- a/Cronet/AndroidManifest.xml
+++ b/Cronet/AndroidManifest.xml
@@ -17,7 +17,7 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="com.android.cronet"
+  package="com.android.net.http"
   android:versionCode="11"
   android:versionName="R-initial">
 </manifest>
diff --git a/Cronet/TEST_MAPPING b/Cronet/TEST_MAPPING
index 815d496..b1f3088 100644
--- a/Cronet/TEST_MAPPING
+++ b/Cronet/TEST_MAPPING
@@ -1,7 +1,7 @@
 {
-  "postsubmit": [
+  "presubmit": [
     {
-      "name": "CronetApiTest"
+      "name": "CtsCronetTestCases"
     }
   ]
 }
diff --git a/Cronet/jarjar-rules.txt b/Cronet/jarjar-rules.txt
index 7111ebc..76a799e 100644
--- a/Cronet/jarjar-rules.txt
+++ b/Cronet/jarjar-rules.txt
@@ -1,3 +1,3 @@
-rule androidx.** com.android.cronet.@0
-rule android.support.** com.android.cronet.@0
+rule androidx.** com.android.net.http.@0
+rule android.support.** com.android.net.http.@0
 
diff --git a/Cronet/tests/cts/Android.bp b/Cronet/tests/cts/Android.bp
index e71c707..d10c68c 100644
--- a/Cronet/tests/cts/Android.bp
+++ b/Cronet/tests/cts/Android.bp
@@ -18,12 +18,20 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-java_library {
-    name: "CronetApiCommonTests",
-    srcs: ["src/**/*.java"],
+android_test {
+    name: "CtsCronetTestCases",
+    compile_multilib: "both", // Include both the 32 and 64 bit versions
+    defaults: ["cts_defaults"],
+    sdk_version: "test_current",
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
     static_libs: [
         "androidx.test.rules",
         "androidx.core_core",
+        "ctstestrunner-axt",
+        "ctstestserver",
         "junit",
     ],
     libs: [
@@ -32,15 +40,13 @@
         "android.test.mock",
         "androidx.annotation_annotation",
         "framework-cronet",
+        "org.apache.http.legacy",
     ],
-}
 
-android_test {
-    name: "CronetApiTest",
-    sdk_version: "test_current",
-    test_suites: ["device-tests"],
-    certificate: "platform",
-    static_libs: [
-        "CronetApiCommonTests",
+    // Tag this as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts-tethering"
     ],
 }
diff --git a/Cronet/tests/cts/AndroidManifest.xml b/Cronet/tests/cts/AndroidManifest.xml
index db0f0b3..5a92dea 100644
--- a/Cronet/tests/cts/AndroidManifest.xml
+++ b/Cronet/tests/cts/AndroidManifest.xml
@@ -18,18 +18,21 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="org.chromium.net.test">
+          package="android.net.http.cts">
 
     <uses-permission android:name="android.permission.INTERNET"/>
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
-    <application>
-        <uses-library android:name="android.test.runner" />
-        <uses-library android:name="framework-cronet" />
+    <application android:networkSecurityConfig="@xml/network_security_config">
+        <uses-library android:name="android.test.runner"/>
+        <uses-library android:name="framework-cronet"/>
     </application>
 
     <instrumentation
         android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="org.chromium.net.test"
-        android:label="Cronet API Networking Tests" />
-</manifest>
\ No newline at end of file
+        android:targetPackage="android.net.http.cts"
+        android:label="CTS tests of android.net.http">
+        <meta-data android:name="listener"
+                   android:value="com.android.cts.runner.CtsTestRunListener"/>
+    </instrumentation>
+</manifest>
diff --git a/Cronet/tests/cts/AndroidTest.xml b/Cronet/tests/cts/AndroidTest.xml
new file mode 100644
index 0000000..d2422f1
--- /dev/null
+++ b/Cronet/tests/cts/AndroidTest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<configuration description="Config for CTS Cronet test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="networking" />
+    <!-- Instant apps cannot create sockets. See b/264248246 -->
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsCronetTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.net.http.cts" />
+        <option name="runtime-hint" value="10s" />
+    </test>
+
+    <!-- Only run CtsCronetTestcasess in MTS if the Tethering Mainline module is installed. -->
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.tethering" />
+    </object>
+</configuration>
diff --git a/Cronet/tests/cts/OWNERS b/Cronet/tests/cts/OWNERS
new file mode 100644
index 0000000..acb6ee6
--- /dev/null
+++ b/Cronet/tests/cts/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 31808
+
+set noparent
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking_xts
+
+# TODO: Temp ownership to develop cronet CTS
+colibie@google.com #{LAST_RESORT_SUGGESTION}
+prohr@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/Cronet/tests/cts/assets/html/hello_world.html b/Cronet/tests/cts/assets/html/hello_world.html
new file mode 100644
index 0000000..ea62ce2
--- /dev/null
+++ b/Cronet/tests/cts/assets/html/hello_world.html
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<html>
+<head>
+    <title>hello world</title>
+</head>
+<body>
+<h3>hello world</h3><br>
+</body>
+</html>
\ No newline at end of file
diff --git a/Cronet/tests/cts/res/xml/network_security_config.xml b/Cronet/tests/cts/res/xml/network_security_config.xml
new file mode 100644
index 0000000..7d7530b
--- /dev/null
+++ b/Cronet/tests/cts/res/xml/network_security_config.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<network-security-config>
+    <domain-config cleartextTrafficPermitted="true">
+        <domain includeSubdomains="true">localhost</domain>
+    </domain-config>
+</network-security-config>
\ No newline at end of file
diff --git a/Cronet/tests/cts/src/org/chromium/net/test/CronetUrlRequestTest.java b/Cronet/tests/cts/src/android/net/http/cts/CronetUrlRequestTest.java
similarity index 78%
rename from Cronet/tests/cts/src/org/chromium/net/test/CronetUrlRequestTest.java
rename to Cronet/tests/cts/src/android/net/http/cts/CronetUrlRequestTest.java
index 7dd9a9a..2898f54 100644
--- a/Cronet/tests/cts/src/org/chromium/net/test/CronetUrlRequestTest.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/CronetUrlRequestTest.java
@@ -13,7 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.chromium.net.test;
+
+package android.net.http.cts;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -21,6 +22,9 @@
 
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.http.cts.util.CronetCtsTestServer;
+import android.net.http.cts.util.TestUrlRequestCallback;
+import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep;
 
 import androidx.annotation.NonNull;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -29,22 +33,18 @@
 import org.chromium.net.CronetEngine;
 import org.chromium.net.UrlRequest;
 import org.chromium.net.UrlResponseInfo;
-import org.chromium.net.test.util.TestUrlRequestCallback;
-import org.chromium.net.test.util.TestUrlRequestCallback.ResponseStep;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.Random;
-
 @RunWith(AndroidJUnit4.class)
 public class CronetUrlRequestTest {
     private static final String TAG = CronetUrlRequestTest.class.getSimpleName();
-    private static final String HTTPS_PREFIX = "https://";
 
-    private final String[] mTestDomains = {"www.google.com", "www.android.com"};
     @NonNull private CronetEngine mCronetEngine;
     @NonNull private ConnectivityManager mCm;
+    @NonNull private CronetCtsTestServer mTestServer;
 
     @Before
     public void setUp() throws Exception {
@@ -56,6 +56,13 @@
                 // .enableBrotli(true)
                 .enableQuic(true);
         mCronetEngine = builder.build();
+        mTestServer = new CronetCtsTestServer(context);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mCronetEngine.shutdown();
+        mTestServer.shutdown();
     }
 
     private static void assertGreaterThan(String msg, int first, int second) {
@@ -66,25 +73,20 @@
         assertNotNull("This test requires a working Internet connection", mCm.getActiveNetwork());
     }
 
-    private String getRandomDomain() {
-        int index = (new Random()).nextInt(mTestDomains.length);
-        return mTestDomains[index];
-    }
-
     @Test
     public void testUrlRequestGet_CompletesSuccessfully() throws Exception {
         assertHasTestableNetworks();
-        String url = HTTPS_PREFIX + getRandomDomain();
+        String url = mTestServer.getSuccessUrl();
         TestUrlRequestCallback callback = new TestUrlRequestCallback();
-        UrlRequest.Builder builder = mCronetEngine.newUrlRequestBuilder(url, callback,
-                callback.getExecutor());
+        UrlRequest.Builder builder =
+                mCronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor());
         builder.build().start();
 
         callback.expectCallback(ResponseStep.ON_SUCCEEDED);
 
         UrlResponseInfo info = callback.mResponseInfo;
-        assertEquals("Unexpected http status code from " + url + ".", 200,
-                info.getHttpStatusCode());
+        assertEquals(
+                "Unexpected http status code from " + url + ".", 200, info.getHttpStatusCode());
         assertGreaterThan(
                 "Received byte from " + url + " is 0.", (int) info.getReceivedByteCount(), 0);
     }
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/CronetCtsTestServer.kt b/Cronet/tests/cts/src/android/net/http/cts/util/CronetCtsTestServer.kt
new file mode 100644
index 0000000..3ccb571
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/CronetCtsTestServer.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.http.cts.util
+
+import android.content.Context
+import android.webkit.cts.CtsTestServer
+
+/** Extends CtsTestServer to handle POST requests and other cronet specific test requests */
+class CronetCtsTestServer(context: Context) : CtsTestServer(context) {
+
+    val successUrl: String = getAssetUrl("html/hello_world.html")
+}
diff --git a/Cronet/tests/cts/src/org/chromium/net/test/util/TestUrlRequestCallback.java b/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
similarity index 99%
rename from Cronet/tests/cts/src/org/chromium/net/test/util/TestUrlRequestCallback.java
rename to Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
index 3c7c001..c7143f5 100644
--- a/Cronet/tests/cts/src/org/chromium/net/test/util/TestUrlRequestCallback.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.chromium.net.test.util;
+package android.net.http.cts.util;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/OWNERS_core_networking b/OWNERS_core_networking
index 3a08422..172670e 100644
--- a/OWNERS_core_networking
+++ b/OWNERS_core_networking
@@ -19,3 +19,4 @@
 waynema@google.com
 xiaom@google.com
 yumike@google.com
+yuyanghuang@google.com
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index 481557b..3f4da10 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -17,6 +17,18 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// TODO: This is currently not used, but is being merged early, so Cronet can be disabled in
+// tm-mainline-prod.
+// Both cronet_java_defaults and cronet_java_prejarjar_defaults can be used to
+// specify a java_defaults target that either enables or disables Cronet. This
+// is used to disable Cronet on tm-mainline-prod.
+// Note: they must either both be enabled or disabled.
+cronet_java_defaults = "CronetJavaDefaultsEnabled"
+cronet_java_prejarjar_defaults = "CronetJavaPrejarjarDefaultsEnabled"
+// This is a placeholder comment to avoid merge conflicts
+// as cronet_defaults may have different values
+// depending on the branch
+
 java_sdk_library {
     name: "framework-tethering",
     defaults: ["framework-module-defaults"],
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 72f83fa..44d3ffc 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -27,6 +27,7 @@
 import static android.system.OsConstants.ETH_P_IP;
 import static android.system.OsConstants.ETH_P_IPV6;
 
+import static com.android.net.module.util.NetworkStackConstants.IPV4_MIN_MTU;
 import static com.android.net.module.util.ip.ConntrackMonitor.ConntrackEvent;
 import static com.android.networkstack.tethering.BpfUtils.DOWNSTREAM;
 import static com.android.networkstack.tethering.BpfUtils.UPSTREAM;
@@ -82,6 +83,8 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -143,6 +146,8 @@
     static final int NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED = 432_000;
     @VisibleForTesting
     static final int NF_CONNTRACK_UDP_TIMEOUT_STREAM = 180;
+    @VisibleForTesting
+    static final int INVALID_MTU = 0;
 
     // List of TCP port numbers which aren't offloaded because the packets require the netfilter
     // conntrack helper. See also TetherController::setForwardRules in netd.
@@ -263,6 +268,10 @@
     // TODO: Support multi-upstream interfaces.
     private int mLastIPv4UpstreamIfindex = 0;
 
+    // Tracks the IPv4 upstream interface information.
+    @Nullable
+    private UpstreamInfo mIpv4UpstreamInfo = null;
+
     // Runnable that used by scheduling next polling of stats.
     private final Runnable mScheduledPollingStats = () -> {
         updateForwardedStats();
@@ -320,6 +329,19 @@
             return SdkLevel.isAtLeastS();
         }
 
+        /**
+         * Gets the MTU of the given interface.
+         */
+        public int getNetworkInterfaceMtu(@NonNull String iface) {
+            try {
+                final NetworkInterface networkInterface = NetworkInterface.getByName(iface);
+                return networkInterface == null ? INVALID_MTU : networkInterface.getMTU();
+            } catch (SocketException e) {
+                Log.e(TAG, "Could not get MTU for interface " + iface, e);
+                return INVALID_MTU;
+            }
+        }
+
         /** Get downstream4 BPF map. */
         @Nullable public IBpfMap<Tether4Key, Tether4Value> getBpfDownstream4Map() {
             if (!isAtLeastS()) return null;
@@ -868,6 +890,7 @@
         if (!isUsingBpf()) return;
 
         int upstreamIndex = 0;
+        int mtu = INVALID_MTU;
 
         // This will not work on a network that is using 464xlat because hasIpv4Address will not be
         // true.
@@ -877,6 +900,17 @@
             final String ifaceName = ns.linkProperties.getInterfaceName();
             final InterfaceParams params = mDeps.getInterfaceParams(ifaceName);
             final boolean isVcn = isVcnInterface(ifaceName);
+            mtu = ns.linkProperties.getMtu();
+            if (mtu == INVALID_MTU) {
+                // Get mtu via kernel if mtu is not found in LinkProperties.
+                mtu = mDeps.getNetworkInterfaceMtu(ifaceName);
+            }
+
+            // Use default mtu if can't find any.
+            if (mtu == INVALID_MTU) mtu = NetworkStackConstants.ETHER_MTU;
+            // Clamp to minimum ipv4 mtu
+            if (mtu < IPV4_MIN_MTU) mtu = IPV4_MIN_MTU;
+
             if (!isVcn && params != null && !params.hasMacAddress /* raw ip upstream only */) {
                 upstreamIndex = params.index;
             }
@@ -905,8 +939,11 @@
         // after the upstream is lost do not incorrectly add rules pointing at the upstream.
         if (upstreamIndex == 0) {
             mIpv4UpstreamIndices.clear();
+            mIpv4UpstreamInfo = null;
             return;
         }
+
+        mIpv4UpstreamInfo = new UpstreamInfo(upstreamIndex, mtu);
         Collection<InetAddress> addresses = ns.linkProperties.getAddresses();
         for (final InetAddress addr: addresses) {
             if (isValidUpstreamIpv4Address(addr)) {
@@ -1051,6 +1088,9 @@
         }
         pw.decreaseIndent();
 
+        pw.println("IPv4 Upstream Information: "
+                + (mIpv4UpstreamInfo != null ? mIpv4UpstreamInfo : "<empty>"));
+
         pw.println();
         pw.println("Forwarding counters:");
         pw.increaseIndent();
@@ -1258,10 +1298,10 @@
 
         final String ageStr = (value.lastUsed == 0) ? "-"
                 : String.format("%dms", (now - value.lastUsed) / 1_000_000);
-        return String.format("%s [%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %s",
+        return String.format("%s [%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %d %s",
                 l4protoToString(key.l4proto), key.dstMac, key.iif, getIfName(key.iif),
                 src4, key.srcPort, value.oif, getIfName(value.oif),
-                public4, publicPort, dst4, value.dstPort, value.ethDstMac, ageStr);
+                public4, publicPort, dst4, value.dstPort, value.ethDstMac, value.pmtu, ageStr);
     }
 
     private void dumpIpv4ForwardingRuleMap(long now, boolean downstream,
@@ -1283,13 +1323,13 @@
         try (IBpfMap<Tether4Key, Tether4Value> upstreamMap = mDeps.getBpfUpstream4Map();
                 IBpfMap<Tether4Key, Tether4Value> downstreamMap = mDeps.getBpfDownstream4Map()) {
             pw.println("IPv4 Upstream: proto [inDstMac] iif(iface) src -> nat -> "
-                    + "dst [outDstMac] age");
+                    + "dst [outDstMac] pmtu age");
             pw.increaseIndent();
             dumpIpv4ForwardingRuleMap(now, UPSTREAM, upstreamMap, pw);
             pw.decreaseIndent();
 
             pw.println("IPv4 Downstream: proto [inDstMac] iif(iface) src -> nat -> "
-                    + "dst [outDstMac] age");
+                    + "dst [outDstMac] pmtu age");
             pw.increaseIndent();
             dumpIpv4ForwardingRuleMap(now, DOWNSTREAM, downstreamMap, pw);
             pw.decreaseIndent();
@@ -1540,6 +1580,28 @@
         }
     }
 
+    /** Upstream information class. */
+    private static final class UpstreamInfo {
+        // TODO: add clat interface information
+        public final int ifIndex;
+        public final int mtu;
+
+        private UpstreamInfo(final int ifIndex, final int mtu) {
+            this.ifIndex = ifIndex;
+            this.mtu = mtu;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(ifIndex, mtu);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("ifIndex: %d, mtu: %d", ifIndex, mtu);
+        }
+    }
+
     /**
      * A BPF tethering stats provider to provide network statistics to the system.
      * Note that this class' data may only be accessed on the handler thread.
@@ -1711,20 +1773,20 @@
 
         @NonNull
         private Tether4Value makeTetherUpstream4Value(@NonNull ConntrackEvent e,
-                int upstreamIndex) {
-            return new Tether4Value(upstreamIndex,
+                @NonNull UpstreamInfo upstreamInfo) {
+            return new Tether4Value(upstreamInfo.ifIndex,
                     NULL_MAC_ADDRESS /* ethDstMac (rawip) */,
                     NULL_MAC_ADDRESS /* ethSrcMac (rawip) */, ETH_P_IP,
-                    NetworkStackConstants.ETHER_MTU, toIpv4MappedAddressBytes(e.tupleReply.dstIp),
+                    upstreamInfo.mtu, toIpv4MappedAddressBytes(e.tupleReply.dstIp),
                     toIpv4MappedAddressBytes(e.tupleReply.srcIp), e.tupleReply.dstPort,
                     e.tupleReply.srcPort, 0 /* lastUsed, filled by bpf prog only */);
         }
 
         @NonNull
         private Tether4Value makeTetherDownstream4Value(@NonNull ConntrackEvent e,
-                @NonNull ClientInfo c, int upstreamIndex) {
+                @NonNull ClientInfo c, @NonNull UpstreamInfo upstreamInfo) {
             return new Tether4Value(c.downstreamIfindex,
-                    c.clientMac, c.downstreamMac, ETH_P_IP, NetworkStackConstants.ETHER_MTU,
+                    c.clientMac, c.downstreamMac, ETH_P_IP, upstreamInfo.mtu,
                     toIpv4MappedAddressBytes(e.tupleOrig.dstIp),
                     toIpv4MappedAddressBytes(e.tupleOrig.srcIp),
                     e.tupleOrig.dstPort, e.tupleOrig.srcPort,
@@ -1773,9 +1835,11 @@
                 return;
             }
 
-            final Tether4Value upstream4Value = makeTetherUpstream4Value(e, upstreamIndex);
+            if (mIpv4UpstreamInfo == null || mIpv4UpstreamInfo.ifIndex != upstreamIndex) return;
+
+            final Tether4Value upstream4Value = makeTetherUpstream4Value(e, mIpv4UpstreamInfo);
             final Tether4Value downstream4Value = makeTetherDownstream4Value(e, tetherClient,
-                    upstreamIndex);
+                    mIpv4UpstreamInfo);
 
             maybeAddDevMap(upstreamIndex, tetherClient.downstreamIfindex);
             maybeSetLimit(upstreamIndex);
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 06e665c..e48019c 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -146,6 +146,7 @@
 import com.android.networkstack.tethering.util.PrefixUtils;
 import com.android.networkstack.tethering.util.TetheringUtils;
 import com.android.networkstack.tethering.util.VersionedBroadcastListener;
+import com.android.networkstack.tethering.wear.WearableConnectionManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -257,6 +258,7 @@
     private final BpfCoordinator mBpfCoordinator;
     private final PrivateAddressCoordinator mPrivateAddressCoordinator;
     private final TetheringMetrics mTetheringMetrics;
+    private final WearableConnectionManager mWearableConnectionManager;
     private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
 
     private volatile TetheringConfiguration mConfig;
@@ -393,6 +395,12 @@
                     }
                 });
 
+        if (SdkLevel.isAtLeastT() && mConfig.isWearTetheringEnabled()) {
+            mWearableConnectionManager = mDeps.getWearableConnectionManager(mContext);
+        } else {
+            mWearableConnectionManager = null;
+        }
+
         startStateMachineUpdaters();
     }
 
@@ -2407,6 +2415,9 @@
 
     /** Unregister tethering event callback */
     void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
+        if (callback == null) {
+            throw new NullPointerException();
+        }
         mHandler.post(() -> {
             mTetheringEventCallbacks.unregister(callback);
         });
@@ -2646,6 +2657,13 @@
         mPrivateAddressCoordinator.dump(pw);
         pw.decreaseIndent();
 
+        if (mWearableConnectionManager != null) {
+            pw.println("WearableConnectionManager:");
+            pw.increaseIndent();
+            mWearableConnectionManager.dump(pw);
+            pw.decreaseIndent();
+        }
+
         pw.println("Log:");
         pw.increaseIndent();
         if (CollectionUtils.contains(args, "--short")) {
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 903de9d..b6591a9 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -123,6 +123,13 @@
      */
     public static final String TETHER_FORCE_USB_FUNCTIONS =
             "tether_force_usb_functions";
+
+    /**
+     * Experiment flag to enable TETHERING_WEAR.
+     */
+    public static final String TETHER_ENABLE_WEAR_TETHERING =
+            "tether_enable_wear_tethering";
+
     /**
      * Default value that used to periodic polls tether offload stats from tethering offload HAL
      * to make the data warnings work.
@@ -158,6 +165,8 @@
     private final boolean mEnableWifiP2pDedicatedIp;
     private final int mP2pLeasesSubnetPrefixLength;
 
+    private final boolean mEnableWearTethering;
+
     private final int mUsbTetheringFunction;
     protected final ContentResolver mContentResolver;
 
@@ -234,6 +243,8 @@
 
         mP2pLeasesSubnetPrefixLength = getP2pLeasesSubnetPrefixLengthFromRes(res, configLog);
 
+        mEnableWearTethering = shouldEnableWearTethering(ctx);
+
         configLog.log(toString());
     }
 
@@ -317,6 +328,11 @@
         return mP2pLeasesSubnetPrefixLength;
     }
 
+    /** Returns true if wearable device tethering is enabled. */
+    public boolean isWearTetheringEnabled() {
+        return mEnableWearTethering;
+    }
+
     /** Does the dumping.*/
     public void dump(PrintWriter pw) {
         pw.print("activeDataSubId: ");
@@ -362,6 +378,9 @@
         pw.print("p2pLeasesSubnetPrefixLength: ");
         pw.println(mP2pLeasesSubnetPrefixLength);
 
+        pw.print("enableWearTethering: ");
+        pw.println(mEnableWearTethering);
+
         pw.print("mUsbTetheringFunction: ");
         pw.println(isUsingNcm() ? "NCM" : "RNDIS");
     }
@@ -387,6 +406,7 @@
                 isCarrierConfigAffirmsEntitlementCheckRequired));
         sj.add(String.format("enableBpfOffload:%s", mEnableBpfOffload));
         sj.add(String.format("enableLegacyDhcpServer:%s", mEnableLegacyDhcpServer));
+        sj.add(String.format("enableWearTethering:%s", mEnableWearTethering));
         return String.format("TetheringConfiguration{%s}", sj.toString());
     }
 
@@ -557,6 +577,11 @@
                 TETHER_ENABLE_LEGACY_DHCP_SERVER, false /** defaultValue */);
     }
 
+    private boolean shouldEnableWearTethering(Context context) {
+        return SdkLevel.isAtLeastT()
+            && isTetheringFeatureEnabled(context, TETHER_ENABLE_WEAR_TETHERING);
+    }
+
     private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) {
         // Due to the limitation of static mock for testing, using #getDeviceConfigProperty instead
         // of DeviceConfig#getBoolean. If using #getBoolean here, the test can't know that the
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 611d1cf..741a5c5 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.net.INetd;
 import android.net.ip.IpServer;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -29,12 +30,14 @@
 import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 import com.android.internal.util.StateMachine;
 import com.android.net.module.util.SharedLog;
 import com.android.networkstack.apishim.BluetoothPanShimImpl;
 import com.android.networkstack.apishim.common.BluetoothPanShim;
 import com.android.networkstack.tethering.metrics.TetheringMetrics;
+import com.android.networkstack.tethering.wear.WearableConnectionManager;
 
 import java.util.ArrayList;
 
@@ -171,4 +174,12 @@
     public TetheringMetrics getTetheringMetrics() {
         return new TetheringMetrics();
     }
+
+    /**
+     * Returns the implementation of WearableConnectionManager.
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public WearableConnectionManager getWearableConnectionManager(Context ctx) {
+        return new WearableConnectionManager(ctx);
+    }
 }
diff --git a/Tethering/src/com/android/networkstack/tethering/wear/WearableConnectionManager.java b/Tethering/src/com/android/networkstack/tethering/wear/WearableConnectionManager.java
new file mode 100644
index 0000000..a1b535a
--- /dev/null
+++ b/Tethering/src/com/android/networkstack/tethering/wear/WearableConnectionManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.tethering.wear;
+
+import android.content.Context;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+/**
+ * Manages Bluetooth connections from Wearable devices.
+ */
+public class WearableConnectionManager {
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public WearableConnectionManager(Context context) {
+    }
+
+    public void dump(IndentingPrintWriter pw) {
+    }
+}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index e5fe3f8..1978e99 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -32,6 +32,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.staticMockMarker;
+import static com.android.net.module.util.NetworkStackConstants.IPV4_MIN_MTU;
 import static com.android.net.module.util.ip.ConntrackMonitor.ConntrackEvent;
 import static com.android.net.module.util.netlink.ConntrackMessage.DYING_MASK;
 import static com.android.net.module.util.netlink.ConntrackMessage.ESTABLISHED_MASK;
@@ -41,6 +42,7 @@
 import static com.android.net.module.util.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE;
 import static com.android.net.module.util.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
 import static com.android.networkstack.tethering.BpfCoordinator.CONNTRACK_TIMEOUT_UPDATE_INTERVAL_MS;
+import static com.android.networkstack.tethering.BpfCoordinator.INVALID_MTU;
 import static com.android.networkstack.tethering.BpfCoordinator.NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED;
 import static com.android.networkstack.tethering.BpfCoordinator.NF_CONNTRACK_UDP_TIMEOUT_STREAM;
 import static com.android.networkstack.tethering.BpfCoordinator.NON_OFFLOADED_UPSTREAM_IPV4_TCP_PORTS;
@@ -154,9 +156,9 @@
 
     private static final int INVALID_IFINDEX = 0;
     private static final int UPSTREAM_IFINDEX = 1001;
-    private static final int UPSTREAM_IFINDEX2 = 1002;
-    private static final int DOWNSTREAM_IFINDEX = 1003;
-    private static final int DOWNSTREAM_IFINDEX2 = 1004;
+    private static final int UPSTREAM_IFINDEX2 = 1003;
+    private static final int DOWNSTREAM_IFINDEX = 2001;
+    private static final int DOWNSTREAM_IFINDEX2 = 2002;
 
     private static final String UPSTREAM_IFACE = "rmnet0";
     private static final String UPSTREAM_IFACE2 = "wlan0";
@@ -283,6 +285,11 @@
             private int mDstPort = REMOTE_PORT;
             private long mLastUsed = 0;
 
+            public Builder setPmtu(short pmtu) {
+                mPmtu = pmtu;
+                return this;
+            }
+
             public Tether4Value build() {
                 return new Tether4Value(mOif, mEthDstMac, mEthSrcMac, mEthProto, mPmtu,
                         mSrc46, mDst46, mSrcPort, mDstPort, mLastUsed);
@@ -303,6 +310,11 @@
             private int mDstPort = PRIVATE_PORT;
             private long mLastUsed = 0;
 
+            public Builder setPmtu(short pmtu) {
+                mPmtu = pmtu;
+                return this;
+            }
+
             public Tether4Value build() {
                 return new Tether4Value(mOif, mEthDstMac, mEthSrcMac, mEthProto, mPmtu,
                         mSrc46, mDst46, mSrcPort, mDstPort, mLastUsed);
@@ -375,6 +387,7 @@
     private HashMap<IpServer, HashMap<Inet4Address, ClientInfo>> mTetherClients;
 
     private long mElapsedRealtimeNanos = 0;
+    private int mMtu = NetworkStackConstants.ETHER_MTU;
     private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
             ArgumentCaptor.forClass(ArrayList.class);
     private final TestLooper mTestLooper = new TestLooper();
@@ -430,6 +443,10 @@
                         return mElapsedRealtimeNanos;
                     }
 
+                    public int getNetworkInterfaceMtu(@NonNull String iface) {
+                        return mMtu;
+                    }
+
                     @Nullable
                     public IBpfMap<Tether4Key, Tether4Value> getBpfDownstream4Map() {
                         return mBpfDownstream4Map;
@@ -1518,6 +1535,7 @@
         final LinkProperties lp = new LinkProperties();
         lp.setInterfaceName(upstreamInfo.interfaceParams.name);
         lp.addLinkAddress(new LinkAddress(upstreamInfo.address, 32 /* prefix length */));
+        lp.setMtu(mMtu);
         final NetworkCapabilities capabilities = new NetworkCapabilities()
                 .addTransportType(upstreamInfo.transportType);
         coordinator.updateUpstreamNetworkState(new UpstreamNetworkState(lp, capabilities,
@@ -2108,7 +2126,7 @@
     @Test
     public void testIpv6ForwardingRuleToString() throws Exception {
         final Ipv6ForwardingRule rule = buildTestForwardingRule(UPSTREAM_IFINDEX, NEIGH_A, MAC_A);
-        assertEquals("upstreamIfindex: 1001, downstreamIfindex: 1003, address: 2001:db8::1, "
+        assertEquals("upstreamIfindex: 1001, downstreamIfindex: 2001, address: 2001:db8::1, "
                 + "srcMac: 12:34:56:78:90:ab, dstMac: 00:00:00:00:00:0a", rule.toString());
     }
 
@@ -2195,4 +2213,72 @@
 
         verifyDump(coordinator);
     }
+
+    private void verifyAddTetherOffloadRule4Mtu(final int ifaceMtu, final boolean isKernelMtu,
+            final int expectedMtu) throws Exception {
+        // BpfCoordinator#updateUpstreamNetworkState geta mtu from LinkProperties. If not found,
+        // try to get from kernel.
+        if (isKernelMtu) {
+            // LinkProperties mtu is invalid and kernel mtu is valid.
+            mMtu = INVALID_MTU;
+            doReturn(ifaceMtu).when(mDeps).getNetworkInterfaceMtu(any());
+        } else {
+            // LinkProperties mtu is valid and kernel mtu is invalid.
+            mMtu = ifaceMtu;
+            doReturn(INVALID_MTU).when(mDeps).getNetworkInterfaceMtu(any());
+        }
+
+        final BpfCoordinator coordinator = makeBpfCoordinator();
+        initBpfCoordinatorForRule4(coordinator);
+
+        final Tether4Key expectedUpstream4KeyTcp = new TestUpstream4Key.Builder()
+                .setProto(IPPROTO_TCP)
+                .build();
+        final Tether4Key expectedDownstream4KeyTcp = new TestDownstream4Key.Builder()
+                .setProto(IPPROTO_TCP)
+                .build();
+        final Tether4Value expectedUpstream4ValueTcp = new TestUpstream4Value.Builder()
+                .setPmtu((short) expectedMtu)
+                .build();
+        final Tether4Value expectedDownstream4ValueTcp = new TestDownstream4Value.Builder()
+                .setPmtu((short) expectedMtu)
+                .build();
+
+        mConsumer.accept(new TestConntrackEvent.Builder()
+                .setMsgType(IPCTNL_MSG_CT_NEW)
+                .setProto(IPPROTO_TCP)
+                .build());
+        verify(mBpfUpstream4Map)
+                .insertEntry(eq(expectedUpstream4KeyTcp), eq(expectedUpstream4ValueTcp));
+        verify(mBpfDownstream4Map)
+                .insertEntry(eq(expectedDownstream4KeyTcp), eq(expectedDownstream4ValueTcp));
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testAddTetherOffloadRule4LowMtuFromLinkProperties() throws Exception {
+        verifyAddTetherOffloadRule4Mtu(
+                IPV4_MIN_MTU, false /* isKernelMtu */, IPV4_MIN_MTU /* expectedMtu */);
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testAddTetherOffloadRule4LowMtuFromKernel() throws Exception {
+        verifyAddTetherOffloadRule4Mtu(
+                IPV4_MIN_MTU, true /* isKernelMtu */, IPV4_MIN_MTU /* expectedMtu */);
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testAddTetherOffloadRule4LessThanIpv4MinMtu() throws Exception {
+        verifyAddTetherOffloadRule4Mtu(
+                IPV4_MIN_MTU - 1, false /* isKernelMtu */, IPV4_MIN_MTU /* expectedMtu */);
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testAddTetherOffloadRule4InvalidMtu() throws Exception {
+        verifyAddTetherOffloadRule4Mtu(INVALID_MTU, false /* isKernelMtu */,
+                NetworkStackConstants.ETHER_MTU /* expectedMtu */);
+    }
 }
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
index 38f1e9c..da81bda 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
@@ -666,7 +666,7 @@
 
             // Calling System.gc() or System.runFinalization() doesn't guarantee GCs or finalizers
             // are executed synchronously. The finalizer is called after GC on a separate thread.
-            final int attempts = 100;
+            final int attempts = 600;
             final long waitIntervalMs = 50;
             for (int i = 0; i < attempts; i++) {
                 forceGc();
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
index 9b9507b..e756bd3 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
@@ -49,6 +49,7 @@
 import android.net.LinkProperties;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -62,9 +63,12 @@
 import com.android.net.module.util.SharedLog;
 import com.android.networkstack.tethering.TestConnectivityManager.NetworkRequestInfo;
 import com.android.networkstack.tethering.TestConnectivityManager.TestNetworkAgent;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -92,6 +96,8 @@
     private static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities.Builder()
             .addTransportType(TRANSPORT_WIFI).addCapability(NET_CAPABILITY_INTERNET).build();
 
+    @Rule public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
     @Mock private Context mContext;
     @Mock private EntitlementManager mEntitleMgr;
     @Mock private IConnectivityManager mCS;
@@ -301,6 +307,7 @@
     }
 
     @Test
+    @IgnoreAfter(Build.VERSION_CODES.TIRAMISU)
     public void testSelectPreferredUpstreamType() throws Exception {
         final Collection<Integer> preferredTypes = new ArrayList<>();
         preferredTypes.add(TYPE_WIFI);
@@ -556,6 +563,7 @@
     }
 
     @Test
+    @IgnoreAfter(Build.VERSION_CODES.TIRAMISU)
     public void testSelectMobileWhenMobileIsNotDefault() {
         final Collection<Integer> preferredTypes = new ArrayList<>();
         // Mobile has higher pirority than wifi.
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 8eb9cfd..229dce3 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -54,7 +54,6 @@
         "//packages/modules/Connectivity/tests/native/utilities",
         "//packages/modules/Connectivity/service-t/native/libs/libnetworkstats",
         "//packages/modules/Connectivity/tests/unit/jni",
-        "//system/netd/tests",
     ],
 }
 
diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c
index 14cddf6..7350209 100644
--- a/bpf_progs/clatd.c
+++ b/bpf_progs/clatd.c
@@ -52,9 +52,17 @@
     __be32 identification;
 };
 
+// constants for passing in to 'bool is_ethernet'
+static const bool RAWIP = false;
+static const bool ETHER = true;
+
+#define KVER_4_14 KVER(4, 14, 0)
+
 DEFINE_BPF_MAP_GRW(clat_ingress6_map, HASH, ClatIngress6Key, ClatIngress6Value, 16, AID_SYSTEM)
 
-static inline __always_inline int nat64(struct __sk_buff* skb, bool is_ethernet) {
+static inline __always_inline int nat64(struct __sk_buff* skb,
+                                        const bool is_ethernet,
+                                        const unsigned kver) {
     // Require ethernet dst mac address to be our unicast address.
     if (is_ethernet && (skb->pkt_type != PACKET_HOST)) return TC_ACT_PIPE;
 
@@ -106,6 +114,9 @@
     __u16 tot_len = ntohs(ip6->payload_len) + sizeof(struct iphdr);  // cannot overflow, see above
 
     if (proto == IPPROTO_FRAGMENT) {
+        // Fragment handling requires bpf_skb_adjust_room which is 4.14+
+        if (kver < KVER_4_14) return TC_ACT_PIPE;
+
         // Must have (ethernet and) ipv6 header and ipv6 fragment extension header
         if (data + l2_header_size + sizeof(*ip6) + sizeof(struct frag_hdr) > data_end)
             return TC_ACT_PIPE;
@@ -208,7 +219,20 @@
     //   return -ENOTSUPP;
     bpf_csum_update(skb, sum6);
 
-    if (frag_off != htons(IP_DF)) {
+    // Technically 'kver < KVER_4_14' already implies 'frag_off == htons(IP_DF)' due to logic above,
+    // thus the initial 'kver >= KVER_4_14' check here is entirely superfluous.
+    //
+    // However, we *need* the compiler (when compiling the program for 4.9) to entirely
+    // optimize out the call to bpf_skb_adjust_room() bpf helper: it's not enough for it to emit
+    // an unreachable call to it, it must *not* emit it at all (otherwise the 4.9 kernel's
+    // bpf verifier will refuse to load a program with an unknown bpf helper call)
+    //
+    // This is easiest to achieve by being very explicit in the if clause,
+    // better safe than sorry...
+    //
+    // Note: we currently have no TreeHugger coverage for 4.9-T devices (there are no such
+    // Pixel or cuttlefish devices), so likely you won't notice for months if this breaks...
+    if (kver >= KVER_4_14 && frag_off != htons(IP_DF)) {
         // If we're converting an IPv6 Fragment, we need to trim off 8 more bytes
         // We're beyond recovery on error here... but hard to imagine how this could fail.
         if (bpf_skb_adjust_room(skb, -(__s32)sizeof(struct frag_hdr), BPF_ADJ_ROOM_NET, /*flags*/0))
@@ -243,14 +267,24 @@
     return TC_ACT_PIPE;
 }
 
-DEFINE_BPF_PROG("schedcls/ingress6/clat_ether", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_ether)
+DEFINE_BPF_PROG_KVER("schedcls/ingress6/clat_ether$4_14", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_ether_4_14, KVER_4_14)
 (struct __sk_buff* skb) {
-    return nat64(skb, true);
+    return nat64(skb, ETHER, KVER_4_14);
 }
 
-DEFINE_BPF_PROG("schedcls/ingress6/clat_rawip", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_rawip)
+DEFINE_BPF_PROG_KVER_RANGE("schedcls/ingress6/clat_ether$4_9", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_ether_4_9, KVER_NONE, KVER_4_14)
 (struct __sk_buff* skb) {
-    return nat64(skb, false);
+    return nat64(skb, ETHER, KVER_NONE);
+}
+
+DEFINE_BPF_PROG_KVER("schedcls/ingress6/clat_rawip$4_14", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_rawip_4_14, KVER_4_14)
+(struct __sk_buff* skb) {
+    return nat64(skb, RAWIP, KVER_4_14);
+}
+
+DEFINE_BPF_PROG_KVER_RANGE("schedcls/ingress6/clat_rawip$4_9", AID_ROOT, AID_SYSTEM, sched_cls_ingress6_clat_rawip_4_9, KVER_NONE, KVER_4_14)
+(struct __sk_buff* skb) {
+    return nat64(skb, RAWIP, KVER_NONE);
 }
 
 DEFINE_BPF_MAP_GRW(clat_egress4_map, HASH, ClatEgress4Key, ClatEgress4Value, 16, AID_SYSTEM)
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index 3eb4e02..43920d0 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -109,8 +109,9 @@
 // (this is because these are currently attached by the mainline provided libnetd_updatable .so
 // which is loaded into netd and thus runs as netd uid/gid/selinux context)
 #define DEFINE_NETD_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, minKV, maxKV) \
-    DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog, \
-                        minKV, maxKV, false, "fs_bpf_netd_readonly", "")
+    DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog,                               \
+                        minKV, maxKV, BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, false,                \
+                        "fs_bpf_netd_readonly", "", false, false, false)
 
 #define DEFINE_NETD_BPF_PROG_KVER(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv) \
     DEFINE_NETD_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, KVER_INF)
@@ -120,8 +121,9 @@
 
 // programs that only need to be usable by the system server
 #define DEFINE_SYS_BPF_PROG(SECTION_NAME, prog_uid, prog_gid, the_prog) \
-    DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog, \
-                        KVER_NONE, KVER_INF, false, "fs_bpf_net_shared", "")
+    DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog, KVER_NONE, KVER_INF,  \
+                        BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, false, "fs_bpf_net_shared", \
+                        "", false, false, false)
 
 static __always_inline int is_system_uid(uint32_t uid) {
     // MIN_SYSTEM_UID is AID_ROOT == 0, so uint32_t is *always* >= 0
@@ -194,19 +196,38 @@
 DEFINE_UPDATE_STATS(stats_map_B, StatsKey)
 
 // both of these return 0 on success or -EFAULT on failure (and zero out the buffer)
-static __always_inline inline int bpf_skb_load_bytes_net(const struct __sk_buff* skb, int off,
-                                                         void* to, int len, bool is_4_19) {
-    return is_4_19
-        ? bpf_skb_load_bytes_relative(skb, off, to, len, BPF_HDR_START_NET)
-        : bpf_skb_load_bytes(skb, off, to, len);
+static __always_inline inline int bpf_skb_load_bytes_net(const struct __sk_buff* const skb,
+                                                         const int L3_off,
+                                                         void* const to,
+                                                         const int len,
+                                                         const unsigned kver) {
+    // 'kver' (here and throughout) is the compile time guaranteed minimum kernel version,
+    // ie. we're building (a version of) the bpf program for kver (or newer!) kernels.
+    //
+    // 4.19+ kernels support the 'bpf_skb_load_bytes_relative()' bpf helper function,
+    // so we can use it.  On pre-4.19 kernels we cannot use the relative load helper,
+    // and thus will simply get things wrong if there's any L2 (ethernet) header in the skb.
+    //
+    // Luckily, for cellular traffic, there likely isn't any, as cell is usually 'rawip'.
+    //
+    // However, this does mean that wifi (and ethernet) on 4.14 is basically a lost cause:
+    // we'll be making decisions based on the *wrong* bytes (fetched from the wrong offset),
+    // because the 'L3_off' passed to bpf_skb_load_bytes() should be increased by l2_header_size,
+    // which for ethernet is 14 and not 0 like it is for rawip.
+    //
+    // For similar reasons this will fail with non-offloaded VLAN tags on < 4.19 kernels,
+    // since those extend the ethernet header from 14 to 18 bytes.
+    return kver >= KVER(4, 19, 0)
+        ? bpf_skb_load_bytes_relative(skb, L3_off, to, len, BPF_HDR_START_NET)
+        : bpf_skb_load_bytes(skb, L3_off, to, len);
 }
 
-static __always_inline inline bool skip_owner_match(struct __sk_buff* skb, bool is_4_19) {
+static __always_inline inline bool skip_owner_match(struct __sk_buff* skb, const unsigned kver) {
     uint32_t flag = 0;
     if (skb->protocol == htons(ETH_P_IP)) {
         uint8_t proto;
         // no need to check for success, proto will be zeroed if bpf_skb_load_bytes_net() fails
-        (void)bpf_skb_load_bytes_net(skb, IP_PROTO_OFF, &proto, sizeof(proto), is_4_19);
+        (void)bpf_skb_load_bytes_net(skb, IP_PROTO_OFF, &proto, sizeof(proto), kver);
         if (proto == IPPROTO_ESP) return true;
         if (proto != IPPROTO_TCP) return false;  // handles read failure above
         uint8_t ihl;
@@ -215,19 +236,19 @@
         // (a little bit deeper in the packet in spite of ihl being zeroed) of the tcp flags
         // field will also fail, and that failure we already handle correctly
         // (we also don't check that ihl in [0x45,0x4F] nor that ipv4 header checksum is correct)
-        (void)bpf_skb_load_bytes_net(skb, IPPROTO_IHL_OFF, &ihl, sizeof(ihl), is_4_19);
+        (void)bpf_skb_load_bytes_net(skb, IPPROTO_IHL_OFF, &ihl, sizeof(ihl), kver);
         // if the read below fails, we'll just assume no TCP flags are set, which is fine.
         (void)bpf_skb_load_bytes_net(skb, (ihl & 0xF) * 4 + TCP_FLAG32_OFF,
-                                     &flag, sizeof(flag), is_4_19);
+                                     &flag, sizeof(flag), kver);
     } else if (skb->protocol == htons(ETH_P_IPV6)) {
         uint8_t proto;
         // no need to check for success, proto will be zeroed if bpf_skb_load_bytes_net() fails
-        (void)bpf_skb_load_bytes_net(skb, IPV6_PROTO_OFF, &proto, sizeof(proto), is_4_19);
+        (void)bpf_skb_load_bytes_net(skb, IPV6_PROTO_OFF, &proto, sizeof(proto), kver);
         if (proto == IPPROTO_ESP) return true;
         if (proto != IPPROTO_TCP) return false;  // handles read failure above
         // if the read below fails, we'll just assume no TCP flags are set, which is fine.
         (void)bpf_skb_load_bytes_net(skb, sizeof(struct ipv6hdr) + TCP_FLAG32_OFF,
-                                     &flag, sizeof(flag), is_4_19);
+                                     &flag, sizeof(flag), kver);
     } else {
         return false;
     }
@@ -250,8 +271,8 @@
 #define DROP_IF_UNSET (DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH | LOW_POWER_STANDBY_MATCH)
 
 static __always_inline inline int bpf_owner_match(struct __sk_buff* skb, uint32_t uid,
-                                                  bool egress, bool is_4_19) {
-    if (skip_owner_match(skb, is_4_19)) return PASS;
+                                                  bool egress, const unsigned kver) {
+    if (skip_owner_match(skb, kver)) return PASS;
 
     if (is_system_uid(uid)) return PASS;
 
@@ -288,13 +309,13 @@
                                                             StatsKey* key, uint32_t selectedMap) {
     if (selectedMap == SELECT_MAP_A) {
         update_stats_map_A(skb, egress, key);
-    } else if (selectedMap == SELECT_MAP_B) {
+    } else {
         update_stats_map_B(skb, egress, key);
     }
 }
 
 static __always_inline inline int bpf_traffic_account(struct __sk_buff* skb, bool egress,
-                                                      bool is_4_19) {
+                                                      const unsigned kver) {
     uint32_t sock_uid = bpf_get_socket_uid(skb);
     uint64_t cookie = bpf_get_socket_cookie(skb);
     UidTagValue* utag = bpf_cookie_tag_map_lookup_elem(&cookie);
@@ -314,7 +335,7 @@
         return PASS;
     }
 
-    int match = bpf_owner_match(skb, sock_uid, egress, is_4_19);
+    int match = bpf_owner_match(skb, sock_uid, egress, kver);
     if (egress && (match == DROP)) {
         // If an outbound packet is going to be dropped, we do not count that
         // traffic.
@@ -362,25 +383,25 @@
 DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/ingress/stats$4_19", AID_ROOT, AID_SYSTEM,
                                 bpf_cgroup_ingress_4_19, KVER(4, 19, 0), KVER_INF)
 (struct __sk_buff* skb) {
-    return bpf_traffic_account(skb, INGRESS, /* is_4_19 */ true);
+    return bpf_traffic_account(skb, INGRESS, KVER(4, 19, 0));
 }
 
 DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/ingress/stats$4_14", AID_ROOT, AID_SYSTEM,
                                 bpf_cgroup_ingress_4_14, KVER_NONE, KVER(4, 19, 0))
 (struct __sk_buff* skb) {
-    return bpf_traffic_account(skb, INGRESS, /* is_4_19 */ false);
+    return bpf_traffic_account(skb, INGRESS, KVER_NONE);
 }
 
 DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/egress/stats$4_19", AID_ROOT, AID_SYSTEM,
                                 bpf_cgroup_egress_4_19, KVER(4, 19, 0), KVER_INF)
 (struct __sk_buff* skb) {
-    return bpf_traffic_account(skb, EGRESS, /* is_4_19 */ true);
+    return bpf_traffic_account(skb, EGRESS, KVER(4, 19, 0));
 }
 
 DEFINE_NETD_BPF_PROG_KVER_RANGE("cgroupskb/egress/stats$4_14", AID_ROOT, AID_SYSTEM,
                                 bpf_cgroup_egress_4_14, KVER_NONE, KVER(4, 19, 0))
 (struct __sk_buff* skb) {
-    return bpf_traffic_account(skb, EGRESS, /* is_4_19 */ false);
+    return bpf_traffic_account(skb, EGRESS, KVER_NONE);
 }
 
 // WARNING: Android T's non-updatable netd depends on the name of this program.
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index c2d245c..87b0a64 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -260,6 +260,7 @@
   public class IpSecManager {
     method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+    method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void startTunnelModeTransformMigration(@NonNull android.net.IpSecTransform, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress);
   }
 
   public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
diff --git a/framework-t/src/android/net/IIpSecService.aidl b/framework-t/src/android/net/IIpSecService.aidl
index 933256a..88ffd0e 100644
--- a/framework-t/src/android/net/IIpSecService.aidl
+++ b/framework-t/src/android/net/IIpSecService.aidl
@@ -66,6 +66,12 @@
     IpSecTransformResponse createTransform(
             in IpSecConfig c, in IBinder binder, in String callingPackage);
 
+    void migrateTransform(
+            int transformId,
+            in String newSourceAddress,
+            in String newDestinationAddress,
+            in String callingPackage);
+
     void deleteTransform(int transformId);
 
     void applyTransportModeTransform(
diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java
index 9cceac2..c8469b1 100644
--- a/framework-t/src/android/net/IpSecManager.java
+++ b/framework-t/src/android/net/IpSecManager.java
@@ -37,6 +37,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.build.SdkLevel;
 
 import dalvik.system.CloseGuard;
 
@@ -65,6 +66,24 @@
     private static final String TAG = "IpSecManager";
 
     /**
+     * Feature flag to declare the kernel support of updating IPsec SAs.
+     *
+     * <p>Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
+     * has the requisite kernel support for migrating IPsec tunnels to new source/destination
+     * addresses.
+     *
+     * <p>This feature implies that the device supports XFRM Migration (CONFIG_XFRM_MIGRATE) and has
+     * the kernel fixes to allow XFRM Migration correctly
+     *
+     * @see android.content.pm.PackageManager#FEATURE_IPSEC_TUNNEL_MIGRATION
+     * @hide
+     */
+    // Redefine this flag here so that IPsec code shipped in a mainline module can build on old
+    // platforms before FEATURE_IPSEC_TUNNEL_MIGRATION API is released.
+    public static final String FEATURE_IPSEC_TUNNEL_MIGRATION =
+            "android.software.ipsec_tunnel_migration";
+
+    /**
      * Used when applying a transform to direct traffic through an {@link IpSecTransform}
      * towards the host.
      *
@@ -591,7 +610,7 @@
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
-            mCloseGuard.open("constructor");
+            mCloseGuard.open("close");
         }
 
         /** Get the encapsulation socket's file descriptor. */
@@ -804,16 +823,18 @@
          * Update the underlying network for this IpSecTunnelInterface.
          *
          * <p>This new underlying network will be used for all transforms applied AFTER this call is
-         * complete. Before new {@link IpSecTransform}(s) with matching addresses are applied to
-         * this tunnel interface, traffic will still use the old SA, and be routed on the old
+         * complete. Before {@link IpSecTransform}(s) with matching addresses are applied to this
+         * tunnel interface, traffic will still use the old transform, and be routed on the old
          * underlying network.
          *
          * <p>To migrate IPsec tunnel mode traffic, a caller should:
          *
          * <ol>
          *   <li>Update the IpSecTunnelInterface’s underlying network.
-         *   <li>Apply {@link IpSecTransform}(s) with matching addresses to this
-         *       IpSecTunnelInterface.
+         *   <li>Apply the new {@link IpSecTransform}(s) to this IpSecTunnelInterface. These can be
+         *       new {@link IpSecTransform}(s) with matching addresses, or {@link IpSecTransform}(s)
+         *       that have started migration (see {@link
+         *       IpSecManager#startTunnelModeTransformMigration}).
          * </ol>
          *
          * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel.
@@ -822,7 +843,6 @@
          *     method will throw an {@link IllegalArgumentException}. If the IpSecTunnelInterface is
          *     later added to this network, all outbound traffic will be blackholed.
          */
-        // TODO: b/169171001 Update the documentation when transform migration is supported.
         // The purpose of making updating network and applying transforms separate is to leave open
         // the possibility to support lossless migration procedures. To do that, Android platform
         // will need to support multiple inbound tunnel mode transforms, just like it can support
@@ -871,7 +891,7 @@
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
-            mCloseGuard.open("constructor");
+            mCloseGuard.open("close");
         }
 
         /**
@@ -988,6 +1008,60 @@
     }
 
     /**
+     * Migrate an active Tunnel Mode IPsec Transform to new source/destination addresses.
+     *
+     * <p>Begins the process of migrating a transform and cache the new addresses. To complete the
+     * migration once started, callers MUST apply the same transform to the appropriate tunnel using
+     * {@link IpSecManager#applyTunnelModeTransform}. Otherwise, the address update will not be
+     * committed and the transform will still only process traffic between the current source and
+     * destination address. One common use case is that the control plane will start the migration
+     * process and then hand off the transform to the IPsec caller to perform the actual migration
+     * when the tunnel is ready.
+     *
+     * <p>If this method is called multiple times before {@link
+     * IpSecManager#applyTunnelModeTransform} is called, when the transform is applied, it will be
+     * migrated to the addresses from the last call.
+     *
+     * <p>The provided source and destination addresses MUST share the same address family, but they
+     * can have a different family from the current addresses.
+     *
+     * <p>Transform migration is only supported for tunnel mode transforms. Calling this method on
+     * other types of transforms will throw an {@code UnsupportedOperationException}.
+     *
+     * @see IpSecTunnelInterface#setUnderlyingNetwork
+     * @param transform a tunnel mode {@link IpSecTransform}
+     * @param newSourceAddress the new source address
+     * @param newDestinationAddress the new destination address
+     * @hide
+     */
+    @SystemApi
+    @RequiresFeature(FEATURE_IPSEC_TUNNEL_MIGRATION)
+    @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
+    public void startTunnelModeTransformMigration(
+            @NonNull IpSecTransform transform,
+            @NonNull InetAddress newSourceAddress,
+            @NonNull InetAddress newDestinationAddress) {
+        if (!SdkLevel.isAtLeastU()) {
+            throw new UnsupportedOperationException(
+                    "Transform migration only supported for Android 14+");
+        }
+
+        Objects.requireNonNull(transform, "transform was null");
+        Objects.requireNonNull(newSourceAddress, "newSourceAddress was null");
+        Objects.requireNonNull(newDestinationAddress, "newDestinationAddress was null");
+
+        try {
+            mService.migrateTransform(
+                    transform.getResourceId(),
+                    newSourceAddress.getHostAddress(),
+                    newDestinationAddress.getHostAddress(),
+                    mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * @hide
      */
     public IpSecTransformResponse createTransform(IpSecConfig config, IBinder binder,
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index c0ae822..b2da371 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -52,7 +52,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.net.module.util.CollectionUtils;
 import com.android.net.module.util.NetworkIdentityUtils;
-import com.android.net.module.util.NetworkStatsUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -280,23 +279,21 @@
     private final int mRoaming;
     private final int mDefaultNetwork;
     private final int mRatType;
-    /**
-     * The subscriber Id match rule defines how the template should match networks with
-     * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
-     */
-    private final int mSubscriberIdMatchRule;
 
     // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
     private final int mOemManaged;
 
-    private static void checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule) {
+    private static void checkValidMatchSubscriberIds(int matchRule, String[] matchSubscriberIds) {
         switch (matchRule) {
             case MATCH_MOBILE:
             case MATCH_CARRIER:
                 // MOBILE and CARRIER templates must always specify a subscriber ID.
-                if (subscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL) {
-                    throw new IllegalArgumentException("Invalid SubscriberIdMatchRule "
-                            + "on match rule: " + getMatchRuleName(matchRule));
+                if (matchSubscriberIds.length == 0) {
+                    throw new IllegalArgumentException("checkValidMatchSubscriberIds with empty"
+                            + " list of ids for rule" + getMatchRuleName(matchRule));
+                } else if (CollectionUtils.contains(matchSubscriberIds, null)) {
+                    throw new IllegalArgumentException("checkValidMatchSubscriberIds list of ids"
+                            + " may not contain null for rule " + getMatchRuleName(matchRule));
                 }
                 return;
             default:
@@ -312,28 +309,21 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.TIRAMISU,
             publicAlternatives = "Use {@code Builder} instead.")
     public NetworkTemplate(int matchRule, String subscriberId, String wifiNetworkKey) {
-        this(matchRule, subscriberId, new String[] { subscriberId }, wifiNetworkKey);
-    }
-
-    /** @hide */
-    public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
-            String wifiNetworkKey) {
         // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
         // to metered networks. It is now possible to match mobile with any meteredness, but
         // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
         //constructor passes METERED_YES for these types.
-        this(matchRule, subscriberId, matchSubscriberIds,
+        this(matchRule, subscriberId, new String[] { subscriberId },
                 wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
                 (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD
                         || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL,
-                ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
+                ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
     }
 
     /** @hide */
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String[] matchWifiNetworkKeys, int metered, int roaming,
-            int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) {
+            int defaultNetwork, int ratType, int oemManaged) {
         Objects.requireNonNull(matchWifiNetworkKeys);
         Objects.requireNonNull(matchSubscriberIds);
         mMatchRule = matchRule;
@@ -345,8 +335,7 @@
         mDefaultNetwork = defaultNetwork;
         mRatType = ratType;
         mOemManaged = oemManaged;
-        mSubscriberIdMatchRule = subscriberIdMatchRule;
-        checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
+        checkValidMatchSubscriberIds(matchRule, matchSubscriberIds);
         if (!isKnownMatchRule(matchRule)) {
             throw new IllegalArgumentException("Unknown network template rule " + matchRule
                     + " will not match any identity.");
@@ -363,7 +352,6 @@
         mDefaultNetwork = in.readInt();
         mRatType = in.readInt();
         mOemManaged = in.readInt();
-        mSubscriberIdMatchRule = in.readInt();
     }
 
     @Override
@@ -377,7 +365,6 @@
         dest.writeInt(mDefaultNetwork);
         dest.writeInt(mRatType);
         dest.writeInt(mOemManaged);
-        dest.writeInt(mSubscriberIdMatchRule);
     }
 
     @Override
@@ -414,15 +401,13 @@
         if (mOemManaged != OEM_MANAGED_ALL) {
             builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
         }
-        builder.append(", subscriberIdMatchRule=")
-                .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule));
         return builder.toString();
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys),
-                mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, mSubscriberIdMatchRule);
+                mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged);
     }
 
     @Override
@@ -436,23 +421,11 @@
                     && mDefaultNetwork == other.mDefaultNetwork
                     && mRatType == other.mRatType
                     && mOemManaged == other.mOemManaged
-                    && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
                     && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
         }
         return false;
     }
 
-    private static String subscriberIdMatchRuleToString(int rule) {
-        switch (rule) {
-            case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT:
-                return "EXACT_MATCH";
-            case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL:
-                return "ALL";
-            default:
-                return "Unknown rule " + rule;
-        }
-    }
-
     /** @hide */
     public boolean isMatchRuleMobile() {
         switch (mMatchRule) {
@@ -627,13 +600,13 @@
 
     /**
      * Check if this template matches {@code subscriberId}. Returns true if this
-     * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a
-     * {@code mMatchSubscriberIds} array that contains {@code subscriberId}.
+     * template was created with a {@code mMatchSubscriberIds} array that contains
+     * {@code subscriberId} or if {@code mMatchSubscriberIds} is empty.
      *
      * @hide
      */
     public boolean matchesSubscriberId(@Nullable String subscriberId) {
-        return mSubscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
+        return mMatchSubscriberIds.length == 0
                 || CollectionUtils.contains(mMatchSubscriberIds, subscriberId);
     }
 
@@ -812,7 +785,11 @@
             // could handle incompatible subscriberIds. See b/217805241.
             return new NetworkTemplate(template.mMatchRule, merged[0], merged,
                     CollectionUtils.isEmpty(matchWifiNetworkKeys)
-                            ? null : matchWifiNetworkKeys[0]);
+                            ? new String[0] : new String[] { matchWifiNetworkKeys[0] },
+                    (template.mMatchRule == MATCH_MOBILE
+                            || template.mMatchRule == MATCH_MOBILE_WILDCARD
+                            || template.mMatchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL,
+                    ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
         }
 
         return template;
@@ -1024,14 +1001,11 @@
         @NonNull
         public NetworkTemplate build() {
             assertRequestableParameters();
-            final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty()
-                    ? NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
-                    : NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT;
             return new NetworkTemplate(getWildcardDeducedMatchRule(),
                     mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(),
                     mMatchSubscriberIds.toArray(new String[0]),
                     mMatchWifiNetworkKeys.toArray(new String[0]), mMetered, mRoaming,
-                    mDefaultNetwork, mRatType, mOemManaged, subscriberIdMatchRule);
+                    mDefaultNetwork, mRatType, mOemManaged);
         }
     }
 }
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 752c347..f623b05 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -31,6 +31,7 @@
     method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreferences(@NonNull android.os.UserHandle, @NonNull java.util.List<android.net.ProfileNetworkPreference>, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setRequireVpnForUids(boolean, @NonNull java.util.Collection<android.util.Range<java.lang.Integer>>);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setUidFirewallRule(int, int, int);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setVpnDefaultForUids(@NonNull String, @NonNull java.util.Collection<android.util.Range<java.lang.Integer>>);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
     method public void systemReady();
@@ -62,6 +63,7 @@
     field public static final int FIREWALL_RULE_DENY = 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_BLOCKING = 3; // 0x3
     field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK = 2; // 0x2
   }
 
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 1b4b42f..40defd4 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -1232,16 +1232,19 @@
     }
 
     /**
-     * Preference for {@link ProfileNetworkPreference#setPreference(int)}.
+     * Preference for {@link ProfileNetworkPreference.Builder#setPreference(int)}.
      * See {@link #setProfileNetworkPreferences(UserHandle, List, Executor, Runnable)}
-     * Specify that the traffic for this user should by follow the default rules.
+     * Specify that the traffic for this user should by follow the default rules:
+     * applications in the profile designated by the UserHandle behave like any
+     * other application and use the system default network as their default
+     * network. Compare other PROFILE_NETWORK_PREFERENCE_* settings.
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0;
 
     /**
-     * Preference for {@link ProfileNetworkPreference#setPreference(int)}.
+     * Preference for {@link ProfileNetworkPreference.Builder#setPreference(int)}.
      * See {@link #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
@@ -1252,16 +1255,38 @@
     public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1;
 
     /**
-     * Preference for {@link ProfileNetworkPreference#setPreference(int)}.
+     * Preference for {@link ProfileNetworkPreference.Builder#setPreference(int)}.
      * See {@link #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
+     * should not have a default network at all (that is, network accesses that
+     * do not specify a network explicitly terminate with an error), even if there
+     * is a system default network available to apps outside this preference.
+     * The apps can still use a non-enterprise network if they request it explicitly
+     * provided that specific network doesn't require any specific permission they
+     * do not hold.
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK = 2;
 
+    /**
+     * Preference for {@link ProfileNetworkPreference.Builder#setPreference(int)}.
+     * See {@link #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}.
+     * If there is no such network, the apps will have no default
+     * network at all, even if there are available non-enterprise networks on the
+     * device (that is, network accesses that do not specify a network explicitly
+     * terminate with an error). Additionally, the designated apps should be
+     * blocked from using any non-enterprise network even if they specify it
+     * explicitly, unless they hold specific privilege overriding this (see
+     * {@link android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS}).
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING = 3;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
@@ -1378,6 +1403,17 @@
         }
     }
 
+    private static UidRange[] getUidRangeArray(@NonNull Collection<Range<Integer>> ranges) {
+        Objects.requireNonNull(ranges);
+        final UidRange[] rangesArray = new UidRange[ranges.size()];
+        int index = 0;
+        for (Range<Integer> range : ranges) {
+            rangesArray[index++] = new UidRange(range.getLower(), range.getUpper());
+        }
+
+        return rangesArray;
+    }
+
     /**
      * Adds or removes a requirement for given UID ranges to use the VPN.
      *
@@ -1397,6 +1433,12 @@
      * {@link NetworkCallback#onBlockedStatusChanged} callbacks called after the changes take
      * effect.
      * <p>
+     * This method will block the specified UIDs from accessing non-VPN networks, but does not
+     * affect what the UIDs get as their default network.
+     * Compare {@link #setVpnDefaultForUids(String, Collection)}, which declares that the UIDs
+     * should only have a VPN as their default network, but does not block them from accessing other
+     * networks if they request them explicitly with the {@link Network} API.
+     * <p>
      * This method should be called only by the VPN code.
      *
      * @param ranges the UID ranges to restrict
@@ -1416,11 +1458,7 @@
         // This method is not necessarily expected to be used outside the system server, so
         // parceling may not be necessary, but it could be used out-of-process, e.g., by the network
         // stack process, or by tests.
-        UidRange[] rangesArray = new UidRange[ranges.size()];
-        int index = 0;
-        for (Range<Integer> range : ranges) {
-            rangesArray[index++] = new UidRange(range.getLower(), range.getUpper());
-        }
+        final UidRange[] rangesArray = getUidRangeArray(ranges);
         try {
             mService.setRequireVpnForUids(requireVpn, rangesArray);
         } catch (RemoteException e) {
@@ -1429,6 +1467,41 @@
     }
 
     /**
+     * Inform the system that this VPN session should manage the passed UIDs.
+     *
+     * A VPN with the specified session ID may call this method to inform the system that the UIDs
+     * in the specified range are subject to a VPN.
+     * When this is called, the system will only choose a VPN for the default network of the UIDs in
+     * the specified ranges.
+     *
+     * This method declares that the UIDs in the range will only have a VPN for their default
+     * network, but does not block the UIDs from accessing other networks (permissions allowing) by
+     * explicitly requesting it with the {@link Network} API.
+     * Compare {@link #setRequireVpnForUids(boolean, Collection)}, which does not affect what
+     * network the UIDs get as default, but will block them from accessing non-VPN networks.
+     *
+     * @param session The VPN session which manages the passed UIDs.
+     * @param ranges The uid ranges which will treat VPN as their only default network.
+     *
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK,
+            android.Manifest.permission.NETWORK_SETTINGS})
+    @SystemApi(client = MODULE_LIBRARIES)
+    public void setVpnDefaultForUids(@NonNull String session,
+            @NonNull Collection<Range<Integer>> ranges) {
+        Objects.requireNonNull(ranges);
+        final UidRange[] rangesArray = getUidRangeArray(ranges);
+        try {
+            mService.setVpnNetworkPreference(session, rangesArray);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Informs ConnectivityService of whether the legacy lockdown VPN, as implemented by
      * LockdownVpnTracker, is in use. This is deprecated for new devices starting from Android 12
      * but is still supported for backwards compatibility.
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 43d2f07..7b6e769 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -249,4 +249,6 @@
     void replaceFirewallChain(int chain, in int[] uids);
 
     IBinder getCompanionDeviceManagerProxyService();
+
+    void setVpnNetworkPreference(String session, in UidRange[] ranges);
 }
diff --git a/netd/Android.bp b/netd/Android.bp
index c731b8b..473460d 100644
--- a/netd/Android.bp
+++ b/netd/Android.bp
@@ -63,6 +63,7 @@
     ],
     srcs: [
         "BpfHandlerTest.cpp",
+        "BpfBaseTest.cpp"
     ],
     static_libs: [
         "libnetd_updatable",
@@ -72,6 +73,7 @@
         "libcutils",
         "liblog",
         "libnetdutils",
+        "libprocessgroup",
     ],
     compile_multilib: "both",
     multilib: {
diff --git a/tests/native/connectivity_native_test/bpf_base_test.cpp b/netd/BpfBaseTest.cpp
similarity index 79%
rename from tests/native/connectivity_native_test/bpf_base_test.cpp
rename to netd/BpfBaseTest.cpp
index f164b2f..624d216 100644
--- a/tests/native/connectivity_native_test/bpf_base_test.cpp
+++ b/netd/BpfBaseTest.cpp
@@ -37,7 +37,7 @@
 
 #include "bpf/BpfMap.h"
 #include "bpf/BpfUtils.h"
-#include "bpf_shared.h"
+#include "netd.h"
 
 using android::base::Result;
 
@@ -61,26 +61,6 @@
     ASSERT_EQ(0, access((cg2_path + "/cgroup.controllers").c_str(), R_OK));
 }
 
-TEST_F(BpfBasicTest, TestTrafficControllerSetUp) {
-    ASSERT_EQ(0, access(BPF_EGRESS_PROG_PATH, R_OK));
-    ASSERT_EQ(0, access(BPF_INGRESS_PROG_PATH, R_OK));
-    ASSERT_EQ(0, access(XT_BPF_INGRESS_PROG_PATH, R_OK));
-    ASSERT_EQ(0, access(XT_BPF_EGRESS_PROG_PATH, R_OK));
-    ASSERT_EQ(0, access(COOKIE_TAG_MAP_PATH, R_OK));
-    ASSERT_EQ(0, access(UID_COUNTERSET_MAP_PATH, R_OK));
-    ASSERT_EQ(0, access(STATS_MAP_A_PATH, R_OK));
-    ASSERT_EQ(0, access(STATS_MAP_B_PATH, R_OK));
-    ASSERT_EQ(0, access(IFACE_INDEX_NAME_MAP_PATH, R_OK));
-    ASSERT_EQ(0, access(IFACE_STATS_MAP_PATH, R_OK));
-    ASSERT_EQ(0, access(CONFIGURATION_MAP_PATH, R_OK));
-    ASSERT_EQ(0, access(UID_OWNER_MAP_PATH, R_OK));
-}
-
-TEST_F(BpfBasicTest, TestSocketFilterSetUp) {
-    ASSERT_EQ(0, access(CGROUP_SOCKET_PROG_PATH, R_OK));
-    ASSERT_EQ(0, access(UID_PERMISSION_MAP_PATH, R_OK));
-}
-
 TEST_F(BpfBasicTest, TestTagSocket) {
     BpfMap<uint64_t, UidTagValue> cookieTagMap(COOKIE_TAG_MAP_PATH);
     ASSERT_TRUE(cookieTagMap.isValid());
diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
index 6cee08a..9e71eb3 100644
--- a/service-t/src/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static android.Manifest.permission.DUMP;
+import static android.net.IpSecManager.FEATURE_IPSEC_TUNNEL_MIGRATION;
 import static android.net.IpSecManager.INVALID_RESOURCE_ID;
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
@@ -36,6 +37,7 @@
 import android.net.IpSecAlgorithm;
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
+import android.net.IpSecMigrateInfoParcel;
 import android.net.IpSecSpiResponse;
 import android.net.IpSecTransform;
 import android.net.IpSecTransformResponse;
@@ -590,14 +592,19 @@
     }
 
     /**
-     * Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is
-     * created, the SpiRecord that originally tracked the SAs will reliquish the
-     * responsibility of freeing the underlying SA to this class via the mOwnedByTransform flag.
+     * Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is created, the
+     * SpiRecord that originally tracked the SAs will reliquish the responsibility of freeing the
+     * underlying SA to this class via the mOwnedByTransform flag.
+     *
+     * <p>This class is not thread-safe, and expects that that users of this class will ensure
+     * synchronization and thread safety by holding the IpSecService.this instance lock
      */
     private final class TransformRecord extends OwnedResourceRecord {
         private final IpSecConfig mConfig;
         private final SpiRecord mSpi;
         private final EncapSocketRecord mSocket;
+        private String mNewSourceAddress = null;
+        private String mNewDestinationAddress = null;
 
         TransformRecord(
                 int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) {
@@ -621,6 +628,51 @@
             return mSocket;
         }
 
+        @GuardedBy("IpSecService.this")
+        public String getNewSourceAddress() {
+            return mNewSourceAddress;
+        }
+
+        @GuardedBy("IpSecService.this")
+        public String getNewDestinationAddress() {
+            return mNewDestinationAddress;
+        }
+
+        private void verifyTunnelModeOrThrow() {
+            if (mConfig.getMode() != IpSecTransform.MODE_TUNNEL) {
+                throw new UnsupportedOperationException(
+                        "Migration requested/called on non-tunnel-mode transform");
+            }
+        }
+
+        /** Start migrating this transform to new source and destination addresses */
+        @GuardedBy("IpSecService.this")
+        public void startMigration(String newSourceAddress, String newDestinationAddress) {
+            verifyTunnelModeOrThrow();
+            Objects.requireNonNull(newSourceAddress, "newSourceAddress was null");
+            Objects.requireNonNull(newDestinationAddress, "newDestinationAddress was null");
+            mNewSourceAddress = newSourceAddress;
+            mNewDestinationAddress = newDestinationAddress;
+        }
+
+        /** Finish migration and update addresses. */
+        @GuardedBy("IpSecService.this")
+        public void finishMigration() {
+            verifyTunnelModeOrThrow();
+            mConfig.setSourceAddress(mNewSourceAddress);
+            mConfig.setDestinationAddress(mNewDestinationAddress);
+            mNewSourceAddress = null;
+            mNewDestinationAddress = null;
+        }
+
+        /** Return if this transform is going to be migrated. */
+        @GuardedBy("IpSecService.this")
+        public boolean isMigrating() {
+            verifyTunnelModeOrThrow();
+
+            return mNewSourceAddress != null;
+        }
+
         /** always guarded by IpSecService#this */
         @Override
         public void freeUnderlyingResources() {
@@ -1630,6 +1682,14 @@
                 android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
     }
 
+    private void enforceMigrateFeature() {
+        if (!mContext.getPackageManager().hasSystemFeature(FEATURE_IPSEC_TUNNEL_MIGRATION)) {
+            throw new UnsupportedOperationException(
+                    "IPsec Tunnel migration requires"
+                            + " PackageManager.FEATURE_IPSEC_TUNNEL_MIGRATION");
+        }
+    }
+
     private void createOrUpdateTransform(
             IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
             throws RemoteException {
@@ -1726,6 +1786,45 @@
     }
 
     /**
+     * Migrate an active Tunnel Mode IPsec Transform to new source/destination addresses.
+     *
+     * <p>Begins the process of migrating a transform and cache the new addresses. To complete the
+     * migration once started, callers MUST apply the same transform to the appropriate tunnel using
+     * {@link #applyTunnelModeTransform}. Otherwise, the address update will not be committed and
+     * the transform will still only process traffic between the current source and destination
+     * address. One common use case is that the control plane will start the migration process and
+     * then hand off the transform to the IPsec caller to perform the actual migration when the
+     * tunnel is ready.
+     *
+     * <p>If this method is called multiple times before {@link #applyTunnelModeTransform} is
+     * called, when the transform is applied, it will be migrated to the addresses from the last
+     * call.
+     *
+     * <p>The provided source and destination addresses MUST share the same address family, but they
+     * can have a different family from the current addresses.
+     *
+     * <p>Transform migration is only supported for tunnel mode transforms. Calling this method on
+     * other types of transforms will throw an {@code UnsupportedOperationException}.
+     */
+    @Override
+    public synchronized void migrateTransform(
+            int transformId,
+            String newSourceAddress,
+            String newDestinationAddress,
+            String callingPackage) {
+        Objects.requireNonNull(newSourceAddress, "newSourceAddress was null");
+        Objects.requireNonNull(newDestinationAddress, "newDestinationAddress was null");
+
+        enforceTunnelFeatureAndPermissions(callingPackage);
+        enforceMigrateFeature();
+
+        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+        TransformRecord transformInfo =
+                userRecord.mTransformRecords.getResourceOrThrow(transformId);
+        transformInfo.startMigration(newSourceAddress, newDestinationAddress);
+    }
+
+    /**
      * Delete a transport mode transform that was previously allocated by + registered with the
      * system server. If this is called on an inactive (or non-existent) transform, it will not
      * return an error. It's safe to de-allocate transforms that may have already been deleted for
@@ -1784,12 +1883,15 @@
 
     /**
      * Apply an active tunnel mode transform to a TunnelInterface, which will apply the IPsec
-     * security association as a correspondent policy to the provided interface
+     * security association as a correspondent policy to the provided interface.
+     *
+     * <p>If the transform is migrating, migrate the IPsec security association to new
+     * source/destination addresses, and mark the migration as finished.
      */
     @Override
     public synchronized void applyTunnelModeTransform(
-            int tunnelResourceId, int direction,
-            int transformResourceId, String callingPackage) throws RemoteException {
+            int tunnelResourceId, int direction, int transformResourceId, String callingPackage)
+            throws RemoteException {
         enforceTunnelFeatureAndPermissions(callingPackage);
         checkDirection(direction);
 
@@ -1868,6 +1970,32 @@
 
             // Update SA with tunnel mark (ikey or okey based on direction)
             createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
+
+            if (transformInfo.isMigrating()) {
+                if (!mContext.getPackageManager()
+                        .hasSystemFeature(FEATURE_IPSEC_TUNNEL_MIGRATION)) {
+                    Log.wtf(
+                            TAG,
+                            "Attempted to migrate a transform without"
+                                    + " FEATURE_IPSEC_TUNNEL_MIGRATION");
+                }
+
+                for (int selAddrFamily : ADDRESS_FAMILIES) {
+                    final IpSecMigrateInfoParcel migrateInfo =
+                            new IpSecMigrateInfoParcel(
+                                    Binder.getCallingUid(),
+                                    selAddrFamily,
+                                    direction,
+                                    c.getSourceAddress(),
+                                    c.getDestinationAddress(),
+                                    transformInfo.getNewSourceAddress(),
+                                    transformInfo.getNewDestinationAddress(),
+                                    c.getXfrmInterfaceId());
+
+                    mNetd.ipSecMigrate(migrateInfo);
+                }
+                transformInfo.finishMigration();
+            }
         } catch (ServiceSpecificException e) {
             if (e.errorCode == EINVAL) {
                 throw new IllegalArgumentException(e.toString());
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index 0605abe..51683de 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -491,10 +491,19 @@
             mDeps.makeIpClient(mContext, name, mIpClientCallback);
             mIpClientCallback.awaitIpClientStart();
 
+            if (mIpConfig.getProxySettings() == ProxySettings.STATIC
+                    || mIpConfig.getProxySettings() == ProxySettings.PAC) {
+                mIpClient.setHttpProxy(mIpConfig.getHttpProxy());
+            }
+
             if (sTcpBufferSizes == null) {
                 sTcpBufferSizes = mDeps.getTcpBufferSizesFromResource(mContext);
             }
-            provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);
+            if (!TextUtils.isEmpty(sTcpBufferSizes)) {
+                mIpClient.setTcpBufferSizes(sTcpBufferSizes);
+            }
+
+            mIpClient.startProvisioning(createProvisioningConfiguration(mIpConfig));
         }
 
         void onIpLayerStarted(@NonNull final LinkProperties linkProperties) {
@@ -635,20 +644,6 @@
             mRequestIds.clear();
         }
 
-        private static void provisionIpClient(@NonNull final IpClientManager ipClient,
-                @NonNull final IpConfiguration config, @NonNull final String tcpBufferSizes) {
-            if (config.getProxySettings() == ProxySettings.STATIC ||
-                    config.getProxySettings() == ProxySettings.PAC) {
-                ipClient.setHttpProxy(config.getHttpProxy());
-            }
-
-            if (!TextUtils.isEmpty(tcpBufferSizes)) {
-                ipClient.setTcpBufferSizes(tcpBufferSizes);
-            }
-
-            ipClient.startProvisioning(createProvisioningConfiguration(config));
-        }
-
         private static ProvisioningConfiguration createProvisioningConfiguration(
                 @NonNull final IpConfiguration config) {
             if (config.getIpAssignment() == IpAssignment.STATIC) {
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index cf53002..6206d83 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -69,6 +69,7 @@
 import android.annotation.Nullable;
 import android.annotation.TargetApi;
 import android.app.AlarmManager;
+import android.app.BroadcastOptions;
 import android.app.PendingIntent;
 import android.app.usage.NetworkStatsManager;
 import android.content.ApexEnvironment;
@@ -114,6 +115,7 @@
 import android.net.netstats.provider.NetworkStatsProvider;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.Handler;
@@ -149,6 +151,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FileRotator;
+import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
 import com.android.net.module.util.BestClock;
 import com.android.net.module.util.BinderUtils;
@@ -166,6 +169,9 @@
 import com.android.net.module.util.Struct.U8;
 import com.android.net.module.util.bpf.CookieTagMapKey;
 import com.android.net.module.util.bpf.CookieTagMapValue;
+import com.android.networkstack.apishim.BroadcastOptionsShimImpl;
+import com.android.networkstack.apishim.ConstantsShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
 import com.android.server.BpfNetMaps;
 
 import java.io.File;
@@ -526,8 +532,22 @@
                 case MSG_BROADCAST_NETWORK_STATS_UPDATED: {
                     final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
                     updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                    Bundle opts = null;
+                    if (SdkLevel.isAtLeastU()) {
+                        try {
+                            // This allows us to discard older broadcasts still waiting to
+                            // be delivered.
+                            opts = BroadcastOptionsShimImpl.newInstance(
+                                    BroadcastOptions.makeBasic())
+                                    .setDeliveryGroupPolicy(
+                                            ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT)
+                                    .toBundle();
+                        } catch (UnsupportedApiLevelException e) {
+                            Log.wtf(TAG, "Using unsupported API" + e);
+                        }
+                    }
                     mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
-                            READ_NETWORK_USAGE_HISTORY);
+                            READ_NETWORK_USAGE_HISTORY, opts);
                     break;
                 }
             }
@@ -2797,7 +2817,7 @@
             return;
         }
         if (map.isEmpty()) {
-            pw.println("No entries");
+            pw.println("");
             return;
         }
         // If there is a concurrent entry deletion, value could be null. http://b/220084230.
diff --git a/service/Android.bp b/service/Android.bp
index 224fa19..8fa6436 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -206,6 +206,7 @@
     libs: [
         "framework-annotations-lib",
         "framework-connectivity-pre-jarjar",
+        "framework-connectivity-t-pre-jarjar",
         "framework-tethering",
         "framework-wifi",
         "service-connectivity-pre-jarjar",
diff --git a/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
index f7871f3..fdd1478 100644
--- a/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
+++ b/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
@@ -18,7 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.Network;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Pair;
 
 import com.android.server.connectivity.mdns.util.MdnsLogger;
@@ -58,26 +60,29 @@
         }
     }
 
-    private final WeakReference<MdnsSocketClient> weakRequestSender;
+    private final WeakReference<MdnsSocketClientBase> weakRequestSender;
     private final MdnsPacketWriter packetWriter;
     private final String[] serviceTypeLabels;
     private final List<String> subtypes;
     private final boolean expectUnicastResponse;
     private final int transactionId;
+    private final Network network;
 
     EnqueueMdnsQueryCallable(
-            @NonNull MdnsSocketClient requestSender,
+            @NonNull MdnsSocketClientBase requestSender,
             @NonNull MdnsPacketWriter packetWriter,
             @NonNull String serviceType,
             @NonNull Collection<String> subtypes,
             boolean expectUnicastResponse,
-            int transactionId) {
+            int transactionId,
+            @Nullable Network network) {
         weakRequestSender = new WeakReference<>(requestSender);
         this.packetWriter = packetWriter;
         serviceTypeLabels = TextUtils.split(serviceType, "\\.");
         this.subtypes = new ArrayList<>(subtypes);
         this.expectUnicastResponse = expectUnicastResponse;
         this.transactionId = transactionId;
+        this.network = network;
     }
 
     // Incompatible return type for override of Callable#call().
@@ -86,7 +91,7 @@
     @Nullable
     public Pair<Integer, List<String>> call() {
         try {
-            MdnsSocketClient requestSender = weakRequestSender.get();
+            MdnsSocketClientBase requestSender = weakRequestSender.get();
             if (requestSender == null) {
                 return null;
             }
@@ -127,15 +132,24 @@
                     MdnsConstants.QCLASS_INTERNET
                             | (expectUnicastResponse ? MdnsConstants.QCLASS_UNICAST : 0));
 
-            InetAddress mdnsAddress = MdnsConstants.getMdnsIPv4Address();
-            if (requestSender.isOnIPv6OnlyNetwork()) {
-                mdnsAddress = MdnsConstants.getMdnsIPv6Address();
-            }
+            if (requestSender instanceof MdnsMultinetworkSocketClient) {
+                sendPacketToIpv4AndIpv6(requestSender, MdnsConstants.MDNS_PORT, network);
+                for (Integer emulatorPort : castShellEmulatorMdnsPorts) {
+                    sendPacketToIpv4AndIpv6(requestSender, emulatorPort, network);
+                }
+            } else if (requestSender instanceof MdnsSocketClient) {
+                final MdnsSocketClient client = (MdnsSocketClient) requestSender;
+                InetAddress mdnsAddress = MdnsConstants.getMdnsIPv4Address();
+                if (client.isOnIPv6OnlyNetwork()) {
+                    mdnsAddress = MdnsConstants.getMdnsIPv6Address();
+                }
 
-            sendPacketTo(requestSender,
-                    new InetSocketAddress(mdnsAddress, MdnsConstants.MDNS_PORT));
-            for (Integer emulatorPort : castShellEmulatorMdnsPorts) {
-                sendPacketTo(requestSender, new InetSocketAddress(mdnsAddress, emulatorPort));
+                sendPacketTo(client, new InetSocketAddress(mdnsAddress, MdnsConstants.MDNS_PORT));
+                for (Integer emulatorPort : castShellEmulatorMdnsPorts) {
+                    sendPacketTo(client, new InetSocketAddress(mdnsAddress, emulatorPort));
+                }
+            } else {
+                throw new IOException("Unknown socket client type: " + requestSender.getClass());
             }
             return Pair.create(transactionId, subtypes);
         } catch (IOException e) {
@@ -145,7 +159,7 @@
         }
     }
 
-    private void sendPacketTo(MdnsSocketClient requestSender, InetSocketAddress address)
+    private void sendPacketTo(MdnsSocketClientBase requestSender, InetSocketAddress address)
             throws IOException {
         DatagramPacket packet = packetWriter.getPacket(address);
         if (expectUnicastResponse) {
@@ -154,4 +168,31 @@
             requestSender.sendMulticastPacket(packet);
         }
     }
+
+    private void sendPacketFromNetwork(MdnsSocketClientBase requestSender,
+            InetSocketAddress address, Network network)
+            throws IOException {
+        DatagramPacket packet = packetWriter.getPacket(address);
+        if (expectUnicastResponse) {
+            requestSender.sendUnicastPacket(packet, network);
+        } else {
+            requestSender.sendMulticastPacket(packet, network);
+        }
+    }
+
+    private void sendPacketToIpv4AndIpv6(MdnsSocketClientBase requestSender, int port,
+            Network network) {
+        try {
+            sendPacketFromNetwork(requestSender,
+                    new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), port), network);
+        } catch (IOException e) {
+            Log.i(TAG, "Can't send packet to IPv4", e);
+        }
+        try {
+            sendPacketFromNetwork(requestSender,
+                    new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), port), network);
+        } catch (IOException e) {
+            Log.i(TAG, "Can't send packet to IPv6", e);
+        }
+    }
 }
\ No newline at end of file
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service/mdns/com/android/server/connectivity/mdns/MdnsAdvertiser.java
index dee78fd..4e40efe 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsAdvertiser.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsAdvertiser.java
@@ -16,14 +16,402 @@
 
 package com.android.server.connectivity.mdns;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkAddress;
+import android.net.Network;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.os.Looper;
+import android.util.ArrayMap;
 import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
 
 /**
  * MdnsAdvertiser manages advertising services per {@link com.android.server.NsdService} requests.
  *
- * TODO: implement
+ * All methods except the constructor must be called on the looper thread.
  */
 public class MdnsAdvertiser {
     private static final String TAG = MdnsAdvertiser.class.getSimpleName();
-    public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final Looper mLooper;
+    private final AdvertiserCallback mCb;
+
+    // Max-sized buffers to be used as temporary buffer to read/build packets. May be used by
+    // multiple components, but only for self-contained operations in the looper thread, so not
+    // concurrently.
+    // TODO: set according to MTU. 1300 should fit for ethernet MTU 1500 with some overhead.
+    private final byte[] mPacketCreationBuffer = new byte[1300];
+
+    private final MdnsSocketProvider mSocketProvider;
+    private final ArrayMap<Network, InterfaceAdvertiserRequest> mAdvertiserRequests =
+            new ArrayMap<>();
+    private final ArrayMap<MdnsInterfaceSocket, MdnsInterfaceAdvertiser> mAllAdvertisers =
+            new ArrayMap<>();
+    private final SparseArray<Registration> mRegistrations = new SparseArray<>();
+    private final Dependencies mDeps;
+
+    /**
+     * Dependencies for {@link MdnsAdvertiser}, useful for testing.
+     */
+    @VisibleForTesting
+    public static class Dependencies {
+        /**
+         * @see MdnsInterfaceAdvertiser
+         */
+        public MdnsInterfaceAdvertiser makeAdvertiser(@NonNull MdnsInterfaceSocket socket,
+                @NonNull List<LinkAddress> initialAddresses,
+                @NonNull Looper looper, @NonNull byte[] packetCreationBuffer,
+                @NonNull MdnsInterfaceAdvertiser.Callback cb) {
+            // Note NetworkInterface is final and not mockable
+            final String logTag = socket.getInterface().getName();
+            return new MdnsInterfaceAdvertiser(logTag, socket, initialAddresses, looper,
+                    packetCreationBuffer, cb);
+        }
+    }
+
+    private final MdnsInterfaceAdvertiser.Callback mInterfaceAdvertiserCb =
+            new MdnsInterfaceAdvertiser.Callback() {
+        @Override
+        public void onRegisterServiceSucceeded(
+                @NonNull MdnsInterfaceAdvertiser advertiser, int serviceId) {
+            // Wait for all current interfaces to be done probing before notifying of success.
+            if (anyAdvertiser(a -> a.isProbing(serviceId))) return;
+            // The service may still be unregistered/renamed if a conflict is found on a later added
+            // interface, or if a conflicting announcement/reply is detected (RFC6762 9.)
+
+            final Registration registration = mRegistrations.get(serviceId);
+            if (registration == null) {
+                Log.wtf(TAG, "Register succeeded for unknown registration");
+                return;
+            }
+            if (!registration.mNotifiedRegistrationSuccess) {
+                mCb.onRegisterServiceSucceeded(serviceId, registration.getServiceInfo());
+                registration.mNotifiedRegistrationSuccess = true;
+            }
+        }
+
+        @Override
+        public void onServiceConflict(@NonNull MdnsInterfaceAdvertiser advertiser, int serviceId) {
+            // TODO: handle conflicts found after registration (during or after probing)
+        }
+
+        @Override
+        public void onDestroyed(@NonNull MdnsInterfaceSocket socket) {
+            for (int i = mAdvertiserRequests.size() - 1; i >= 0; i--) {
+                if (mAdvertiserRequests.valueAt(i).onAdvertiserDestroyed(socket)) {
+                    mAdvertiserRequests.removeAt(i);
+                }
+            }
+            mAllAdvertisers.remove(socket);
+        }
+    };
+
+    /**
+     * A request for a {@link MdnsInterfaceAdvertiser}.
+     *
+     * This class tracks services to be advertised on all sockets provided via a registered
+     * {@link MdnsSocketProvider.SocketCallback}.
+     */
+    private class InterfaceAdvertiserRequest implements MdnsSocketProvider.SocketCallback {
+        /** Registrations to add to newer MdnsInterfaceAdvertisers when sockets are created. */
+        @NonNull
+        private final SparseArray<Registration> mPendingRegistrations = new SparseArray<>();
+        @NonNull
+        private final ArrayMap<MdnsInterfaceSocket, MdnsInterfaceAdvertiser> mAdvertisers =
+                new ArrayMap<>();
+
+        InterfaceAdvertiserRequest(@Nullable Network requestedNetwork) {
+            mSocketProvider.requestSocket(requestedNetwork, this);
+        }
+
+        /**
+         * Called when an advertiser was destroyed, after all services were unregistered and it sent
+         * exit announcements, or the interface is gone.
+         *
+         * @return true if this {@link InterfaceAdvertiserRequest} should now be deleted.
+         */
+        boolean onAdvertiserDestroyed(@NonNull MdnsInterfaceSocket socket) {
+            mAdvertisers.remove(socket);
+            if (mAdvertisers.size() == 0 && mPendingRegistrations.size() == 0) {
+                // No advertiser is using sockets from this request anymore (in particular for exit
+                // announcements), and there is no registration so newer sockets will not be
+                // necessary, so the request can be unregistered.
+                mSocketProvider.unrequestSocket(this);
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Get the ID of a conflicting service, or -1 if none.
+         */
+        int getConflictingService(@NonNull NsdServiceInfo info) {
+            for (int i = 0; i < mPendingRegistrations.size(); i++) {
+                final NsdServiceInfo other = mPendingRegistrations.valueAt(i).getServiceInfo();
+                if (info.getServiceName().equals(other.getServiceName())
+                        && info.getServiceType().equals(other.getServiceType())) {
+                    return mPendingRegistrations.keyAt(i);
+                }
+            }
+            return -1;
+        }
+
+        void addService(int id, Registration registration)
+                throws NameConflictException {
+            final int conflicting = getConflictingService(registration.getServiceInfo());
+            if (conflicting >= 0) {
+                throw new NameConflictException(conflicting);
+            }
+
+            mPendingRegistrations.put(id, registration);
+            for (int i = 0; i < mAdvertisers.size(); i++) {
+                mAdvertisers.valueAt(i).addService(id, registration.getServiceInfo());
+            }
+        }
+
+        void removeService(int id) {
+            mPendingRegistrations.remove(id);
+            for (int i = 0; i < mAdvertisers.size(); i++) {
+                mAdvertisers.valueAt(i).removeService(id);
+            }
+        }
+
+        @Override
+        public void onSocketCreated(@NonNull Network network,
+                @NonNull MdnsInterfaceSocket socket,
+                @NonNull List<LinkAddress> addresses) {
+            MdnsInterfaceAdvertiser advertiser = mAllAdvertisers.get(socket);
+            if (advertiser == null) {
+                advertiser = mDeps.makeAdvertiser(socket, addresses, mLooper, mPacketCreationBuffer,
+                        mInterfaceAdvertiserCb);
+                mAllAdvertisers.put(socket, advertiser);
+                advertiser.start();
+            }
+            mAdvertisers.put(socket, advertiser);
+            for (int i = 0; i < mPendingRegistrations.size(); i++) {
+                try {
+                    advertiser.addService(mPendingRegistrations.keyAt(i),
+                            mPendingRegistrations.valueAt(i).getServiceInfo());
+                } catch (NameConflictException e) {
+                    Log.wtf(TAG, "Name conflict adding services that should have unique names", e);
+                }
+            }
+        }
+
+        @Override
+        public void onInterfaceDestroyed(@NonNull Network network,
+                @NonNull MdnsInterfaceSocket socket) {
+            final MdnsInterfaceAdvertiser advertiser = mAdvertisers.get(socket);
+            if (advertiser != null) advertiser.destroyNow();
+        }
+
+        @Override
+        public void onAddressesChanged(@NonNull Network network,
+                @NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> addresses) {
+            final MdnsInterfaceAdvertiser advertiser = mAdvertisers.get(socket);
+            if (advertiser != null) advertiser.updateAddresses(addresses);
+        }
+    }
+
+    private static class Registration {
+        @NonNull
+        final String mOriginalName;
+        boolean mNotifiedRegistrationSuccess;
+        private int mConflictCount;
+        @NonNull
+        private NsdServiceInfo mServiceInfo;
+
+        private Registration(@NonNull NsdServiceInfo serviceInfo) {
+            this.mOriginalName = serviceInfo.getServiceName();
+            this.mServiceInfo = serviceInfo;
+        }
+
+        /**
+         * Update the registration to use a different service name, after a conflict was found.
+         *
+         * If a name conflict was found during probing or because different advertising requests
+         * used the same name, the registration is attempted again with a new name (here using
+         * a number suffix, (1), (2) etc). Registration success is notified once probing succeeds
+         * with a new name. This matches legacy behavior based on mdnsresponder, and appendix D of
+         * RFC6763.
+         * @return The new service info with the updated name.
+         */
+        @NonNull
+        private NsdServiceInfo updateForConflict() {
+            mConflictCount++;
+            // In case of conflict choose a different service name. After the first conflict use
+            // "Name (2)", then "Name (3)" etc.
+            // TODO: use a hidden method in NsdServiceInfo once MdnsAdvertiser is moved to service-t
+            final NsdServiceInfo newInfo = new NsdServiceInfo();
+            newInfo.setServiceName(mOriginalName + " (" + (mConflictCount + 1) + ")");
+            newInfo.setServiceType(mServiceInfo.getServiceType());
+            for (Map.Entry<String, byte[]> attr : mServiceInfo.getAttributes().entrySet()) {
+                newInfo.setAttribute(attr.getKey(), attr.getValue());
+            }
+            newInfo.setHost(mServiceInfo.getHost());
+            newInfo.setPort(mServiceInfo.getPort());
+            newInfo.setNetwork(mServiceInfo.getNetwork());
+            // interfaceIndex is not set when registering
+
+            mServiceInfo = newInfo;
+            return mServiceInfo;
+        }
+
+        @NonNull
+        public NsdServiceInfo getServiceInfo() {
+            return mServiceInfo;
+        }
+    }
+
+    /**
+     * Callbacks for advertising services.
+     *
+     * Every method is called on the MdnsAdvertiser looper thread.
+     */
+    public interface AdvertiserCallback {
+        /**
+         * Called when a service was successfully registered, after probing.
+         *
+         * @param serviceId ID of the service provided when registering.
+         * @param registeredInfo Registered info, which may be different from the requested info,
+         *                       after probing and possibly choosing alternative service names.
+         */
+        void onRegisterServiceSucceeded(int serviceId, NsdServiceInfo registeredInfo);
+
+        /**
+         * Called when service registration failed.
+         *
+         * @param serviceId ID of the service provided when registering.
+         * @param errorCode One of {@code NsdManager.FAILURE_*}
+         */
+        void onRegisterServiceFailed(int serviceId, int errorCode);
+
+        // Unregistration is notified immediately as success in NsdService so no callback is needed
+        // here.
+    }
+
+    public MdnsAdvertiser(@NonNull Looper looper, @NonNull MdnsSocketProvider socketProvider,
+            @NonNull AdvertiserCallback cb) {
+        this(looper, socketProvider, cb, new Dependencies());
+    }
+
+    @VisibleForTesting
+    MdnsAdvertiser(@NonNull Looper looper, @NonNull MdnsSocketProvider socketProvider,
+            @NonNull AdvertiserCallback cb, @NonNull Dependencies deps) {
+        mLooper = looper;
+        mCb = cb;
+        mSocketProvider = socketProvider;
+        mDeps = deps;
+    }
+
+    private void checkThread() {
+        if (Thread.currentThread() != mLooper.getThread()) {
+            throw new IllegalStateException("This must be called on the looper thread");
+        }
+    }
+
+    /**
+     * Add a service to advertise.
+     * @param id A unique ID for the service.
+     * @param service The service info to advertise.
+     */
+    public void addService(int id, NsdServiceInfo service) {
+        checkThread();
+        if (mRegistrations.get(id) != null) {
+            Log.e(TAG, "Adding duplicate registration for " + service);
+            // TODO (b/264986328): add a more specific error code
+            mCb.onRegisterServiceFailed(id, NsdManager.FAILURE_INTERNAL_ERROR);
+            return;
+        }
+
+        if (DBG) {
+            Log.i(TAG, "Adding service " + service + " with ID " + id);
+        }
+
+        try {
+            final Registration registration = new Registration(service);
+            while (!tryAddRegistration(id, registration)) {
+                registration.updateForConflict();
+            }
+
+            mRegistrations.put(id, registration);
+        } catch (IOException e) {
+            Log.e(TAG, "Error adding service " + service, e);
+            removeService(id);
+            // TODO (b/264986328): add a more specific error code
+            mCb.onRegisterServiceFailed(id, NsdManager.FAILURE_INTERNAL_ERROR);
+        }
+    }
+
+    private boolean tryAddRegistration(int id, @NonNull Registration registration)
+            throws IOException {
+        final NsdServiceInfo serviceInfo = registration.getServiceInfo();
+        final Network network = serviceInfo.getNetwork();
+        try {
+            InterfaceAdvertiserRequest advertiser = mAdvertiserRequests.get(network);
+            if (advertiser == null) {
+                advertiser = new InterfaceAdvertiserRequest(network);
+                mAdvertiserRequests.put(network, advertiser);
+            }
+            advertiser.addService(id, registration);
+        } catch (NameConflictException e) {
+            if (DBG) {
+                Log.i(TAG, "Service name conflicts: " + serviceInfo.getServiceName());
+            }
+            removeService(id);
+            return false;
+        }
+
+        // When adding a service to a specific network, check that it does not conflict with other
+        // registrations advertising on all networks
+        final InterfaceAdvertiserRequest allNetworksAdvertiser = mAdvertiserRequests.get(null);
+        if (network != null && allNetworksAdvertiser != null
+                && allNetworksAdvertiser.getConflictingService(serviceInfo) >= 0) {
+            if (DBG) {
+                Log.i(TAG, "Service conflicts with advertisement on all networks: "
+                        + serviceInfo.getServiceName());
+            }
+            removeService(id);
+            return false;
+        }
+
+        mRegistrations.put(id, registration);
+        return true;
+    }
+
+    /**
+     * Remove a previously added service.
+     * @param id ID used when registering.
+     */
+    public void removeService(int id) {
+        checkThread();
+        if (!mRegistrations.contains(id)) return;
+        if (DBG) {
+            Log.i(TAG, "Removing service with ID " + id);
+        }
+        for (int i = mAdvertiserRequests.size() - 1; i >= 0; i--) {
+            final InterfaceAdvertiserRequest advertiser = mAdvertiserRequests.valueAt(i);
+            advertiser.removeService(id);
+        }
+        mRegistrations.remove(id);
+    }
+
+    private boolean anyAdvertiser(@NonNull Predicate<MdnsInterfaceAdvertiser> predicate) {
+        for (int i = 0; i < mAllAdvertisers.size(); i++) {
+            if (predicate.test(mAllAdvertisers.valueAt(i))) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsAnnouncer.java b/service/mdns/com/android/server/connectivity/mdns/MdnsAnnouncer.java
index 91e08a8..7c84323 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsAnnouncer.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsAnnouncer.java
@@ -22,10 +22,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.net.SocketAddress;
 import java.util.Collections;
 import java.util.List;
-import java.util.function.Supplier;
 
 /**
  * Sends mDns announcements when a service registration changes and at regular intervals.
@@ -40,14 +38,12 @@
     @NonNull
     private final String mLogTag;
 
-    static class AnnouncementInfo implements MdnsPacketRepeater.Request {
+    /** Announcement request to send with {@link MdnsAnnouncer}. */
+    public static class AnnouncementInfo implements MdnsPacketRepeater.Request {
         @NonNull
         private final MdnsPacket mPacket;
-        @NonNull
-        private final Supplier<Iterable<SocketAddress>> mDestinationsSupplier;
 
-        AnnouncementInfo(List<MdnsRecord> announcedRecords, List<MdnsRecord> additionalRecords,
-                Supplier<Iterable<SocketAddress>> destinationsSupplier) {
+        AnnouncementInfo(List<MdnsRecord> announcedRecords, List<MdnsRecord> additionalRecords) {
             // Records to announce (as answers)
             // Records to place in the "Additional records", with NSEC negative responses
             // to mark records that have been verified unique
@@ -57,7 +53,6 @@
                     announcedRecords,
                     Collections.emptyList() /* authorityRecords */,
                     additionalRecords);
-            mDestinationsSupplier = destinationsSupplier;
         }
 
         @Override
@@ -66,11 +61,6 @@
         }
 
         @Override
-        public Iterable<SocketAddress> getDestinations(int index) {
-            return mDestinationsSupplier.get();
-        }
-
-        @Override
         public long getDelayMs(int nextIndex) {
             // Delay is doubled for each announcement
             return ANNOUNCEMENT_INITIAL_DELAY_MS << (nextIndex - 1);
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java b/service/mdns/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
index 0f3c23a..cc6b98b 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
@@ -34,18 +34,18 @@
  * This class keeps tracking the set of registered {@link MdnsServiceBrowserListener} instances, and
  * notify them when a mDNS service instance is found, updated, or removed?
  */
-public class MdnsDiscoveryManager implements MdnsSocketClient.Callback {
+public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
     private static final String TAG = MdnsDiscoveryManager.class.getSimpleName();
     public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     private static final MdnsLogger LOGGER = new MdnsLogger("MdnsDiscoveryManager");
 
     private final ExecutorProvider executorProvider;
-    private final MdnsSocketClient socketClient;
+    private final MdnsSocketClientBase socketClient;
 
     private final Map<String, MdnsServiceTypeClient> serviceTypeClients = new ArrayMap<>();
 
-    public MdnsDiscoveryManager(
-            @NonNull ExecutorProvider executorProvider, @NonNull MdnsSocketClient socketClient) {
+    public MdnsDiscoveryManager(@NonNull ExecutorProvider executorProvider,
+            @NonNull MdnsSocketClientBase socketClient) {
         this.executorProvider = executorProvider;
         this.socketClient = socketClient;
     }
@@ -76,12 +76,16 @@
                 return;
             }
         }
+        // Request the network for discovery.
+        socketClient.notifyNetworkRequested(listener, searchOptions.getNetwork());
+
         // All listeners of the same service types shares the same MdnsServiceTypeClient.
         MdnsServiceTypeClient serviceTypeClient = serviceTypeClients.get(serviceType);
         if (serviceTypeClient == null) {
             serviceTypeClient = createServiceTypeClient(serviceType);
             serviceTypeClients.put(serviceType, serviceTypeClient);
         }
+        // TODO(b/264634275): Wait for a socket to be created before sending packets.
         serviceTypeClient.startSendAndReceive(listener, searchOptions);
     }
 
@@ -96,20 +100,22 @@
     public synchronized void unregisterListener(
             @NonNull String serviceType, @NonNull MdnsServiceBrowserListener listener) {
         LOGGER.log("Unregistering listener for service type: %s", serviceType);
+        if (DBG) Log.d(TAG, "Unregistering listener for serviceType:" + serviceType);
         MdnsServiceTypeClient serviceTypeClient = serviceTypeClients.get(serviceType);
         if (serviceTypeClient == null) {
             return;
         }
         if (serviceTypeClient.stopSendAndReceive(listener)) {
             // No listener is registered for the service type anymore, remove it from the list of
-          // the
-            // service type clients.
+            // the service type clients.
             serviceTypeClients.remove(serviceType);
             if (serviceTypeClients.isEmpty()) {
                 // No discovery request. Stops the socket client.
                 socketClient.stopDiscovery();
             }
         }
+        // Unrequested the network.
+        socketClient.notifyNetworkUnrequested(listener);
     }
 
     @Override
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java b/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
new file mode 100644
index 0000000..997dcbb
--- /dev/null
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkAddress;
+import android.net.nsd.NsdServiceInfo;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.connectivity.mdns.MdnsPacketRepeater.PacketRepeaterCallback;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * A class that handles advertising services on a {@link MdnsInterfaceSocket} tied to an interface.
+ */
+public class MdnsInterfaceAdvertiser {
+    private static final boolean DBG = MdnsAdvertiser.DBG;
+    @VisibleForTesting
+    public static final long EXIT_ANNOUNCEMENT_DELAY_MS = 100L;
+    @NonNull
+    private final String mTag;
+    @NonNull
+    private final ProbingCallback mProbingCallback = new ProbingCallback();
+    @NonNull
+    private final AnnouncingCallback mAnnouncingCallback = new AnnouncingCallback();
+    @NonNull
+    private final MdnsRecordRepository mRecordRepository;
+    @NonNull
+    private final Callback mCb;
+    // Callbacks are on the same looper thread, but posted to the next handler loop
+    @NonNull
+    private final Handler mCbHandler;
+    @NonNull
+    private final MdnsInterfaceSocket mSocket;
+    @NonNull
+    private final MdnsAnnouncer mAnnouncer;
+    @NonNull
+    private final MdnsProber mProber;
+    @NonNull
+    private final MdnsReplySender mReplySender;
+
+    /**
+     * Callbacks called by {@link MdnsInterfaceAdvertiser} to report status updates.
+     */
+    interface Callback {
+        /**
+         * Called by the advertiser after it successfully registered a service, after probing.
+         */
+        void onRegisterServiceSucceeded(@NonNull MdnsInterfaceAdvertiser advertiser, int serviceId);
+
+        /**
+         * Called by the advertiser when a conflict was found, during or after probing.
+         *
+         * If a conflict is found during probing, the {@link #renameServiceForConflict} must be
+         * called to restart probing and attempt registration with a different name.
+         */
+        void onServiceConflict(@NonNull MdnsInterfaceAdvertiser advertiser, int serviceId);
+
+        /**
+         * Called by the advertiser when it destroyed itself.
+         *
+         * This can happen after a call to {@link #destroyNow()}, or after all services were
+         * unregistered and the advertiser finished sending exit announcements.
+         */
+        void onDestroyed(@NonNull MdnsInterfaceSocket socket);
+    }
+
+    /**
+     * Callbacks from {@link MdnsProber}.
+     */
+    private class ProbingCallback implements
+            PacketRepeaterCallback<MdnsProber.ProbingInfo> {
+        @Override
+        public void onFinished(MdnsProber.ProbingInfo info) {
+            final MdnsAnnouncer.AnnouncementInfo announcementInfo;
+            if (DBG) {
+                Log.v(mTag, "Probing finished for service " + info.getServiceId());
+            }
+            mCbHandler.post(() -> mCb.onRegisterServiceSucceeded(
+                    MdnsInterfaceAdvertiser.this, info.getServiceId()));
+            try {
+                announcementInfo = mRecordRepository.onProbingSucceeded(info);
+            } catch (IOException e) {
+                Log.e(mTag, "Error building announcements", e);
+                return;
+            }
+
+            mAnnouncer.startSending(info.getServiceId(), announcementInfo,
+                    0L /* initialDelayMs */);
+        }
+    }
+
+    /**
+     * Callbacks from {@link MdnsAnnouncer}.
+     */
+    private class AnnouncingCallback
+            implements PacketRepeaterCallback<MdnsAnnouncer.AnnouncementInfo> {
+        // TODO: implement
+    }
+
+    /**
+     * Dependencies for {@link MdnsInterfaceAdvertiser}, useful for testing.
+     */
+    @VisibleForTesting
+    public static class Dependencies {
+        /** @see MdnsRecordRepository */
+        @NonNull
+        public MdnsRecordRepository makeRecordRepository(@NonNull Looper looper) {
+            return new MdnsRecordRepository(looper);
+        }
+
+        /** @see MdnsReplySender */
+        @NonNull
+        public MdnsReplySender makeReplySender(@NonNull Looper looper,
+                @NonNull MdnsInterfaceSocket socket, @NonNull byte[] packetCreationBuffer) {
+            return new MdnsReplySender(looper, socket, packetCreationBuffer);
+        }
+
+        /** @see MdnsAnnouncer */
+        public MdnsAnnouncer makeMdnsAnnouncer(@NonNull String interfaceTag, @NonNull Looper looper,
+                @NonNull MdnsReplySender replySender,
+                @Nullable PacketRepeaterCallback<MdnsAnnouncer.AnnouncementInfo> cb) {
+            return new MdnsAnnouncer(interfaceTag, looper, replySender, cb);
+        }
+
+        /** @see MdnsProber */
+        public MdnsProber makeMdnsProber(@NonNull String interfaceTag, @NonNull Looper looper,
+                @NonNull MdnsReplySender replySender,
+                @NonNull PacketRepeaterCallback<MdnsProber.ProbingInfo> cb) {
+            return new MdnsProber(interfaceTag, looper, replySender, cb);
+        }
+    }
+
+    public MdnsInterfaceAdvertiser(@NonNull String logTag,
+            @NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> initialAddresses,
+            @NonNull Looper looper, @NonNull byte[] packetCreationBuffer, @NonNull Callback cb) {
+        this(logTag, socket, initialAddresses, looper, packetCreationBuffer, cb,
+                new Dependencies());
+    }
+
+    public MdnsInterfaceAdvertiser(@NonNull String logTag,
+            @NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> initialAddresses,
+            @NonNull Looper looper, @NonNull byte[] packetCreationBuffer, @NonNull Callback cb,
+            @NonNull Dependencies deps) {
+        mTag = MdnsInterfaceAdvertiser.class.getSimpleName() + "/" + logTag;
+        mRecordRepository = deps.makeRecordRepository(looper);
+        mRecordRepository.updateAddresses(initialAddresses);
+        mSocket = socket;
+        mCb = cb;
+        mCbHandler = new Handler(looper);
+        mReplySender = deps.makeReplySender(looper, socket, packetCreationBuffer);
+        mAnnouncer = deps.makeMdnsAnnouncer(logTag, looper, mReplySender,
+                mAnnouncingCallback);
+        mProber = deps.makeMdnsProber(logTag, looper, mReplySender, mProbingCallback);
+    }
+
+    /**
+     * Start the advertiser.
+     *
+     * The advertiser will stop itself when all services are removed and exit announcements sent,
+     * notifying via {@link Callback#onDestroyed}. This can also be triggered manually via
+     * {@link #destroyNow()}.
+     */
+    public void start() {
+        // TODO: start receiving packets
+    }
+
+    /**
+     * Start advertising a service.
+     *
+     * @throws NameConflictException There is already a service being advertised with that name.
+     */
+    public void addService(int id, NsdServiceInfo service) throws NameConflictException {
+        final int replacedExitingService = mRecordRepository.addService(id, service);
+        // Cancel announcements for the existing service. This only happens for exiting services
+        // (so cancelling exiting announcements), as per RecordRepository.addService.
+        if (replacedExitingService >= 0) {
+            if (DBG) {
+                Log.d(mTag, "Service " + replacedExitingService
+                        + " getting re-added, cancelling exit announcements");
+            }
+            mAnnouncer.stop(replacedExitingService);
+        }
+        mProber.startProbing(mRecordRepository.setServiceProbing(id));
+    }
+
+    /**
+     * Stop advertising a service.
+     *
+     * This will trigger exit announcements for the service.
+     */
+    public void removeService(int id) {
+        mProber.stop(id);
+        mAnnouncer.stop(id);
+        final MdnsAnnouncer.AnnouncementInfo exitInfo = mRecordRepository.exitService(id);
+        if (exitInfo != null) {
+            // This effectively schedules destroyNow(), as it is to be called when the exit
+            // announcement finishes if there is no service left.
+            // A non-zero exit announcement delay follows legacy mdnsresponder behavior, and is
+            // also useful to ensure that when a host receives the exit announcement, the service
+            // has been unregistered on all interfaces; so an announcement sent from interface A
+            // that was already in-flight while unregistering won't be received after the exit on
+            // interface B.
+            mAnnouncer.startSending(id, exitInfo, EXIT_ANNOUNCEMENT_DELAY_MS);
+        } else {
+            // No exit announcement necessary: remove the service immediately.
+            mRecordRepository.removeService(id);
+            if (mRecordRepository.getServicesCount() == 0) {
+                destroyNow();
+            }
+        }
+    }
+
+    /**
+     * Update interface addresses used to advertise.
+     *
+     * This causes new address records to be announced.
+     */
+    public void updateAddresses(@NonNull List<LinkAddress> newAddresses) {
+        mRecordRepository.updateAddresses(newAddresses);
+        // TODO: restart advertising, but figure out what exit messages need to be sent for the
+        // previous addresses
+    }
+
+    /**
+     * Destroy the advertiser immediately, not sending any exit announcement.
+     *
+     * <p>Useful when the underlying network went away. This will trigger an onDestroyed callback.
+     */
+    public void destroyNow() {
+        for (int serviceId : mRecordRepository.clearServices()) {
+            mProber.stop(serviceId);
+            mAnnouncer.stop(serviceId);
+        }
+
+        // TODO: stop receiving packets
+        mCbHandler.post(() -> mCb.onDestroyed(mSocket));
+    }
+
+    /**
+     * Reset a service to the probing state due to a conflict found on the network.
+     */
+    public void restartProbingForConflict(int serviceId) {
+        // TODO: implement
+    }
+
+    /**
+     * Rename a service following a conflict found on the network, and restart probing.
+     */
+    public void renameServiceForConflict(int serviceId, NsdServiceInfo newInfo) {
+        // TODO: implement
+    }
+
+    /**
+     * Indicates whether probing is in progress for the given service on this interface.
+     *
+     * Also returns false if the specified service is not registered.
+     */
+    public boolean isProbing(int serviceId) {
+        return mRecordRepository.isProbing(serviceId);
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java b/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
index 6090415..d1290b6 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
@@ -22,10 +22,15 @@
 import android.annotation.NonNull;
 import android.net.LinkAddress;
 import android.net.util.SocketUtils;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 import android.util.Log;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetSocketAddress;
@@ -41,15 +46,19 @@
  * otherwise.
  *
  * @see MulticastSocket for javadoc of each public method.
+ * @see MulticastSocket for javadoc of each public method.
  */
 public class MdnsInterfaceSocket {
     private static final String TAG = MdnsInterfaceSocket.class.getSimpleName();
     @NonNull private final MulticastSocket mMulticastSocket;
     @NonNull private final NetworkInterface mNetworkInterface;
+    @NonNull private final MulticastPacketReader mPacketReader;
+    @NonNull private final ParcelFileDescriptor mFileDescriptor;
     private boolean mJoinedIpv4 = false;
     private boolean mJoinedIpv6 = false;
 
-    public MdnsInterfaceSocket(@NonNull NetworkInterface networkInterface, int port)
+    public MdnsInterfaceSocket(@NonNull NetworkInterface networkInterface, int port,
+            @NonNull Looper looper, @NonNull byte[] packetReadBuffer)
             throws IOException {
         mNetworkInterface = networkInterface;
         mMulticastSocket = new MulticastSocket(port);
@@ -58,11 +67,19 @@
         mMulticastSocket.setNetworkInterface(networkInterface);
 
         // Bind socket to the interface for receiving from that interface only.
-        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(mMulticastSocket)) {
-            SocketUtils.bindSocketToInterface(pfd.getFileDescriptor(), mNetworkInterface.getName());
+        mFileDescriptor = ParcelFileDescriptor.fromDatagramSocket(mMulticastSocket);
+        try {
+            final FileDescriptor fd = mFileDescriptor.getFileDescriptor();
+            final int flags = Os.fcntlInt(fd, OsConstants.F_GETFL, 0);
+            Os.fcntlInt(fd, OsConstants.F_SETFL, flags | OsConstants.SOCK_NONBLOCK);
+            SocketUtils.bindSocketToInterface(fd, mNetworkInterface.getName());
         } catch (ErrnoException e) {
             throw new IOException("Error setting socket options", e);
         }
+
+        mPacketReader = new MulticastPacketReader(networkInterface.getName(), mFileDescriptor,
+                new Handler(looper), packetReadBuffer);
+        mPacketReader.start();
     }
 
     /**
@@ -74,23 +91,14 @@
         mMulticastSocket.send(packet);
     }
 
-    /**
-     * Receives a datagram packet from this socket.
-     *
-     * <p>This method could be used on any thread.
-     */
-    public void receive(@NonNull DatagramPacket packet) throws IOException {
-        mMulticastSocket.receive(packet);
-    }
-
-    private boolean hasIpv4Address(List<LinkAddress> addresses) {
+    private static boolean hasIpv4Address(@NonNull List<LinkAddress> addresses) {
         for (LinkAddress address : addresses) {
             if (address.isIpv4()) return true;
         }
         return false;
     }
 
-    private boolean hasIpv6Address(List<LinkAddress> addresses) {
+    private static boolean hasIpv6Address(@NonNull List<LinkAddress> addresses) {
         for (LinkAddress address : addresses) {
             if (address.isIpv6()) return true;
         }
@@ -103,7 +111,7 @@
         maybeJoinIpv6(addresses);
     }
 
-    private boolean joinGroup(InetSocketAddress multicastAddress) {
+    private boolean joinGroup(@NonNull InetSocketAddress multicastAddress) {
         try {
             mMulticastSocket.joinGroup(multicastAddress, mNetworkInterface);
             return true;
@@ -114,7 +122,7 @@
         }
     }
 
-    private void maybeJoinIpv4(List<LinkAddress> addresses) {
+    private void maybeJoinIpv4(@NonNull List<LinkAddress> addresses) {
         final boolean hasAddr = hasIpv4Address(addresses);
         if (!mJoinedIpv4 && hasAddr) {
             mJoinedIpv4 = joinGroup(MULTICAST_IPV4_ADDRESS);
@@ -124,7 +132,7 @@
         }
     }
 
-    private void maybeJoinIpv6(List<LinkAddress> addresses) {
+    private void maybeJoinIpv6(@NonNull List<LinkAddress> addresses) {
         final boolean hasAddr = hasIpv6Address(addresses);
         if (!mJoinedIpv6 && hasAddr) {
             mJoinedIpv6 = joinGroup(MULTICAST_IPV6_ADDRESS);
@@ -134,33 +142,32 @@
         }
     }
 
-    /*** Destroy this socket by leaving all joined multicast groups and closing this socket. */
+    /*** Destroy the socket */
     public void destroy() {
-        if (mJoinedIpv4) {
-            try {
-                mMulticastSocket.leaveGroup(MULTICAST_IPV4_ADDRESS, mNetworkInterface);
-            } catch (IOException e) {
-                Log.e(TAG, "Error leaving IPv4 group for " + mNetworkInterface, e);
-            }
-        }
-        if (mJoinedIpv6) {
-            try {
-                mMulticastSocket.leaveGroup(MULTICAST_IPV6_ADDRESS, mNetworkInterface);
-            } catch (IOException e) {
-                Log.e(TAG, "Error leaving IPv4 group for " + mNetworkInterface, e);
-            }
+        mPacketReader.stop();
+        try {
+            mFileDescriptor.close();
+        } catch (IOException e) {
+            Log.e(TAG, "Close file descriptor failed.");
         }
         mMulticastSocket.close();
     }
 
     /**
-     * Returns the index of the network interface that this socket is bound to. If the interface
-     * cannot be determined, returns -1.
+     * Add a handler to receive callbacks when reads the packet from socket. If the handler is
+     * already set, this is a no-op.
+     */
+    public void addPacketHandler(@NonNull MulticastPacketReader.PacketHandler handler) {
+        mPacketReader.addPacketHandler(handler);
+    }
+
+    /**
+     * Returns the network interface that this socket is bound to.
      *
      * <p>This method could be used on any thread.
      */
-    public int getInterfaceIndex() {
-        return mNetworkInterface.getIndex();
+    public NetworkInterface getInterface() {
+        return mNetworkInterface;
     }
 
     /*** Returns whether this socket has joined IPv4 group */
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java b/service/mdns/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
new file mode 100644
index 0000000..d959065
--- /dev/null
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns;
+
+import static com.android.server.connectivity.mdns.MdnsSocketProvider.ensureRunningOnHandlerThread;
+import static com.android.server.connectivity.mdns.MdnsSocketProvider.isNetworkMatched;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkAddress;
+import android.net.Network;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The {@link MdnsMultinetworkSocketClient} manages the multinetwork socket for mDns
+ *
+ *  * <p>This class is not thread safe.
+ */
+public class MdnsMultinetworkSocketClient implements MdnsSocketClientBase {
+    private static final String TAG = MdnsMultinetworkSocketClient.class.getSimpleName();
+    private static final boolean DBG = MdnsDiscoveryManager.DBG;
+
+    @NonNull private final Handler mHandler;
+    @NonNull private final MdnsSocketProvider mSocketProvider;
+    @NonNull private final MdnsResponseDecoder mResponseDecoder;
+
+    private final Map<MdnsServiceBrowserListener, InterfaceSocketCallback> mRequestedNetworks =
+            new ArrayMap<>();
+    private final ArrayMap<MdnsInterfaceSocket, Network> mActiveNetworkSockets = new ArrayMap<>();
+    private final ArrayMap<MdnsInterfaceSocket, ReadPacketHandler> mSocketPacketHandlers =
+            new ArrayMap<>();
+    private MdnsSocketClientBase.Callback mCallback = null;
+    private int mReceivedPacketNumber = 0;
+
+    public MdnsMultinetworkSocketClient(@NonNull Looper looper,
+            @NonNull MdnsSocketProvider provider) {
+        mHandler = new Handler(looper);
+        mSocketProvider = provider;
+        mResponseDecoder = new MdnsResponseDecoder(
+                new MdnsResponseDecoder.Clock(), null /* serviceType */);
+    }
+
+    private class InterfaceSocketCallback implements MdnsSocketProvider.SocketCallback {
+        @Override
+        public void onSocketCreated(@NonNull Network network,
+                @NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> addresses) {
+            // The socket may be already created by other request before, try to get the stored
+            // ReadPacketHandler.
+            ReadPacketHandler handler = mSocketPacketHandlers.get(socket);
+            if (handler == null) {
+                // First request to create this socket. Initial a ReadPacketHandler for this socket.
+                handler = new ReadPacketHandler(network, socket.getInterface().getIndex());
+                mSocketPacketHandlers.put(socket, handler);
+            }
+            socket.addPacketHandler(handler);
+            mActiveNetworkSockets.put(socket, network);
+        }
+
+        @Override
+        public void onInterfaceDestroyed(@NonNull Network network,
+                @NonNull MdnsInterfaceSocket socket) {
+            mSocketPacketHandlers.remove(socket);
+            mActiveNetworkSockets.remove(socket);
+        }
+    }
+
+    private class ReadPacketHandler implements MulticastPacketReader.PacketHandler {
+        private final Network mNetwork;
+        private final int mInterfaceIndex;
+
+        ReadPacketHandler(@NonNull Network network, int interfaceIndex) {
+            mNetwork = network;
+            mInterfaceIndex = interfaceIndex;
+        }
+
+        @Override
+        public void handlePacket(byte[] recvbuf, int length, InetSocketAddress src) {
+            processResponsePacket(recvbuf, length, mInterfaceIndex, mNetwork);
+        }
+    }
+
+    /*** Set callback for receiving mDns response */
+    @Override
+    public void setCallback(@Nullable MdnsSocketClientBase.Callback callback) {
+        ensureRunningOnHandlerThread(mHandler);
+        mCallback = callback;
+    }
+
+    /***
+     * Notify that the given network is requested for mdns discovery / resolution
+     *
+     * @param listener the listener for discovery.
+     * @param network the target network for discovery. Null means discovery on all possible
+     *                interfaces.
+     */
+    @Override
+    public void notifyNetworkRequested(@NonNull MdnsServiceBrowserListener listener,
+            @Nullable Network network) {
+        ensureRunningOnHandlerThread(mHandler);
+        InterfaceSocketCallback callback = mRequestedNetworks.get(listener);
+        if (callback != null) {
+            throw new IllegalArgumentException("Can not register duplicated listener");
+        }
+
+        if (DBG) Log.d(TAG, "notifyNetworkRequested: network=" + network);
+        callback = new InterfaceSocketCallback();
+        mRequestedNetworks.put(listener, callback);
+        mSocketProvider.requestSocket(network, callback);
+    }
+
+    /*** Notify that the network is unrequested */
+    @Override
+    public void notifyNetworkUnrequested(@NonNull MdnsServiceBrowserListener listener) {
+        ensureRunningOnHandlerThread(mHandler);
+        final InterfaceSocketCallback callback = mRequestedNetworks.remove(listener);
+        if (callback == null) {
+            Log.e(TAG, "Can not be unrequested with unknown listener=" + listener);
+            return;
+        }
+        mSocketProvider.unrequestSocket(callback);
+    }
+
+    private void sendMdnsPacket(@NonNull DatagramPacket packet, @Nullable Network targetNetwork) {
+        final boolean isIpv6 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
+                instanceof Inet6Address;
+        final boolean isIpv4 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
+                instanceof Inet4Address;
+        for (int i = 0; i < mActiveNetworkSockets.size(); i++) {
+            final MdnsInterfaceSocket socket = mActiveNetworkSockets.keyAt(i);
+            final Network network = mActiveNetworkSockets.valueAt(i);
+            // Check ip capability and network before sending packet
+            if (((isIpv6 && socket.hasJoinedIpv6()) || (isIpv4 && socket.hasJoinedIpv4()))
+                    && isNetworkMatched(targetNetwork, network)) {
+                try {
+                    socket.send(packet);
+                } catch (IOException e) {
+                    Log.e(TAG, "Failed to send a mDNS packet.", e);
+                }
+            }
+        }
+    }
+
+    private void processResponsePacket(byte[] recvbuf, int length, int interfaceIndex,
+            @NonNull Network network) {
+        int packetNumber = ++mReceivedPacketNumber;
+
+        final List<MdnsResponse> responses = new ArrayList<>();
+        final int errorCode = mResponseDecoder.decode(
+                recvbuf, length, responses, interfaceIndex, network);
+        if (errorCode == MdnsResponseDecoder.SUCCESS) {
+            for (MdnsResponse response : responses) {
+                if (mCallback != null) {
+                    mCallback.onResponseReceived(response);
+                }
+            }
+        } else if (errorCode != MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE) {
+            if (mCallback != null) {
+                mCallback.onFailedToParseMdnsResponse(packetNumber, errorCode);
+            }
+        }
+    }
+
+    /** Sends a mDNS request packet that asks for multicast response. */
+    @Override
+    public void sendMulticastPacket(@NonNull DatagramPacket packet) {
+        sendMulticastPacket(packet, null /* network */);
+    }
+
+    /**
+     * Sends a mDNS request packet via given network that asks for multicast response. Null network
+     * means sending packet via all networks.
+     */
+    @Override
+    public void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
+        mHandler.post(() -> sendMdnsPacket(packet, network));
+    }
+
+    /** Sends a mDNS request packet that asks for unicast response. */
+    @Override
+    public void sendUnicastPacket(@NonNull DatagramPacket packet) {
+        sendUnicastPacket(packet, null /* network */);
+    }
+
+    /**
+     * Sends a mDNS request packet via given network that asks for unicast response. Null network
+     * means sending packet via all networks.
+     */
+    @Override
+    public void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
+        // TODO: Separate unicast packet.
+        mHandler.post(() -> sendMdnsPacket(packet, network));
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsPacketReader.java b/service/mdns/com/android/server/connectivity/mdns/MdnsPacketReader.java
index 856a2cd..aa38844 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsPacketReader.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsPacketReader.java
@@ -38,8 +38,13 @@
 
     /** Constructs a reader for the given packet. */
     public MdnsPacketReader(DatagramPacket packet) {
-        buf = packet.getData();
-        count = packet.getLength();
+        this(packet.getData(), packet.getLength());
+    }
+
+    /** Constructs a reader for the given packet. */
+    public MdnsPacketReader(byte[] buffer, int length) {
+        buf = buffer;
+        count = length;
         pos = 0;
         limit = -1;
         labelDictionary = new SparseArray<>(16);
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsPacketRepeater.java b/service/mdns/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
index 015dbd8..ae54e70 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
@@ -24,7 +24,7 @@
 import android.util.Log;
 
 import java.io.IOException;
-import java.net.SocketAddress;
+import java.net.InetSocketAddress;
 
 /**
  * A class used to send several packets at given time intervals.
@@ -32,6 +32,14 @@
  */
 public abstract class MdnsPacketRepeater<T extends MdnsPacketRepeater.Request> {
     private static final boolean DBG = MdnsAdvertiser.DBG;
+    private static final InetSocketAddress IPV4_ADDR = new InetSocketAddress(
+            MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT);
+    private static final InetSocketAddress IPV6_ADDR = new InetSocketAddress(
+            MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
+    private static final InetSocketAddress[] ALL_ADDRS = new InetSocketAddress[] {
+            IPV4_ADDR, IPV6_ADDR
+    };
+
     @NonNull
     private final MdnsReplySender mReplySender;
     @NonNull
@@ -70,12 +78,6 @@
         MdnsPacket getPacket(int index);
 
         /**
-         * Get a set of destinations for the packet for one iteration.
-         */
-        @NonNull
-        Iterable<SocketAddress> getDestinations(int index);
-
-        /**
          * Get the delay in milliseconds until the next packet transmission.
          */
         long getDelayMs(int nextIndex);
@@ -110,12 +112,13 @@
             }
 
             final MdnsPacket packet = request.getPacket(index);
-            final Iterable<SocketAddress> destinations = request.getDestinations(index);
             if (DBG) {
-                Log.v(getTag(), "Sending packets to " + destinations + " for iteration "
-                        + index + " out of " + request.getNumSends());
+                Log.v(getTag(), "Sending packets for iteration " + index + " out of "
+                        + request.getNumSends());
             }
-            for (SocketAddress destination : destinations) {
+            // Send to both v4 and v6 addresses; the reply sender will take care of ignoring the
+            // send when the socket has not joined the relevant group.
+            for (InetSocketAddress destination : ALL_ADDRS) {
                 try {
                     mReplySender.sendNow(packet, destination);
                 } catch (IOException e) {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsProber.java b/service/mdns/com/android/server/connectivity/mdns/MdnsProber.java
index db7049e..2cd9148 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsProber.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsProber.java
@@ -22,12 +22,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.net.module.util.CollectionUtils;
 
-import java.net.SocketAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.function.Supplier;
 
 /**
  * Sends mDns probe requests to verify service records are unique on the network.
@@ -46,26 +44,21 @@
         mLogTag = MdnsProber.class.getSimpleName() + "/" + interfaceTag;
     }
 
-    static class ProbingInfo implements Request {
+    /** Probing request to send with {@link MdnsProber}. */
+    public static class ProbingInfo implements Request {
 
         private final int mServiceId;
         @NonNull
         private final MdnsPacket mPacket;
-        @NonNull
-        private final Supplier<Iterable<SocketAddress>> mDestinationsSupplier;
 
         /**
          * Create a new ProbingInfo
          * @param serviceId Service to probe for.
          * @param probeRecords Records to be probed for uniqueness.
-         * @param destinationsSupplier Supplier for the probe destinations. Will be called on the
-         *                             probe handler thread for each probe.
          */
-        ProbingInfo(int serviceId, @NonNull List<MdnsRecord> probeRecords,
-                @NonNull Supplier<Iterable<SocketAddress>> destinationsSupplier) {
+        ProbingInfo(int serviceId, @NonNull List<MdnsRecord> probeRecords) {
             mServiceId = serviceId;
             mPacket = makePacket(probeRecords);
-            mDestinationsSupplier = destinationsSupplier;
         }
 
         public int getServiceId() {
@@ -78,12 +71,6 @@
             return mPacket;
         }
 
-        @NonNull
-        @Override
-        public Iterable<SocketAddress> getDestinations(int index) {
-            return mDestinationsSupplier.get();
-        }
-
         @Override
         public long getDelayMs(int nextIndex) {
             // As per https://datatracker.ietf.org/doc/html/rfc6762#section-8.1
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsRecordRepository.java b/service/mdns/com/android/server/connectivity/mdns/MdnsRecordRepository.java
new file mode 100644
index 0000000..bb9c751
--- /dev/null
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsRecordRepository.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkAddress;
+import android.net.nsd.NsdServiceInfo;
+import android.os.Looper;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A repository of records advertised through {@link MdnsInterfaceAdvertiser}.
+ *
+ * Must be used on a consistent looper thread.
+ */
+public class MdnsRecordRepository {
+    // TTLs as per RFC6762 10.
+    // TTL for records with a host name as the resource record's name (e.g., A, AAAA, HINFO) or a
+    // host name contained within the resource record's rdata (e.g., SRV, reverse mapping PTR
+    // record)
+    private static final long NAME_RECORDS_TTL_MILLIS = TimeUnit.SECONDS.toMillis(120);
+    // TTL for other records
+    private static final long NON_NAME_RECORDS_TTL_MILLIS = TimeUnit.MINUTES.toMillis(75);
+
+    // Top-level domain for link-local queries, as per RFC6762 3.
+    private static final String LOCAL_TLD = "local";
+
+    // Service type for service enumeration (RFC6763 9.)
+    private static final String[] DNS_SD_SERVICE_TYPE =
+            new String[] { "_services", "_dns-sd", "_udp", LOCAL_TLD };
+
+    // Map of service unique ID -> records for service
+    @NonNull
+    private final SparseArray<ServiceRegistration> mServices = new SparseArray<>();
+    @NonNull
+    private final Looper mLooper;
+    @NonNull
+    private String[] mDeviceHostname;
+
+    public MdnsRecordRepository(@NonNull Looper looper) {
+        this(looper, new Dependencies());
+    }
+
+    @VisibleForTesting
+    public MdnsRecordRepository(@NonNull Looper looper, @NonNull Dependencies deps) {
+        mDeviceHostname = deps.getHostname();
+        mLooper = looper;
+    }
+
+    /**
+     * Dependencies to use with {@link MdnsRecordRepository}, useful for testing.
+     */
+    @VisibleForTesting
+    public static class Dependencies {
+        /**
+         * Get a unique hostname to be used by the device.
+         */
+        @NonNull
+        public String[] getHostname() {
+            // Generate a very-probably-unique hostname. This allows minimizing possible conflicts
+            // to the point that probing for it is no longer necessary (as per RFC6762 8.1 last
+            // paragraph), and does not leak more information than what could already be obtained by
+            // looking at the mDNS packets source address.
+            // This differs from historical behavior that just used "Android.local" for many
+            // devices, creating a lot of conflicts.
+            // Having a different hostname per interface is an acceptable option as per RFC6762 14.
+            // This hostname will change every time the interface is reconnected, so this does not
+            // allow tracking the device.
+            // TODO: consider deriving a hostname from other sources, such as the IPv6 addresses
+            // (reusing the same privacy-protecting mechanics).
+            return new String[] {
+                    "Android_" + UUID.randomUUID().toString().replace("-", ""), LOCAL_TLD };
+        }
+
+        /**
+         * @see NetworkInterface#getInetAddresses().
+         */
+        @NonNull
+        public Enumeration<InetAddress> getInterfaceInetAddresses(@NonNull NetworkInterface iface) {
+            return iface.getInetAddresses();
+        }
+    }
+
+    private static class RecordInfo<T extends MdnsRecord> {
+        public final T record;
+        public final NsdServiceInfo serviceInfo;
+
+        /**
+         * Whether the name of this record is expected to be fully owned by the service or may be
+         * advertised by other hosts as well (shared).
+         */
+        public final boolean isSharedName;
+
+        /**
+         * Whether probing is still in progress for the record.
+         */
+        public boolean isProbing;
+
+        RecordInfo(NsdServiceInfo serviceInfo, T record, boolean sharedName,
+                 boolean probing) {
+            this.serviceInfo = serviceInfo;
+            this.record = record;
+            this.isSharedName = sharedName;
+            this.isProbing = probing;
+        }
+    }
+
+    private static class ServiceRegistration {
+        @NonNull
+        public final List<RecordInfo<?>> allRecords;
+        @NonNull
+        public final RecordInfo<MdnsPointerRecord> ptrRecord;
+        @NonNull
+        public final RecordInfo<MdnsServiceRecord> srvRecord;
+        @NonNull
+        public final RecordInfo<MdnsTextRecord> txtRecord;
+        @NonNull
+        public final NsdServiceInfo serviceInfo;
+
+        /**
+         * Whether the service is sending exit announcements and will be destroyed soon.
+         */
+        public boolean exiting = false;
+
+        /**
+         * Create a ServiceRegistration for dns-sd service registration (RFC6763).
+         *
+         * @param deviceHostname Hostname of the device (for the interface used)
+         * @param serviceInfo Service to advertise
+         */
+        ServiceRegistration(@NonNull String[] deviceHostname, @NonNull NsdServiceInfo serviceInfo) {
+            this.serviceInfo = serviceInfo;
+
+            final String[] serviceType = splitServiceType(serviceInfo);
+            final String[] serviceName = splitFullyQualifiedName(serviceInfo, serviceType);
+
+            // Service PTR record
+            ptrRecord = new RecordInfo<>(
+                    serviceInfo,
+                    new MdnsPointerRecord(
+                            serviceType,
+                            0L /* receiptTimeMillis */,
+                            false /* cacheFlush */,
+                            NON_NAME_RECORDS_TTL_MILLIS,
+                            serviceName),
+                    true /* sharedName */, true /* probing */);
+
+            srvRecord = new RecordInfo<>(
+                    serviceInfo,
+                    new MdnsServiceRecord(serviceName,
+                            0L /* receiptTimeMillis */,
+                            true /* cacheFlush */,
+                            NAME_RECORDS_TTL_MILLIS, 0 /* servicePriority */, 0 /* serviceWeight */,
+                            serviceInfo.getPort(),
+                            deviceHostname),
+                    false /* sharedName */, true /* probing */);
+
+            txtRecord = new RecordInfo<>(
+                    serviceInfo,
+                    new MdnsTextRecord(serviceName,
+                            0L /* receiptTimeMillis */,
+                            true /* cacheFlush */, // Service name is verified unique after probing
+                            NON_NAME_RECORDS_TTL_MILLIS,
+                            attrsToTextEntries(serviceInfo.getAttributes())),
+                    false /* sharedName */, true /* probing */);
+
+            final ArrayList<RecordInfo<?>> allRecords = new ArrayList<>(4);
+            allRecords.add(ptrRecord);
+            allRecords.add(srvRecord);
+            allRecords.add(txtRecord);
+            // Service type enumeration record (RFC6763 9.)
+            allRecords.add(new RecordInfo<>(
+                    serviceInfo,
+                    new MdnsPointerRecord(
+                            DNS_SD_SERVICE_TYPE,
+                            0L /* receiptTimeMillis */,
+                            false /* cacheFlush */,
+                            NON_NAME_RECORDS_TTL_MILLIS,
+                            serviceType),
+                    true /* sharedName */, true /* probing */));
+
+            this.allRecords = Collections.unmodifiableList(allRecords);
+        }
+
+        void setProbing(boolean probing) {
+            for (RecordInfo<?> info : allRecords) {
+                info.isProbing = probing;
+            }
+        }
+    }
+
+    /**
+     * Inform the repository of the latest interface addresses.
+     */
+    public void updateAddresses(@NonNull List<LinkAddress> newAddresses) {
+        // TODO: implement to update addresses in records
+    }
+
+    /**
+     * Add a service to the repository.
+     *
+     * This may remove/replace any existing service that used the name added but is exiting.
+     * @param serviceId A unique service ID.
+     * @param serviceInfo Service info to add.
+     * @return If the added service replaced another with a matching name (which was exiting), the
+     *         ID of the replaced service.
+     * @throws NameConflictException There is already a (non-exiting) service using the name.
+     */
+    public int addService(int serviceId, NsdServiceInfo serviceInfo) throws NameConflictException {
+        if (mServices.contains(serviceId)) {
+            throw new IllegalArgumentException(
+                    "Service ID must not be reused across registrations: " + serviceId);
+        }
+
+        final int existing = getServiceByName(serviceInfo.getServiceName());
+        // It's OK to re-add a service that is exiting
+        if (existing >= 0 && !mServices.get(existing).exiting) {
+            throw new NameConflictException(existing);
+        }
+
+        final ServiceRegistration registration = new ServiceRegistration(
+                mDeviceHostname, serviceInfo);
+        mServices.put(serviceId, registration);
+
+        // Remove existing exiting service
+        mServices.remove(existing);
+        return existing;
+    }
+
+    /**
+     * @return The ID of the service identified by its name, or -1 if none.
+     */
+    private int getServiceByName(@NonNull String serviceName) {
+        for (int i = 0; i < mServices.size(); i++) {
+            final ServiceRegistration registration = mServices.valueAt(i);
+            if (serviceName.equals(registration.serviceInfo.getServiceName())) {
+                return mServices.keyAt(i);
+            }
+        }
+        return -1;
+    }
+
+    private MdnsProber.ProbingInfo makeProbingInfo(int serviceId,
+            @NonNull MdnsServiceRecord srvRecord) {
+        final List<MdnsRecord> probingRecords = new ArrayList<>();
+        // Probe with cacheFlush cleared; it is set when announcing, as it was verified unique:
+        // RFC6762 10.2
+        probingRecords.add(new MdnsServiceRecord(srvRecord.getName(),
+                0L /* receiptTimeMillis */,
+                false /* cacheFlush */,
+                srvRecord.getTtl(),
+                srvRecord.getServicePriority(), srvRecord.getServiceWeight(),
+                srvRecord.getServicePort(),
+                srvRecord.getServiceHost()));
+
+        return new MdnsProber.ProbingInfo(serviceId, probingRecords);
+    }
+
+    private static List<MdnsServiceInfo.TextEntry> attrsToTextEntries(Map<String, byte[]> attrs) {
+        final List<MdnsServiceInfo.TextEntry> out = new ArrayList<>(attrs.size());
+        for (Map.Entry<String, byte[]> attr : attrs.entrySet()) {
+            out.add(new MdnsServiceInfo.TextEntry(attr.getKey(), attr.getValue()));
+        }
+        return out;
+    }
+
+    /**
+     * Mark a service in the repository as exiting.
+     * @param id ID of the service, used at registration time.
+     * @return The exit announcement to indicate the service was removed, or null if not necessary.
+     */
+    @Nullable
+    public MdnsAnnouncer.AnnouncementInfo exitService(int id) {
+        final ServiceRegistration registration = mServices.get(id);
+        if (registration == null) return null;
+        if (registration.exiting) return null;
+
+        registration.exiting = true;
+
+        // TODO: implement
+        return null;
+    }
+
+    /**
+     * Remove a service from the repository
+     */
+    public void removeService(int id) {
+        mServices.remove(id);
+    }
+
+    /**
+     * @return The number of services currently held in the repository, including exiting services.
+     */
+    public int getServicesCount() {
+        return mServices.size();
+    }
+
+    /**
+     * Remove all services from the repository
+     * @return IDs of the removed services
+     */
+    @NonNull
+    public int[] clearServices() {
+        final int[] ret = new int[mServices.size()];
+        for (int i = 0; i < mServices.size(); i++) {
+            ret[i] = mServices.keyAt(i);
+        }
+        mServices.clear();
+        return ret;
+    }
+
+    /**
+     * Called to indicate that probing succeeded for a service.
+     * @param probeSuccessInfo The successful probing info.
+     * @return The {@link MdnsAnnouncer.AnnouncementInfo} to send, now that probing has succeeded.
+     */
+    public MdnsAnnouncer.AnnouncementInfo onProbingSucceeded(
+            MdnsProber.ProbingInfo probeSuccessInfo) throws IOException {
+        // TODO: implement: set service as not probing anymore and generate announcements
+        throw new IOException("Announcements not implemented");
+    }
+
+    /**
+     * (Re)set a service to the probing state.
+     * @return The {@link MdnsProber.ProbingInfo} to send for probing.
+     */
+    @Nullable
+    public MdnsProber.ProbingInfo setServiceProbing(int serviceId) {
+        final ServiceRegistration registration = mServices.get(serviceId);
+        if (registration == null) return null;
+
+        registration.setProbing(true);
+        return makeProbingInfo(serviceId, registration.srvRecord.record);
+    }
+
+    /**
+     * Indicates whether a given service is in probing state.
+     */
+    public boolean isProbing(int serviceId) {
+        final ServiceRegistration registration = mServices.get(serviceId);
+        if (registration == null) return false;
+
+        return registration.srvRecord.isProbing;
+    }
+
+    private static String[] splitFullyQualifiedName(
+            @NonNull NsdServiceInfo info, @NonNull String[] serviceType) {
+        final String[] split = new String[serviceType.length + 1];
+        split[0] = info.getServiceName();
+        System.arraycopy(serviceType, 0, split, 1, serviceType.length);
+
+        return split;
+    }
+
+    private static String[] splitServiceType(@NonNull NsdServiceInfo info) {
+        // String.split(pattern, 0) removes trailing empty strings, which would appear when
+        // splitting "domain.name." (with a dot a the end), so this is what is needed here.
+        final String[] split = info.getServiceType().split("\\.", 0);
+        final String[] type = new String[split.length + 1];
+        System.arraycopy(split, 0, type, 0, split.length);
+        type[split.length] = LOCAL_TLD;
+
+        return type;
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsReplySender.java b/service/mdns/com/android/server/connectivity/mdns/MdnsReplySender.java
index 1fdbc5c..c6b8f47 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsReplySender.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsReplySender.java
@@ -21,8 +21,10 @@
 
 import java.io.IOException;
 import java.net.DatagramPacket;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetSocketAddress;
 import java.net.MulticastSocket;
-import java.net.SocketAddress;
 
 /**
  * A class that handles sending mDNS replies to a {@link MulticastSocket}, possibly queueing them
@@ -32,14 +34,14 @@
  */
 public class MdnsReplySender {
     @NonNull
-    private final MulticastSocket mSocket;
+    private final MdnsInterfaceSocket mSocket;
     @NonNull
     private final Looper mLooper;
     @NonNull
     private final byte[] mPacketCreationBuffer;
 
     public MdnsReplySender(@NonNull Looper looper,
-            @NonNull MulticastSocket socket, @NonNull byte[] packetCreationBuffer) {
+            @NonNull MdnsInterfaceSocket socket, @NonNull byte[] packetCreationBuffer) {
         mLooper = looper;
         mSocket = socket;
         mPacketCreationBuffer = packetCreationBuffer;
@@ -50,11 +52,16 @@
      *
      * Must be called on the looper thread used by the {@link MdnsReplySender}.
      */
-    public void sendNow(@NonNull MdnsPacket packet, @NonNull SocketAddress destination)
+    public void sendNow(@NonNull MdnsPacket packet, @NonNull InetSocketAddress destination)
             throws IOException {
         if (Thread.currentThread() != mLooper.getThread()) {
             throw new IllegalStateException("sendNow must be called in the handler thread");
         }
+        if (!((destination.getAddress() instanceof Inet6Address && mSocket.hasJoinedIpv6())
+                || (destination.getAddress() instanceof Inet4Address && mSocket.hasJoinedIpv4()))) {
+            // Skip sending if the socket has not joined the v4/v6 group (there was no address)
+            return;
+        }
 
         // TODO: support packets over size (send in multiple packets with TC bit set)
         final MdnsPacketWriter writer = new MdnsPacketWriter(mPacketCreationBuffer);
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java b/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
index 7cf84f6..50f2069 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
@@ -101,7 +101,24 @@
      */
     public int decode(@NonNull DatagramPacket packet, @NonNull List<MdnsResponse> responses,
             int interfaceIndex, @Nullable Network network) {
-        MdnsPacketReader reader = new MdnsPacketReader(packet);
+        return decode(packet.getData(), packet.getLength(), responses, interfaceIndex, network);
+    }
+
+    /**
+     * Decodes all mDNS responses for the desired service type from a packet. The class does not
+     * check
+     * the responses for completeness; the caller should do that.
+     *
+     * @param recvbuf The received data buffer to read from.
+     * @param length The length of received data buffer.
+     * @param interfaceIndex the network interface index (or {@link
+     *     MdnsSocket#INTERFACE_INDEX_UNSPECIFIED} if not known) at which the packet was received
+     * @param network the network at which the packet was received, or null if it is unknown.
+     * @return A list of mDNS responses, or null if the packet contained no appropriate responses.
+     */
+    public int decode(@NonNull byte[] recvbuf, int length, @NonNull List<MdnsResponse> responses,
+            int interfaceIndex, @Nullable Network network) {
+        MdnsPacketReader reader = new MdnsPacketReader(recvbuf, length);
 
         List<MdnsRecord> records;
         try {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java b/service/mdns/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java
index fcf9058..73a7e3a 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java
@@ -35,4 +35,6 @@
     public static final int ERROR_READING_TXT_RDATA = 10;
     public static final int ERROR_SKIPPING_UNKNOWN_RECORD = 11;
     public static final int ERROR_END_OF_FILE = 12;
+    public static final int ERROR_READING_NSEC_RDATA = 13;
+    public static final int ERROR_READING_ANY_RDATA = 14;
 }
\ No newline at end of file
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index 538f376..d26fbdb 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.Network;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -52,7 +53,7 @@
 
     private final String serviceType;
     private final String[] serviceTypeLabels;
-    private final MdnsSocketClient socketClient;
+    private final MdnsSocketClientBase socketClient;
     private final ScheduledExecutorService executor;
     private final Object lock = new Object();
     private final Set<MdnsServiceBrowserListener> listeners = new ArraySet<>();
@@ -77,11 +78,11 @@
      * Constructor of {@link MdnsServiceTypeClient}.
      *
      * @param socketClient Sends and receives mDNS packet.
-     * @param executor     A {@link ScheduledExecutorService} used to schedule query tasks.
+     * @param executor         A {@link ScheduledExecutorService} used to schedule query tasks.
      */
     public MdnsServiceTypeClient(
             @NonNull String serviceType,
-            @NonNull MdnsSocketClient socketClient,
+            @NonNull MdnsSocketClientBase socketClient,
             @NonNull ScheduledExecutorService executor) {
         this.serviceType = serviceType;
         this.socketClient = socketClient;
@@ -169,7 +170,8 @@
                                     new QueryTaskConfig(
                                             searchOptions.getSubtypes(),
                                             searchOptions.isPassiveMode(),
-                                            ++currentSessionId)));
+                                            ++currentSessionId,
+                                            searchOptions.getNetwork())));
         }
     }
 
@@ -322,9 +324,10 @@
         private int burstCounter;
         private int timeToRunNextTaskInMs;
         private boolean isFirstBurst;
+        @Nullable private final Network network;
 
         QueryTaskConfig(@NonNull Collection<String> subtypes, boolean usePassiveMode,
-                long sessionId) {
+                long sessionId, @Nullable Network network) {
             this.usePassiveMode = usePassiveMode;
             this.subtypes = new ArrayList<>(subtypes);
             this.queriesPerBurst = QUERIES_PER_BURST;
@@ -346,6 +349,7 @@
                 // doubles until it maxes out at TIME_BETWEEN_BURSTS_MS.
                 this.timeBetweenBurstsInMs = INITIAL_TIME_BETWEEN_BURSTS_MS;
             }
+            this.network = network;
         }
 
         QueryTaskConfig getConfigForNextRun() {
@@ -405,7 +409,8 @@
                                 serviceType,
                                 config.subtypes,
                                 config.expectUnicastResponse,
-                                config.transactionId)
+                                config.transactionId,
+                                config.network)
                                 .call();
             } catch (RuntimeException e) {
                 LOGGER.e(String.format("Failed to run EnqueueMdnsQueryCallable for subtype: %s",
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java b/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
index 64c4495..5fd1354 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
@@ -40,9 +40,9 @@
     private static final MdnsLogger LOGGER = new MdnsLogger("MdnsSocket");
 
     static final int INTERFACE_INDEX_UNSPECIFIED = -1;
-    protected static final InetSocketAddress MULTICAST_IPV4_ADDRESS =
+    public static final InetSocketAddress MULTICAST_IPV4_ADDRESS =
             new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT);
-    protected static final InetSocketAddress MULTICAST_IPV6_ADDRESS =
+    public static final InetSocketAddress MULTICAST_IPV6_ADDRESS =
             new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
     private final MulticastNetworkInterfaceProvider multicastNetworkInterfaceProvider;
     private final MulticastSocket multicastSocket;
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
index 6a321d1..907687e 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
@@ -16,6 +16,8 @@
 
 package com.android.server.connectivity.mdns;
 
+import static com.android.server.connectivity.mdns.MdnsSocketClientBase.Callback;
+
 import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -47,7 +49,7 @@
  *
  * <p>See https://tools.ietf.org/html/rfc6763 (namely sections 4 and 5).
  */
-public class MdnsSocketClient {
+public class MdnsSocketClient implements MdnsSocketClientBase {
 
     private static final String TAG = "MdnsClient";
     // TODO: The following values are copied from cast module. We need to think about the
@@ -116,11 +118,13 @@
         }
     }
 
+    @Override
     public synchronized void setCallback(@Nullable Callback callback) {
         this.callback = callback;
     }
 
     @RequiresPermission(permission.CHANGE_WIFI_MULTICAST_STATE)
+    @Override
     public synchronized void startDiscovery() throws IOException {
         if (multicastSocket != null) {
             LOGGER.w("Discovery is already in progress.");
@@ -160,6 +164,7 @@
     }
 
     @RequiresPermission(permission.CHANGE_WIFI_MULTICAST_STATE)
+    @Override
     public void stopDiscovery() {
         LOGGER.log("Stop discovery.");
         if (multicastSocket == null && unicastSocket == null) {
@@ -195,11 +200,13 @@
     }
 
     /** Sends a mDNS request packet that asks for multicast response. */
+    @Override
     public void sendMulticastPacket(@NonNull DatagramPacket packet) {
         sendMdnsPacket(packet, multicastPacketQueue);
     }
 
     /** Sends a mDNS request packet that asks for unicast response. */
+    @Override
     public void sendUnicastPacket(DatagramPacket packet) {
         if (useSeparateSocketForUnicast) {
             sendMdnsPacket(packet, unicastPacketQueue);
@@ -512,11 +519,4 @@
     public boolean isOnIPv6OnlyNetwork() {
         return multicastSocket != null && multicastSocket.isOnIPv6OnlyNetwork();
     }
-
-    /** Callback for {@link MdnsSocketClient}. */
-    public interface Callback {
-        void onResponseReceived(@NonNull MdnsResponse response);
-
-        void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode);
-    }
 }
\ No newline at end of file
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClientBase.java b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
new file mode 100644
index 0000000..23504a0
--- /dev/null
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
@@ -0,0 +1,80 @@
+/*
+ * 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 com.android.server.connectivity.mdns;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.Network;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+
+/**
+ * Base class for multicast socket client.
+ *
+ * @hide
+ */
+public interface MdnsSocketClientBase {
+    /*** Start mDns discovery on given network. */
+    default void startDiscovery() throws IOException { }
+
+    /*** Stop mDns discovery. */
+    default void stopDiscovery() { }
+
+    /*** Set callback for receiving mDns response */
+    void setCallback(@Nullable Callback callback);
+
+    /*** Sends a mDNS request packet that asks for multicast response. */
+    void sendMulticastPacket(@NonNull DatagramPacket packet);
+
+    /**
+     * Sends a mDNS request packet via given network that asks for multicast response. Null network
+     * means sending packet via all networks.
+     */
+    default void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
+        throw new UnsupportedOperationException(
+                "This socket client doesn't support per-network sending");
+    }
+
+    /*** Sends a mDNS request packet that asks for unicast response. */
+    void sendUnicastPacket(@NonNull DatagramPacket packet);
+
+    /**
+     * Sends a mDNS request packet via given network that asks for unicast response. Null network
+     * means sending packet via all networks.
+     */
+    default void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
+        throw new UnsupportedOperationException(
+                "This socket client doesn't support per-network sending");
+    }
+
+    /*** Notify that the given network is requested for mdns discovery / resolution */
+    default void notifyNetworkRequested(@NonNull MdnsServiceBrowserListener listener,
+            @Nullable Network network) { }
+
+    /*** Notify that the network is unrequested */
+    default void notifyNetworkUnrequested(@NonNull MdnsServiceBrowserListener listener) { }
+
+    /*** Callback for mdns response  */
+    interface Callback {
+        /*** Receive a mdns response */
+        void onResponseReceived(@NonNull MdnsResponse response);
+
+        /*** Parse a mdns response failed */
+        void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode);
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketProvider.java b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketProvider.java
index b8c324e..9298852 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketProvider.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketProvider.java
@@ -35,6 +35,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.CollectionUtils;
 import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
 import com.android.net.module.util.ip.NetlinkMonitor;
 import com.android.net.module.util.netlink.NetlinkConstants;
@@ -42,7 +43,6 @@
 import com.android.server.connectivity.mdns.util.MdnsLogger;
 
 import java.io.IOException;
-import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.ArrayList;
@@ -60,8 +60,13 @@
 public class MdnsSocketProvider {
     private static final String TAG = MdnsSocketProvider.class.getSimpleName();
     private static final boolean DBG = MdnsDiscoveryManager.DBG;
+    // This buffer size matches what MdnsSocketClient uses currently.
+    // But 1440 should generally be enough because of standard Ethernet.
+    // Note: mdnsresponder mDNSEmbeddedAPI.h uses 8940 for Ethernet jumbo frames.
+    private static final int READ_BUFFER_SIZE = 2048;
     private static final MdnsLogger LOGGER = new MdnsLogger(TAG);
     @NonNull private final Context mContext;
+    @NonNull private final Looper mLooper;
     @NonNull private final Handler mHandler;
     @NonNull private final Dependencies mDependencies;
     @NonNull private final NetworkCallback mNetworkCallback;
@@ -75,6 +80,7 @@
             new ArrayMap<>();
     private final List<String> mLocalOnlyInterfaces = new ArrayList<>();
     private final List<String> mTetheredInterfaces = new ArrayList<>();
+    private final byte[] mPacketReadBuffer = new byte[READ_BUFFER_SIZE];
     private boolean mMonitoringSockets = false;
 
     public MdnsSocketProvider(@NonNull Context context, @NonNull Looper looper) {
@@ -84,6 +90,7 @@
     MdnsSocketProvider(@NonNull Context context, @NonNull Looper looper,
             @NonNull Dependencies deps) {
         mContext = context;
+        mLooper = looper;
         mHandler = new Handler(looper);
         mDependencies = deps;
         mNetworkCallback = new NetworkCallback() {
@@ -119,32 +126,33 @@
     @VisibleForTesting
     public static class Dependencies {
         /*** Get network interface by given interface name */
-        public NetworkInterfaceWrapper getNetworkInterfaceByName(String interfaceName)
+        public NetworkInterfaceWrapper getNetworkInterfaceByName(@NonNull String interfaceName)
                 throws SocketException {
             final NetworkInterface ni = NetworkInterface.getByName(interfaceName);
             return ni == null ? null : new NetworkInterfaceWrapper(ni);
         }
 
         /*** Check whether given network interface can support mdns */
-        public boolean canScanOnInterface(NetworkInterfaceWrapper networkInterface) {
+        public boolean canScanOnInterface(@NonNull NetworkInterfaceWrapper networkInterface) {
             return MulticastNetworkInterfaceProvider.canScanOnInterface(networkInterface);
         }
 
         /*** Create a MdnsInterfaceSocket */
-        public MdnsInterfaceSocket createMdnsInterfaceSocket(NetworkInterface networkInterface,
-                int port) throws IOException {
-            return new MdnsInterfaceSocket(networkInterface, port);
+        public MdnsInterfaceSocket createMdnsInterfaceSocket(
+                @NonNull NetworkInterface networkInterface, int port, @NonNull Looper looper,
+                @NonNull byte[] packetReadBuffer) throws IOException {
+            return new MdnsInterfaceSocket(networkInterface, port, looper, packetReadBuffer);
         }
     }
 
     /*** Data class for storing socket related info  */
     private static class SocketInfo {
         final MdnsInterfaceSocket mSocket;
-        final List<LinkAddress> mAddresses = new ArrayList<>();
+        final List<LinkAddress> mAddresses;
 
         SocketInfo(MdnsInterfaceSocket socket, List<LinkAddress> addresses) {
             mSocket = socket;
-            mAddresses.addAll(addresses);
+            mAddresses = new ArrayList<>(addresses);
         }
     }
 
@@ -160,8 +168,9 @@
         }
     }
 
-    private void ensureRunningOnHandlerThread() {
-        if (mHandler.getLooper().getThread() != Thread.currentThread()) {
+    /*** Ensure that current running thread is same as given handler thread */
+    public static void ensureRunningOnHandlerThread(Handler handler) {
+        if (handler.getLooper().getThread() != Thread.currentThread()) {
             throw new IllegalStateException(
                     "Not running on Handler thread: " + Thread.currentThread().getName());
         }
@@ -169,7 +178,7 @@
 
     /*** Start monitoring sockets by listening callbacks for sockets creation or removal */
     public void startMonitoringSockets() {
-        ensureRunningOnHandlerThread();
+        ensureRunningOnHandlerThread(mHandler);
         if (mMonitoringSockets) {
             Log.d(TAG, "Already monitoring sockets.");
             return;
@@ -188,7 +197,7 @@
 
     /*** Stop monitoring sockets and unregister callbacks */
     public void stopMonitoringSockets() {
-        ensureRunningOnHandlerThread();
+        ensureRunningOnHandlerThread(mHandler);
         if (!mMonitoringSockets) {
             Log.d(TAG, "Monitoring sockets hasn't been started.");
             return;
@@ -204,19 +213,15 @@
         mMonitoringSockets = false;
     }
 
-    private static boolean isNetworkMatched(@Nullable Network targetNetwork,
+    /*** Check whether the target network is matched current network */
+    public static boolean isNetworkMatched(@Nullable Network targetNetwork,
             @NonNull Network currentNetwork) {
         return targetNetwork == null || targetNetwork.equals(currentNetwork);
     }
 
     private boolean matchRequestedNetwork(Network network) {
-        for (int i = 0; i < mCallbacksToRequestedNetworks.size(); i++) {
-            final Network requestedNetwork =  mCallbacksToRequestedNetworks.valueAt(i);
-            if (isNetworkMatched(requestedNetwork, network)) {
-                return true;
-            }
-        }
-        return false;
+        return hasAllNetworksRequest()
+                || mCallbacksToRequestedNetworks.containsValue(network);
     }
 
     private boolean hasAllNetworksRequest() {
@@ -244,7 +249,7 @@
             // Try to join the group again.
             socketInfo.mSocket.joinGroup(addresses);
 
-            notifyAddressesChanged(network, lp);
+            notifyAddressesChanged(network, socketInfo.mSocket, lp);
         }
     }
 
@@ -279,15 +284,6 @@
         current.addAll(updated);
     }
 
-    private static List<LinkAddress> getLinkAddressFromNetworkInterface(
-            NetworkInterfaceWrapper networkInterface) {
-        List<LinkAddress> addresses = new ArrayList<>();
-        for (InterfaceAddress address : networkInterface.getInterfaceAddresses()) {
-            addresses.add(new LinkAddress(address));
-        }
-        return addresses;
-    }
-
     private void createSocket(Network network, LinkProperties lp) {
         final String interfaceName = lp.getInterfaceName();
         if (interfaceName == null) {
@@ -307,10 +303,12 @@
                         + " with interfaceName:" + interfaceName);
             }
             final MdnsInterfaceSocket socket = mDependencies.createMdnsInterfaceSocket(
-                    networkInterface.getNetworkInterface(), MdnsConstants.MDNS_PORT);
+                    networkInterface.getNetworkInterface(), MdnsConstants.MDNS_PORT, mLooper,
+                    mPacketReadBuffer);
             final List<LinkAddress> addresses;
             if (network.netId == INetd.LOCAL_NET_ID) {
-                addresses = getLinkAddressFromNetworkInterface(networkInterface);
+                addresses = CollectionUtils.map(
+                        networkInterface.getInterfaceAddresses(), LinkAddress::new);
                 mTetherInterfaceSockets.put(interfaceName, new SocketInfo(socket, addresses));
             } else {
                 addresses = lp.getLinkAddresses();
@@ -355,12 +353,13 @@
         }
     }
 
-    private void notifyAddressesChanged(Network network, LinkProperties lp) {
+    private void notifyAddressesChanged(Network network, MdnsInterfaceSocket socket,
+            LinkProperties lp) {
         for (int i = 0; i < mCallbacksToRequestedNetworks.size(); i++) {
             final Network requestedNetwork = mCallbacksToRequestedNetworks.valueAt(i);
             if (isNetworkMatched(requestedNetwork, network)) {
                 mCallbacksToRequestedNetworks.keyAt(i)
-                        .onAddressesChanged(network, lp.getLinkAddresses());
+                        .onAddressesChanged(network, socket, lp.getLinkAddresses());
             }
         }
     }
@@ -401,7 +400,7 @@
      * @param cb the callback to listen the socket creation.
      */
     public void requestSocket(@Nullable Network network, @NonNull SocketCallback cb) {
-        ensureRunningOnHandlerThread();
+        ensureRunningOnHandlerThread(mHandler);
         mCallbacksToRequestedNetworks.put(cb, network);
         if (network == null) {
             // Does not specify a required network, create sockets for all possible
@@ -424,7 +423,7 @@
 
     /*** Unrequest the socket */
     public void unrequestSocket(@NonNull SocketCallback cb) {
-        ensureRunningOnHandlerThread();
+        ensureRunningOnHandlerThread(mHandler);
         mCallbacksToRequestedNetworks.remove(cb);
         if (hasAllNetworksRequest()) {
             // Still has a request for all networks (interfaces).
@@ -433,16 +432,24 @@
 
         // Check if remaining requests are matched any of sockets.
         for (int i = mNetworkSockets.size() - 1; i >= 0; i--) {
-            if (matchRequestedNetwork(mNetworkSockets.keyAt(i))) continue;
-            mNetworkSockets.removeAt(i).mSocket.destroy();
+            final Network network = mNetworkSockets.keyAt(i);
+            if (matchRequestedNetwork(network)) continue;
+            final SocketInfo info = mNetworkSockets.removeAt(i);
+            info.mSocket.destroy();
+            // Still notify to unrequester for socket destroy.
+            cb.onInterfaceDestroyed(network, info.mSocket);
         }
 
         // Remove all sockets for tethering interface because these sockets do not have associated
         // networks, and they should invoke by a request for all networks (interfaces). If there is
         // no such request, the sockets for tethering interface should be removed.
         for (int i = mTetherInterfaceSockets.size() - 1; i >= 0; i--) {
-            mTetherInterfaceSockets.removeAt(i).mSocket.destroy();
+            final SocketInfo info = mTetherInterfaceSockets.valueAt(i);
+            info.mSocket.destroy();
+            // Still notify to unrequester for socket destroy.
+            cb.onInterfaceDestroyed(new Network(INetd.LOCAL_NET_ID), info.mSocket);
         }
+        mTetherInterfaceSockets.clear();
     }
 
     /*** Callbacks for listening socket changes */
@@ -455,6 +462,6 @@
                 @NonNull MdnsInterfaceSocket socket) {}
         /*** Notify the addresses is changed on the network */
         default void onAddressesChanged(@NonNull Network network,
-                @NonNull List<LinkAddress> addresses) {}
+                @NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> addresses) {}
     }
 }
diff --git a/service/mdns/com/android/server/connectivity/mdns/MulticastPacketReader.java b/service/mdns/com/android/server/connectivity/mdns/MulticastPacketReader.java
new file mode 100644
index 0000000..20cc47f
--- /dev/null
+++ b/service/mdns/com/android/server/connectivity/mdns/MulticastPacketReader.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns;
+
+import static com.android.server.connectivity.mdns.MdnsSocketProvider.ensureRunningOnHandlerThread;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.system.Os;
+import android.util.ArraySet;
+
+import com.android.net.module.util.FdEventsReader;
+
+import java.io.FileDescriptor;
+import java.net.InetSocketAddress;
+import java.util.Set;
+
+/** Simple reader for mDNS packets. */
+public class MulticastPacketReader extends FdEventsReader<MulticastPacketReader.RecvBuffer> {
+    @NonNull
+    private final String mLogTag;
+    @NonNull
+    private final ParcelFileDescriptor mSocket;
+    @NonNull
+    private final Handler mHandler;
+    @NonNull
+    private final Set<PacketHandler> mPacketHandlers = new ArraySet<>();
+
+    interface PacketHandler {
+        void handlePacket(byte[] recvbuf, int length, InetSocketAddress src);
+    }
+
+    public static final class RecvBuffer {
+        final byte[] data;
+        final InetSocketAddress src;
+
+        private RecvBuffer(byte[] data, InetSocketAddress src) {
+            this.data = data;
+            this.src = src;
+        }
+    }
+
+    /**
+     * Create a new {@link MulticastPacketReader}.
+     * @param socket Socket to read from. This will *not* be closed when the reader terminates.
+     * @param buffer Buffer to read packets into. Will only be used from the handler thread.
+     */
+    protected MulticastPacketReader(@NonNull String interfaceTag,
+            @NonNull ParcelFileDescriptor socket, @NonNull Handler handler,
+            @NonNull byte[] buffer) {
+        super(handler, new RecvBuffer(buffer, new InetSocketAddress()));
+        mLogTag = MulticastPacketReader.class.getSimpleName() + "/" + interfaceTag;
+        mSocket = socket;
+        mHandler = handler;
+    }
+
+    @Override
+    protected int recvBufSize(@NonNull RecvBuffer buffer) {
+        return buffer.data.length;
+    }
+
+    @Override
+    protected FileDescriptor createFd() {
+        // Keep a reference to the PFD as it would close the fd in its finalizer otherwise
+        return mSocket.getFileDescriptor();
+    }
+
+    @Override
+    protected void onStop() {
+        // Do nothing (do not close the FD)
+    }
+
+    @Override
+    protected int readPacket(@NonNull FileDescriptor fd, @NonNull RecvBuffer buffer)
+            throws Exception {
+        return Os.recvfrom(
+                fd, buffer.data, 0, buffer.data.length, 0 /* flags */, buffer.src);
+    }
+
+    @Override
+    protected void handlePacket(@NonNull RecvBuffer recvbuf, int length) {
+        for (PacketHandler handler : mPacketHandlers) {
+            handler.handlePacket(recvbuf.data, length, recvbuf.src);
+        }
+    }
+
+    /**
+     * Add a packet handler to deal with received packets. If the handler is already set,
+     * this is a no-op.
+     */
+    public void addPacketHandler(@NonNull PacketHandler handler) {
+        ensureRunningOnHandlerThread(mHandler);
+        mPacketHandlers.add(handler);
+    }
+}
+
diff --git a/service/mdns/com/android/server/connectivity/mdns/NameConflictException.java b/service/mdns/com/android/server/connectivity/mdns/NameConflictException.java
new file mode 100644
index 0000000..c123d02
--- /dev/null
+++ b/service/mdns/com/android/server/connectivity/mdns/NameConflictException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns;
+
+/**
+ * An exception thrown when a service name conflicts with an existing service.
+ */
+public class NameConflictException extends Exception {
+    /**
+     * ID of the existing service that conflicted.
+     */
+    public final int conflictingServiceId;
+    public NameConflictException(int conflictingServiceId) {
+        this.conflictingServiceId = conflictingServiceId;
+    }
+}
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index bce9f53..26ec37a 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -279,9 +279,10 @@
     private static synchronized void ensureInitialized(final Context context) {
         if (sInitialized) return;
         if (sEnableJavaBpfMap == null) {
-            sEnableJavaBpfMap = DeviceConfigUtils.isFeatureEnabled(context,
+            sEnableJavaBpfMap = SdkLevel.isAtLeastU() ||
+                    DeviceConfigUtils.isFeatureEnabled(context,
                     DeviceConfig.NAMESPACE_TETHERING, BPF_NET_MAPS_ENABLE_JAVA_BPF_MAP,
-                    false /* defaultValue */) || SdkLevel.isAtLeastU();
+                    false /* defaultValue */);
         }
         Log.d(TAG, "BpfNetMaps is initialized with sEnableJavaBpfMap=" + sEnableJavaBpfMap);
 
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index e3e12fd..a7e6a2e 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -242,6 +242,8 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
+import androidx.annotation.RequiresApi;
+
 import com.android.connectivity.resources.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -262,6 +264,10 @@
 import com.android.net.module.util.PermissionUtils;
 import com.android.net.module.util.TcUtils;
 import com.android.net.module.util.netlink.InetDiagMessage;
+import com.android.networkstack.apishim.BroadcastOptionsShimImpl;
+import com.android.networkstack.apishim.ConstantsShim;
+import com.android.networkstack.apishim.common.BroadcastOptionsShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
 import com.android.server.connectivity.AutodestructReference;
 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
 import com.android.server.connectivity.ClatCoordinator;
@@ -286,6 +292,7 @@
 import com.android.server.connectivity.ProxyTracker;
 import com.android.server.connectivity.QosCallbackTracker;
 import com.android.server.connectivity.UidRangeUtils;
+import com.android.server.connectivity.VpnNetworkPreferenceInfo;
 import com.android.server.connectivity.wear.CompanionDeviceManagerProxyService;
 
 import libcore.io.IoUtils;
@@ -371,6 +378,10 @@
     private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
     private static final int DEFAULT_NASCENT_DELAY_MS = 5_000;
 
+    // Delimiter used when creating the broadcast delivery group for sending
+    // CONNECTIVITY_ACTION broadcast.
+    private static final char DELIVERY_GROUP_KEY_DELIMITER = ';';
+
     // The maximum value for the blocking validation result, in milliseconds.
     public static final int MAX_VALIDATION_IGNORE_AFTER_ROAM_TIME_MS = 10000;
 
@@ -747,6 +758,12 @@
     private static final int EVENT_USER_DOES_NOT_WANT = 58;
 
     /**
+     * Event to set VPN as preferred network for specific apps.
+     * obj = VpnNetworkPreferenceInfo
+     */
+    private static final int EVENT_SET_VPN_NETWORK_PREFERENCE = 59;
+
+    /**
      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
      * should be shown.
      */
@@ -1404,6 +1421,16 @@
                         + ", ingress=true, PRIO_POLICE, ETH_P_ALL) failure: ", e);
             }
         }
+
+        /**
+         * Wraps {@link BroadcastOptionsShimImpl#newInstance(BroadcastOptions)}
+         */
+        // TODO: when available in all active branches:
+        //  @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+        @RequiresApi(Build.VERSION_CODES.CUR_DEVELOPMENT)
+        public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
+            return BroadcastOptionsShimImpl.newInstance(options);
+        }
     }
 
     public ConnectivityService(Context context) {
@@ -1625,6 +1652,17 @@
                 TYPE_NONE, NetworkRequest.Type.REQUEST);
     }
 
+    private NetworkRequest createVpnRequest() {
+        final NetworkCapabilities netCap = new NetworkCapabilities.Builder()
+                .withoutDefaultCapabilities()
+                .addTransportType(TRANSPORT_VPN)
+                .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
+                .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
+                .build();
+        netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
+        return createNetworkRequest(NetworkRequest.Type.REQUEST, netCap);
+    }
+
     private NetworkRequest createDefaultInternetRequestForTransport(
             int transportType, NetworkRequest.Type type) {
         final NetworkCapabilities netCap = new NetworkCapabilities();
@@ -3019,6 +3057,7 @@
                         ConnectivityManager.EXTRA_NETWORK_INFO);
                 final BroadcastOptions opts = BroadcastOptions.makeBasic();
                 opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
+                applyMostRecentPolicyForConnectivityAction(opts, ni);
                 options = opts.toBundle();
                 intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
             }
@@ -3030,6 +3069,32 @@
         }
     }
 
+    private void applyMostRecentPolicyForConnectivityAction(BroadcastOptions options,
+            NetworkInfo info) {
+        // Delivery group policy APIs are only available on U+.
+        if (!SdkLevel.isAtLeastU()) return;
+
+        final BroadcastOptionsShim optsShim = mDeps.makeBroadcastOptionsShim(options);
+        try {
+            // This allows us to discard older broadcasts still waiting to be delivered
+            // which have the same namespace and key.
+            optsShim.setDeliveryGroupPolicy(ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT);
+            optsShim.setDeliveryGroupMatchingKey(ConnectivityManager.CONNECTIVITY_ACTION,
+                    createDeliveryGroupKeyForConnectivityAction(info));
+        } catch (UnsupportedApiLevelException e) {
+            Log.wtf(TAG, "Using unsupported API" + e);
+        }
+    }
+
+    @VisibleForTesting
+    static String createDeliveryGroupKeyForConnectivityAction(NetworkInfo info) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(info.getType()).append(DELIVERY_GROUP_KEY_DELIMITER);
+        sb.append(info.getSubtype()).append(DELIVERY_GROUP_KEY_DELIMITER);
+        sb.append(info.getExtraInfo());
+        return sb.toString();
+    }
+
     /**
      * Called by SystemServer through ConnectivityManager when the system is ready.
      */
@@ -3125,22 +3190,23 @@
     private void updateMtu(@NonNull LinkProperties newLp, @Nullable LinkProperties oldLp) {
         final String iface = newLp.getInterfaceName();
         final int mtu = newLp.getMtu();
-        if (oldLp == null && mtu == 0) {
+        if (mtu == 0) {
             // Silently ignore unset MTU value.
             return;
         }
-        if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
-            if (VDBG) log("identical MTU - not setting");
+        if (oldLp != null && newLp.isIdenticalMtu(oldLp)
+                && TextUtils.equals(oldLp.getInterfaceName(), iface)) {
+            if (VDBG) log("identical MTU and iface - not setting");
             return;
         }
-        if (!LinkProperties.isValidMtu(mtu, newLp.hasGlobalIpv6Address())) {
-            if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
+        // Cannot set MTU without interface name
+        if (TextUtils.isEmpty(iface)) {
+            if (VDBG) log("Setting MTU size with null iface.");
             return;
         }
 
-        // Cannot set MTU without interface name
-        if (TextUtils.isEmpty(iface)) {
-            loge("Setting MTU size with null iface.");
+        if (!LinkProperties.isValidMtu(mtu, newLp.hasGlobalIpv6Address())) {
+            loge("Unexpected mtu value: " + mtu + ", " + iface);
             return;
         }
 
@@ -4347,6 +4413,9 @@
             mNetworkForNetId.remove(nai.network.getNetId());
         }
         propagateUnderlyingNetworkCapabilities(nai.network);
+        // Update allowed network lists in netd. This should be called after removing nai
+        // from mNetworkAgentInfos.
+        updateProfileAllowedNetworks();
         // Remove all previously satisfied requests.
         for (int i = 0; i < nai.numNetworkRequests(); i++) {
             final NetworkRequest request = nai.requestAt(i);
@@ -4781,6 +4850,7 @@
                 }
             }
         }
+
         nri.mPerUidCounter.decrementCount(nri.mUid);
         mNetworkRequestInfoLogs.log("RELEASE " + nri);
         checkNrisConsistency(nri);
@@ -5531,6 +5601,9 @@
                     nai.onPreventAutomaticReconnect();
                     nai.disconnect();
                     break;
+                case EVENT_SET_VPN_NETWORK_PREFERENCE:
+                    handleSetVpnNetworkPreference((VpnNetworkPreferenceInfo) msg.obj);
+                    break;
             }
         }
     }
@@ -6144,12 +6217,16 @@
         if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
         }
+        if (!mProfileNetworkPreferences.isEmpty()) {
+            updateProfileAllowedNetworks();
+        }
     }
 
     private void onUserRemoved(@NonNull final UserHandle user) {
         // If there was a network preference for this user, remove it.
         handleSetProfileNetworkPreference(
-                List.of(new ProfileNetworkPreferenceInfo(user, null, true)),
+                List.of(new ProfileNetworkPreferenceInfo(user, null, true,
+                        false /* blockingNonEnterprise */)),
                 null /* listener */);
         if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
@@ -7122,6 +7199,12 @@
     private NetworkPreferenceList<UserHandle, ProfileNetworkPreferenceInfo>
             mProfileNetworkPreferences = new NetworkPreferenceList<>();
 
+    // Current VPN network preferences. This object follows the same threading rules as the OEM
+    // network preferences above.
+    @NonNull
+    private NetworkPreferenceList<String, VpnNetworkPreferenceInfo>
+            mVpnNetworkPreferences = new NetworkPreferenceList<>();
+
     // A set of UIDs that should use mobile data preferentially if available. This object follows
     // the same threading rules as the OEM network preferences above.
     @NonNull
@@ -8660,6 +8743,73 @@
         }
     }
 
+    /**
+     * Collect restricted uid ranges for the given network and UserHandle, these uids
+     * are not restricted for matched enterprise networks but being restricted for non-matched
+     * enterprise networks and non-enterprise networks.
+     */
+    @NonNull
+    private ArraySet<UidRange> getRestrictedUidRangesForEnterpriseBlocking(
+            @NonNull NetworkAgentInfo nai, @NonNull UserHandle user) {
+        final ArraySet<UidRange> restrictedUidRanges = new ArraySet<>();
+        for (final ProfileNetworkPreferenceInfo pref : mProfileNetworkPreferences) {
+            if (!pref.user.equals(user) || !pref.blockingNonEnterprise) continue;
+
+            if (nai.networkCapabilities.hasCapability(NET_CAPABILITY_ENTERPRISE)) {
+                // The NC is built from a `ProfileNetworkPreference` which has only one
+                // enterprise ID, so it's guaranteed to have exactly one.
+                final int prefId = pref.capabilities.getEnterpriseIds()[0];
+                if (nai.networkCapabilities.hasEnterpriseId(prefId)) {
+                    continue;
+                }
+            }
+
+            if (UidRangeUtils.doesRangeSetOverlap(restrictedUidRanges,
+                    pref.capabilities.getUidRanges())) {
+                throw new IllegalArgumentException(
+                        "Overlapping uid range in preference: " + pref);
+            }
+            restrictedUidRanges.addAll(pref.capabilities.getUidRanges());
+        }
+        return restrictedUidRanges;
+    }
+
+    private void updateProfileAllowedNetworks() {
+        ensureRunningOnConnectivityServiceThread();
+        final ArrayList<NativeUidRangeConfig> configs = new ArrayList<>();
+        final List<UserHandle> users = mContext.getSystemService(UserManager.class)
+                        .getUserHandles(true /* excludeDying */);
+        if (users.isEmpty()) {
+            throw new IllegalStateException("No user is available");
+        }
+
+        for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
+            ArraySet<UidRange> allowedUidRanges = new ArraySet<>();
+            for (final UserHandle user : users) {
+                final ArraySet<UidRange> restrictedUidRanges =
+                        getRestrictedUidRangesForEnterpriseBlocking(nai, user);
+                allowedUidRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
+                        UidRange.createForUser(user), restrictedUidRanges));
+            }
+
+            final UidRangeParcel[] rangesParcel = toUidRangeStableParcels(allowedUidRanges);
+            configs.add(new NativeUidRangeConfig(
+                    nai.network.netId, rangesParcel, 0 /* subPriority */));
+        }
+
+        // The netd API replaces the previous configs with the current configs.
+        // Thus, for network disconnection or preference removal, no need to
+        // unset previous config. Instead, collecting all currently needed
+        // configs and issue to netd.
+        try {
+            mNetd.setNetworkAllowlist(configs.toArray(new NativeUidRangeConfig[0]));
+        } catch (ServiceSpecificException e) {
+            // Has the interface disappeared since the network was built?
+        } catch (RemoteException e) {
+            // Netd died. This usually causes a runtime restart anyway.
+        }
+    }
+
     private void makeDefaultNetwork(@Nullable final NetworkAgentInfo newDefaultNetwork) {
         try {
             if (null != newDefaultNetwork) {
@@ -9292,6 +9442,7 @@
             networkAgent.setCreated();
             networkAgent.onNetworkCreated();
             updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
+            updateProfileAllowedNetworks();
         }
 
         if (!networkAgent.everConnected() && state == NetworkInfo.State.CONNECTED) {
@@ -10828,6 +10979,7 @@
         for (final ProfileNetworkPreference preference : preferences) {
             final NetworkCapabilities nc;
             boolean allowFallback = true;
+            boolean blockingNonEnterprise = false;
             switch (preference.getPreference()) {
                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT:
                     nc = null;
@@ -10837,6 +10989,9 @@
                                 "Invalid enterprise identifier in setProfileNetworkPreferences");
                     }
                     break;
+                case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING:
+                    blockingNonEnterprise = true;
+                    // continue to process the enterprise preference.
                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK:
                     allowFallback = false;
                     // continue to process the enterprise preference.
@@ -10870,7 +11025,8 @@
                     throw new IllegalArgumentException(
                             "Invalid preference in setProfileNetworkPreferences");
             }
-            preferenceList.add(new ProfileNetworkPreferenceInfo(profile, nc, allowFallback));
+            preferenceList.add(new ProfileNetworkPreferenceInfo(
+                    profile, nc, allowFallback, blockingNonEnterprise));
             if (hasDefaultPreference && preferenceList.size() > 1) {
                 throw new IllegalArgumentException(
                         "Default profile preference should not be set along with other preference");
@@ -10983,6 +11139,7 @@
         removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_PROFILE);
         addPerAppDefaultNetworkRequests(
                 createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences));
+        updateProfileAllowedNetworks();
 
         // Finally, rematch.
         rematchAllNetworksAndRequests();
@@ -11112,6 +11269,60 @@
     }
 
     /**
+     * Sets the specified UIDs to get/receive the VPN as the only default network.
+     *
+     * Calling this will overwrite the existing network preference for this session, and the
+     * specified UIDs won't get any default network when no VPN is connected.
+     *
+     * @param session The VPN session which manages the passed UIDs.
+     * @param ranges The uid ranges which will treat VPN as the only preferred network. Clear the
+     *               setting for this session if the array is empty. Null is not allowed, the
+     *               method will use {@link Objects#requireNonNull(Object)} to check this variable.
+     * @hide
+     */
+    @Override
+    public void setVpnNetworkPreference(String session, UidRange[] ranges) {
+        Objects.requireNonNull(ranges);
+        enforceNetworkStackOrSettingsPermission();
+        final UidRange[] sortedRanges = UidRangeUtils.sortRangesByStartUid(ranges);
+        if (UidRangeUtils.sortedRangesContainOverlap(sortedRanges)) {
+            throw new IllegalArgumentException(
+                    "setVpnNetworkPreference: Passed UID ranges overlap");
+        }
+
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_VPN_NETWORK_PREFERENCE,
+                new VpnNetworkPreferenceInfo(session,
+                        new ArraySet<UidRange>(Arrays.asList(ranges)))));
+    }
+
+    private void handleSetVpnNetworkPreference(VpnNetworkPreferenceInfo preferenceInfo) {
+        Log.d(TAG, "handleSetVpnNetworkPreference: preferenceInfo = " + preferenceInfo);
+
+        mVpnNetworkPreferences = mVpnNetworkPreferences.minus(preferenceInfo.getKey());
+        mVpnNetworkPreferences = mVpnNetworkPreferences.plus(preferenceInfo);
+
+        removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_VPN);
+        addPerAppDefaultNetworkRequests(createNrisForVpnNetworkPreference(mVpnNetworkPreferences));
+        // Finally, rematch.
+        rematchAllNetworksAndRequests();
+    }
+
+    private ArraySet<NetworkRequestInfo> createNrisForVpnNetworkPreference(
+            @NonNull NetworkPreferenceList<String, VpnNetworkPreferenceInfo> preferenceList) {
+        final ArraySet<NetworkRequestInfo> nris = new ArraySet<>();
+        for (VpnNetworkPreferenceInfo preferenceInfo : preferenceList) {
+            final List<NetworkRequest> requests = new ArrayList<>();
+            // Request VPN only, so other networks won't be the fallback options when VPN is not
+            // connected temporarily.
+            requests.add(createVpnRequest());
+            final Set<UidRange> uidRanges = new ArraySet(preferenceInfo.getUidRangesNoCopy());
+            setNetworkRequestUids(requests, uidRanges);
+            nris.add(new NetworkRequestInfo(Process.myUid(), requests, PREFERENCE_ORDER_VPN));
+        }
+        return nris;
+    }
+
+    /**
      * Check the validity of an OEM network preference to be used for testing purposes.
      * @param preference the preference to validate
      * @return true if this is a valid OEM network preference test request.
diff --git a/service/src/com/android/server/connectivity/DscpPolicyTracker.java b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
index 2bfad10..8d566b6 100644
--- a/service/src/com/android/server/connectivity/DscpPolicyTracker.java
+++ b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
@@ -66,8 +66,8 @@
 
     private Set<String> mAttachedIfaces;
 
-    private final BpfMap<Struct.U32, DscpPolicyValue> mBpfDscpIpv4Policies;
-    private final BpfMap<Struct.U32, DscpPolicyValue> mBpfDscpIpv6Policies;
+    private final BpfMap<Struct.S32, DscpPolicyValue> mBpfDscpIpv4Policies;
+    private final BpfMap<Struct.S32, DscpPolicyValue> mBpfDscpIpv6Policies;
 
     // The actual policy rules used by the BPF code to process packets
     // are in mBpfDscpIpv4Policies and mBpfDscpIpv4Policies. Both of
@@ -85,10 +85,10 @@
     public DscpPolicyTracker() throws ErrnoException {
         mAttachedIfaces = new HashSet<String>();
         mIfaceIndexToPolicyIdBpfMapIndex = new HashMap<Integer, SparseIntArray>();
-        mBpfDscpIpv4Policies = new BpfMap<Struct.U32, DscpPolicyValue>(IPV4_POLICY_MAP_PATH,
-                BpfMap.BPF_F_RDWR, Struct.U32.class, DscpPolicyValue.class);
-        mBpfDscpIpv6Policies = new BpfMap<Struct.U32, DscpPolicyValue>(IPV6_POLICY_MAP_PATH,
-                BpfMap.BPF_F_RDWR, Struct.U32.class, DscpPolicyValue.class);
+        mBpfDscpIpv4Policies = new BpfMap<Struct.S32, DscpPolicyValue>(IPV4_POLICY_MAP_PATH,
+                BpfMap.BPF_F_RDWR, Struct.S32.class, DscpPolicyValue.class);
+        mBpfDscpIpv6Policies = new BpfMap<Struct.S32, DscpPolicyValue>(IPV6_POLICY_MAP_PATH,
+                BpfMap.BPF_F_RDWR, Struct.S32.class, DscpPolicyValue.class);
     }
 
     private boolean isUnusedIndex(int index) {
@@ -181,7 +181,7 @@
             // are both null or if they are both instances of Inet4Address.
             if (matchesIpv4(policy)) {
                 mBpfDscpIpv4Policies.insertOrReplaceEntry(
-                        new Struct.U32(addIndex),
+                        new Struct.S32(addIndex),
                         new DscpPolicyValue(policy.getSourceAddress(),
                             policy.getDestinationAddress(), ifIndex,
                             policy.getSourcePort(), policy.getDestinationPortRange(),
@@ -192,7 +192,7 @@
             // are both null or if they are both instances of Inet6Address.
             if (matchesIpv6(policy)) {
                 mBpfDscpIpv6Policies.insertOrReplaceEntry(
-                        new Struct.U32(addIndex),
+                        new Struct.S32(addIndex),
                         new DscpPolicyValue(policy.getSourceAddress(),
                                 policy.getDestinationAddress(), ifIndex,
                                 policy.getSourcePort(), policy.getDestinationPortRange(),
@@ -258,8 +258,8 @@
             boolean sendCallback) {
         int status = DSCP_POLICY_STATUS_POLICY_NOT_FOUND;
         try {
-            mBpfDscpIpv4Policies.replaceEntry(new Struct.U32(index), DscpPolicyValue.NONE);
-            mBpfDscpIpv6Policies.replaceEntry(new Struct.U32(index), DscpPolicyValue.NONE);
+            mBpfDscpIpv4Policies.replaceEntry(new Struct.S32(index), DscpPolicyValue.NONE);
+            mBpfDscpIpv6Policies.replaceEntry(new Struct.S32(index), DscpPolicyValue.NONE);
             status = DSCP_POLICY_STATUS_DELETED;
         } catch (ErrnoException e) {
             Log.e(TAG, "Failed to delete policy from map: ", e);
diff --git a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceInfo.java b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceInfo.java
index 10f3886..7679660 100644
--- a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceInfo.java
+++ b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceInfo.java
@@ -32,13 +32,15 @@
     @Nullable
     public final NetworkCapabilities capabilities;
     public final boolean allowFallback;
+    public final boolean blockingNonEnterprise;
 
     public ProfileNetworkPreferenceInfo(@NonNull final UserHandle user,
             @Nullable final NetworkCapabilities capabilities,
-            final boolean allowFallback) {
+            final boolean allowFallback, final boolean blockingNonEnterprise) {
         this.user = user;
         this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities);
         this.allowFallback = allowFallback;
+        this.blockingNonEnterprise = blockingNonEnterprise;
     }
 
     @Override
@@ -57,6 +59,7 @@
         return "[ProfileNetworkPreference user=" + user
                 + " caps=" + capabilities
                 + " allowFallback=" + allowFallback
+                + " blockingNonEnterprise=" + blockingNonEnterprise
                 + "]";
     }
 }
diff --git a/service/src/com/android/server/connectivity/UidRangeUtils.java b/service/src/com/android/server/connectivity/UidRangeUtils.java
index 541340b..f36797d 100644
--- a/service/src/com/android/server/connectivity/UidRangeUtils.java
+++ b/service/src/com/android/server/connectivity/UidRangeUtils.java
@@ -184,4 +184,41 @@
         uidRangeSet.add(new UidRange(start, stop));
         return uidRangeSet;
     }
+
+    private static int compare(UidRange range1, UidRange range2) {
+        return range1.start - range2.start;
+    }
+
+    /**
+     * Sort the given UidRange array.
+     *
+     * @param ranges The array of UidRange which is going to be sorted.
+     * @return Array of UidRange.
+     */
+    public static UidRange[] sortRangesByStartUid(UidRange[] ranges) {
+        final ArrayList uidRanges = new ArrayList(Arrays.asList(ranges));
+        Collections.sort(uidRanges, UidRangeUtils::compare);
+        return (UidRange[]) uidRanges.toArray(new UidRange[0]);
+    }
+
+    /**
+     * Check if the given sorted UidRange array contains overlap or not.
+     *
+     * Note that the sorted UidRange array must be sorted by increasing lower bound. If it's not,
+     * the behavior is undefined.
+     *
+     * @param ranges The sorted UidRange array which is going to be checked if there is an overlap
+     *               or not.
+     * @return A boolean to indicate if the given sorted UidRange array contains overlap or not.
+     */
+    public static boolean sortedRangesContainOverlap(UidRange[] ranges) {
+        final ArrayList uidRanges = new ArrayList(Arrays.asList(ranges));
+        for (int i = 0; i + 1 < uidRanges.size(); i++) {
+            if (((UidRange) uidRanges.get(i + 1)).start <= ((UidRange) uidRanges.get(i)).stop) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }
diff --git a/service/src/com/android/server/connectivity/VpnNetworkPreferenceInfo.java b/service/src/com/android/server/connectivity/VpnNetworkPreferenceInfo.java
new file mode 100644
index 0000000..3e111ab
--- /dev/null
+++ b/service/src/com/android/server/connectivity/VpnNetworkPreferenceInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.annotation.NonNull;
+import android.net.UidRange;
+import android.util.ArraySet;
+
+/**
+ * Record the session and UidRange for a VPN preference.
+ */
+public class VpnNetworkPreferenceInfo
+        implements NetworkPreferenceList.NetworkPreference<String> {
+
+    @NonNull
+    public final String mSession;
+
+    @NonNull
+    public final ArraySet<UidRange> mUidRanges;
+
+    public VpnNetworkPreferenceInfo(@NonNull String session,
+            @NonNull ArraySet<UidRange> uidRanges) {
+        this.mSession = session;
+        this.mUidRanges = uidRanges;
+    }
+
+    @Override
+    public boolean isCancel() {
+        return mUidRanges.isEmpty();
+    }
+
+    @Override
+    @NonNull
+    public String getKey() {
+        return mSession;
+    }
+
+    @NonNull
+    public ArraySet<UidRange> getUidRangesNoCopy() {
+        return mUidRanges;
+    }
+
+    /** toString */
+    public String toString() {
+        return "[VpnNetworkPreference session = " + mSession
+                + " uidRanges = " + mUidRanges
+                + "]";
+    }
+}
diff --git a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
index cdf32a4..3c2340c 100644
--- a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
+++ b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
@@ -19,8 +19,8 @@
 import android.net.NetworkStats.DEFAULT_NETWORK_ALL
 import android.net.NetworkStats.METERED_ALL
 import android.net.NetworkStats.METERED_YES
-import android.net.NetworkStats.ROAMING_YES
 import android.net.NetworkStats.ROAMING_ALL
+import android.net.NetworkStats.ROAMING_YES
 import android.net.NetworkTemplate
 import android.net.NetworkTemplate.MATCH_BLUETOOTH
 import android.net.NetworkTemplate.MATCH_CARRIER
@@ -33,8 +33,6 @@
 import android.net.NetworkTemplate.NETWORK_TYPE_ALL
 import android.net.NetworkTemplate.OEM_MANAGED_ALL
 import android.telephony.TelephonyManager
-import com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
-import com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT
 import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.SC_V2
@@ -80,7 +78,7 @@
                         val expectedTemplate = NetworkTemplate(matchRule, TEST_IMSI1,
                                 arrayOf(TEST_IMSI1), emptyArray<String>(), METERED_YES,
                                 ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                                OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                                OEM_MANAGED_ALL)
                         assertEquals(expectedTemplate, it)
                     }
         }
@@ -93,7 +91,7 @@
                         val expectedTemplate = NetworkTemplate(matchRule, TEST_IMSI1,
                                 arrayOf(TEST_IMSI1), emptyArray<String>(), METERED_YES,
                                 ROAMING_YES, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                                OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                                OEM_MANAGED_ALL)
                         assertEquals(expectedTemplate, it)
                     }
         }
@@ -109,7 +107,7 @@
             val expectedTemplate = NetworkTemplate(MATCH_MOBILE_WILDCARD, null /*subscriberId*/,
                     emptyArray<String>() /*subscriberIds*/, emptyArray<String>(),
                     METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                    OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+                    OEM_MANAGED_ALL)
             assertEquals(expectedTemplate, it)
         }
 
@@ -121,7 +119,7 @@
                     val expectedTemplate = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1,
                             arrayOf(TEST_IMSI1), emptyArray<String>(), METERED_YES,
                             ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_UMTS,
-                            OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                            OEM_MANAGED_ALL)
                     assertEquals(expectedTemplate, it)
                 }
 
@@ -131,7 +129,7 @@
             val expectedTemplate = NetworkTemplate(MATCH_WIFI_WILDCARD, null /*subscriberId*/,
                     emptyArray<String>() /*subscriberIds*/, emptyArray<String>(),
                     METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                    OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+                    OEM_MANAGED_ALL)
             assertEquals(expectedTemplate, it)
         }
 
@@ -141,7 +139,7 @@
             val expectedTemplate = NetworkTemplate(MATCH_WIFI, null /*subscriberId*/,
                     emptyArray<String>() /*subscriberIds*/, arrayOf(TEST_WIFI_KEY1),
                     METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                    OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+                    OEM_MANAGED_ALL)
             assertEquals(expectedTemplate, it)
         }
 
@@ -152,7 +150,7 @@
                     val expectedTemplate = NetworkTemplate(MATCH_WIFI, TEST_IMSI1,
                             arrayOf(TEST_IMSI1), arrayOf(TEST_WIFI_KEY1),
                             METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                            OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                            OEM_MANAGED_ALL)
                     assertEquals(expectedTemplate, it)
                 }
 
@@ -163,7 +161,7 @@
                 val expectedTemplate = NetworkTemplate(matchRule, null /*subscriberId*/,
                         emptyArray<String>() /*subscriberIds*/, emptyArray<String>(),
                         METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                        OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+                        OEM_MANAGED_ALL)
                 assertEquals(expectedTemplate, it)
             }
         }
@@ -198,7 +196,7 @@
             val expectedTemplate = NetworkTemplate(MATCH_WIFI_WILDCARD, null /*subscriberId*/,
                     emptyArray<String>() /*subscriberIds*/, emptyArray<String>(),
                     METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                    OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+                    OEM_MANAGED_ALL)
             assertEquals(expectedTemplate, it)
         }
     }
diff --git a/tests/cts/OWNERS b/tests/cts/OWNERS
index 089d06f..8388cb7 100644
--- a/tests/cts/OWNERS
+++ b/tests/cts/OWNERS
@@ -2,6 +2,5 @@
 set noparent
 file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking_xts
 
-# Only temporary ownership to improve ethernet code quality (b/236280707)
-# TODO: remove by 12/31/2022
-per-file net/src/android/net/cts/EthernetManagerTest.kt = prohr@google.com #{LAST_RESORT_SUGGESTION}
+# IPsec
+per-file **IpSec* = benedictwong@google.com, nharold@google.com
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 8c18a89..a62ef8a 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
@@ -97,6 +97,7 @@
 import android.telephony.TelephonyManager;
 import android.test.MoreAsserts;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Range;
 
@@ -108,6 +109,7 @@
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 import com.android.testutils.RecorderCallback;
+import com.android.testutils.RecorderCallback.CallbackEntry;
 import com.android.testutils.TestableNetworkCallback;
 
 import org.junit.After;
@@ -136,6 +138,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
+import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -839,8 +842,13 @@
         callback.eventuallyExpect(RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED,
                 NETWORK_CALLBACK_TIMEOUT_MS,
                 entry -> (Objects.equals(expectUnderlyingNetworks,
-                        ((RecorderCallback.CallbackEntry.CapabilitiesChanged) entry)
-                                .getCaps().getUnderlyingNetworks())));
+                        entry.getCaps().getUnderlyingNetworks())));
+    }
+
+    private void expectVpnNetwork(TestableNetworkCallback callback) {
+        callback.eventuallyExpect(RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED,
+                NETWORK_CALLBACK_TIMEOUT_MS,
+                entry -> entry.getCaps().hasTransport(TRANSPORT_VPN));
     }
 
     @Test @IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
@@ -1622,7 +1630,7 @@
                 mCM.registerDefaultNetworkCallbackForUid(remoteUid, remoteUidCallback,
                         new Handler(Looper.getMainLooper()));
             }, NETWORK_SETTINGS);
-            remoteUidCallback.expectAvailableCallbacks(network);
+            remoteUidCallback.expectAvailableCallbacksWithBlockedReasonNone(network);
 
             // The remote UDP socket can receive packets coming from the TUN interface
             checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_PASS);
@@ -1666,6 +1674,56 @@
             });
     }
 
+    @Test
+    public void testSetVpnDefaultForUids() throws Exception {
+        assumeTrue(supportedHardware());
+        assumeTrue(SdkLevel.isAtLeastU());
+
+        final Network defaultNetwork = mCM.getActiveNetwork();
+        assertNotNull("There must be a default network", defaultNetwork);
+
+        final TestableNetworkCallback defaultNetworkCallback = new TestableNetworkCallback();
+        final String session = UUID.randomUUID().toString();
+        final int myUid = Process.myUid();
+
+        testAndCleanup(() -> {
+            mCM.registerDefaultNetworkCallback(defaultNetworkCallback);
+            defaultNetworkCallback.expectAvailableCallbacks(defaultNetwork);
+
+            final Range<Integer> myUidRange = new Range<>(myUid, myUid);
+            runWithShellPermissionIdentity(() -> {
+                mCM.setVpnDefaultForUids(session, List.of(myUidRange));
+            }, NETWORK_SETTINGS);
+
+            // The VPN will be the only default network for the app, so it's expected to receive
+            // onLost() callback.
+            defaultNetworkCallback.eventuallyExpect(CallbackEntry.LOST);
+
+            final ArrayList<Network> underlyingNetworks = new ArrayList<>();
+            underlyingNetworks.add(defaultNetwork);
+            startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"} /* addresses */,
+                    new String[] {"0.0.0.0/0", "::/0"} /* routes */,
+                    "" /* allowedApplications */, "" /* disallowedApplications */,
+                    null /* proxyInfo */, underlyingNetworks, false /* isAlwaysMetered */);
+
+            expectVpnNetwork(defaultNetworkCallback);
+        }, /* cleanup */ () -> {
+                stopVpn();
+                defaultNetworkCallback.eventuallyExpect(CallbackEntry.LOST);
+            }, /* cleanup */ () -> {
+                runWithShellPermissionIdentity(() -> {
+                    mCM.setVpnDefaultForUids(session, new ArraySet<>());
+                }, NETWORK_SETTINGS);
+                // The default network of the app will be changed back to wifi when the VPN network
+                // preference feature is disabled.
+                defaultNetworkCallback.eventuallyExpect(CallbackEntry.AVAILABLE,
+                        NETWORK_CALLBACK_TIMEOUT_MS,
+                        entry -> defaultNetwork.equals(entry.getNetwork()));
+            }, /* cleanup */ () -> {
+                mCM.unregisterNetworkCallback(defaultNetworkCallback);
+            });
+    }
+
     private ByteBuffer buildIpv4UdpPacket(final Inet4Address dstAddr, final Inet4Address srcAddr,
             final short dstPort, final short srcPort, final byte[] payload) throws IOException {
 
@@ -1756,7 +1814,7 @@
     }
 
     private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
-        public void expectAvailableCallbacks(Network network) {
+        public void expectAvailableCallbacksWithBlockedReasonNone(Network network) {
             super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
                     BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
         }
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
index 4d90a4a..10a2821 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -120,4 +120,8 @@
     public void testBlockIncomingPackets() throws Exception {
         runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testBlockIncomingPackets");
     }
+
+    public void testSetVpnDefaultForUids() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetVpnDefaultForUids");
+    }
 }
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 7624f9c..61b597a 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -233,6 +233,7 @@
 import java.util.Objects;
 import java.util.Random;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
@@ -2378,7 +2379,7 @@
     }
 
     private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
-        public void expectAvailableCallbacks(Network network) {
+        public void expectAvailableCallbacksWithBlockedReasonNone(Network network) {
             super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
                     BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
         }
@@ -2390,7 +2391,7 @@
             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
         }
         private void assertNoBlockedStatusCallback() {
-            super.assertNoCallbackThat(NO_CALLBACK_TIMEOUT_MS,
+            super.assertNoCallback(NO_CALLBACK_TIMEOUT_MS,
                     c -> c instanceof CallbackEntry.BlockedStatus);
         }
     }
@@ -2431,7 +2432,7 @@
         final List<DetailedBlockedStatusCallback> allCallbacks =
                 List.of(myUidCallback, otherUidCallback);
         for (DetailedBlockedStatusCallback callback : allCallbacks) {
-            callback.expectAvailableCallbacks(defaultNetwork);
+            callback.expectAvailableCallbacksWithBlockedReasonNone(defaultNetwork);
         }
 
         final Range<Integer> myUidRange = new Range<>(myUid, myUid);
@@ -2469,6 +2470,17 @@
         runWithShellPermissionIdentity(() -> doTestBlockedStatusCallback(), NETWORK_SETTINGS);
     }
 
+    @Test
+    public void testSetVpnDefaultForUids() {
+        assumeTrue(TestUtils.shouldTestUApis());
+        final String session = UUID.randomUUID().toString();
+        assertThrows(NullPointerException.class, () -> mCm.setVpnDefaultForUids(session, null));
+        assertThrows(SecurityException.class,
+                () -> mCm.setVpnDefaultForUids(session, new ArraySet<>()));
+        // For testing the complete behavior of setVpnDefaultForUids(), please refer to
+        // HostsideVpnTests.
+    }
+
     private void doTestLegacyLockdownEnabled() throws Exception {
         NetworkInfo info = mCm.getActiveNetworkInfo();
         assertNotNull(info);
@@ -2967,7 +2979,7 @@
             defaultCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
                     entry -> cellNetwork.equals(entry.getNetwork()));
             // The network should not validate again.
-            wifiCb.assertNoCallbackThat(NO_CALLBACK_TIMEOUT_MS, c -> isValidatedCaps(c));
+            wifiCb.assertNoCallback(NO_CALLBACK_TIMEOUT_MS, c -> isValidatedCaps(c));
         } finally {
             resetAvoidBadWifi(previousAvoidBadWifi);
             mHttpServer.stop();
@@ -3139,7 +3151,7 @@
      */
     private void assertNoCallbackExceptCapOrLpChange(
             @NonNull final TestableNetworkCallback cb) {
-        cb.assertNoCallbackThat(NO_CALLBACK_TIMEOUT_MS,
+        cb.assertNoCallback(NO_CALLBACK_TIMEOUT_MS,
                 c -> !(c instanceof CallbackEntry.CapabilitiesChanged
                         || c instanceof CallbackEntry.LinkPropertiesChanged));
     }
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index 7e91478..b924f65 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -57,8 +57,8 @@
 import android.os.Handler
 import android.os.Looper
 import android.os.OutcomeReceiver
-import android.os.SystemProperties
 import android.os.Process
+import android.os.SystemProperties
 import android.platform.test.annotations.AppModeFull
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.net.module.util.ArrayTrackRecord
@@ -77,16 +77,10 @@
 import com.android.testutils.assertThrows
 import com.android.testutils.runAsShell
 import com.android.testutils.waitForIdle
-import org.junit.After
-import org.junit.Assume.assumeFalse
-import org.junit.Assume.assumeTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
 import java.io.IOException
 import java.net.Inet6Address
-import java.util.Random
 import java.net.Socket
+import java.util.Random
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.ExecutionException
 import java.util.concurrent.TimeUnit
@@ -99,6 +93,12 @@
 import kotlin.test.assertNull
 import kotlin.test.assertTrue
 import kotlin.test.fail
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
 
 private const val TAG = "EthernetManagerTest"
 // This timeout does not affect the test duration for passing tests. It needs to be long enough to
@@ -530,12 +530,10 @@
         eventuallyExpect(Lost::class) { n?.equals(it.network) ?: true }
 
     private fun TestableNetworkCallback.assertNeverLost(n: Network? = null) =
-        assertNoCallbackThat() {
-            it is Lost && (n?.equals(it.network) ?: true)
-        }
+        assertNoCallback { it is Lost && (n?.equals(it.network) ?: true) }
 
     private fun TestableNetworkCallback.assertNeverAvailable(n: Network? = null) =
-        assertNoCallbackThat { it is Available && (n?.equals(it.network) ?: true) }
+        assertNoCallback { it is Available && (n?.equals(it.network) ?: true) }
 
     private fun TestableNetworkCallback.expectCapabilitiesWithInterfaceName(name: String) =
         expect<CapabilitiesChanged> { it.caps.networkSpecifier == EthernetNetworkSpecifier(name) }
diff --git a/tests/cts/net/src/android/net/cts/RateLimitTest.java b/tests/cts/net/src/android/net/cts/RateLimitTest.java
index 28cec1a..36b98fc 100644
--- a/tests/cts/net/src/android/net/cts/RateLimitTest.java
+++ b/tests/cts/net/src/android/net/cts/RateLimitTest.java
@@ -301,29 +301,32 @@
     public void testIngressRateLimit_testLimit() throws Exception {
         assumeKernelSupport();
 
+        // These tests are not very precise, especially on lower-end devices.
+        // Add 30% tolerance to reduce test flakiness. Burst size is constant at 128KiB.
+        final double toleranceFactor = 1.3;
+
         // If this value is too low, this test might become flaky because of the burst value that
         // allows to send at a higher data rate for a short period of time. The faster the data rate
         // and the longer the test, the less this test will be affected.
         final long dataLimitInBytesPerSecond = 2_000_000; // 2MB/s
         long resultInBytesPerSecond = runIngressDataRateMeasurement(Duration.ofSeconds(1));
         assertGreaterThan("Failed initial test with rate limit disabled", resultInBytesPerSecond,
-                dataLimitInBytesPerSecond);
+                (long) (dataLimitInBytesPerSecond * toleranceFactor));
 
         // enable rate limit and wait until the tc filter is installed before starting the test.
         ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext,
                 dataLimitInBytesPerSecond);
         waitForTcPoliceFilterInstalled(Duration.ofSeconds(1));
 
-        resultInBytesPerSecond = runIngressDataRateMeasurement(Duration.ofSeconds(10));
-        // Add 10% tolerance to reduce test flakiness. Burst size is constant at 128KiB.
+        resultInBytesPerSecond = runIngressDataRateMeasurement(Duration.ofSeconds(15));
         assertLessThan("Failed test with rate limit enabled", resultInBytesPerSecond,
-                (long) (dataLimitInBytesPerSecond * 1.1));
+                (long) (dataLimitInBytesPerSecond * toleranceFactor));
 
         ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext, -1);
 
         resultInBytesPerSecond = runIngressDataRateMeasurement(Duration.ofSeconds(1));
         assertGreaterThan("Failed test with rate limit disabled", resultInBytesPerSecond,
-                dataLimitInBytesPerSecond);
+                (long) (dataLimitInBytesPerSecond * toleranceFactor));
     }
 
     @Test
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index aa5654a..c294e7b 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -20,8 +20,6 @@
 #include <set>
 #include <string>
 
-#include <android/api-level.h>
-#include <android-base/properties.h>
 #include <android-modules-utils/sdk_level.h>
 #include <bpf/BpfUtils.h>
 
@@ -45,7 +43,7 @@
 class BpfExistenceTest : public ::testing::Test {
 };
 
-// Part of Android R platform, but mainlined in S
+// Part of Android R platform (for 4.9+), but mainlined in S
 static const set<string> PLATFORM_ONLY_IN_R = {
     PLATFORM "map_offload_tether_ingress_map",
     PLATFORM "map_offload_tether_limit_map",
@@ -128,17 +126,18 @@
     SHARED "prog_dscpPolicy_schedcls_set_dscp_ether",
 };
 
-void addAll(set<string>* a, const set<string>& b) {
-    a->insert(b.begin(), b.end());
+static void addAll(set<string>& a, const set<string>& b) {
+    a.insert(b.begin(), b.end());
 }
 
-#define DO_EXPECT(B, V) do { \
-    if (B) addAll(expected, (V)); else addAll(unexpected, (V)); \
-} while (0)
+#define DO_EXPECT(B, V) addAll((B) ? mustExist : mustNotExist, (V))
 
-void getFileLists(set<string>* expected, set<string>* unexpected) {
-    unexpected->clear();
-    expected->clear();
+TEST_F(BpfExistenceTest, TestPrograms) {
+    // Only unconfined root is guaranteed to be able to access everything in /sys/fs/bpf.
+    ASSERT_EQ(0, getuid()) << "This test must run as root.";
+
+    set<string> mustExist;
+    set<string> mustNotExist;
 
     // We do not actually check the platform P/Q (netd) and Q (clatd) things
     // and only verify the mainline module relevant R+ offload maps & progs.
@@ -147,24 +146,23 @@
     // and not to test the platform itself, which may have been modified by vendor or oems,
     // so we should only test for the removal of stuff that was mainline'd,
     // and for the presence of mainline stuff.
-    DO_EXPECT(IsAtLeastR() && !IsAtLeastS(), PLATFORM_ONLY_IN_R);
 
+    // R can potentially run on pre-4.9 kernel non-eBPF capable devices.
+    DO_EXPECT(IsAtLeastR() && !IsAtLeastS() && isAtLeastKernelVersion(4, 9, 0), PLATFORM_ONLY_IN_R);
+
+    // S requires Linux Kernel 4.9+ and thus requires eBPF support.
     DO_EXPECT(IsAtLeastS(), MAINLINE_FOR_S_PLUS);
     DO_EXPECT(IsAtLeastS() && isAtLeastKernelVersion(5, 10, 0), MAINLINE_FOR_S_5_10_PLUS);
 
     // Nothing added or removed in SCv2.
 
+    // T still only requires Linux Kernel 4.9+.
     DO_EXPECT(IsAtLeastT(), MAINLINE_FOR_T_PLUS);
     DO_EXPECT(IsAtLeastT() && isAtLeastKernelVersion(4, 14, 0), MAINLINE_FOR_T_4_14_PLUS);
     DO_EXPECT(IsAtLeastT() && isAtLeastKernelVersion(5, 4, 0), MAINLINE_FOR_T_5_4_PLUS);
     DO_EXPECT(IsAtLeastT() && isAtLeastKernelVersion(5, 15, 0), MAINLINE_FOR_T_5_15_PLUS);
-}
 
-void checkFiles() {
-    set<string> mustExist;
-    set<string> mustNotExist;
-
-    getFileLists(&mustExist, &mustNotExist);
+    // U requires Linux Kernel 4.14+, but nothing (as yet) added or removed in U.
 
     for (const auto& file : mustExist) {
         EXPECT_EQ(0, access(file.c_str(), R_OK)) << file << " does not exist";
@@ -178,19 +176,3 @@
         }
     }
 }
-
-TEST_F(BpfExistenceTest, TestPrograms) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
-
-    // Pre-flight check to ensure test has been updated.
-    uint64_t buildVersionSdk = android_get_device_api_level();
-    ASSERT_NE(0, buildVersionSdk) << "Unable to determine device SDK version";
-    if (buildVersionSdk > __ANDROID_API_T__ && buildVersionSdk != __ANDROID_API_FUTURE__) {
-            FAIL() << "Unknown OS version " << buildVersionSdk << ", please update this test";
-    }
-
-    // Only unconfined root is guaranteed to be able to access everything in /sys/fs/bpf.
-    ASSERT_EQ(0, getuid()) << "This test must run as root.";
-
-    checkFiles();
-}
diff --git a/tests/unit/java/android/net/IpSecTransformTest.java b/tests/unit/java/android/net/IpSecTransformTest.java
index c1bd719..8bc1bbd 100644
--- a/tests/unit/java/android/net/IpSecTransformTest.java
+++ b/tests/unit/java/android/net/IpSecTransformTest.java
@@ -18,22 +18,92 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.os.Build;
+import android.test.mock.MockContext;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.IpSecService;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRunner;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.net.InetAddress;
+
 /** Unit tests for {@link IpSecTransform}. */
 @SmallTest
 @RunWith(DevSdkIgnoreRunner.class)
 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
 public class IpSecTransformTest {
+    @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
+    private static final int DROID_SPI = 0xD1201D;
+    private static final int TEST_RESOURCE_ID = 0x1234;
+
+    private static final InetAddress SRC_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.200");
+    private static final InetAddress DST_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.201");
+    private static final InetAddress SRC_ADDRESS_V6 =
+            InetAddresses.parseNumericAddress("2001:db8::200");
+    private static final InetAddress DST_ADDRESS_V6 =
+            InetAddresses.parseNumericAddress("2001:db8::201");
+
+    private MockContext mMockContext;
+    private IpSecService mMockIpSecService;
+    private IpSecManager mIpSecManager;
+
+    @Before
+    public void setUp() throws Exception {
+        mMockIpSecService = mock(IpSecService.class);
+        mIpSecManager = new IpSecManager(mock(Context.class) /* unused */, mMockIpSecService);
+
+        // Set up mMockContext since IpSecTransform needs an IpSecManager instance and a non-null
+        // package name to create transform
+        mMockContext =
+                new MockContext() {
+                    @Override
+                    public String getSystemServiceName(Class<?> serviceClass) {
+                        if (serviceClass.equals(IpSecManager.class)) {
+                            return Context.IPSEC_SERVICE;
+                        }
+                        throw new UnsupportedOperationException();
+                    }
+
+                    @Override
+                    public Object getSystemService(String name) {
+                        if (name.equals(Context.IPSEC_SERVICE)) {
+                            return mIpSecManager;
+                        }
+                        throw new UnsupportedOperationException();
+                    }
+
+                    @Override
+                    public String getOpPackageName() {
+                        return "fooPackage";
+                    }
+                };
+
+        final IpSecSpiResponse spiResp =
+                new IpSecSpiResponse(IpSecManager.Status.OK, TEST_RESOURCE_ID, DROID_SPI);
+        when(mMockIpSecService.allocateSecurityParameterIndex(any(), anyInt(), any()))
+                .thenReturn(spiResp);
+
+        final IpSecTransformResponse transformResp =
+                new IpSecTransformResponse(IpSecManager.Status.OK, TEST_RESOURCE_ID);
+        when(mMockIpSecService.createTransform(any(), any(), any())).thenReturn(transformResp);
+    }
 
     @Test
     public void testCreateTransformCopiesConfig() {
@@ -64,4 +134,34 @@
 
         assertEquals(config1, config2);
     }
+
+    private IpSecTransform buildTestTransform() throws Exception {
+        final IpSecManager.SecurityParameterIndex spi =
+                mIpSecManager.allocateSecurityParameterIndex(DST_ADDRESS);
+        return new IpSecTransform.Builder(mMockContext).buildTunnelModeTransform(SRC_ADDRESS, spi);
+    }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testStartTransformMigration() throws Exception {
+        mIpSecManager.startTunnelModeTransformMigration(
+                buildTestTransform(), SRC_ADDRESS_V6, DST_ADDRESS_V6);
+        verify(mMockIpSecService)
+                .migrateTransform(
+                        anyInt(),
+                        eq(SRC_ADDRESS_V6.getHostAddress()),
+                        eq(DST_ADDRESS_V6.getHostAddress()),
+                        any());
+    }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreAfter(Build.VERSION_CODES.TIRAMISU)
+    public void testStartTransformMigrationOnSdkBeforeU() throws Exception {
+        try {
+            mIpSecManager.startTunnelModeTransformMigration(
+                    buildTestTransform(), SRC_ADDRESS_V6, DST_ADDRESS_V6);
+            fail("Expect to fail since migration is not supported before U");
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
 }
diff --git a/tests/unit/java/android/net/NetworkTemplateTest.kt b/tests/unit/java/android/net/NetworkTemplateTest.kt
index 3cf0228..c3440c5 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -49,7 +49,6 @@
 import android.net.wifi.WifiInfo
 import android.os.Build
 import android.telephony.TelephonyManager
-import com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.DevSdkIgnoreRunner
 import com.android.testutils.assertParcelSane
@@ -448,19 +447,18 @@
 
     @Test
     fun testParcelUnparcel() {
-        val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, emptyArray<String>(),
+        val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, arrayOf(TEST_IMSI1),
                 emptyArray<String>(), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
-                TelephonyManager.NETWORK_TYPE_LTE, OEM_MANAGED_ALL,
-                SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                TelephonyManager.NETWORK_TYPE_LTE, OEM_MANAGED_ALL)
         val templateWifi = NetworkTemplate(MATCH_WIFI, null, emptyArray<String>(),
                 arrayOf(TEST_WIFI_KEY1), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, 0,
-                OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
-        val templateOem = NetworkTemplate(MATCH_MOBILE, null, emptyArray<String>(),
+                OEM_MANAGED_ALL)
+        val templateOem = NetworkTemplate(MATCH_MOBILE_WILDCARD, null, emptyArray<String>(),
                 emptyArray<String>(), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, 0,
-                OEM_MANAGED_YES, SUBSCRIBER_ID_MATCH_RULE_EXACT)
-        assertParcelSane(templateMobile, 10)
-        assertParcelSane(templateWifi, 10)
-        assertParcelSane(templateOem, 10)
+                OEM_MANAGED_YES)
+        assertParcelSane(templateMobile, 9)
+        assertParcelSane(templateWifi, 9)
+        assertParcelSane(templateOem, 9)
     }
 
     // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with
@@ -514,12 +512,10 @@
 
         val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
                 matchWifiNetworkKeys, METERED_ALL, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_YES,
-                SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_YES)
         val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
                 matchWifiNetworkKeys, METERED_ALL, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
-                SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
 
         for (identityOemManagedState in oemManagedStates) {
             val ident = buildNetworkIdentity(mockContext, buildNetworkState(networkType,
@@ -530,8 +526,7 @@
             for (templateOemManagedState in oemManagedStates) {
                 val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
                         matchWifiNetworkKeys, METERED_ALL, ROAMING_ALL,
-                        DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, templateOemManagedState,
-                        SUBSCRIBER_ID_MATCH_RULE_EXACT)
+                        DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, templateOemManagedState)
                 if (identityOemManagedState == templateOemManagedState) {
                     template.assertMatches(ident)
                 } else {
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 16f7039..51f54a4 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -64,6 +64,7 @@
 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
 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_BLOCKING;
 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;
@@ -150,6 +151,7 @@
 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM;
 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_PROFILE;
 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_VPN;
+import static com.android.server.ConnectivityService.createDeliveryGroupKeyForConnectivityAction;
 import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister;
 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister;
@@ -209,6 +211,7 @@
 import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
@@ -359,6 +362,8 @@
 import com.android.net.module.util.NetworkMonitorUtils;
 import com.android.networkstack.apishim.ConstantsShim;
 import com.android.networkstack.apishim.NetworkAgentConfigShimImpl;
+import com.android.networkstack.apishim.common.BroadcastOptionsShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
 import com.android.server.ConnectivityService.NetworkRequestInfo;
 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
@@ -573,6 +578,7 @@
     @Mock BpfNetMaps mBpfNetMaps;
     @Mock CarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
     @Mock TetheringManager mTetheringManager;
+    @Mock BroadcastOptionsShim mBroadcastOptionsShim;
 
     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
     // underlying binder calls.
@@ -820,6 +826,25 @@
             // null should not pass the test
             return null;
         }
+
+        @Override
+        public void sendStickyBroadcast(Intent intent, Bundle options) {
+            // Verify that delivery group policy APIs were used on U.
+            if (SdkLevel.isAtLeastU() && CONNECTIVITY_ACTION.equals(intent.getAction())) {
+                final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO,
+                        NetworkInfo.class);
+                try {
+                    verify(mBroadcastOptionsShim).setDeliveryGroupPolicy(
+                            eq(ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT));
+                    verify(mBroadcastOptionsShim).setDeliveryGroupMatchingKey(
+                            eq(CONNECTIVITY_ACTION),
+                            eq(createDeliveryGroupKeyForConnectivityAction(ni)));
+                } catch (UnsupportedApiLevelException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            super.sendStickyBroadcast(intent, options);
+        }
     }
 
     // This was only added in the T SDK, but this test needs to build against the R+S SDKs, too.
@@ -1058,15 +1083,30 @@
          * @param validated Indicate if network should pretend to be validated.
          */
         public void connect(boolean validated) {
-            connect(validated, true, false /* isStrictMode */);
+            connect(validated, true, false /* privateDnsProbeSent */);
         }
 
         /**
          * Transition this NetworkAgent to CONNECTED state.
+         *
          * @param validated Indicate if network should pretend to be validated.
+         *                  Note that if this is true, this method will mock the NetworkMonitor
+         *                  probes to pretend the network is invalid after it validated once,
+         *                  so that subsequent attempts (with mNetworkMonitor.forceReevaluation)
+         *                  will fail unless setNetworkValid is called again manually.
          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
+         * @param privateDnsProbeSent whether the private DNS probe should be considered to have
+         *                            been sent, assuming |validated| is true.
+         *                            If |validated| is false, |privateDnsProbeSent| is not used.
+         *                            If |validated| is true and |privateDnsProbeSent| is false,
+         *                            the probe has not been sent.
+         *                            If |validated| is true and |privateDnsProbeSent| is true,
+         *                            the probe has been sent and has succeeded. When the NM probes
+         *                            are mocked to be invalid, private DNS is the reason this
+         *                            network is invalid ; see @param |validated|.
          */
-        public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
+        public void connect(boolean validated, boolean hasInternet,
+                boolean privateDnsProbeSent) {
             final ConditionVariable validatedCv = new ConditionVariable();
             final ConditionVariable capsChangedCv = new ConditionVariable();
             final NetworkRequest request = new NetworkRequest.Builder()
@@ -1074,7 +1114,7 @@
                     .clearCapabilities()
                     .build();
             if (validated) {
-                setNetworkValid(isStrictMode);
+                setNetworkValid(privateDnsProbeSent);
             }
             final NetworkCallback callback = new NetworkCallback() {
                 public void onCapabilitiesChanged(Network network,
@@ -1099,14 +1139,15 @@
             if (validated) {
                 // Wait for network to validate.
                 waitFor(validatedCv);
-                setNetworkInvalid(isStrictMode);
+                setNetworkInvalid(privateDnsProbeSent);
             }
             mCm.unregisterNetworkCallback(callback);
         }
 
-        public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
-            setNetworkPortal(redirectUrl, isStrictMode);
-            connect(false, true /* hasInternet */, isStrictMode);
+        public void connectWithCaptivePortal(String redirectUrl,
+                boolean privateDnsProbeSent) {
+            setNetworkPortal(redirectUrl, privateDnsProbeSent);
+            connect(false, true /* hasInternet */, privateDnsProbeSent);
         }
 
         public void connectWithPartialConnectivity() {
@@ -1114,16 +1155,16 @@
             connect(false);
         }
 
-        public void connectWithPartialValidConnectivity(boolean isStrictMode) {
-            setNetworkPartialValid(isStrictMode);
-            connect(false, true /* hasInternet */, isStrictMode);
+        public void connectWithPartialValidConnectivity(boolean privateDnsProbeSent) {
+            setNetworkPartialValid(privateDnsProbeSent);
+            connect(false, true /* hasInternet */, privateDnsProbeSent);
         }
 
-        void setNetworkValid(boolean isStrictMode) {
+        void setNetworkValid(boolean privateDnsProbeSent) {
             mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID;
             mNmValidationRedirectUrl = null;
             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS;
-            if (isStrictMode) {
+            if (privateDnsProbeSent) {
                 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
             }
             // The probesCompleted equals to probesSucceeded for the case of valid network, so put
@@ -1131,15 +1172,16 @@
             setProbesStatus(probesSucceeded, probesSucceeded);
         }
 
-        void setNetworkInvalid(boolean isStrictMode) {
+        void setNetworkInvalid(boolean invalidBecauseOfPrivateDns) {
             mNmValidationResult = VALIDATION_RESULT_INVALID;
             mNmValidationRedirectUrl = null;
             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
                     | NETWORK_VALIDATION_PROBE_HTTP;
             int probesSucceeded = 0;
-            // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
-            // tried to validate the private DNS but failed.
-            if (isStrictMode) {
+            // If |invalidBecauseOfPrivateDns| is true, it means the network is invalid because
+            // NetworkMonitor tried to validate the private DNS but failed. Therefore it
+            // didn't get a chance to try the HTTP probe.
+            if (invalidBecauseOfPrivateDns) {
                 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
                 probesSucceeded = probesCompleted;
                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
@@ -1147,14 +1189,14 @@
             setProbesStatus(probesCompleted, probesSucceeded);
         }
 
-        void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
-            setNetworkInvalid(isStrictMode);
+        void setNetworkPortal(String redirectUrl, boolean privateDnsProbeSent) {
+            setNetworkInvalid(privateDnsProbeSent);
             mNmValidationRedirectUrl = redirectUrl;
             // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
             // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
             int probesSucceeded = VALIDATION_RESULT_INVALID;
-            if (isStrictMode) {
+            if (privateDnsProbeSent) {
                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
             }
             setProbesStatus(probesCompleted, probesSucceeded);
@@ -1169,7 +1211,7 @@
             setProbesStatus(probesCompleted, probesSucceeded);
         }
 
-        void setNetworkPartialValid(boolean isStrictMode) {
+        void setNetworkPartialValid(boolean privateDnsProbeSent) {
             setNetworkPartial();
             mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
             mNmValidationRedirectUrl = null;
@@ -1178,7 +1220,7 @@
             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
             // Assume the partial network cannot pass the private DNS validation as well, so only
             // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
-            if (isStrictMode) {
+            if (privateDnsProbeSent) {
                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
             }
             setProbesStatus(probesCompleted, probesSucceeded);
@@ -1473,8 +1515,9 @@
             registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
         }
 
-        private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
-            mMockNetworkAgent.connect(validated, hasInternet, isStrictMode);
+        private void connect(boolean validated, boolean hasInternet,
+                boolean privateDnsProbeSent) {
+            mMockNetworkAgent.connect(validated, hasInternet, privateDnsProbeSent);
         }
 
         private void connect(boolean validated) {
@@ -1491,10 +1534,10 @@
         }
 
         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
-                boolean hasInternet, boolean isStrictMode) throws Exception {
+                boolean hasInternet, boolean privateDnsProbeSent) throws Exception {
             setOwnerAndAdminUid(uid);
             registerAgent(false, ranges, lp);
-            connect(validated, hasInternet, isStrictMode);
+            connect(validated, hasInternet, privateDnsProbeSent);
             waitForIdle();
         }
 
@@ -1507,11 +1550,11 @@
             establish(lp, uid, uidRangesForUids(uid), true, true, false);
         }
 
-        public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
-                throws Exception {
+        public void establishForMyUid(boolean validated, boolean hasInternet,
+                boolean privateDnsProbeSent) throws Exception {
             final int uid = Process.myUid();
             establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet,
-                    isStrictMode);
+                    privateDnsProbeSent);
         }
 
         public void establishForMyUid() throws Exception {
@@ -2034,6 +2077,12 @@
             assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
             mActiveRateLimit.put(iface, -1L);
         }
+
+        @Override
+        public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
+            reset(mBroadcastOptionsShim);
+            return mBroadcastOptionsShim;
+        }
     }
 
     private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
@@ -2757,7 +2806,8 @@
             // for any other request.
             generalCb.expectLosing(net2);
             net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS);
-            generalCb.assertNoCallback();
+            // Timeout 0 because after a while LOST will actually arrive
+            generalCb.assertNoCallback(0 /* timeoutMs */);
             net2.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
         } else {
             net2.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
@@ -2957,14 +3007,12 @@
      */
     private class TestNetworkCallback extends TestableNetworkCallback {
         TestNetworkCallback() {
-            super(TEST_CALLBACK_TIMEOUT_MS);
-        }
-
-        @Override
-        public void assertNoCallback() {
-            // TODO: better support this use case in TestableNetworkCallback
-            waitForIdle();
-            assertNoCallback(0 /* timeout */);
+            // In the context of this test, the testable network callbacks should use waitForIdle
+            // before calling assertNoCallback in an effort to detect issues where a callback is
+            // not yet sent but a message currently in the queue of a handler will cause it to
+            // be sent soon.
+            super(TEST_CALLBACK_TIMEOUT_MS, TEST_CALLBACK_TIMEOUT_MS,
+                    ConnectivityServiceTest.this::waitForIdle);
         }
 
         public CallbackEntry.Losing expectLosing(final HasNetwork n, final long timeoutMs) {
@@ -2990,9 +3038,15 @@
 
     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
     // only be declared in a static or top level type".
+    static void assertNoCallbacks(final long timeoutMs, TestNetworkCallback ... callbacks) {
+        for (TestNetworkCallback c : callbacks) {
+            c.assertNoCallback(timeoutMs);
+        }
+    }
+
     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
         for (TestNetworkCallback c : callbacks) {
-            c.assertNoCallback();
+            c.assertNoCallback(); // each callback uses its own timeout
         }
     }
 
@@ -3128,7 +3182,10 @@
         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
         cellNetworkCallback.expectLosing(mCellNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
+        // Cell will disconnect after the lingering period. Before that elapses check that
+        // there have been no callbacks.
+        assertNoCallbacks(0 /* timeoutMs */,
+                genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
         mWiFiNetworkAgent.disconnect();
         genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -3439,7 +3496,7 @@
         callback.expectLosing(mCellNetworkAgent);
 
         // Let linger run its course.
-        callback.assertNoCallback();
+        callback.assertNoCallback(0 /* timeoutMs */);
         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
         callback.expect(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
 
@@ -4219,7 +4276,7 @@
 
         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
         // probe.
-        mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
         // If the user chooses yes to use this partial connectivity wifi, switch the default
         // network to wifi and check if wifi becomes valid or not.
         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
@@ -4306,7 +4363,7 @@
         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
         expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
 
-        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkValid(false /* privateDnsProbeSent */);
 
         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
         // validated.
@@ -4324,7 +4381,8 @@
         // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
         // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
         // notifyNetworkConnected.
-        mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
+        mWiFiNetworkAgent.connectWithPartialValidConnectivity(
+                false /* privateDnsProbeSent */);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
         callback.expectLosing(mCellNetworkAgent);
@@ -4353,7 +4411,8 @@
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String redirectUrl = "http://android.com/path";
-        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
+        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl,
+                false /* privateDnsProbeSent */);
         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
 
@@ -4378,7 +4437,7 @@
                 && !nc.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
 
         // Report partial connectivity is accepted.
-        mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
                 false /* always */);
         waitForIdle();
@@ -4408,7 +4467,8 @@
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String firstRedirectUrl = "http://example.com/firstPath";
-        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
+        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl,
+                false /* privateDnsProbeSent */);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
 
@@ -4421,13 +4481,14 @@
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String secondRedirectUrl = "http://example.com/secondPath";
-        mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
+        mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl,
+                false /* privateDnsProbeSent */);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
 
         // Make captive portal disappear then revalidate.
         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
-        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkValid(false /* privateDnsProbeSent */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
         captivePortalCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
 
@@ -4436,7 +4497,7 @@
 
         // Break network connectivity.
         // Expect NET_CAPABILITY_VALIDATED onLost callback.
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
         validatedCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
     }
@@ -4488,7 +4549,8 @@
         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
 
         // Turn into a captive portal.
-        mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkPortal("http://example.com",
+                false /* privateDnsProbeSent */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         validatedCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -4501,7 +4563,7 @@
         startCaptivePortalApp(mWiFiNetworkAgent);
 
         // Report that the captive portal is dismissed, and check that callbacks are fired
-        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkValid(false /* privateDnsProbeSent */);
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
         captivePortalCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -4559,7 +4621,8 @@
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String firstRedirectUrl = "http://example.com/firstPath";
 
-        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
+        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl,
+                false /* privateDnsProbeSent */);
         mWiFiNetworkAgent.expectDisconnected();
         mWiFiNetworkAgent.expectPreventReconnectReceived();
 
@@ -4578,7 +4641,8 @@
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         final String redirectUrl = "http://example.com/firstPath";
 
-        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
+        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl,
+                false /* privateDnsProbeSent */);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
 
         final CaptivePortalData testData = new CaptivePortalData.Builder()
@@ -4611,7 +4675,8 @@
 
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
 
-        mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false /* isStrictMode */);
+        mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL,
+                false /* privateDnsProbeSent */);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         return captivePortalCallback;
     }
@@ -5812,7 +5877,7 @@
         wifiCallback.assertNoCallback();
 
         // Wifi validates. Cell is no longer needed, because it's outscored.
-        mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkValid(true /* privateDnsProbeSent */);
         // Have CS reconsider the network (see testPartialConnectivity)
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
         wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
@@ -5820,7 +5885,7 @@
         wifiCallback.assertNoCallback();
 
         // Wifi is no longer validated. Cell is needed again.
-        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
         wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         cellCallback.expectOnNetworkNeeded(defaultCaps);
@@ -5842,7 +5907,7 @@
         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         cellCallback.assertNoCallback();
         wifiCallback.assertNoCallback();
-        mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkValid(true /* privateDnsProbeSent */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
         wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         cellCallback.expectOnNetworkUnneeded(defaultCaps);
@@ -5850,7 +5915,7 @@
 
         // Wifi loses validation. Because the device doesn't avoid bad wifis, cell is
         // not needed.
-        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
         wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         cellCallback.assertNoCallback();
@@ -5870,7 +5935,7 @@
                 .clearCapabilities()
                 .addTransportType(TRANSPORT_WIFI)
                 .build();
-        final TestableNetworkCallback wifiCallback = new TestableNetworkCallback();
+        final TestNetworkCallback wifiCallback = new TestNetworkCallback();
         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
 
         // Bring up validated cell and unvalidated wifi.
@@ -5945,7 +6010,7 @@
         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
 
         // Fail validation on wifi.
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         validatedWifiCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -5996,7 +6061,7 @@
         wifiNetwork = mWiFiNetworkAgent.getNetwork();
 
         // Fail validation on wifi and expect the dialog to appear.
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         validatedWifiCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -7155,7 +7220,7 @@
         mCm.registerNetworkCallback(request, callback);
 
         // Bring up wifi aware network.
-        wifiAware.connect(false, false, false /* isStrictMode */);
+        wifiAware.connect(false, false, false /* privateDnsProbeSent */);
         callback.expectAvailableCallbacksUnvalidated(wifiAware);
 
         assertNull(mCm.getActiveNetworkInfo());
@@ -7733,7 +7798,7 @@
         mWiFiNetworkAgent.connect(false);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         // Private DNS resolution failed, checking if the notification will be shown or not.
-        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
         // If network validation failed, NetworkMonitor will re-evaluate the network.
@@ -7745,14 +7810,14 @@
                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
         // shown.
-        mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkValid(true /* privateDnsProbeSent */);
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
         // shown again.
-        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
@@ -8214,7 +8279,7 @@
 
         // Connect a VPN.
         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
 
         // Connect cellular data.
@@ -8370,7 +8435,7 @@
                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
                         .isVpnValidationRequired(),
                 mMockVpn.getAgent().getNetworkCapabilities()));
-        mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
+        mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
 
         mMockVpn.connect(false);
 
@@ -8453,7 +8518,7 @@
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         defaultCallback.assertNoCallback();
@@ -8479,7 +8544,7 @@
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
@@ -8505,7 +8570,7 @@
 
         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         // Even though the VPN is unvalidated, it becomes the default network for our app.
@@ -8527,7 +8592,7 @@
                 mMockVpn.getAgent().getNetworkCapabilities()));
 
         // Pretend that the VPN network validates.
-        mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
+        mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
         mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
         // Expect to see the validated capability, but no other changes, because the VPN is already
         // the default network for the app.
@@ -8558,7 +8623,7 @@
         mCellNetworkAgent.connect(true);
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
@@ -8602,7 +8667,7 @@
         vpnNetworkCallback.assertNoCallback();
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
@@ -8767,7 +8832,7 @@
         vpnNetworkCallback.assertNoCallback();
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
@@ -10402,6 +10467,7 @@
         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_CELLULAR)));
         verify(mMockNetd).networkDestroy(cellNetId);
+        verify(mMockNetd).setNetworkAllowlist(any());
         verifyNoMoreInteractions(mMockNetd);
         verifyNoMoreInteractions(mClatCoordinator);
         reset(mMockNetd);
@@ -10442,13 +10508,14 @@
         verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_CELLULAR)));
         verify(mMockNetd).networkDestroy(cellNetId);
+        verify(mMockNetd).setNetworkAllowlist(any());
         verifyNoMoreInteractions(mMockNetd);
         verifyNoMoreInteractions(mClatCoordinator);
 
         mCm.unregisterNetworkCallback(networkCallback);
     }
 
-    private void expectNat64PrefixChange(TestableNetworkCallback callback,
+    private void expectNat64PrefixChange(TestNetworkCallback callback,
             TestNetworkAgentWrapper agent, IpPrefix prefix) {
         callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix));
     }
@@ -12312,7 +12379,8 @@
         b1.expectNoBroadcast(500);
 
         final ExpectedBroadcast b2 = registerPacProxyBroadcast();
-        mMockVpn.connect(true /* validated */, true /* hasInternet */, false /* isStrictMode */);
+        mMockVpn.connect(true /* validated */, true /* hasInternet */,
+                false /* privateDnsProbeSent */);
         waitForIdle();
         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
         // Vpn is connected with proxy, so the proxy broadcast will be sent to inform the apps to
@@ -14810,7 +14878,7 @@
 
         // Make sure changes to the work agent send callbacks to the app in the work profile, but
         // not to the other apps.
-        workAgent.setNetworkValid(true /* isStrictMode */);
+        workAgent.setNetworkValid(true /* privateDnsProbeSent */);
         workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent,
                 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)
@@ -14923,7 +14991,7 @@
                 workAgent2.getNetwork().netId,
                 uidRangeFor(testHandle, profileNetworkPreference), PREFERENCE_ORDER_PROFILE));
 
-        workAgent2.setNetworkValid(true /* isStrictMode */);
+        workAgent2.setNetworkValid(true /* privateDnsProbeSent */);
         workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
         profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2,
                 nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
@@ -15752,6 +15820,171 @@
                 PREFERENCE_ORDER_PROFILE));
     }
 
+    @Test
+    public void testProfileNetworkPreferenceBlocking_changePreference() throws Exception {
+        final InOrder inOrder = inOrder(mMockNetd);
+        final UserHandle testHandle = setupEnterpriseNetwork();
+        doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
+                .when(mUserManager).getUserHandles(anyBoolean());
+
+        // Start with 1 default network and 1 enterprise network, both networks should
+        // not be restricted since the blocking preference is not set yet.
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(true);
+
+        // Verify uid ranges 0~99999, 200000~299999 are all allowed for cellular.
+        final UidRange profileUidRange =
+                UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
+        ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
+        allowedAllUidRanges.add(PRIMARY_UIDRANGE);
+        allowedAllUidRanges.add(profileUidRange);
+        final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
+                allowedAllUidRanges);
+        final NativeUidRangeConfig cellAllAllowedConfig = new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                allowAllUidRangesParcel,
+                0 /* subPriority */);
+        inOrder.verify(mMockNetd).setNetworkAllowlist(
+                new NativeUidRangeConfig[]{cellAllAllowedConfig});
+
+        // Verify the same uid ranges are also applied for enterprise network.
+        final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
+                NET_ENTERPRISE_ID_1);
+        enterpriseAgent.connect(true);
+        final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
+                enterpriseAgent.getNetwork().netId,
+                allowAllUidRangesParcel,
+                0 /* subPriority */);
+        // Network agents are stored in an ArraySet which does not guarantee the order and
+        // making the order of the list undeterministic. Thus, verify this in order insensitive way.
+        final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
+                NativeUidRangeConfig[].class);
+        inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+        assertContainsAll(List.of(configsCaptor.getValue()),
+                List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+
+        // Setup profile preference which only applies to test app uid on the managed profile.
+        ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
+        prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
+                .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
+                .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
+        final TestOnCompleteListener listener = new TestOnCompleteListener();
+        mCm.setProfileNetworkPreferences(testHandle,
+                List.of(prefBuilder.build()),
+                r -> r.run(), listener);
+        listener.expectOnComplete();
+
+        // Verify Netd is called for the preferences changed.
+        // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
+        // Enterprise: 0~99999, 200000~299999
+        final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
+        excludeAppRanges.add(PRIMARY_UIDRANGE);
+        excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
+                profileUidRange,
+                new ArraySet(new UidRange[]{
+                        (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
+        ));
+        final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
+        final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                excludeAppRangesParcel,
+                0 /* subPriority */);
+        inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+        assertContainsAll(List.of(configsCaptor.getValue()),
+                List.of(cellExcludeAppConfig, enterpriseAllAllowedConfig));
+
+        // Verify unset by giving all allowed set for all users when the preference got removed.
+        mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+                r -> r.run(), listener);
+        listener.expectOnComplete();
+        inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+        assertContainsAll(List.of(configsCaptor.getValue()),
+                List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+
+        // Verify issuing with cellular set only when a network with enterprise capability
+        // disconnects.
+        enterpriseAgent.disconnect();
+        waitForIdle();
+        inOrder.verify(mMockNetd).setNetworkAllowlist(
+                new NativeUidRangeConfig[]{cellAllAllowedConfig});
+    }
+
+    @Test
+    public void testProfileNetworkPreferenceBlocking_networkChanges() throws Exception {
+        final InOrder inOrder = inOrder(mMockNetd);
+        final UserHandle testHandle = setupEnterpriseNetwork();
+        doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
+                .when(mUserManager).getUserHandles(anyBoolean());
+
+        // Setup profile preference which only applies to test app uid on the managed profile.
+        ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
+        prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
+                .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
+                .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
+        final TestOnCompleteListener listener = new TestOnCompleteListener();
+        mCm.setProfileNetworkPreferences(testHandle,
+                List.of(prefBuilder.build()),
+                r -> r.run(), listener);
+        listener.expectOnComplete();
+        inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+
+        // Start with 1 default network, which should be restricted since the blocking
+        // preference is already set.
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(true);
+
+        // Verify cellular network applies to the allow list.
+        // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
+        // Enterprise: 0~99999, 200000~299999
+        final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
+        final UidRange profileUidRange =
+                UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
+        excludeAppRanges.add(PRIMARY_UIDRANGE);
+        excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
+                profileUidRange,
+                new ArraySet(new UidRange[]{
+                        (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
+        ));
+        final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
+        final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                excludeAppRangesParcel,
+                0 /* subPriority */);
+        inOrder.verify(mMockNetd).setNetworkAllowlist(
+                new NativeUidRangeConfig[]{cellExcludeAppConfig});
+
+        // Verify enterprise network is not blocked for test app.
+        final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
+                NET_ENTERPRISE_ID_1);
+        enterpriseAgent.connect(true);
+        ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
+        allowedAllUidRanges.add(PRIMARY_UIDRANGE);
+        allowedAllUidRanges.add(profileUidRange);
+        final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
+                allowedAllUidRanges);
+        final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
+                enterpriseAgent.getNetwork().netId,
+                allowAllUidRangesParcel,
+                0 /* subPriority */);
+        // Network agents are stored in an ArraySet which does not guarantee the order and
+        // making the order of the list undeterministic. Thus, verify this in order insensitive way.
+        final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
+                NativeUidRangeConfig[].class);
+        inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+        assertContainsAll(List.of(configsCaptor.getValue()),
+                List.of(enterpriseAllAllowedConfig, cellExcludeAppConfig));
+
+        // Verify issuing with cellular set only when enterprise network disconnects.
+        enterpriseAgent.disconnect();
+        waitForIdle();
+        inOrder.verify(mMockNetd).setNetworkAllowlist(
+                new NativeUidRangeConfig[]{cellExcludeAppConfig});
+
+        mCellNetworkAgent.disconnect();
+        waitForIdle();
+        inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+    }
+
     /**
      * Make sure wrong preferences for per-profile default networking are rejected.
      */
@@ -15762,7 +15995,7 @@
         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
                 new ProfileNetworkPreference.Builder();
         profileNetworkPreferenceBuilder.setPreference(
-                PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK + 1);
+                PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING + 1);
         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
         assertThrows("Should not be able to set an illegal preference",
                 IllegalArgumentException.class,
@@ -16184,7 +16417,7 @@
             final NetworkCallback[] callbacks = new NetworkCallback[remainingCount];
             doAsUid(otherAppUid, () -> {
                 for (int i = 0; i < remainingCount; ++i) {
-                    callbacks[i] = new TestableNetworkCallback();
+                    callbacks[i] = new TestNetworkCallback();
                     mCm.registerDefaultNetworkCallback(callbacks[i]);
                 }
             });
@@ -16923,7 +17156,8 @@
                     mWiFiNetworkAgent);
             mDefaultNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
                     mWiFiNetworkAgent);
-            mWiFiNetworkAgent.setNetworkPortal(TEST_REDIRECT_URL, false /* isStrictMode */);
+            mWiFiNetworkAgent.setNetworkPortal(TEST_REDIRECT_URL,
+                    false /* privateDnsProbeSent */);
             mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
             // Wi-Fi is now detected to have a portal : cell should become the default network.
             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
@@ -16933,7 +17167,7 @@
                     mWiFiNetworkAgent);
 
             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
-            mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
+            mWiFiNetworkAgent.setNetworkValid(false /* privateDnsProbeSent */);
             mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
             wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_CAPTIVE_PORTAL,
@@ -16954,7 +17188,7 @@
                     mWiFiNetworkAgent);
 
             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
-            mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
+            mWiFiNetworkAgent.setNetworkValid(false /* privateDnsProbeSent */);
             mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
             wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
@@ -16968,7 +17202,7 @@
         mWiFiNetworkAgent.setNetworkCapabilities(wifiNc2, true);
         mDefaultNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
                 mWiFiNetworkAgent);
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
+        mWiFiNetworkAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
 
         if (enabled) {
@@ -17155,7 +17389,16 @@
         mWiFiNetworkAgent.sendLinkProperties(new LinkProperties(lp2));
 
         waitForIdle();
-        // TODO(b/246398088): the MTU should be set on the new interface.
-        verify(mMockNetd, never()).interfaceSetMtu(eq(ifaceName2), eq(mtu));
+        verify(mMockNetd).interfaceSetMtu(eq(ifaceName2), eq(mtu));
+    }
+
+    @Test
+    public void testCreateDeliveryGroupKeyForConnectivityAction() throws Exception {
+        final NetworkInfo info = new NetworkInfo(0 /* type */, 2 /* subtype */,
+                "MOBILE" /* typeName */, "LTE" /* subtypeName */);
+        assertEquals("0;2;null", createDeliveryGroupKeyForConnectivityAction(info));
+
+        info.setExtraInfo("test_info");
+        assertEquals("0;2;test_info", createDeliveryGroupKeyForConnectivityAction(info));
     }
 }
diff --git a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
index 624071a..1618a62 100644
--- a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -23,6 +23,7 @@
 import static android.net.IpSecManager.DIRECTION_FWD;
 import static android.net.IpSecManager.DIRECTION_IN;
 import static android.net.IpSecManager.DIRECTION_OUT;
+import static android.net.IpSecManager.FEATURE_IPSEC_TUNNEL_MIGRATION;
 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
@@ -30,11 +31,16 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -49,6 +55,7 @@
 import android.net.IpSecAlgorithm;
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
+import android.net.IpSecMigrateInfoParcel;
 import android.net.IpSecSpiResponse;
 import android.net.IpSecTransform;
 import android.net.IpSecTransformResponse;
@@ -130,6 +137,9 @@
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
     };
 
+    private static final String NEW_SRC_ADDRESS = "2001:db8:2::1";
+    private static final String NEW_DST_ADDRESS = "2001:db8:2::2";
+
     AppOpsManager mMockAppOps = mock(AppOpsManager.class);
     ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class);
 
@@ -369,8 +379,8 @@
                 .ipSecAddSecurityAssociation(
                         eq(mUid),
                         eq(config.getMode()),
-                        eq(config.getSourceAddress()),
-                        eq(config.getDestinationAddress()),
+                        eq(mSourceAddr),
+                        eq(mDestinationAddr),
                         eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
                         eq(TEST_SPI),
                         eq(0),
@@ -910,9 +920,60 @@
         }
     }
 
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testApplyAndMigrateTunnelModeTransformOutbound() throws Exception {
+        verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_OUT);
+    }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testApplyAndMigrateTunnelModeTransformOutboundReleasedSpi() throws Exception {
+        verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_OUT);
+    }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testApplyAndMigrateTunnelModeTransformInbound() throws Exception {
+        verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_IN);
+    }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testApplyAndMigrateTunnelModeTransformInboundReleasedSpi() throws Exception {
+        verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_IN);
+    }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testApplyAndMigrateTunnelModeTransformForward() throws Exception {
+        verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_FWD);
+    }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testApplyAndMigrateTunnelModeTransformForwardReleasedSpi() throws Exception {
+        verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_FWD);
+    }
+
     public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply, int direction)
             throws Exception {
-        IpSecConfig ipSecConfig = new IpSecConfig();
+        verifyApplyTunnelModeTransformCommon(
+                new IpSecConfig(), closeSpiBeforeApply, false /* isMigrating */, direction);
+    }
+
+    public void verifyApplyAndMigrateTunnelModeTransformCommon(
+            boolean closeSpiBeforeApply, int direction) throws Exception {
+        verifyApplyTunnelModeTransformCommon(
+                new IpSecConfig(), closeSpiBeforeApply, true /* isMigrating */, direction);
+    }
+
+    public int verifyApplyTunnelModeTransformCommon(
+            IpSecConfig ipSecConfig,
+            boolean closeSpiBeforeApply,
+            boolean isMigrating,
+            int direction)
+            throws Exception {
         ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
         addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
         addAuthAndCryptToIpSecConfig(ipSecConfig);
@@ -928,6 +989,12 @@
 
         int transformResourceId = createTransformResp.resourceId;
         int tunnelResourceId = createTunnelResp.resourceId;
+
+        if (isMigrating) {
+            mIpSecService.migrateTransform(
+                    transformResourceId, NEW_SRC_ADDRESS, NEW_DST_ADDRESS, BLESSED_PACKAGE);
+        }
+
         mIpSecService.applyTunnelModeTransform(
                 tunnelResourceId, direction, transformResourceId, BLESSED_PACKAGE);
 
@@ -947,8 +1014,16 @@
 
         ipSecConfig.setXfrmInterfaceId(tunnelResourceId);
         verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
-    }
 
+        if (isMigrating) {
+            verify(mMockNetd, times(ADDRESS_FAMILIES.length))
+                    .ipSecMigrate(any(IpSecMigrateInfoParcel.class));
+        } else {
+            verify(mMockNetd, never()).ipSecMigrate(any());
+        }
+
+        return tunnelResourceId;
+    }
 
     @Test
     public void testApplyTunnelModeTransformWithClosedSpi() throws Exception {
@@ -1023,7 +1098,7 @@
     }
 
     @Test
-    public void testFeatureFlagVerification() throws Exception {
+    public void testFeatureFlagIpSecTunnelsVerification() throws Exception {
         when(mMockPkgMgr.hasSystemFeature(eq(PackageManager.FEATURE_IPSEC_TUNNELS)))
                 .thenReturn(false);
 
@@ -1035,4 +1110,17 @@
         } catch (UnsupportedOperationException expected) {
         }
     }
+
+    @Test
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testFeatureFlagIpSecTunnelMigrationVerification() throws Exception {
+        when(mMockPkgMgr.hasSystemFeature(eq(FEATURE_IPSEC_TUNNEL_MIGRATION))).thenReturn(false);
+
+        try {
+            mIpSecService.migrateTransform(
+                    1 /* transformId */, NEW_SRC_ADDRESS, NEW_DST_ADDRESS, BLESSED_PACKAGE);
+            fail("Expected UnsupportedOperationException for disabled feature");
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
 }
diff --git a/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java b/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java
index b8c552e..ad4785d 100644
--- a/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java
+++ b/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java
@@ -402,4 +402,27 @@
         expected.add(uids20_24);
         assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
     }
+
+    @Test
+    public void testSortRangesByStartUid() throws Exception {
+        final UidRange uid1 = new UidRange(100, 110);
+        final UidRange uid2 = new UidRange(120, 130);
+        final UidRange[] unsortedRanges = new UidRange[] {uid2, uid1};
+        final UidRange[] sortedRanges = UidRangeUtils.sortRangesByStartUid(unsortedRanges);
+        assertEquals(uid1, sortedRanges[0]);
+        assertEquals(uid2, sortedRanges[1]);
+    }
+
+    @Test
+    public void testSortedRangesContainOverlap() throws Exception {
+        final UidRange uid1 = new UidRange(100, 110);
+        final UidRange uid2 = new UidRange(109, 120);
+        final UidRange uid3 = new UidRange(120, 130);
+        final UidRange[] overlapRanges1 = new UidRange[] {uid1, uid2};
+        final UidRange[] overlapRanges2 = new UidRange[] {uid2, uid3};
+        final UidRange[] notOverlapRanges = new UidRange[] {uid1, uid3};
+        assertTrue(UidRangeUtils.sortedRangesContainOverlap(overlapRanges1));
+        assertTrue(UidRangeUtils.sortedRangesContainOverlap(overlapRanges2));
+        assertFalse(UidRangeUtils.sortedRangesContainOverlap(notOverlapRanges));
+    }
 }
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
new file mode 100644
index 0000000..e2babb1
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns
+
+import android.net.InetAddresses.parseNumericAddress
+import android.net.LinkAddress
+import android.net.Network
+import android.net.nsd.NsdServiceInfo
+import android.os.Build
+import android.os.Handler
+import android.os.HandlerThread
+import com.android.server.connectivity.mdns.MdnsAdvertiser.AdvertiserCallback
+import com.android.server.connectivity.mdns.MdnsSocketProvider.SocketCallback
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.waitForIdle
+import java.util.Objects
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.argThat
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+private const val SERVICE_ID_1 = 1
+private const val SERVICE_ID_2 = 2
+private const val TIMEOUT_MS = 10_000L
+private val TEST_ADDR = parseNumericAddress("2001:db8::123")
+private val TEST_LINKADDR = LinkAddress(TEST_ADDR, 64 /* prefixLength */)
+private val TEST_NETWORK_1 = mock(Network::class.java)
+private val TEST_NETWORK_2 = mock(Network::class.java)
+
+private val SERVICE_1 = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply {
+    port = 12345
+    host = TEST_ADDR
+    network = TEST_NETWORK_1
+}
+
+private val ALL_NETWORKS_SERVICE = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply {
+    port = 12345
+    host = TEST_ADDR
+    network = null
+}
+
+@RunWith(DevSdkIgnoreRunner::class)
+@IgnoreUpTo(Build.VERSION_CODES.S_V2)
+class MdnsAdvertiserTest {
+    private val thread = HandlerThread(MdnsAdvertiserTest::class.simpleName)
+    private val handler by lazy { Handler(thread.looper) }
+    private val socketProvider = mock(MdnsSocketProvider::class.java)
+    private val cb = mock(AdvertiserCallback::class.java)
+
+    private val mockSocket1 = mock(MdnsInterfaceSocket::class.java)
+    private val mockSocket2 = mock(MdnsInterfaceSocket::class.java)
+    private val mockInterfaceAdvertiser1 = mock(MdnsInterfaceAdvertiser::class.java)
+    private val mockInterfaceAdvertiser2 = mock(MdnsInterfaceAdvertiser::class.java)
+    private val mockDeps = mock(MdnsAdvertiser.Dependencies::class.java)
+
+    @Before
+    fun setUp() {
+        thread.start()
+        doReturn(mockInterfaceAdvertiser1).`when`(mockDeps).makeAdvertiser(eq(mockSocket1),
+                any(), any(), any(), any())
+        doReturn(mockInterfaceAdvertiser2).`when`(mockDeps).makeAdvertiser(eq(mockSocket2),
+                any(), any(), any(), any())
+        doReturn(true).`when`(mockInterfaceAdvertiser1).isProbing(anyInt())
+        doReturn(true).`when`(mockInterfaceAdvertiser2).isProbing(anyInt())
+    }
+
+    @After
+    fun tearDown() {
+        thread.quitSafely()
+    }
+
+    @Test
+    fun testAddService_OneNetwork() {
+        val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+        postSync { advertiser.addService(SERVICE_ID_1, SERVICE_1) }
+
+        val socketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java)
+        verify(socketProvider).requestSocket(eq(TEST_NETWORK_1), socketCbCaptor.capture())
+
+        val socketCb = socketCbCaptor.value
+        postSync { socketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR)) }
+
+        val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
+        verify(mockDeps).makeAdvertiser(eq(mockSocket1),
+                eq(listOf(TEST_LINKADDR)), eq(thread.looper), any(), intAdvCbCaptor.capture())
+
+        doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
+        postSync { intAdvCbCaptor.value.onRegisterServiceSucceeded(
+                mockInterfaceAdvertiser1, SERVICE_ID_1) }
+        verify(cb).onRegisterServiceSucceeded(eq(SERVICE_ID_1), argThat { it.matches(SERVICE_1) })
+
+        postSync { socketCb.onInterfaceDestroyed(TEST_NETWORK_1, mockSocket1) }
+        verify(mockInterfaceAdvertiser1).destroyNow()
+    }
+
+    @Test
+    fun testAddService_AllNetworks() {
+        val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+        postSync { advertiser.addService(SERVICE_ID_1, ALL_NETWORKS_SERVICE) }
+
+        val socketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java)
+        verify(socketProvider).requestSocket(eq(ALL_NETWORKS_SERVICE.network),
+                socketCbCaptor.capture())
+
+        val socketCb = socketCbCaptor.value
+        postSync { socketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR)) }
+        postSync { socketCb.onSocketCreated(TEST_NETWORK_2, mockSocket2, listOf(TEST_LINKADDR)) }
+
+        val intAdvCbCaptor1 = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
+        val intAdvCbCaptor2 = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
+        verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
+                eq(thread.looper), any(), intAdvCbCaptor1.capture())
+        verify(mockDeps).makeAdvertiser(eq(mockSocket2), eq(listOf(TEST_LINKADDR)),
+                eq(thread.looper), any(), intAdvCbCaptor2.capture())
+
+        doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
+        postSync { intAdvCbCaptor1.value.onRegisterServiceSucceeded(
+                mockInterfaceAdvertiser1, SERVICE_ID_1) }
+
+        // Need both advertisers to finish probing and call onRegisterServiceSucceeded
+        verify(cb, never()).onRegisterServiceSucceeded(anyInt(), any())
+        doReturn(false).`when`(mockInterfaceAdvertiser2).isProbing(SERVICE_ID_1)
+        postSync { intAdvCbCaptor2.value.onRegisterServiceSucceeded(
+                mockInterfaceAdvertiser2, SERVICE_ID_1) }
+        verify(cb).onRegisterServiceSucceeded(eq(SERVICE_ID_1),
+                argThat { it.matches(ALL_NETWORKS_SERVICE) })
+
+        // Unregister the service
+        postSync { advertiser.removeService(SERVICE_ID_1) }
+        verify(mockInterfaceAdvertiser1).removeService(SERVICE_ID_1)
+        verify(mockInterfaceAdvertiser2).removeService(SERVICE_ID_1)
+
+        // Interface advertisers call onDestroyed after sending exit announcements
+        postSync { intAdvCbCaptor1.value.onDestroyed(mockSocket1) }
+        verify(socketProvider, never()).unrequestSocket(any())
+        postSync { intAdvCbCaptor2.value.onDestroyed(mockSocket2) }
+        verify(socketProvider).unrequestSocket(socketCb)
+    }
+
+    private fun postSync(r: () -> Unit) {
+        handler.post(r)
+        handler.waitForIdle(TIMEOUT_MS)
+    }
+}
+
+// NsdServiceInfo does not implement equals; this is useful to use in argument matchers
+private fun NsdServiceInfo.matches(other: NsdServiceInfo): Boolean {
+    return Objects.equals(serviceName, other.serviceName) &&
+            Objects.equals(serviceType, other.serviceType) &&
+            Objects.equals(attributes, other.attributes) &&
+            Objects.equals(host, other.host) &&
+            port == other.port &&
+            Objects.equals(network, other.network)
+}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
index e9325d5..961f0f0 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
@@ -27,8 +27,6 @@
 import java.net.DatagramPacket
 import java.net.Inet6Address
 import java.net.InetAddress
-import java.net.InetSocketAddress
-import java.net.MulticastSocket
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
 import org.junit.After
@@ -38,6 +36,7 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Mockito.any
 import org.mockito.Mockito.atLeast
+import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.timeout
 import org.mockito.Mockito.verify
@@ -47,19 +46,17 @@
 private const val NEXT_ANNOUNCES_DELAY = 1L
 private const val TEST_TIMEOUT_MS = 1000L
 
-private val destinationsSupplier = {
-    listOf(InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT)) }
-
 @RunWith(DevSdkIgnoreRunner::class)
 @IgnoreUpTo(Build.VERSION_CODES.S_V2)
 class MdnsAnnouncerTest {
 
     private val thread = HandlerThread(MdnsAnnouncerTest::class.simpleName)
-    private val socket = mock(MulticastSocket::class.java)
+    private val socket = mock(MdnsInterfaceSocket::class.java)
     private val buffer = ByteArray(1500)
 
     @Before
     fun setUp() {
+        doReturn(true).`when`(socket).hasJoinedIpv6()
         thread.start()
     }
 
@@ -71,8 +68,7 @@
     private class TestAnnouncementInfo(
         announcedRecords: List<MdnsRecord>,
         additionalRecords: List<MdnsRecord>
-    )
-        : AnnouncementInfo(announcedRecords, additionalRecords, destinationsSupplier) {
+    ) : AnnouncementInfo(announcedRecords, additionalRecords) {
         override fun getDelayMs(nextIndex: Int) =
                 if (nextIndex < FIRST_ANNOUNCES_COUNT) {
                     FIRST_ANNOUNCES_DELAY
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
index 3e3c3bf..83e7696 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
@@ -46,7 +46,7 @@
     private static final String SERVICE_TYPE_2 = "_test._tcp.local";
 
     @Mock private ExecutorProvider executorProvider;
-    @Mock private MdnsSocketClient socketClient;
+    @Mock private MdnsSocketClientBase socketClient;
     @Mock private MdnsServiceTypeClient mockServiceTypeClientOne;
     @Mock private MdnsServiceTypeClient mockServiceTypeClientTwo;
 
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
new file mode 100644
index 0000000..ad22305
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.connectivity.mdns
+
+import android.net.InetAddresses.parseNumericAddress
+import android.net.LinkAddress
+import android.net.nsd.NsdServiceInfo
+import android.os.Build
+import android.os.HandlerThread
+import com.android.server.connectivity.mdns.MdnsAnnouncer.AnnouncementInfo
+import com.android.server.connectivity.mdns.MdnsInterfaceAdvertiser.EXIT_ANNOUNCEMENT_DELAY_MS
+import com.android.server.connectivity.mdns.MdnsPacketRepeater.PacketRepeaterCallback
+import com.android.server.connectivity.mdns.MdnsProber.ProbingInfo
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.waitForIdle
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+
+private const val LOG_TAG = "testlogtag"
+private const val TIMEOUT_MS = 10_000L
+
+private val TEST_ADDRS = listOf(LinkAddress(parseNumericAddress("2001:db8::123"), 64))
+private val TEST_BUFFER = ByteArray(1300)
+
+private const val TEST_SERVICE_ID_1 = 42
+private val TEST_SERVICE_1 = NsdServiceInfo().apply {
+    serviceType = "_testservice._tcp"
+    serviceName = "MyTestService"
+    port = 12345
+}
+
+@RunWith(DevSdkIgnoreRunner::class)
+@IgnoreUpTo(Build.VERSION_CODES.S_V2)
+class MdnsInterfaceAdvertiserTest {
+    private val socket = mock(MdnsInterfaceSocket::class.java)
+    private val thread = HandlerThread(MdnsInterfaceAdvertiserTest::class.simpleName)
+    private val cb = mock(MdnsInterfaceAdvertiser.Callback::class.java)
+    private val deps = mock(MdnsInterfaceAdvertiser.Dependencies::class.java)
+    private val repository = mock(MdnsRecordRepository::class.java)
+    private val replySender = mock(MdnsReplySender::class.java)
+    private val announcer = mock(MdnsAnnouncer::class.java)
+    private val prober = mock(MdnsProber::class.java)
+    private val probeCbCaptor = ArgumentCaptor.forClass(PacketRepeaterCallback::class.java)
+            as ArgumentCaptor<PacketRepeaterCallback<ProbingInfo>>
+    private val announceCbCaptor = ArgumentCaptor.forClass(PacketRepeaterCallback::class.java)
+            as ArgumentCaptor<PacketRepeaterCallback<AnnouncementInfo>>
+
+    private val probeCb get() = probeCbCaptor.value
+    private val announceCb get() = announceCbCaptor.value
+
+    private val advertiser by lazy {
+        MdnsInterfaceAdvertiser(LOG_TAG, socket, TEST_ADDRS, thread.looper, TEST_BUFFER, cb, deps)
+    }
+
+    @Before
+    fun setUp() {
+        doReturn(repository).`when`(deps).makeRecordRepository(any())
+        doReturn(replySender).`when`(deps).makeReplySender(any(), any(), any())
+        doReturn(announcer).`when`(deps).makeMdnsAnnouncer(any(), any(), any(), any())
+        doReturn(prober).`when`(deps).makeMdnsProber(any(), any(), any(), any())
+
+        doReturn(-1).`when`(repository).addService(anyInt(), any())
+        thread.start()
+        advertiser.start()
+
+        verify(deps).makeMdnsProber(any(), any(), any(), probeCbCaptor.capture())
+        verify(deps).makeMdnsAnnouncer(any(), any(), any(), announceCbCaptor.capture())
+    }
+
+    @After
+    fun tearDown() {
+        thread.quitSafely()
+    }
+
+    @Test
+    fun testAddRemoveService() {
+        val testProbingInfo = mock(ProbingInfo::class.java)
+        doReturn(TEST_SERVICE_ID_1).`when`(testProbingInfo).serviceId
+        doReturn(testProbingInfo).`when`(repository).setServiceProbing(TEST_SERVICE_ID_1)
+
+        advertiser.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        verify(repository).addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        verify(prober).startProbing(testProbingInfo)
+
+        // Simulate probing success: continues to announcing
+        val testAnnouncementInfo = mock(AnnouncementInfo::class.java)
+        doReturn(testAnnouncementInfo).`when`(repository).onProbingSucceeded(testProbingInfo)
+        probeCb.onFinished(testProbingInfo)
+
+        verify(announcer).startSending(TEST_SERVICE_ID_1, testAnnouncementInfo,
+                0L /* initialDelayMs */)
+
+        thread.waitForIdle(TIMEOUT_MS)
+        verify(cb).onRegisterServiceSucceeded(advertiser, TEST_SERVICE_ID_1)
+
+        // Remove the service: expect exit announcements
+        val testExitInfo = mock(AnnouncementInfo::class.java)
+        doReturn(testExitInfo).`when`(repository).exitService(TEST_SERVICE_ID_1)
+        advertiser.removeService(TEST_SERVICE_ID_1)
+
+        verify(announcer).startSending(TEST_SERVICE_ID_1, testExitInfo, EXIT_ANNOUNCEMENT_DELAY_MS)
+
+        // TODO: after exit announcements are implemented, verify that announceCb.onFinished causes
+        // cb.onDestroyed to be called.
+    }
+}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
new file mode 100644
index 0000000..9d42a65
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns;
+
+import static com.android.server.connectivity.mdns.MdnsSocketProvider.SocketCallback;
+import static com.android.server.connectivity.mdns.MulticastPacketReader.PacketHandler;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.net.InetAddresses;
+import android.net.Network;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import com.android.net.module.util.HexDump;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+import com.android.testutils.HandlerUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.DatagramPacket;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.List;
+
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
+public class MdnsMultinetworkSocketClientTest {
+    private static final byte[] BUFFER = new byte[10];
+    private static final long DEFAULT_TIMEOUT = 2000L;
+    @Mock private Network mNetwork;
+    @Mock private MdnsSocketProvider mProvider;
+    @Mock private MdnsInterfaceSocket mSocket;
+    @Mock private MdnsServiceBrowserListener mListener;
+    @Mock private MdnsSocketClientBase.Callback mCallback;
+    private MdnsMultinetworkSocketClient mSocketClient;
+    private Handler mHandler;
+
+    @Before
+    public void setUp() throws SocketException {
+        MockitoAnnotations.initMocks(this);
+        final HandlerThread thread = new HandlerThread("MdnsMultinetworkSocketClientTest");
+        thread.start();
+        mHandler = new Handler(thread.getLooper());
+        mSocketClient = new MdnsMultinetworkSocketClient(thread.getLooper(), mProvider);
+        mHandler.post(() -> mSocketClient.setCallback(mCallback));
+    }
+
+    private SocketCallback expectSocketCallback() {
+        final ArgumentCaptor<SocketCallback> callbackCaptor =
+                ArgumentCaptor.forClass(SocketCallback.class);
+        mHandler.post(() -> mSocketClient.notifyNetworkRequested(mListener, mNetwork));
+        verify(mProvider, timeout(DEFAULT_TIMEOUT))
+                .requestSocket(eq(mNetwork), callbackCaptor.capture());
+        return callbackCaptor.getValue();
+    }
+
+    private NetworkInterface createEmptyNetworkInterface() {
+        try {
+            Constructor<NetworkInterface> constructor =
+                    NetworkInterface.class.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            return constructor.newInstance();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testSendPacket() throws IOException {
+        final SocketCallback callback = expectSocketCallback();
+        final DatagramPacket ipv4Packet = new DatagramPacket(BUFFER, 0 /* offset */, BUFFER.length,
+                InetAddresses.parseNumericAddress("192.0.2.1"), 0 /* port */);
+        final DatagramPacket ipv6Packet = new DatagramPacket(BUFFER, 0 /* offset */, BUFFER.length,
+                InetAddresses.parseNumericAddress("2001:db8::"), 0 /* port */);
+        doReturn(true).when(mSocket).hasJoinedIpv4();
+        doReturn(true).when(mSocket).hasJoinedIpv6();
+        doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
+        // Notify socket created
+        callback.onSocketCreated(mNetwork, mSocket, List.of());
+
+        // Send packet to IPv4 with target network and verify sending has been called.
+        mSocketClient.sendMulticastPacket(ipv4Packet, mNetwork);
+        HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+        verify(mSocket).send(ipv4Packet);
+
+        // Send packet to IPv6 without target network and verify sending has been called.
+        mSocketClient.sendMulticastPacket(ipv6Packet);
+        HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+        verify(mSocket).send(ipv6Packet);
+    }
+
+    @Test
+    public void testReceivePacket() {
+        final SocketCallback callback = expectSocketCallback();
+        final byte[] data = HexDump.hexStringToByteArray(
+                // scapy.raw(scapy.dns_compress(
+                //     scapy.DNS(rd=0, qr=1, aa=1, qd = None,
+                //     an =
+                //     scapy.DNSRR(type='PTR', rrname='_testtype._tcp.local',
+                //         rdata='testservice._testtype._tcp.local', rclass='IN', ttl=4500) /
+                //     scapy.DNSRRSRV(rrname='testservice._testtype._tcp.local', rclass=0x8001,
+                //         port=31234, target='Android.local', ttl=120))
+                // )).hex().upper()
+                "000084000000000200000000095F7465737474797065045F746370056C6F63616C00000C0001000011"
+                        + "94000E0B7465737473657276696365C00CC02C00218001000000780010000000007A0207"
+                        + "416E64726F6964C01B");
+
+        doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
+        // Notify socket created
+        callback.onSocketCreated(mNetwork, mSocket, List.of());
+
+        final ArgumentCaptor<PacketHandler> handlerCaptor =
+                ArgumentCaptor.forClass(PacketHandler.class);
+        verify(mSocket).addPacketHandler(handlerCaptor.capture());
+
+        // Send the data and verify the received records.
+        final PacketHandler handler = handlerCaptor.getValue();
+        handler.handlePacket(data, data.length, null /* src */);
+        final ArgumentCaptor<MdnsResponse> responseCaptor =
+                ArgumentCaptor.forClass(MdnsResponse.class);
+        verify(mCallback).onResponseReceived(responseCaptor.capture());
+        final MdnsResponse response = responseCaptor.getValue();
+        assertTrue(response.hasPointerRecords());
+        assertArrayEquals("_testtype._tcp.local".split("\\."),
+                response.getPointerRecords().get(0).getName());
+        assertTrue(response.hasServiceRecord());
+        assertEquals("testservice", response.getServiceRecord().getServiceInstanceName());
+        assertEquals("Android.local".split("\\."),
+                response.getServiceRecord().getServiceHost());
+    }
+}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt
index 419121c..3caa97d 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt
@@ -25,8 +25,6 @@
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
 import com.android.testutils.DevSdkIgnoreRunner
 import java.net.DatagramPacket
-import java.net.InetSocketAddress
-import java.net.MulticastSocket
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.TimeUnit
 import kotlin.test.assertEquals
@@ -38,15 +36,13 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Mockito.any
 import org.mockito.Mockito.atLeast
+import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.timeout
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 
-private val destinationsSupplier = {
-    listOf(InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT)) }
-
 private const val TEST_TIMEOUT_MS = 10_000L
 private const val SHORT_TIMEOUT_MS = 200L
 
@@ -57,7 +53,7 @@
 @IgnoreUpTo(Build.VERSION_CODES.S_V2)
 class MdnsProberTest {
     private val thread = HandlerThread(MdnsProberTest::class.simpleName)
-    private val socket = mock(MulticastSocket::class.java)
+    private val socket = mock(MdnsInterfaceSocket::class.java)
     @Suppress("UNCHECKED_CAST")
     private val cb = mock(MdnsPacketRepeater.PacketRepeaterCallback::class.java)
         as MdnsPacketRepeater.PacketRepeaterCallback<ProbingInfo>
@@ -65,6 +61,7 @@
 
     @Before
     fun setUp() {
+        doReturn(true).`when`(socket).hasJoinedIpv6()
         thread.start()
     }
 
@@ -74,7 +71,7 @@
     }
 
     private class TestProbeInfo(probeRecords: List<MdnsRecord>, private val delayMs: Long = 1L) :
-            ProbingInfo(1 /* serviceId */, probeRecords, destinationsSupplier) {
+            ProbingInfo(1 /* serviceId */, probeRecords) {
         // Just send the packets quickly. Timing-related tests for MdnsPacketRepeater are already
         // done in MdnsAnnouncerTest.
         override fun getDelayMs(nextIndex: Int) = delayMs
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
new file mode 100644
index 0000000..502a36a
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.mdns
+
+import android.net.InetAddresses.parseNumericAddress
+import android.net.nsd.NsdServiceInfo
+import android.os.Build
+import android.os.HandlerThread
+import com.android.server.connectivity.mdns.MdnsRecordRepository.Dependencies
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import java.net.NetworkInterface
+import java.util.Collections
+import kotlin.test.assertContentEquals
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import kotlin.test.assertNotNull
+import kotlin.test.assertTrue
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val TEST_SERVICE_ID_1 = 42
+private const val TEST_SERVICE_ID_2 = 43
+private const val TEST_PORT = 12345
+private val TEST_HOSTNAME = arrayOf("Android_000102030405060708090A0B0C0D0E0F", "local")
+private val TEST_ADDRESSES = arrayOf(
+        parseNumericAddress("192.0.2.111"),
+        parseNumericAddress("2001:db8::111"),
+        parseNumericAddress("2001:db8::222"))
+
+private val TEST_SERVICE_1 = NsdServiceInfo().apply {
+    serviceType = "_testservice._tcp"
+    serviceName = "MyTestService"
+    port = TEST_PORT
+}
+
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
+class MdnsRecordRepositoryTest {
+    private val thread = HandlerThread(MdnsRecordRepositoryTest::class.simpleName)
+    private val deps = object : Dependencies() {
+        override fun getHostname() = TEST_HOSTNAME
+        override fun getInterfaceInetAddresses(iface: NetworkInterface) =
+                Collections.enumeration(TEST_ADDRESSES.toList())
+    }
+
+    @Before
+    fun setUp() {
+        thread.start()
+    }
+
+    @After
+    fun tearDown() {
+        thread.quitSafely()
+    }
+
+    @Test
+    fun testAddServiceAndProbe() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        assertEquals(0, repository.servicesCount)
+        assertEquals(-1, repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1))
+        assertEquals(1, repository.servicesCount)
+
+        val probingInfo = repository.setServiceProbing(TEST_SERVICE_ID_1)
+        assertNotNull(probingInfo)
+        assertTrue(repository.isProbing(TEST_SERVICE_ID_1))
+
+        assertEquals(TEST_SERVICE_ID_1, probingInfo.serviceId)
+        val packet = probingInfo.getPacket(0)
+
+        assertEquals(MdnsConstants.FLAGS_QUERY, packet.flags)
+        assertEquals(0, packet.answers.size)
+        assertEquals(0, packet.additionalRecords.size)
+
+        assertEquals(1, packet.questions.size)
+        val expectedName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
+        assertEquals(MdnsAnyRecord(expectedName, false /* unicast */), packet.questions[0])
+
+        assertEquals(1, packet.authorityRecords.size)
+        assertEquals(MdnsServiceRecord(expectedName,
+                0L /* receiptTimeMillis */,
+                false /* cacheFlush */,
+                120_000L /* ttlMillis */,
+                0 /* servicePriority */, 0 /* serviceWeight */,
+                TEST_PORT, TEST_HOSTNAME), packet.authorityRecords[0])
+
+        assertContentEquals(intArrayOf(TEST_SERVICE_ID_1), repository.clearServices())
+    }
+
+    @Test
+    fun testAddAndConflicts() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        assertFailsWith(NameConflictException::class) {
+            repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1)
+        }
+    }
+
+    @Test
+    fun testExitingServiceReAdded() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        repository.exitService(TEST_SERVICE_ID_1)
+
+        assertEquals(TEST_SERVICE_ID_1, repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1))
+        assertEquals(1, repository.servicesCount)
+
+        repository.removeService(TEST_SERVICE_ID_2)
+        assertEquals(0, repository.servicesCount)
+    }
+}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
index 697116c..a45ca68 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
@@ -62,7 +62,7 @@
 import java.net.DatagramPacket;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
-import java.net.SocketAddress;
+import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -80,7 +80,10 @@
     private static final int INTERFACE_INDEX = 999;
     private static final String SERVICE_TYPE = "_googlecast._tcp.local";
     private static final String[] SERVICE_TYPE_LABELS = TextUtils.split(SERVICE_TYPE, "\\.");
-    private static final Network NETWORK = mock(Network.class);
+    private static final InetSocketAddress IPV4_ADDRESS = new InetSocketAddress(
+            MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT);
+    private static final InetSocketAddress IPV6_ADDRESS = new InetSocketAddress(
+            MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
 
     @Mock
     private MdnsServiceBrowserListener mockListenerOne;
@@ -89,13 +92,16 @@
     @Mock
     private MdnsPacketWriter mockPacketWriter;
     @Mock
-    private MdnsSocketClient mockSocketClient;
+    private MdnsMultinetworkSocketClient mockSocketClient;
+    @Mock
+    private Network mockNetwork;
     @Captor
     private ArgumentCaptor<MdnsServiceInfo> serviceInfoCaptor;
 
     private final byte[] buf = new byte[10];
 
-    private DatagramPacket[] expectedPackets;
+    private DatagramPacket[] expectedIPv4Packets;
+    private DatagramPacket[] expectedIPv6Packets;
     private ScheduledFuture<?>[] expectedSendFutures;
     private FakeExecutor currentThreadExecutor = new FakeExecutor();
 
@@ -106,30 +112,52 @@
     public void setUp() throws IOException {
         MockitoAnnotations.initMocks(this);
 
-        expectedPackets = new DatagramPacket[16];
+        expectedIPv4Packets = new DatagramPacket[16];
+        expectedIPv6Packets = new DatagramPacket[16];
         expectedSendFutures = new ScheduledFuture<?>[16];
 
         for (int i = 0; i < expectedSendFutures.length; ++i) {
-            expectedPackets[i] = new DatagramPacket(buf, 0, 5);
+            expectedIPv4Packets[i] = new DatagramPacket(buf, 0 /* offset */, 5 /* length */,
+                    MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT);
+            expectedIPv6Packets[i] = new DatagramPacket(buf, 0 /* offset */, 5 /* length */,
+                    MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
             expectedSendFutures[i] = Mockito.mock(ScheduledFuture.class);
         }
-        when(mockPacketWriter.getPacket(any(SocketAddress.class)))
-                .thenReturn(expectedPackets[0])
-                .thenReturn(expectedPackets[1])
-                .thenReturn(expectedPackets[2])
-                .thenReturn(expectedPackets[3])
-                .thenReturn(expectedPackets[4])
-                .thenReturn(expectedPackets[5])
-                .thenReturn(expectedPackets[6])
-                .thenReturn(expectedPackets[7])
-                .thenReturn(expectedPackets[8])
-                .thenReturn(expectedPackets[9])
-                .thenReturn(expectedPackets[10])
-                .thenReturn(expectedPackets[11])
-                .thenReturn(expectedPackets[12])
-                .thenReturn(expectedPackets[13])
-                .thenReturn(expectedPackets[14])
-                .thenReturn(expectedPackets[15]);
+        when(mockPacketWriter.getPacket(IPV4_ADDRESS))
+                .thenReturn(expectedIPv4Packets[0])
+                .thenReturn(expectedIPv4Packets[1])
+                .thenReturn(expectedIPv4Packets[2])
+                .thenReturn(expectedIPv4Packets[3])
+                .thenReturn(expectedIPv4Packets[4])
+                .thenReturn(expectedIPv4Packets[5])
+                .thenReturn(expectedIPv4Packets[6])
+                .thenReturn(expectedIPv4Packets[7])
+                .thenReturn(expectedIPv4Packets[8])
+                .thenReturn(expectedIPv4Packets[9])
+                .thenReturn(expectedIPv4Packets[10])
+                .thenReturn(expectedIPv4Packets[11])
+                .thenReturn(expectedIPv4Packets[12])
+                .thenReturn(expectedIPv4Packets[13])
+                .thenReturn(expectedIPv4Packets[14])
+                .thenReturn(expectedIPv4Packets[15]);
+
+        when(mockPacketWriter.getPacket(IPV6_ADDRESS))
+                .thenReturn(expectedIPv6Packets[0])
+                .thenReturn(expectedIPv6Packets[1])
+                .thenReturn(expectedIPv6Packets[2])
+                .thenReturn(expectedIPv6Packets[3])
+                .thenReturn(expectedIPv6Packets[4])
+                .thenReturn(expectedIPv6Packets[5])
+                .thenReturn(expectedIPv6Packets[6])
+                .thenReturn(expectedIPv6Packets[7])
+                .thenReturn(expectedIPv6Packets[8])
+                .thenReturn(expectedIPv6Packets[9])
+                .thenReturn(expectedIPv6Packets[10])
+                .thenReturn(expectedIPv6Packets[11])
+                .thenReturn(expectedIPv6Packets[12])
+                .thenReturn(expectedIPv6Packets[13])
+                .thenReturn(expectedIPv6Packets[14])
+                .thenReturn(expectedIPv6Packets[15]);
 
         client =
                 new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor) {
@@ -282,8 +310,8 @@
         //MdnsConfigsFlagsImpl.alwaysAskForUnicastResponseInEachBurst.override(true);
         MdnsSearchOptions searchOptions =
                 MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
-        QueryTaskConfig config =
-                new QueryTaskConfig(searchOptions.getSubtypes(), searchOptions.isPassiveMode(), 1);
+        QueryTaskConfig config = new QueryTaskConfig(
+                searchOptions.getSubtypes(), searchOptions.isPassiveMode(), 1, mockNetwork);
 
         // This is the first query. We will ask for unicast response.
         assertTrue(config.expectUnicastResponse);
@@ -311,8 +339,8 @@
     public void testQueryTaskConfig_askForUnicastInFirstQuery() {
         MdnsSearchOptions searchOptions =
                 MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
-        QueryTaskConfig config =
-                new QueryTaskConfig(searchOptions.getSubtypes(), searchOptions.isPassiveMode(), 1);
+        QueryTaskConfig config = new QueryTaskConfig(
+                searchOptions.getSubtypes(), searchOptions.isPassiveMode(), 1, mockNetwork);
 
         // This is the first query. We will ask for unicast response.
         assertTrue(config.expectUnicastResponse);
@@ -409,7 +437,7 @@
         MdnsResponse response = mock(MdnsResponse.class);
         when(response.getServiceInstanceName()).thenReturn("service-instance-1");
         doReturn(INTERFACE_INDEX).when(response).getInterfaceIndex();
-        doReturn(NETWORK).when(response).getNetwork();
+        doReturn(mockNetwork).when(response).getNetwork();
         when(response.isComplete()).thenReturn(false);
 
         client.processResponse(response);
@@ -423,7 +451,7 @@
                 List.of() /* subTypes */,
                 Collections.singletonMap("key", null) /* attributes */,
                 INTERFACE_INDEX,
-                NETWORK);
+                mockNetwork);
 
         verify(mockListenerOne, never()).onServiceFound(any(MdnsServiceInfo.class));
         verify(mockListenerOne, never()).onServiceUpdated(any(MdnsServiceInfo.class));
@@ -443,7 +471,7 @@
                         /* subtype= */ "ABCDE",
                         Collections.emptyMap(),
                         /* interfaceIndex= */ 20,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(initialResponse);
 
         // Process a second response with a different port and updated text attributes.
@@ -455,7 +483,7 @@
                         /* subtype= */ "ABCDE",
                         Collections.singletonMap("key", "value"),
                         /* interfaceIndex= */ 20,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(secondResponse);
 
         // Verify onServiceNameDiscovered was called once for the initial response.
@@ -469,7 +497,7 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", null) /* attributes */,
                 20 /* interfaceIndex */,
-                NETWORK);
+                mockNetwork);
 
         // Verify onServiceFound was called once for the initial response.
         verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
@@ -480,7 +508,7 @@
         assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
         assertNull(initialServiceInfo.getAttributeByKey("key"));
         assertEquals(initialServiceInfo.getInterfaceIndex(), 20);
-        assertEquals(NETWORK, initialServiceInfo.getNetwork());
+        assertEquals(mockNetwork, initialServiceInfo.getNetwork());
 
         // Verify onServiceUpdated was called once for the second response.
         verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
@@ -492,7 +520,7 @@
         assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
         assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value");
         assertEquals(updatedServiceInfo.getInterfaceIndex(), 20);
-        assertEquals(NETWORK, updatedServiceInfo.getNetwork());
+        assertEquals(mockNetwork, updatedServiceInfo.getNetwork());
     }
 
     @Test
@@ -509,7 +537,7 @@
                         /* subtype= */ "ABCDE",
                         Collections.emptyMap(),
                         /* interfaceIndex= */ 20,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(initialResponse);
 
         // Process a second response with a different port and updated text attributes.
@@ -521,7 +549,7 @@
                         /* subtype= */ "ABCDE",
                         Collections.singletonMap("key", "value"),
                         /* interfaceIndex= */ 20,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(secondResponse);
 
         System.out.println("secondResponses ip"
@@ -538,7 +566,7 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", null) /* attributes */,
                 20 /* interfaceIndex */,
-                NETWORK);
+                mockNetwork);
 
         // Verify onServiceFound was called once for the initial response.
         verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
@@ -549,7 +577,7 @@
         assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
         assertNull(initialServiceInfo.getAttributeByKey("key"));
         assertEquals(initialServiceInfo.getInterfaceIndex(), 20);
-        assertEquals(NETWORK, initialServiceInfo.getNetwork());
+        assertEquals(mockNetwork, initialServiceInfo.getNetwork());
 
         // Verify onServiceUpdated was called once for the second response.
         verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
@@ -561,7 +589,7 @@
         assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
         assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value");
         assertEquals(updatedServiceInfo.getInterfaceIndex(), 20);
-        assertEquals(NETWORK, updatedServiceInfo.getNetwork());
+        assertEquals(mockNetwork, updatedServiceInfo.getNetwork());
     }
 
     private void verifyServiceRemovedNoCallback(MdnsServiceBrowserListener listener) {
@@ -599,12 +627,12 @@
                         /* subtype= */ "ABCDE",
                         Collections.emptyMap(),
                         INTERFACE_INDEX,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(initialResponse);
         MdnsResponse response = mock(MdnsResponse.class);
         doReturn("goodbye-service").when(response).getServiceInstanceName();
         doReturn(INTERFACE_INDEX).when(response).getInterfaceIndex();
-        doReturn(NETWORK).when(response).getNetwork();
+        doReturn(mockNetwork).when(response).getNetwork();
         doReturn(true).when(response).isGoodbye();
         client.processResponse(response);
         // Verify removed callback won't be called if the service is not existed.
@@ -615,9 +643,9 @@
         doReturn(serviceName).when(response).getServiceInstanceName();
         client.processResponse(response);
         verifyServiceRemovedCallback(
-                mockListenerOne, serviceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX, NETWORK);
+                mockListenerOne, serviceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX, mockNetwork);
         verifyServiceRemovedCallback(
-                mockListenerTwo, serviceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX, NETWORK);
+                mockListenerTwo, serviceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX, mockNetwork);
     }
 
     @Test
@@ -631,7 +659,7 @@
                         /* subtype= */ "ABCDE",
                         Collections.emptyMap(),
                         INTERFACE_INDEX,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(initialResponse);
 
         client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
@@ -647,7 +675,7 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", null) /* attributes */,
                 INTERFACE_INDEX,
-                NETWORK);
+                mockNetwork);
 
         // Verify onServiceFound was called once for the existing response.
         verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
@@ -684,7 +712,7 @@
         MdnsResponse initialResponse =
                 createMockResponse(
                         serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
-                        Map.of(), INTERFACE_INDEX, NETWORK);
+                        Map.of(), INTERFACE_INDEX, mockNetwork);
         client.processResponse(initialResponse);
 
         // Clear the scheduled runnable.
@@ -718,7 +746,7 @@
         MdnsResponse initialResponse =
                 createMockResponse(
                         serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
-                        Map.of(), INTERFACE_INDEX, NETWORK);
+                        Map.of(), INTERFACE_INDEX, mockNetwork);
         client.processResponse(initialResponse);
 
         // Clear the scheduled runnable.
@@ -737,7 +765,7 @@
 
         // Verify removed callback was called.
         verifyServiceRemovedCallback(mockListenerOne, serviceInstanceName, SERVICE_TYPE_LABELS,
-                INTERFACE_INDEX, NETWORK);
+                INTERFACE_INDEX, mockNetwork);
     }
 
     @Test
@@ -758,7 +786,7 @@
         MdnsResponse initialResponse =
                 createMockResponse(
                         serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
-                        Map.of(), INTERFACE_INDEX, NETWORK);
+                        Map.of(), INTERFACE_INDEX, mockNetwork);
         client.processResponse(initialResponse);
 
         // Clear the scheduled runnable.
@@ -792,7 +820,7 @@
         MdnsResponse initialResponse =
                 createMockResponse(
                         serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
-                        Map.of(), INTERFACE_INDEX, NETWORK);
+                        Map.of(), INTERFACE_INDEX, mockNetwork);
         client.processResponse(initialResponse);
 
         // Clear the scheduled runnable.
@@ -804,7 +832,7 @@
 
         // Verify removed callback was called.
         verifyServiceRemovedCallback(mockListenerOne, serviceInstanceName, SERVICE_TYPE_LABELS,
-                INTERFACE_INDEX, NETWORK);
+                INTERFACE_INDEX, mockNetwork);
     }
 
     @Test
@@ -824,7 +852,7 @@
                         "ABCDE" /* subtype */,
                         Collections.emptyMap(),
                         INTERFACE_INDEX,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(initialResponse);
 
         // Process a second response which has ip address to make response become complete.
@@ -836,7 +864,7 @@
                         "ABCDE" /* subtype */,
                         Collections.emptyMap(),
                         INTERFACE_INDEX,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(secondResponse);
 
         // Process a third response with a different ip address, port and updated text attributes.
@@ -848,7 +876,7 @@
                         "ABCDE" /* subtype */,
                         Collections.singletonMap("key", "value"),
                         INTERFACE_INDEX,
-                        NETWORK);
+                        mockNetwork);
         client.processResponse(thirdResponse);
 
         // Process the last response which is goodbye message.
@@ -868,7 +896,7 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", null) /* attributes */,
                 INTERFACE_INDEX,
-                NETWORK);
+                mockNetwork);
 
         // Verify onServiceFound was second called for the second response.
         inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
@@ -881,7 +909,7 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", null) /* attributes */,
                 INTERFACE_INDEX,
-                NETWORK);
+                mockNetwork);
 
         // Verify onServiceUpdated was third called for the third response.
         inOrder.verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
@@ -894,7 +922,7 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", "value") /* attributes */,
                 INTERFACE_INDEX,
-                NETWORK);
+                mockNetwork);
 
         // Verify onServiceRemoved was called for the last response.
         inOrder.verify(mockListenerOne).onServiceRemoved(serviceInfoCaptor.capture());
@@ -907,7 +935,7 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", "value") /* attributes */,
                 INTERFACE_INDEX,
-                NETWORK);
+                mockNetwork);
 
         // Verify onServiceNameRemoved was called for the last response.
         inOrder.verify(mockListenerOne).onServiceNameRemoved(serviceInfoCaptor.capture());
@@ -920,18 +948,34 @@
                 Collections.singletonList("ABCDE") /* subTypes */,
                 Collections.singletonMap("key", "value") /* attributes */,
                 INTERFACE_INDEX,
-                NETWORK);
+                mockNetwork);
     }
 
     // verifies that the right query was enqueued with the right delay, and send query by executing
     // the runnable.
     private void verifyAndSendQuery(int index, long timeInMs, boolean expectsUnicastResponse) {
+        verifyAndSendQuery(
+                index, timeInMs, expectsUnicastResponse, true /* multipleSocketDiscovery */);
+    }
+
+    private void verifyAndSendQuery(int index, long timeInMs, boolean expectsUnicastResponse,
+            boolean multipleSocketDiscovery) {
         assertEquals(currentThreadExecutor.getAndClearLastScheduledDelayInMs(), timeInMs);
         currentThreadExecutor.getAndClearLastScheduledRunnable().run();
         if (expectsUnicastResponse) {
-            verify(mockSocketClient).sendUnicastPacket(expectedPackets[index]);
+            verify(mockSocketClient).sendUnicastPacket(
+                    expectedIPv4Packets[index], null /* network */);
+            if (multipleSocketDiscovery) {
+                verify(mockSocketClient).sendUnicastPacket(
+                        expectedIPv6Packets[index], null /* network */);
+            }
         } else {
-            verify(mockSocketClient).sendMulticastPacket(expectedPackets[index]);
+            verify(mockSocketClient).sendMulticastPacket(
+                    expectedIPv4Packets[index], null /* network */);
+            if (multipleSocketDiscovery) {
+                verify(mockSocketClient).sendMulticastPacket(
+                        expectedIPv6Packets[index], null /* network */);
+            }
         }
     }
 
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
index 2bb61a6a..07bbbb5 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
@@ -96,7 +96,7 @@
                 .getNetworkInterfaceByName(LOCAL_ONLY_IFACE_NAME);
         doReturn(mTetheredIfaceWrapper).when(mDeps).getNetworkInterfaceByName(TETHERED_IFACE_NAME);
         doReturn(mock(MdnsInterfaceSocket.class))
-                .when(mDeps).createMdnsInterfaceSocket(any(), anyInt());
+                .when(mDeps).createMdnsInterfaceSocket(any(), anyInt(), any(), any());
         final HandlerThread thread = new HandlerThread("MdnsSocketProviderTest");
         thread.start();
         mHandler = new Handler(thread.getLooper());
@@ -159,12 +159,13 @@
         }
 
         @Override
-        public void onAddressesChanged(Network network, List<LinkAddress> addresses) {
+        public void onAddressesChanged(Network network, MdnsInterfaceSocket socket,
+                List<LinkAddress> addresses) {
             mHistory.add(new AddressesChangedEvent(network, addresses));
         }
 
         public void expectedSocketCreatedForNetwork(Network network, List<LinkAddress> addresses) {
-            final SocketEvent event = mHistory.poll(DEFAULT_TIMEOUT, c -> true);
+            final SocketEvent event = mHistory.poll(0L /* timeoutMs */, c -> true);
             assertNotNull(event);
             assertTrue(event instanceof SocketCreatedEvent);
             assertEquals(network, event.mNetwork);
@@ -172,7 +173,7 @@
         }
 
         public void expectedInterfaceDestroyedForNetwork(Network network) {
-            final SocketEvent event = mHistory.poll(DEFAULT_TIMEOUT, c -> true);
+            final SocketEvent event = mHistory.poll(0L /* timeoutMs */, c -> true);
             assertNotNull(event);
             assertTrue(event instanceof InterfaceDestroyedEvent);
             assertEquals(network, event.mNetwork);
@@ -180,7 +181,7 @@
 
         public void expectedAddressesChangedForNetwork(Network network,
                 List<LinkAddress> addresses) {
-            final SocketEvent event = mHistory.poll(DEFAULT_TIMEOUT, c -> true);
+            final SocketEvent event = mHistory.poll(0L /* timeoutMs */, c -> true);
             assertNotNull(event);
             assertTrue(event instanceof AddressesChangedEvent);
             assertEquals(network, event.mNetwork);
@@ -259,7 +260,8 @@
         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
         testCallback1.expectedNoCallback();
         testCallback2.expectedNoCallback();
-        testCallback3.expectedNoCallback();
+        // Expect the socket destroy for tethered interface.
+        testCallback3.expectedInterfaceDestroyedForNetwork(LOCAL_NETWORK);
     }
 
     @Test
diff --git a/tools/gn2bp/Android.bp.swp b/tools/gn2bp/Android.bp.swp
index f6a17a4..2398349 100644
--- a/tools/gn2bp/Android.bp.swp
+++ b/tools/gn2bp/Android.bp.swp
@@ -14,10 +14,60 @@
 //
 // This file is automatically generated by gen_android_bp. Do not edit.
 
+// GN: //components/cronet/android:cronet_api_java
+java_library {
+    name: "cronet_aml_api_java",
+    srcs: [
+        ":cronet_aml_api_sources",
+    ],
+    libs: [
+        "androidx.annotation_annotation",
+    ],
+    sdk_version: "module_current",
+}
+
+// GN: //components/cronet/android:cronet_api_java
+filegroup {
+    name: "cronet_aml_api_sources",
+    srcs: [
+        ":cronet_aml_components_cronet_android_interface_api_version",
+        "components/cronet/android/api/src/android/net/http/BidirectionalStream.java",
+        "components/cronet/android/api/src/android/net/http/CallbackException.java",
+        "components/cronet/android/api/src/android/net/http/CronetEngine.java",
+        "components/cronet/android/api/src/android/net/http/CronetException.java",
+        "components/cronet/android/api/src/android/net/http/ExperimentalBidirectionalStream.java",
+        "components/cronet/android/api/src/android/net/http/ExperimentalCronetEngine.java",
+        "components/cronet/android/api/src/android/net/http/ExperimentalUrlRequest.java",
+        "components/cronet/android/api/src/android/net/http/ICronetEngineBuilder.java",
+        "components/cronet/android/api/src/android/net/http/InlineExecutionProhibitedException.java",
+        "components/cronet/android/api/src/android/net/http/NetworkException.java",
+        "components/cronet/android/api/src/android/net/http/NetworkQualityRttListener.java",
+        "components/cronet/android/api/src/android/net/http/NetworkQualityThroughputListener.java",
+        "components/cronet/android/api/src/android/net/http/QuicException.java",
+        "components/cronet/android/api/src/android/net/http/RequestFinishedInfo.java",
+        "components/cronet/android/api/src/android/net/http/UploadDataProvider.java",
+        "components/cronet/android/api/src/android/net/http/UploadDataSink.java",
+        "components/cronet/android/api/src/android/net/http/UrlRequest.java",
+        "components/cronet/android/api/src/android/net/http/UrlResponseInfo.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/ByteArrayCronetCallback.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/ContentTypeParametersParser.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/CronetRequestCompletionListener.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/CronetResponse.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/ImplicitFlowControlCallback.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/InMemoryTransformCronetCallback.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/JsonCronetCallback.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/RedirectHandler.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/RedirectHandlers.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/StringCronetCallback.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/UploadDataProviders.java",
+        "components/cronet/android/api/src/android/net/http/apihelpers/UrlRequestCallbacks.java",
+    ],
+}
+
 // GN: //base/allocator:buildflags
 cc_genrule {
     name: "cronet_aml_base_allocator_buildflags",
-    cmd: "echo '--flags USE_PARTITION_ALLOC=\"false\" USE_ALLOCATOR_SHIM=\"true\" USE_PARTITION_ALLOC_AS_MALLOC=\"false\" USE_BACKUP_REF_PTR=\"false\" USE_ASAN_BACKUP_REF_PTR=\"false\" USE_PARTITION_ALLOC_AS_GWP_ASAN_STORE=\"false\" USE_MTE_CHECKED_PTR=\"false\" FORCE_ENABLE_RAW_PTR_EXCLUSION=\"false\"' | " +
+    cmd: "echo '--flags USE_ALLOCATOR_SHIM=\"true\" USE_PARTITION_ALLOC=\"false\" USE_PARTITION_ALLOC_AS_MALLOC=\"false\" USE_BACKUP_REF_PTR=\"false\" USE_ASAN_BACKUP_REF_PTR=\"false\" USE_PARTITION_ALLOC_AS_GWP_ASAN_STORE=\"false\" USE_MTE_CHECKED_PTR=\"false\" FORCE_ENABLE_RAW_PTR_EXCLUSION=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -156,7 +206,6 @@
         "base/allocator/partition_allocator/partition_alloc_base/memory/ref_counted.cc",
         "base/allocator/partition_allocator/partition_alloc_base/native_library.cc",
         "base/allocator/partition_allocator/partition_alloc_base/native_library_posix.cc",
-        "base/allocator/partition_allocator/partition_alloc_base/pkey.cc",
         "base/allocator/partition_allocator/partition_alloc_base/posix/safe_strerror.cc",
         "base/allocator/partition_allocator/partition_alloc_base/rand_util.cc",
         "base/allocator/partition_allocator/partition_alloc_base/rand_util_posix.cc",
@@ -208,8 +257,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
@@ -217,9 +266,7 @@
         "-DPA_PCSCAN_STACK_SUPPORTED",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -231,7 +278,10 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/android_ndk/sources/android/cpufeatures/",
     ],
-    cpp_std: "c++20",
+    header_libs: [
+        "libgtest_prod_headers",
+    ],
+    cpp_std: "c++17",
     target: {
         android_arm: {
             srcs: [
@@ -268,7 +318,7 @@
 // GN: //base/allocator/partition_allocator:partition_alloc_buildflags
 cc_genrule {
     name: "cronet_aml_base_allocator_partition_allocator_partition_alloc_buildflags",
-    cmd: "echo '--flags ENABLE_PARTITION_ALLOC_AS_MALLOC_SUPPORT=\"true\" ENABLE_BACKUP_REF_PTR_SUPPORT=\"true\" ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=\"false\" ENABLE_DANGLING_RAW_PTR_CHECKS=\"false\" PUT_REF_COUNT_IN_PREVIOUS_SLOT=\"true\" ENABLE_GWP_ASAN_SUPPORT=\"true\" ENABLE_MTE_CHECKED_PTR_SUPPORT=\"false\" RECORD_ALLOC_INFO=\"false\" USE_FREESLOT_BITMAP=\"false\" GLUE_CORE_POOLS=\"false\" ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=\"false\" STARSCAN=\"true\" PA_USE_BASE_TRACING=\"true\" ENABLE_PKEYS=\"false\"' | " +
+    cmd: "echo '--flags ENABLE_PARTITION_ALLOC_AS_MALLOC_SUPPORT=\"true\" ENABLE_BACKUP_REF_PTR_SUPPORT=\"true\" ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=\"false\" ENABLE_DANGLING_RAW_PTR_CHECKS=\"false\" PUT_REF_COUNT_IN_PREVIOUS_SLOT=\"true\" ENABLE_GWP_ASAN_SUPPORT=\"true\" ENABLE_MTE_CHECKED_PTR_SUPPORT=\"false\" RECORD_ALLOC_INFO=\"false\" USE_FREESLOT_BITMAP=\"false\" ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=\"false\" STARSCAN=\"true\" PA_USE_BASE_TRACING=\"true\" ENABLE_PKEYS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -321,7 +371,7 @@
          "--includes " +
          "base/android/jni_generator/jni_generator_helper.h " +
          "--jar_file " +
-         "$(location third_party/android_sdk/public/platforms/android-33/android.jar) " +
+         "$(location :current_android_jar) " +
          "--output_name " +
          "Runnable_jni.h " +
          "--output_name " +
@@ -331,18 +381,20 @@
          "--input_file " +
          "java/lang/Runtime.class " +
          "--javap " +
-         "$$(find out/.path -name javap)",
+         "$$(find out/.path -name javap) " +
+         "--package_prefix " +
+         "android.net.http.internal",
     out: [
         "base/android_runtime_jni_headers/Runnable_jni.h",
         "base/android_runtime_jni_headers/Runtime_jni.h",
     ],
     tool_files: [
+        ":current_android_jar",
         "base/android/jni_generator/android_jar.classes",
         "base/android/jni_generator/jni_generator.py",
         "build/android/gyp/util/__init__.py",
         "build/android/gyp/util/build_utils.py",
         "build/gn_helpers.py",
-        "third_party/android_sdk/public/platforms/android-33/android.jar",
     ],
     apex_available: [
         "com.android.tethering",
@@ -901,6 +953,9 @@
         "cronet_aml_build_chromeos_buildflags",
         "cronet_aml_build_config_compiler_compiler_buildflags",
     ],
+    export_header_lib_headers: [
+        "libgtest_prod_headers",
+    ],
     defaults: [
         "cronet_aml_defaults",
     ],
@@ -908,8 +963,8 @@
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
         "-DBASE_IMPLEMENTATION",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
@@ -922,9 +977,7 @@
         "-DU_USING_ICU_NAMESPACE=0",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -940,7 +993,10 @@
         "third_party/icu/source/common/",
         "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    header_libs: [
+        "libgtest_prod_headers",
+    ],
+    cpp_std: "c++17",
     target: {
         android_arm: {
             srcs: [
@@ -1219,7 +1275,9 @@
          "--input_file " +
          "$(location base/android/java/src/org/chromium/base/task/PostTask.java) " +
          "--input_file " +
-         "$(location base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java)",
+         "$(location base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java) " +
+         "--package_prefix " +
+         "android.net.http.internal",
     out: [
         "base/base_jni_headers/ApkAssets_jni.h",
         "base/base_jni_headers/ApplicationStatus_jni.h",
@@ -1292,16 +1350,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -1312,7 +1368,7 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -1331,7 +1387,7 @@
 cc_genrule {
     name: "cronet_aml_base_build_date",
     cmd: "$(location build/write_build_date_header.py) $(out) " +
-         "1664686800",
+         "1672549200",
     out: [
         "base/generated_build_date.h",
     ],
@@ -1346,7 +1402,7 @@
 // GN: //base:cfi_buildflags
 cc_genrule {
     name: "cronet_aml_base_cfi_buildflags",
-    cmd: "echo '--flags CFI_CAST_CHECK=\"false && false\" CFI_DIAG=\"false && false\" CFI_ICALL_CHECK=\"false && false\" CFI_ENFORCEMENT_TRAP=\"false && !false\" CFI_ENFORCEMENT_DIAGNOSTIC=\"false && false && !false\"' | " +
+    cmd: "echo '--flags CFI_CAST_CHECK=\"false && false\" CFI_ICALL_CHECK=\"false && false\" CFI_ENFORCEMENT_TRAP=\"false && !false\" CFI_ENFORCEMENT_DIAGNOSTIC=\"false && false && !false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1394,7 +1450,7 @@
     name: "cronet_aml_base_debugging_buildflags",
     cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
          "then " +
-         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"false\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"false\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1406,7 +1462,7 @@
          "fi; " +
          "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
          "then " +
-         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"true\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"true\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1418,7 +1474,7 @@
          "fi; " +
          "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
          "then " +
-         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"false\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"true\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"false\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"true\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1430,7 +1486,7 @@
          "fi; " +
          "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
          "then " +
-         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"true\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"true\" UNSAFE_DEVELOPER_BUILD=\"true\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"true\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"true\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1477,7 +1533,7 @@
 // GN: //base:ios_cronet_buildflags
 cc_genrule {
     name: "cronet_aml_base_ios_cronet_buildflags",
-    cmd: "echo '--flags CRONET_BUILD=\"false\"' | " +
+    cmd: "echo '--flags CRONET_BUILD=\"true\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1595,50 +1651,6 @@
     ],
 }
 
-// GN: //base/numerics:base_numerics
-cc_object {
-    name: "cronet_aml_base_numerics_base_numerics",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
 // GN: //base:orderfile_buildflags
 cc_genrule {
     name: "cronet_aml_base_orderfile_buildflags",
@@ -1835,16 +1847,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -1855,7 +1865,7 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -1882,16 +1892,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -1900,7 +1908,7 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -2022,50 +2030,6 @@
     ],
 }
 
-// GN: //build:buildflag_header_h
-cc_object {
-    name: "cronet_aml_build_buildflag_header_h",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
 // GN: //build:chromecast_buildflags
 cc_genrule {
     name: "cronet_aml_build_chromecast_buildflags",
@@ -2187,17 +2151,15 @@
         "cronet_aml_defaults",
     ],
     cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DLIBCXX_BUILDING_LIBCXXABI",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_BUILDING_LIBRARY",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCPP_OVERRIDABLE_FUNC_VIS=__attribute__((__visibility__(\"default\")))",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
@@ -2285,18 +2247,16 @@
         "cronet_aml_defaults",
     ],
     cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DLIBCXXABI_SILENT_TERMINATE",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_BUILDING_LIBRARY",
         "-D_LIBCPP_CONSTINIT=constinit",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -2404,14 +2364,13 @@
         ":cronet_aml_components_cronet_android_cronet_static",
         ":cronet_aml_components_cronet_cronet_common",
         ":cronet_aml_components_cronet_metrics_util",
-        ":cronet_aml_components_cronet_native_cronet_native_impl",
-        ":cronet_aml_components_grpc_support_grpc_support",
         ":cronet_aml_components_metrics_library_support",
         "components/cronet/android/cronet_jni.cc",
     ],
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -2433,7 +2392,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -2466,8 +2424,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
@@ -2477,9 +2435,7 @@
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -2496,11 +2452,11 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     linker_scripts: [
         "base/android/library_loader/anchor_functions.lds",
     ],
-    stem: "libcronet.109.0.5386.0",
+    stem: "libcronet.108.0.5359.128",
     target: {
         android_x86: {
             cflags: [
@@ -2551,7 +2507,9 @@
          "--input_file " +
          "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java) " +
          "--input_file " +
-         "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java)",
+         "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java) " +
+         "--package_prefix " +
+         "android.net.http.internal",
     out: [
         "components/cronet/android/cronet_jni_headers/CronetBidirectionalStream_jni.h",
         "components/cronet/android/cronet_jni_headers/CronetLibraryLoader_jni.h",
@@ -2602,7 +2560,6 @@
         "base/android/java/src/org/chromium/base/Function.java",
         "base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
         "base/android/java/src/org/chromium/base/IntStringCallback.java",
-        "base/android/java/src/org/chromium/base/IntentUtils.java",
         "base/android/java/src/org/chromium/base/JNIUtils.java",
         "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
         "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
@@ -2627,6 +2584,7 @@
         "base/android/java/src/org/chromium/base/RadioUtils.java",
         "base/android/java/src/org/chromium/base/StreamUtil.java",
         "base/android/java/src/org/chromium/base/StrictModeContext.java",
+        "base/android/java/src/org/chromium/base/SysUtils.java",
         "base/android/java/src/org/chromium/base/ThreadUtils.java",
         "base/android/java/src/org/chromium/base/TimeUtils.java",
         "base/android/java/src/org/chromium/base/TimezoneUtils.java",
@@ -2669,6 +2627,8 @@
         "base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java",
         "base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java",
         "base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java",
+        "base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
+        "base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
         "base/android/java/src/org/chromium/base/library_loader/Linker.java",
         "base/android/java/src/org/chromium/base/library_loader/LinkerJni.java",
         "base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
@@ -2693,18 +2653,6 @@
         "base/android/java/src/org/chromium/base/metrics/TimingMetric.java",
         "base/android/java/src/org/chromium/base/metrics/UmaRecorder.java",
         "base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java",
-        "base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java",
-        "base/android/java/src/org/chromium/base/process_launcher/BindService.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java",
-        "base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java",
         "base/android/java/src/org/chromium/base/supplier/BooleanSupplier.java",
         "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
         "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
@@ -2739,45 +2687,6 @@
         "build/android/java/src/org/chromium/build/annotations/MainDex.java",
         "build/android/java/src/org/chromium/build/annotations/MockedInTests.java",
         "build/android/java/src/org/chromium/build/annotations/UsedByReflection.java",
-        "components/cronet/android/api/src/org/chromium/net/BidirectionalStream.java",
-        "components/cronet/android/api/src/org/chromium/net/CallbackException.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetEngine.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetException.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetProvider.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalBidirectionalStream.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalUrlRequest.java",
-        "components/cronet/android/api/src/org/chromium/net/ICronetEngineBuilder.java",
-        "components/cronet/android/api/src/org/chromium/net/InlineExecutionProhibitedException.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkException.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkQualityThroughputListener.java",
-        "components/cronet/android/api/src/org/chromium/net/QuicException.java",
-        "components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataProvider.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataProviders.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataSink.java",
-        "components/cronet/android/api/src/org/chromium/net/UrlRequest.java",
-        "components/cronet/android/api/src/org/chromium/net/UrlResponseInfo.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ByteArrayCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ContentTypeParametersParser.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/CronetRequestCompletionListener.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/CronetResponse.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ImplicitFlowControlCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/InMemoryTransformCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/JsonCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/RedirectHandler.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/RedirectHandlers.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/StringCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/UploadDataProviders.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/UrlRequestCallbacks.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetController.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetEngine.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetProvider.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeUrlRequest.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeUrlResponse.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/ResponseMatcher.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/UrlResponseMatcher.java",
         "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamBuilderImpl.java",
         "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CallbackExceptionImpl.java",
@@ -2793,16 +2702,7 @@
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/InputStreamChannel.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetEngine.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetEngineBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetProvider.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUploadDataSinkBase.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequest.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequestUtils.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderWithLibraryLoaderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetProvider.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NetworkExceptionImpl.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NoOpLogger.java",
         "components/cronet/android/java/src/org/chromium/net/impl/Preconditions.java",
@@ -2862,6 +2762,8 @@
          "--header-path " +
          "$(genDir)/components/cronet/android/cronet_jni_registration.h " +
          "--manual_jni_registration " +
+         "--package_prefix " +
+         "android.net.http.internal " +
          ";sed -i -e 's/OUT_SOONG_.TEMP_SBOX_.*_OUT/GEN/g'  " +
          "$(genDir)/components/cronet/android/cronet_jni_registration.h",
     out: [
@@ -2911,7 +2813,6 @@
         "base/android/java/src/org/chromium/base/Function.java",
         "base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
         "base/android/java/src/org/chromium/base/IntStringCallback.java",
-        "base/android/java/src/org/chromium/base/IntentUtils.java",
         "base/android/java/src/org/chromium/base/JNIUtils.java",
         "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
         "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
@@ -2936,6 +2837,7 @@
         "base/android/java/src/org/chromium/base/RadioUtils.java",
         "base/android/java/src/org/chromium/base/StreamUtil.java",
         "base/android/java/src/org/chromium/base/StrictModeContext.java",
+        "base/android/java/src/org/chromium/base/SysUtils.java",
         "base/android/java/src/org/chromium/base/ThreadUtils.java",
         "base/android/java/src/org/chromium/base/TimeUtils.java",
         "base/android/java/src/org/chromium/base/TimezoneUtils.java",
@@ -2978,6 +2880,8 @@
         "base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java",
         "base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java",
         "base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java",
+        "base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
+        "base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
         "base/android/java/src/org/chromium/base/library_loader/Linker.java",
         "base/android/java/src/org/chromium/base/library_loader/LinkerJni.java",
         "base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
@@ -3002,18 +2906,6 @@
         "base/android/java/src/org/chromium/base/metrics/TimingMetric.java",
         "base/android/java/src/org/chromium/base/metrics/UmaRecorder.java",
         "base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java",
-        "base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java",
-        "base/android/java/src/org/chromium/base/process_launcher/BindService.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java",
-        "base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java",
         "base/android/java/src/org/chromium/base/supplier/BooleanSupplier.java",
         "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
         "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
@@ -3048,45 +2940,6 @@
         "build/android/java/src/org/chromium/build/annotations/MainDex.java",
         "build/android/java/src/org/chromium/build/annotations/MockedInTests.java",
         "build/android/java/src/org/chromium/build/annotations/UsedByReflection.java",
-        "components/cronet/android/api/src/org/chromium/net/BidirectionalStream.java",
-        "components/cronet/android/api/src/org/chromium/net/CallbackException.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetEngine.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetException.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetProvider.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalBidirectionalStream.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalUrlRequest.java",
-        "components/cronet/android/api/src/org/chromium/net/ICronetEngineBuilder.java",
-        "components/cronet/android/api/src/org/chromium/net/InlineExecutionProhibitedException.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkException.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkQualityThroughputListener.java",
-        "components/cronet/android/api/src/org/chromium/net/QuicException.java",
-        "components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataProvider.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataProviders.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataSink.java",
-        "components/cronet/android/api/src/org/chromium/net/UrlRequest.java",
-        "components/cronet/android/api/src/org/chromium/net/UrlResponseInfo.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ByteArrayCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ContentTypeParametersParser.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/CronetRequestCompletionListener.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/CronetResponse.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ImplicitFlowControlCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/InMemoryTransformCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/JsonCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/RedirectHandler.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/RedirectHandlers.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/StringCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/UploadDataProviders.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/UrlRequestCallbacks.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetController.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetEngine.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetProvider.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeUrlRequest.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeUrlResponse.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/ResponseMatcher.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/UrlResponseMatcher.java",
         "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamBuilderImpl.java",
         "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CallbackExceptionImpl.java",
@@ -3102,16 +2955,7 @@
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/InputStreamChannel.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetEngine.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetEngineBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetProvider.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUploadDataSinkBase.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequest.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequestUtils.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderWithLibraryLoaderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetProvider.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NetworkExceptionImpl.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NoOpLogger.java",
         "components/cronet/android/java/src/org/chromium/net/impl/Preconditions.java",
@@ -3171,6 +3015,8 @@
          "--header-path " +
          "$(genDir)/components/cronet/android/cronet_jni_registration.h " +
          "--manual_jni_registration " +
+         "--package_prefix " +
+         "android.net.http.internal " +
          ";sed -i -e 's/OUT_SOONG_.TEMP_SBOX_.*_OUT/GEN/g'  " +
          "$(genDir)/components/cronet/android/cronet_jni_registration.h",
     out: [
@@ -3200,6 +3046,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -3221,7 +3068,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -3242,8 +3088,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
@@ -3253,9 +3099,7 @@
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -3265,18 +3109,14 @@
         "buildtools/third_party/libc++/",
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
-        "components/cronet/native/generated/",
-        "components/cronet/native/include/",
-        "components/grpc_support/include/",
         "net/third_party/quiche/overrides/",
         "net/third_party/quiche/src/",
         "net/third_party/quiche/src/quiche/common/platform/default/",
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -3318,7 +3158,7 @@
          "-f " +
          "$(location build/util/LASTCHANGE) " +
          "-e " +
-         "'API_LEVEL=20' " +
+         "'API_LEVEL=19' " +
          "-o " +
          "$(out) " +
          "$(location components/cronet/android/java/src/org/chromium/net/impl/ImplVersion.template)",
@@ -3384,10 +3224,10 @@
          "-f " +
          "$(location build/util/LASTCHANGE) " +
          "-e " +
-         "'API_LEVEL=20' " +
+         "'API_LEVEL=19' " +
          "-o " +
          "$(out) " +
-         "$(location components/cronet/android/api/src/org/chromium/net/ApiVersion.template)",
+         "$(location components/cronet/android/api/src/android/net/http/ApiVersion.template)",
     out: [
         "components/cronet/android/templates/org/chromium/net/ApiVersion.java",
     ],
@@ -3396,7 +3236,7 @@
         "build/util/android_chrome_version.py",
         "build/util/version.py",
         "chrome/VERSION",
-        "components/cronet/android/api/src/org/chromium/net/ApiVersion.template",
+        "components/cronet/android/api/src/android/net/http/ApiVersion.template",
     ],
 }
 
@@ -3575,6 +3415,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -3596,7 +3437,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -3610,8 +3450,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
@@ -3621,9 +3461,7 @@
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -3640,54 +3478,7 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //components/cronet:cronet_version_header
-cc_object {
-    name: "cronet_aml_components_cronet_cronet_version_header",
-    generated_headers: [
-        "cronet_aml_components_cronet_cronet_version_header_action",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -3755,16 +3546,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -3777,300 +3566,7 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //components/cronet/native:cronet_native_headers
-cc_object {
-    name: "cronet_aml_components_cronet_native_cronet_native_headers",
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "components/cronet/native/generated/",
-        "components/cronet/native/include/",
-        "components/grpc_support/include/",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //components/cronet/native:cronet_native_impl
-cc_object {
-    name: "cronet_aml_components_cronet_native_cronet_native_impl",
-    srcs: [
-        "components/cronet/native/buffer.cc",
-        "components/cronet/native/engine.cc",
-        "components/cronet/native/generated/cronet.idl_impl_interface.cc",
-        "components/cronet/native/generated/cronet.idl_impl_struct.cc",
-        "components/cronet/native/io_buffer_with_cronet_buffer.cc",
-        "components/cronet/native/native_metrics_util.cc",
-        "components/cronet/native/runnables.cc",
-        "components/cronet/native/upload_data_sink.cc",
-        "components/cronet/native/url_request.cc",
-    ],
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_components_prefs_prefs",
-        "cronet_aml_crypto_crypto",
-        "cronet_aml_net_net",
-        "cronet_aml_net_preload_decoder",
-        "cronet_aml_net_third_party_quiche_quiche",
-        "cronet_aml_net_uri_template",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_brotli_common",
-        "cronet_aml_third_party_brotli_dec",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-        "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
-        "cronet_aml_url_url",
-    ],
-    generated_headers: [
-        "cronet_aml_components_cronet_cronet_buildflags",
-        "cronet_aml_components_cronet_cronet_version_header_action",
-        "cronet_aml_third_party_metrics_proto_metrics_proto_gen_headers",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
-        "-DGOOGLE_PROTOBUF_NO_RTTI",
-        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-        "-DHAVE_PTHREAD",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "components/cronet/native/generated/",
-        "components/cronet/native/include/",
-        "components/grpc_support/include/",
-        "net/third_party/quiche/overrides/",
-        "net/third_party/quiche/src/",
-        "net/third_party/quiche/src/quiche/common/platform/default/",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-        "third_party/protobuf/src/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //components/grpc_support:grpc_support
-cc_object {
-    name: "cronet_aml_components_grpc_support_grpc_support",
-    srcs: [
-        "components/grpc_support/bidirectional_stream.cc",
-        "components/grpc_support/bidirectional_stream_c.cc",
-    ],
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_crypto_crypto",
-        "cronet_aml_net_net",
-        "cronet_aml_net_preload_decoder",
-        "cronet_aml_net_third_party_quiche_quiche",
-        "cronet_aml_net_uri_template",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_brotli_common",
-        "cronet_aml_third_party_brotli_dec",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-        "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
-        "cronet_aml_url_url",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
-        "-DGOOGLE_PROTOBUF_NO_RTTI",
-        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-        "-DHAVE_PTHREAD",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "net/third_party/quiche/overrides/",
-        "net/third_party/quiche/src/",
-        "net/third_party/quiche/src/quiche/common/platform/default/",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-        "third_party/protobuf/src/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //components/grpc_support:headers
-cc_object {
-    name: "cronet_aml_components_grpc_support_headers",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -4120,8 +3616,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
@@ -4131,9 +3627,7 @@
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -4147,7 +3641,7 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -4178,7 +3672,9 @@
          "--output_name " +
          "PrefService_jni.h " +
          "--input_file " +
-         "$(location components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java)",
+         "$(location components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java) " +
+         "--package_prefix " +
+         "android.net.http.internal",
     out: [
         "components/prefs/android/jni_headers/PrefService_jni.h",
     ],
@@ -4255,16 +3751,14 @@
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
         "-DCOMPONENTS_PREFS_IMPLEMENTATION",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -4277,7 +3771,7 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -4368,16 +3862,14 @@
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
         "-DCRYPTO_IMPLEMENTATION",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -4390,7 +3882,7 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -4432,9 +3924,11 @@
     min_sdk_version: "29",
     target: {
         android: {
+            shared_libs: [
+                "libmediandk",
+            ],
             header_libs: [
                 "jni_headers",
-                "media_ndk_headers",
             ],
         },
         host: {
@@ -4445,50 +3939,6 @@
     },
 }
 
-// GN: //ipc:param_traits
-cc_object {
-    name: "cronet_aml_ipc_param_traits",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
 // GN: //gn:java
 java_library {
     name: "cronet_aml_java",
@@ -4539,7 +3989,6 @@
         "base/android/java/src/org/chromium/base/Function.java",
         "base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
         "base/android/java/src/org/chromium/base/IntStringCallback.java",
-        "base/android/java/src/org/chromium/base/IntentUtils.java",
         "base/android/java/src/org/chromium/base/JNIUtils.java",
         "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
         "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
@@ -4633,21 +4082,6 @@
         "base/android/java/src/org/chromium/base/metrics/TimingMetric.java",
         "base/android/java/src/org/chromium/base/metrics/UmaRecorder.java",
         "base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java",
-        "base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java",
-        "base/android/java/src/org/chromium/base/process_launcher/BindService.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java",
-        "base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java",
-        "base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java",
-        "base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl",
-        "base/android/java/src/org/chromium/base/process_launcher/IParentProcess.aidl",
         "base/android/java/src/org/chromium/base/supplier/BooleanSupplier.java",
         "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
         "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
@@ -4682,45 +4116,6 @@
         "build/android/java/src/org/chromium/build/annotations/MainDex.java",
         "build/android/java/src/org/chromium/build/annotations/MockedInTests.java",
         "build/android/java/src/org/chromium/build/annotations/UsedByReflection.java",
-        "components/cronet/android/api/src/org/chromium/net/BidirectionalStream.java",
-        "components/cronet/android/api/src/org/chromium/net/CallbackException.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetEngine.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetException.java",
-        "components/cronet/android/api/src/org/chromium/net/CronetProvider.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalBidirectionalStream.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalCronetEngine.java",
-        "components/cronet/android/api/src/org/chromium/net/ExperimentalUrlRequest.java",
-        "components/cronet/android/api/src/org/chromium/net/ICronetEngineBuilder.java",
-        "components/cronet/android/api/src/org/chromium/net/InlineExecutionProhibitedException.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkException.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java",
-        "components/cronet/android/api/src/org/chromium/net/NetworkQualityThroughputListener.java",
-        "components/cronet/android/api/src/org/chromium/net/QuicException.java",
-        "components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataProvider.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataProviders.java",
-        "components/cronet/android/api/src/org/chromium/net/UploadDataSink.java",
-        "components/cronet/android/api/src/org/chromium/net/UrlRequest.java",
-        "components/cronet/android/api/src/org/chromium/net/UrlResponseInfo.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ByteArrayCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ContentTypeParametersParser.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/CronetRequestCompletionListener.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/CronetResponse.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/ImplicitFlowControlCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/InMemoryTransformCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/JsonCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/RedirectHandler.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/RedirectHandlers.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/StringCronetCallback.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/UploadDataProviders.java",
-        "components/cronet/android/api/src/org/chromium/net/apihelpers/UrlRequestCallbacks.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetController.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetEngine.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeCronetProvider.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeUrlRequest.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/FakeUrlResponse.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/ResponseMatcher.java",
-        "components/cronet/android/fake/java/org/chromium/net/test/UrlResponseMatcher.java",
         "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamBuilderImpl.java",
         "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CallbackExceptionImpl.java",
@@ -4736,16 +4131,7 @@
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java",
         "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/InputStreamChannel.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetEngine.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetEngineBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaCronetProvider.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUploadDataSinkBase.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequest.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequestUtils.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderWithLibraryLoaderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetProvider.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NetworkExceptionImpl.java",
         "components/cronet/android/java/src/org/chromium/net/impl/NoOpLogger.java",
         "components/cronet/android/java/src/org/chromium/net/impl/Preconditions.java",
@@ -4789,16 +4175,16 @@
         "net/android/java/src/org/chromium/net/X509Util.java",
         "url/android/java/src/org/chromium/url/IDNStringUtil.java",
     ],
+    static_libs: [
+        "modules-utils-build_system",
+    ],
     apex_available: [
-        "//apex_available:platform",
         "com.android.tethering",
     ],
     libs: [
-        "android-support-multidex",
         "androidx.annotation_annotation",
         "androidx.annotation_annotation-experimental-nodeps",
-        "androidx.collection_collection",
-        "androidx.core_core-nodeps",
+        "cronet_aml_api_java",
         "framework-connectivity-t.stubs.module_lib",
         "framework-connectivity.stubs.module_lib",
         "framework-mediaprovider.stubs.module_lib",
@@ -4818,6 +4204,10 @@
         "cronet_aml_java_jni_annotation_preprocessor",
     ],
     sdk_version: "module_current",
+    javacflags: [
+        "-Aorg.chromium.chrome.skipGenJni",
+        "-Apackage_prefix=android.net.http.internal",
+    ],
 }
 
 // GN: //base/android/jni_generator:jni_processor
@@ -5030,94 +4420,6 @@
     ],
 }
 
-// GN: //net:constants
-cc_object {
-    name: "cronet_aml_net_constants",
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //net/data/ssl/chrome_root_store:gen_root_store_inc
-cc_genrule {
-    name: "cronet_aml_net_data_ssl_chrome_root_store_gen_root_store_inc",
-    cmd: "$(location build/gn_run_binary.py) clang_x64/root_store_tool " +
-         "--root-store " +
-         "../../net/data/ssl/chrome_root_store/root_store.textproto " +
-         "--certs " +
-         "../../net/data/ssl/chrome_root_store/root_store.certs " +
-         "--write-cpp-root-store " +
-         "gen/net/data/ssl/chrome_root_store/chrome-root-store-inc.cc " +
-         "--write-cpp-ev-roots " +
-         "gen/net/data/ssl/chrome_root_store/chrome-ev-roots-inc.cc",
-    out: [
-        "net/data/ssl/chrome_root_store/chrome-ev-roots-inc.cc",
-        "net/data/ssl/chrome_root_store/chrome-root-store-inc.cc",
-    ],
-    tool_files: [
-        "build/gn_run_binary.py",
-        "net/data/ssl/chrome_root_store/root_store.certs",
-        "net/data/ssl/chrome_root_store/root_store.textproto",
-    ],
-    apex_available: [
-        "com.android.tethering",
-    ],
-}
-
 // GN: //net/dns:dns
 cc_object {
     name: "cronet_aml_net_dns_dns",
@@ -5163,6 +4465,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -5182,7 +4485,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -5203,8 +4505,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DENABLE_BUILT_IN_DNS",
@@ -5216,9 +4518,7 @@
         "-DNET_IMPLEMENTATION",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -5235,389 +4535,8 @@
         "third_party/boringssl/src/include/",
         "third_party/brotli/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //net/dns:dns_client
-cc_object {
-    name: "cronet_aml_net_dns_dns_client",
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_crypto_crypto",
-        "cronet_aml_net_preload_decoder",
-        "cronet_aml_net_third_party_quiche_quiche",
-        "cronet_aml_net_uri_template",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_brotli_common",
-        "cronet_aml_third_party_brotli_dec",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-        "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
-        "cronet_aml_url_url",
-    ],
-    generated_headers: [
-        "cronet_aml_base_debugging_buildflags",
-        "cronet_aml_base_logging_buildflags",
-        "cronet_aml_build_chromeos_buildflags",
-        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
-        "cronet_aml_net_buildflags",
-        "cronet_aml_net_isolation_info_proto_gen_headers",
-        "cronet_aml_net_net_jni_headers",
-        "cronet_aml_net_net_nqe_proto_gen_headers",
-        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
-        "cronet_aml_url_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DENABLE_BUILT_IN_DNS",
-        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
-        "-DGOOGLE_PROTOBUF_NO_RTTI",
-        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-        "-DHAVE_PTHREAD",
-        "-DHAVE_SYS_UIO_H",
-        "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "net/third_party/quiche/overrides/",
-        "net/third_party/quiche/src/",
-        "net/third_party/quiche/src/quiche/common/platform/default/",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-        "third_party/brotli/include/",
-        "third_party/protobuf/src/",
-        "third_party/zlib/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //net/dns:host_resolver
-cc_object {
-    name: "cronet_aml_net_dns_host_resolver",
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_crypto_crypto",
-        "cronet_aml_net_preload_decoder",
-        "cronet_aml_net_third_party_quiche_quiche",
-        "cronet_aml_net_uri_template",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_brotli_common",
-        "cronet_aml_third_party_brotli_dec",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-        "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
-        "cronet_aml_url_url",
-    ],
-    generated_headers: [
-        "cronet_aml_base_debugging_buildflags",
-        "cronet_aml_base_logging_buildflags",
-        "cronet_aml_build_chromeos_buildflags",
-        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
-        "cronet_aml_net_buildflags",
-        "cronet_aml_net_isolation_info_proto_gen_headers",
-        "cronet_aml_net_net_jni_headers",
-        "cronet_aml_net_net_nqe_proto_gen_headers",
-        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
-        "cronet_aml_url_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DENABLE_BUILT_IN_DNS",
-        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
-        "-DGOOGLE_PROTOBUF_NO_RTTI",
-        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-        "-DHAVE_PTHREAD",
-        "-DHAVE_SYS_UIO_H",
-        "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "net/third_party/quiche/overrides/",
-        "net/third_party/quiche/src/",
-        "net/third_party/quiche/src/quiche/common/platform/default/",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-        "third_party/brotli/include/",
-        "third_party/protobuf/src/",
-        "third_party/zlib/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //net/dns:host_resolver_manager
-cc_object {
-    name: "cronet_aml_net_dns_host_resolver_manager",
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_crypto_crypto",
-        "cronet_aml_net_preload_decoder",
-        "cronet_aml_net_third_party_quiche_quiche",
-        "cronet_aml_net_uri_template",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_brotli_common",
-        "cronet_aml_third_party_brotli_dec",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-        "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
-        "cronet_aml_url_url",
-    ],
-    generated_headers: [
-        "cronet_aml_base_debugging_buildflags",
-        "cronet_aml_base_logging_buildflags",
-        "cronet_aml_build_chromeos_buildflags",
-        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
-        "cronet_aml_net_buildflags",
-        "cronet_aml_net_isolation_info_proto_gen_headers",
-        "cronet_aml_net_net_jni_headers",
-        "cronet_aml_net_net_nqe_proto_gen_headers",
-        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
-        "cronet_aml_url_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DENABLE_BUILT_IN_DNS",
-        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
-        "-DGOOGLE_PROTOBUF_NO_RTTI",
-        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-        "-DHAVE_PTHREAD",
-        "-DHAVE_SYS_UIO_H",
-        "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "net/third_party/quiche/overrides/",
-        "net/third_party/quiche/src/",
-        "net/third_party/quiche/src/quiche/common/platform/default/",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-        "third_party/brotli/include/",
-        "third_party/protobuf/src/",
-        "third_party/zlib/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //net/dns:mdns_client
-cc_object {
-    name: "cronet_aml_net_dns_mdns_client",
-    shared_libs: [
-        "libandroid",
-        "liblog",
-    ],
-    static_libs: [
-        "cronet_aml_base_allocator_partition_allocator_partition_alloc",
-        "cronet_aml_base_base",
-        "cronet_aml_base_base_static",
-        "cronet_aml_base_third_party_double_conversion_double_conversion",
-        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
-        "cronet_aml_crypto_crypto",
-        "cronet_aml_net_preload_decoder",
-        "cronet_aml_net_third_party_quiche_quiche",
-        "cronet_aml_net_uri_template",
-        "cronet_aml_third_party_boringssl_boringssl",
-        "cronet_aml_third_party_brotli_common",
-        "cronet_aml_third_party_brotli_dec",
-        "cronet_aml_third_party_icu_icui18n",
-        "cronet_aml_third_party_icu_icuuc_private",
-        "cronet_aml_third_party_libevent_libevent",
-        "cronet_aml_third_party_modp_b64_modp_b64",
-        "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
-        "cronet_aml_url_url",
-    ],
-    generated_headers: [
-        "cronet_aml_base_debugging_buildflags",
-        "cronet_aml_base_logging_buildflags",
-        "cronet_aml_build_chromeos_buildflags",
-        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
-        "cronet_aml_net_buildflags",
-        "cronet_aml_net_isolation_info_proto_gen_headers",
-        "cronet_aml_net_net_jni_headers",
-        "cronet_aml_net_net_nqe_proto_gen_headers",
-        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
-        "cronet_aml_url_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DENABLE_BUILT_IN_DNS",
-        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
-        "-DGOOGLE_PROTOBUF_NO_RTTI",
-        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-        "-DHAVE_PTHREAD",
-        "-DHAVE_SYS_UIO_H",
-        "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "net/third_party/quiche/overrides/",
-        "net/third_party/quiche/src/",
-        "net/third_party/quiche/src/quiche/common/platform/default/",
-        "third_party/abseil-cpp/",
-        "third_party/boringssl/src/include/",
-        "third_party/brotli/include/",
-        "third_party/protobuf/src/",
-        "third_party/zlib/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -5648,6 +4567,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -5667,7 +4587,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -5688,8 +4607,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DENABLE_BUILT_IN_DNS",
@@ -5701,9 +4620,7 @@
         "-DNET_IMPLEMENTATION",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -5720,9 +4637,8 @@
         "third_party/boringssl/src/include/",
         "third_party/brotli/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -5765,6 +4681,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -5784,7 +4701,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -5806,8 +4722,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DENABLE_BUILT_IN_DNS",
@@ -5819,9 +4735,7 @@
         "-DNET_IMPLEMENTATION",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -5838,9 +4752,8 @@
         "third_party/boringssl/src/include/",
         "third_party/brotli/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -5858,7 +4771,7 @@
 // GN: //net:ios_cronet_buildflags
 cc_genrule {
     name: "cronet_aml_net_ios_cronet_buildflags",
-    cmd: "echo '--flags CRONET_BUILD=\"false\"' | " +
+    cmd: "echo '--flags CRONET_BUILD=\"true\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -5887,9 +4800,9 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/base --cpp_out=lite=true:$(genDir)/external/chromium_org/net/base/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/base --cpp_out=lite=true:$(genDir)/external/cronet/net/base/ $(in)",
     out: [
-        "external/chromium_org/net/base/isolation_info.pb.cc",
+        "external/cronet/net/base/isolation_info.pb.cc",
     ],
     apex_available: [
         "com.android.tethering",
@@ -5905,9 +4818,9 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/base --cpp_out=lite=true:$(genDir)/external/chromium_org/net/base/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/base --cpp_out=lite=true:$(genDir)/external/cronet/net/base/ $(in)",
     out: [
-        "external/chromium_org/net/base/isolation_info.pb.h",
+        "external/cronet/net/base/isolation_info.pb.h",
     ],
     export_include_dirs: [
         ".",
@@ -6415,6 +5328,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -6434,7 +5348,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -6475,8 +5388,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DENABLE_BUILT_IN_DNS",
@@ -6488,9 +5401,7 @@
         "-DNET_IMPLEMENTATION",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -6507,9 +5418,8 @@
         "third_party/boringssl/src/include/",
         "third_party/brotli/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_arm: {
             srcs: [
@@ -6550,6 +5460,7 @@
         "libandroid",
         "liblog",
         "libprotobuf-cpp-lite",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -6566,7 +5477,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
     ],
     generated_headers: [
         "cronet_aml_base_debugging_buildflags",
@@ -6583,8 +5493,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DENABLE_BUILT_IN_DNS",
@@ -6596,9 +5506,7 @@
         "-DNET_IMPLEMENTATION",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -6612,53 +5520,8 @@
         "third_party/boringssl/src/include/",
         "third_party/brotli/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //net:net_export_header
-cc_object {
-    name: "cronet_aml_net_net_export_header",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -6749,7 +5612,9 @@
          "--input_file " +
          "$(location net/android/java/src/org/chromium/net/ProxyChangeListener.java) " +
          "--input_file " +
-         "$(location net/android/java/src/org/chromium/net/X509Util.java)",
+         "$(location net/android/java/src/org/chromium/net/X509Util.java) " +
+         "--package_prefix " +
+         "android.net.http.internal",
     out: [
         "net/net_jni_headers/AndroidCertVerifyResult_jni.h",
         "net/net_jni_headers/AndroidKeyStore_jni.h",
@@ -6786,9 +5651,9 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/nqe/proto --cpp_out=lite=true:$(genDir)/external/chromium_org/net/nqe/proto/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/nqe/proto --cpp_out=lite=true:$(genDir)/external/cronet/net/nqe/proto/ $(in)",
     out: [
-        "external/chromium_org/net/nqe/proto/network_id_proto.pb.cc",
+        "external/cronet/net/nqe/proto/network_id_proto.pb.cc",
     ],
     apex_available: [
         "com.android.tethering",
@@ -6804,9 +5669,9 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/nqe/proto --cpp_out=lite=true:$(genDir)/external/chromium_org/net/nqe/proto/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/nqe/proto --cpp_out=lite=true:$(genDir)/external/cronet/net/nqe/proto/ $(in)",
     out: [
-        "external/chromium_org/net/nqe/proto/network_id_proto.pb.h",
+        "external/cronet/net/nqe/proto/network_id_proto.pb.h",
     ],
     export_include_dirs: [
         ".",
@@ -6829,6 +5694,7 @@
         "libandroid",
         "liblog",
         "libprotobuf-cpp-lite",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -6845,7 +5711,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -6860,8 +5725,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
@@ -6871,9 +5736,7 @@
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -6890,7 +5753,7 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -6933,16 +5796,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -6955,7 +5816,7 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -6981,11 +5842,11 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/third_party/quiche/src --cpp_out=lite=true:$(genDir)/external/chromium_org/net/third_party/quiche/src/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/ $(in)",
     out: [
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.pb.cc",
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.pb.cc",
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.pb.cc",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.pb.cc",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.pb.cc",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.pb.cc",
     ],
     apex_available: [
         "com.android.tethering",
@@ -7003,11 +5864,11 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/third_party/quiche/src --cpp_out=lite=true:$(genDir)/external/chromium_org/net/third_party/quiche/src/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/ $(in)",
     out: [
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.pb.h",
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.pb.h",
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.pb.h",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.pb.h",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.pb.h",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.pb.h",
     ],
     export_include_dirs: [
         ".",
@@ -7028,9 +5889,9 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/third_party/quiche/src/quiche/quic/test_tools --cpp_out=lite=true:$(genDir)/external/chromium_org/net/third_party/quiche/src/quiche/quic/test_tools/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src/quiche/quic/test_tools --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/ $(in)",
     out: [
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.cc",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.cc",
     ],
     apex_available: [
         "com.android.tethering",
@@ -7046,9 +5907,9 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/net/third_party/quiche/src/quiche/quic/test_tools --cpp_out=lite=true:$(genDir)/external/chromium_org/net/third_party/quiche/src/quiche/quic/test_tools/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src/quiche/quic/test_tools --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/ $(in)",
     out: [
-        "external/chromium_org/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.h",
+        "external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.h",
     ],
     export_include_dirs: [
         ".",
@@ -7338,6 +6199,7 @@
         "net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.cc",
         "net/third_party/quiche/src/quiche/quic/core/quic_framer.cc",
         "net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_legacy_version_encapsulator.cc",
         "net/third_party/quiche/src/quiche/quic/core/quic_mtu_discovery.cc",
         "net/third_party/quiche/src/quiche/quic/core/quic_network_blackhole_detector.cc",
         "net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc",
@@ -7396,6 +6258,7 @@
         "libandroid",
         "liblog",
         "libprotobuf-cpp-lite",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -7410,7 +6273,6 @@
         "cronet_aml_third_party_libevent_libevent",
         "cronet_aml_third_party_modp_b64_modp_b64",
         "cronet_aml_third_party_protobuf_protobuf_lite",
-        "cronet_aml_third_party_zlib_zlib",
         "cronet_aml_url_url",
     ],
     generated_headers: [
@@ -7427,8 +6289,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
@@ -7439,9 +6301,7 @@
         "-DIS_QUICHE_IMPL",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -7457,9 +6317,8 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -7505,16 +6364,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -7527,7 +6384,7 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -7570,17 +6427,15 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-DIS_URI_TEMPLATE_IMPL",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -7593,187 +6448,7 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp:absl
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl",
-    generated_headers: [
-        "cronet_aml_build_chromeos_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/algorithm:algorithm
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_algorithm_algorithm",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/algorithm:container
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_algorithm_container",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:atomic_hook
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_atomic_hook",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -7805,16 +6480,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -7824,359 +6497,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:base_internal
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_base_internal",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:config
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_config",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:core_headers
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_core_headers",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:cycleclock_internal
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_cycleclock_internal",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:dynamic_annotations
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_dynamic_annotations",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:endian
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_endian",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:errno_saver
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_errno_saver",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:fast_type_id
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_fast_type_id",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -8204,16 +6525,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -8223,7 +6542,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -8251,16 +6570,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -8270,51 +6587,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:prefetch
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_prefetch",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -8342,16 +6615,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -8361,7 +6632,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -8389,16 +6660,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -8408,7 +6677,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -8436,16 +6705,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -8455,7 +6722,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -8483,16 +6750,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -8502,579 +6767,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/cleanup:cleanup
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_cleanup_cleanup",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/cleanup:cleanup_internal
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_cleanup_cleanup_internal",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:btree
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_btree",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:common
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_common",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:common_policy_traits
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_common_policy_traits",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:compressed_tuple
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_compressed_tuple",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:container_memory
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_container_memory",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:fixed_array
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_fixed_array",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:flat_hash_map
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_flat_hash_map",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:flat_hash_set
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_flat_hash_set",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:hash_function_defaults
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_hash_function_defaults",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:hash_policy_traits
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_hash_policy_traits",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:hashtable_debug_hooks
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_hashtable_debug_hooks",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9103,16 +6796,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9122,315 +6813,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:inlined_vector
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_inlined_vector",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:inlined_vector_internal
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_inlined_vector_internal",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:layout
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_layout",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:node_hash_map
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_node_hash_map",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:node_hash_set
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_node_hash_set",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:node_slot_policy
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_node_slot_policy",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:raw_hash_map
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_map",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9458,16 +6841,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9477,7 +6858,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9507,16 +6888,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9526,7 +6905,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9554,16 +6933,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9573,7 +6950,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9601,16 +6978,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9620,7 +6995,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9648,16 +7023,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9667,7 +7040,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9695,16 +7068,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9714,7 +7085,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9742,16 +7113,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9761,139 +7130,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/functional:any_invocable
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_functional_any_invocable",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/functional:bind_front
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_functional_bind_front",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/functional:function_ref
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_functional_function_ref",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9921,16 +7158,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9940,7 +7175,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -9968,16 +7203,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -9987,7 +7220,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10015,16 +7248,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10034,139 +7265,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/memory:memory
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_memory_memory",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/meta:type_traits
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_meta_type_traits",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/numeric:bits
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_numeric_bits",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10194,16 +7293,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10213,51 +7310,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/numeric:representation
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_numeric_representation",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10285,16 +7338,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10304,51 +7355,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/profiling:sample_recorder
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_profiling_sample_recorder",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10377,16 +7384,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10396,318 +7401,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:distribution_caller
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_distribution_caller",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:fast_uniform_bits
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_fast_uniform_bits",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:fastmath
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_fastmath",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:generate_real
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_generate_real",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:iostream_state_saver
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_iostream_state_saver",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:nonsecure_base
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_nonsecure_base",
-    generated_headers: [
-        "cronet_aml_build_chromeos_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:pcg_engine
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_pcg_engine",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10738,16 +7432,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10757,7 +7449,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10788,16 +7480,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10807,7 +7497,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10838,16 +7528,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10857,54 +7545,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:randen_engine
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_engine",
-    generated_headers: [
-        "cronet_aml_build_chromeos_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10935,16 +7576,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -10954,7 +7593,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -10985,16 +7624,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11004,7 +7641,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11035,16 +7672,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11054,51 +7689,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:salted_seed_seq
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_salted_seed_seq",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11126,16 +7717,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11145,186 +7734,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:traits
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_traits",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:uniform_helper
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_uniform_helper",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:wide_multiply
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_wide_multiply",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/random:random
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_random",
-    generated_headers: [
-        "cronet_aml_build_chromeos_buildflags",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11352,16 +7762,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11371,7 +7779,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11402,16 +7810,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11421,7 +7827,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11450,16 +7856,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11469,7 +7873,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11497,16 +7901,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11516,7 +7918,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11546,16 +7948,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11565,7 +7965,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11599,16 +7999,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11618,7 +8016,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11646,16 +8044,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11665,7 +8061,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11693,16 +8089,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11712,7 +8106,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11740,16 +8134,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11759,139 +8151,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cordz_statistics
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_statistics",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cordz_update_scope
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_update_scope",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cordz_update_tracker
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_update_tracker",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -11921,16 +8181,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -11940,51 +8198,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:str_format
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_strings_str_format",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12017,16 +8231,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12036,7 +8248,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12060,7 +8272,6 @@
         "third_party/abseil-cpp/absl/strings/escaping.cc",
         "third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc",
         "third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc",
-        "third_party/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc",
         "third_party/abseil-cpp/absl/strings/internal/memutil.cc",
         "third_party/abseil-cpp/absl/strings/match.cc",
         "third_party/abseil-cpp/absl/strings/numbers.cc",
@@ -12077,16 +8288,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12096,7 +8305,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12124,16 +8333,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12143,51 +8350,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/synchronization:kernel_timeout_internal
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_synchronization_kernel_timeout_internal",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12221,16 +8384,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12240,7 +8401,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12268,16 +8429,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12287,7 +8446,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12323,16 +8482,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12342,7 +8499,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12374,16 +8531,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12393,7 +8548,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12421,16 +8576,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12440,7 +8593,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12468,16 +8621,14 @@
         "-DABSL_ALLOCATOR_NOTHROW=1",
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12487,227 +8638,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/types:compare
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_types_compare",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/types:optional
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_types_optional",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/types:span
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_types_span",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/types:variant
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_types_variant",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/abseil-cpp/absl/utility:utility
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_utility_utility",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DABSL_ALLOCATOR_NOTHROW=1",
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/abseil-cpp/",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12734,16 +8665,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -12753,7 +8682,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/android_ndk/sources/android/cpufeatures/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -12780,16 +8709,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -12800,7 +8727,7 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -13096,17 +9023,15 @@
         "-DBORINGSSL_ALLOW_CXX_RUNTIME",
         "-DBORINGSSL_IMPLEMENTATION",
         "-DBORINGSSL_NO_STATIC_INITIALIZER",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-DOPENSSL_SMALL",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -13116,7 +9041,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -13140,16 +9065,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -13161,7 +9084,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_arm: {
             srcs: [
@@ -13247,50 +9170,6 @@
     },
 }
 
-// GN: //third_party/boringssl/src/third_party/fiat:fiat_license
-cc_object {
-    name: "cronet_aml_third_party_boringssl_src_third_party_fiat_fiat_license",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
 // GN: //third_party/brotli:common
 cc_library_static {
     name: "cronet_aml_third_party_brotli_common",
@@ -13308,16 +9187,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -13329,7 +9206,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/brotli/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -13362,16 +9239,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -13381,51 +9256,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/brotli/include/",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/brotli:headers
-cc_object {
-    name: "cronet_aml_third_party_brotli_headers",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -13694,8 +9525,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_DLOPEN=0",
@@ -13713,9 +9544,7 @@
         "-DU_USING_ICU_NAMESPACE=0",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -13726,7 +9555,7 @@
         "third_party/icu/source/common/",
         "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     rtti: true,
     target: {
         android_x86: {
@@ -13952,8 +9781,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_DLOPEN=0",
@@ -13972,9 +9801,7 @@
         "-DU_USING_ICU_NAMESPACE=0",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -13985,7 +9812,7 @@
         "third_party/icu/source/common/",
         "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     rtti: true,
     target: {
         android_x86: {
@@ -14001,50 +9828,6 @@
     },
 }
 
-// GN: //third_party/icu:icuuc_public
-cc_object {
-    name: "cronet_aml_third_party_icu_icuuc_public",
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
-}
-
 // GN: //third_party/libevent:libevent
 cc_library_static {
     name: "cronet_aml_third_party_libevent_libevent",
@@ -14070,17 +9853,15 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_CONFIG_H",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -14090,7 +9871,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/libevent/android/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -14140,35 +9921,35 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/third_party/metrics_proto --cpp_out=lite=true:$(genDir)/external/chromium_org/third_party/metrics_proto/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/third_party/metrics_proto --cpp_out=lite=true:$(genDir)/external/cronet/third_party/metrics_proto/ $(in)",
     out: [
-        "external/chromium_org/third_party/metrics_proto/call_stack_profile.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/cast_logs.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/chrome_os_app_list_launch_event.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/chrome_searchbox_stats.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/chrome_user_metrics_extension.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/custom_tab_session.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/execution_context.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/extension_install.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/histogram_event.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/omnibox_event.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/omnibox_focus_type.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/omnibox_input_type.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/perf_data.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/perf_stat.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/printer_event.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/reporting_info.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/sampled_profile.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/structured_data.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/system_profile.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/trace_log.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/translate_event.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/ukm/aggregate.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/ukm/entry.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/ukm/report.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/ukm/source.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/user_action_event.pb.cc",
-        "external/chromium_org/third_party/metrics_proto/user_demographics.pb.cc",
+        "external/cronet/third_party/metrics_proto/call_stack_profile.pb.cc",
+        "external/cronet/third_party/metrics_proto/cast_logs.pb.cc",
+        "external/cronet/third_party/metrics_proto/chrome_os_app_list_launch_event.pb.cc",
+        "external/cronet/third_party/metrics_proto/chrome_searchbox_stats.pb.cc",
+        "external/cronet/third_party/metrics_proto/chrome_user_metrics_extension.pb.cc",
+        "external/cronet/third_party/metrics_proto/custom_tab_session.pb.cc",
+        "external/cronet/third_party/metrics_proto/execution_context.pb.cc",
+        "external/cronet/third_party/metrics_proto/extension_install.pb.cc",
+        "external/cronet/third_party/metrics_proto/histogram_event.pb.cc",
+        "external/cronet/third_party/metrics_proto/omnibox_event.pb.cc",
+        "external/cronet/third_party/metrics_proto/omnibox_focus_type.pb.cc",
+        "external/cronet/third_party/metrics_proto/omnibox_input_type.pb.cc",
+        "external/cronet/third_party/metrics_proto/perf_data.pb.cc",
+        "external/cronet/third_party/metrics_proto/perf_stat.pb.cc",
+        "external/cronet/third_party/metrics_proto/printer_event.pb.cc",
+        "external/cronet/third_party/metrics_proto/reporting_info.pb.cc",
+        "external/cronet/third_party/metrics_proto/sampled_profile.pb.cc",
+        "external/cronet/third_party/metrics_proto/structured_data.pb.cc",
+        "external/cronet/third_party/metrics_proto/system_profile.pb.cc",
+        "external/cronet/third_party/metrics_proto/trace_log.pb.cc",
+        "external/cronet/third_party/metrics_proto/translate_event.pb.cc",
+        "external/cronet/third_party/metrics_proto/ukm/aggregate.pb.cc",
+        "external/cronet/third_party/metrics_proto/ukm/entry.pb.cc",
+        "external/cronet/third_party/metrics_proto/ukm/report.pb.cc",
+        "external/cronet/third_party/metrics_proto/ukm/source.pb.cc",
+        "external/cronet/third_party/metrics_proto/user_action_event.pb.cc",
+        "external/cronet/third_party/metrics_proto/user_demographics.pb.cc",
     ],
     apex_available: [
         "com.android.tethering",
@@ -14210,35 +9991,35 @@
     tools: [
         "cronet_aml_third_party_protobuf_protoc",
     ],
-    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/chromium_org/third_party/metrics_proto --cpp_out=lite=true:$(genDir)/external/chromium_org/third_party/metrics_proto/ $(in)",
+    cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/third_party/metrics_proto --cpp_out=lite=true:$(genDir)/external/cronet/third_party/metrics_proto/ $(in)",
     out: [
-        "external/chromium_org/third_party/metrics_proto/call_stack_profile.pb.h",
-        "external/chromium_org/third_party/metrics_proto/cast_logs.pb.h",
-        "external/chromium_org/third_party/metrics_proto/chrome_os_app_list_launch_event.pb.h",
-        "external/chromium_org/third_party/metrics_proto/chrome_searchbox_stats.pb.h",
-        "external/chromium_org/third_party/metrics_proto/chrome_user_metrics_extension.pb.h",
-        "external/chromium_org/third_party/metrics_proto/custom_tab_session.pb.h",
-        "external/chromium_org/third_party/metrics_proto/execution_context.pb.h",
-        "external/chromium_org/third_party/metrics_proto/extension_install.pb.h",
-        "external/chromium_org/third_party/metrics_proto/histogram_event.pb.h",
-        "external/chromium_org/third_party/metrics_proto/omnibox_event.pb.h",
-        "external/chromium_org/third_party/metrics_proto/omnibox_focus_type.pb.h",
-        "external/chromium_org/third_party/metrics_proto/omnibox_input_type.pb.h",
-        "external/chromium_org/third_party/metrics_proto/perf_data.pb.h",
-        "external/chromium_org/third_party/metrics_proto/perf_stat.pb.h",
-        "external/chromium_org/third_party/metrics_proto/printer_event.pb.h",
-        "external/chromium_org/third_party/metrics_proto/reporting_info.pb.h",
-        "external/chromium_org/third_party/metrics_proto/sampled_profile.pb.h",
-        "external/chromium_org/third_party/metrics_proto/structured_data.pb.h",
-        "external/chromium_org/third_party/metrics_proto/system_profile.pb.h",
-        "external/chromium_org/third_party/metrics_proto/trace_log.pb.h",
-        "external/chromium_org/third_party/metrics_proto/translate_event.pb.h",
-        "external/chromium_org/third_party/metrics_proto/ukm/aggregate.pb.h",
-        "external/chromium_org/third_party/metrics_proto/ukm/entry.pb.h",
-        "external/chromium_org/third_party/metrics_proto/ukm/report.pb.h",
-        "external/chromium_org/third_party/metrics_proto/ukm/source.pb.h",
-        "external/chromium_org/third_party/metrics_proto/user_action_event.pb.h",
-        "external/chromium_org/third_party/metrics_proto/user_demographics.pb.h",
+        "external/cronet/third_party/metrics_proto/call_stack_profile.pb.h",
+        "external/cronet/third_party/metrics_proto/cast_logs.pb.h",
+        "external/cronet/third_party/metrics_proto/chrome_os_app_list_launch_event.pb.h",
+        "external/cronet/third_party/metrics_proto/chrome_searchbox_stats.pb.h",
+        "external/cronet/third_party/metrics_proto/chrome_user_metrics_extension.pb.h",
+        "external/cronet/third_party/metrics_proto/custom_tab_session.pb.h",
+        "external/cronet/third_party/metrics_proto/execution_context.pb.h",
+        "external/cronet/third_party/metrics_proto/extension_install.pb.h",
+        "external/cronet/third_party/metrics_proto/histogram_event.pb.h",
+        "external/cronet/third_party/metrics_proto/omnibox_event.pb.h",
+        "external/cronet/third_party/metrics_proto/omnibox_focus_type.pb.h",
+        "external/cronet/third_party/metrics_proto/omnibox_input_type.pb.h",
+        "external/cronet/third_party/metrics_proto/perf_data.pb.h",
+        "external/cronet/third_party/metrics_proto/perf_stat.pb.h",
+        "external/cronet/third_party/metrics_proto/printer_event.pb.h",
+        "external/cronet/third_party/metrics_proto/reporting_info.pb.h",
+        "external/cronet/third_party/metrics_proto/sampled_profile.pb.h",
+        "external/cronet/third_party/metrics_proto/structured_data.pb.h",
+        "external/cronet/third_party/metrics_proto/system_profile.pb.h",
+        "external/cronet/third_party/metrics_proto/trace_log.pb.h",
+        "external/cronet/third_party/metrics_proto/translate_event.pb.h",
+        "external/cronet/third_party/metrics_proto/ukm/aggregate.pb.h",
+        "external/cronet/third_party/metrics_proto/ukm/entry.pb.h",
+        "external/cronet/third_party/metrics_proto/ukm/report.pb.h",
+        "external/cronet/third_party/metrics_proto/ukm/source.pb.h",
+        "external/cronet/third_party/metrics_proto/user_action_event.pb.h",
+        "external/cronet/third_party/metrics_proto/user_demographics.pb.h",
     ],
     export_include_dirs: [
         ".",
@@ -14262,16 +10043,14 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -14282,7 +10061,7 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -14386,8 +10165,8 @@
         "third_party/protobuf/src/google/protobuf/wire_format_lite.cc",
         "third_party/protobuf/src/google/protobuf/wrappers.pb.cc",
     ],
-    static_libs: [
-        "cronet_aml_third_party_zlib_zlib",
+    shared_libs: [
+        "libz",
     ],
     host_supported: true,
     device_supported: false,
@@ -14395,8 +10174,8 @@
         "cronet_aml_defaults",
     ],
     cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DCR_SYSROOT_KEY=20220331T153654Z-0",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
@@ -14413,9 +10192,7 @@
         "-D_GNU_SOURCE",
         "-D_LARGEFILE64_SOURCE",
         "-D_LARGEFILE_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-msse3",
     ],
@@ -14425,7 +10202,6 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
     cpp_std: "c++20",
 }
@@ -14476,8 +10252,8 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
@@ -14487,9 +10263,7 @@
         "-DHAVE_SYS_UIO_H",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
     ],
     local_include_dirs: [
@@ -14499,7 +10273,7 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -14522,10 +10296,12 @@
         ":cronet_aml_buildtools_third_party_libc__abi_libc__abi",
         "third_party/protobuf/src/google/protobuf/compiler/main.cc",
     ],
+    shared_libs: [
+        "libz",
+    ],
     static_libs: [
         "cronet_aml_third_party_protobuf_protobuf_full",
         "cronet_aml_third_party_protobuf_protoc_lib",
-        "cronet_aml_third_party_zlib_zlib",
     ],
     host_supported: true,
     device_supported: false,
@@ -14533,8 +10309,8 @@
         "cronet_aml_defaults",
     ],
     cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DCR_SYSROOT_KEY=20220331T153654Z-0",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
@@ -14550,9 +10326,7 @@
         "-D_GNU_SOURCE",
         "-D_LARGEFILE64_SOURCE",
         "-D_LARGEFILE_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-msse3",
     ],
@@ -14656,9 +10430,11 @@
         "third_party/protobuf/src/google/protobuf/compiler/subprocess.cc",
         "third_party/protobuf/src/google/protobuf/compiler/zip_writer.cc",
     ],
+    shared_libs: [
+        "libz",
+    ],
     static_libs: [
         "cronet_aml_third_party_protobuf_protobuf_full",
-        "cronet_aml_third_party_zlib_zlib",
     ],
     host_supported: true,
     device_supported: false,
@@ -14666,8 +10442,8 @@
         "cronet_aml_defaults",
     ],
     cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DCR_SYSROOT_KEY=20220331T153654Z-0",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
@@ -14683,9 +10459,7 @@
         "-D_GNU_SOURCE",
         "-D_LARGEFILE64_SOURCE",
         "-D_LARGEFILE_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-msse3",
     ],
@@ -14699,598 +10473,6 @@
     cpp_std: "c++20",
 }
 
-// GN: //third_party/zlib:zlib
-cc_library_static {
-    name: "cronet_aml_third_party_zlib_zlib",
-    srcs: [
-        ":cronet_aml_third_party_zlib_zlib_adler32_simd",
-        ":cronet_aml_third_party_zlib_zlib_inflate_chunk_simd",
-        "third_party/zlib/adler32.c",
-        "third_party/zlib/compress.c",
-        "third_party/zlib/cpu_features.c",
-        "third_party/zlib/crc32.c",
-        "third_party/zlib/deflate.c",
-        "third_party/zlib/gzclose.c",
-        "third_party/zlib/gzlib.c",
-        "third_party/zlib/gzread.c",
-        "third_party/zlib/gzwrite.c",
-        "third_party/zlib/infback.c",
-        "third_party/zlib/inffast.c",
-        "third_party/zlib/inftrees.c",
-        "third_party/zlib/trees.c",
-        "third_party/zlib/uncompr.c",
-        "third_party/zlib/zutil.c",
-    ],
-    host_supported: true,
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DZLIB_DEBUG",
-        "-DZLIB_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/zlib/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_arm: {
-            srcs: [
-                ":cronet_aml_third_party_android_ndk_cpu_features",
-                ":cronet_aml_third_party_zlib_zlib_arm_crc32",
-            ],
-            cflags: [
-                "-DADLER32_SIMD_NEON",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DARMV8_OS_ANDROID",
-                "-DCRC32_ARMV8_CRC32",
-                "-DDEFLATE_SLIDE_HASH_NEON",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_SIMD_NEON",
-            ],
-            local_include_dirs: [
-                "third_party/android_ndk/sources/android/cpufeatures/",
-            ],
-        },
-        android_arm64: {
-            srcs: [
-                ":cronet_aml_third_party_android_ndk_cpu_features",
-                ":cronet_aml_third_party_zlib_zlib_arm_crc32",
-            ],
-            cflags: [
-                "-DADLER32_SIMD_NEON",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DARMV8_OS_ANDROID",
-                "-DCRC32_ARMV8_CRC32",
-                "-DDEFLATE_SLIDE_HASH_NEON",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_READ_64LE",
-                "-DINFLATE_CHUNK_SIMD_NEON",
-            ],
-            local_include_dirs: [
-                "third_party/android_ndk/sources/android/cpufeatures/",
-            ],
-        },
-        android_x86: {
-            srcs: [
-                ":cronet_aml_third_party_android_ndk_cpu_features",
-                ":cronet_aml_third_party_zlib_zlib_crc32_simd",
-            ],
-            cflags: [
-                "-DADLER32_SIMD_SSSE3",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DCRC32_SIMD_SSE42_PCLMUL",
-                "-DDEFLATE_SLIDE_HASH_SSE2",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_SIMD_SSE2",
-                "-DX86_NOT_WINDOWS",
-                "-msse3",
-            ],
-            local_include_dirs: [
-                "third_party/android_ndk/sources/android/cpufeatures/",
-            ],
-        },
-        android_x86_64: {
-            srcs: [
-                ":cronet_aml_third_party_android_ndk_cpu_features",
-                ":cronet_aml_third_party_zlib_zlib_crc32_simd",
-            ],
-            cflags: [
-                "-DADLER32_SIMD_SSSE3",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DCRC32_SIMD_SSE42_PCLMUL",
-                "-DDEFLATE_SLIDE_HASH_SSE2",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_READ_64LE",
-                "-DINFLATE_CHUNK_SIMD_SSE2",
-                "-DX86_NOT_WINDOWS",
-                "-msse3",
-            ],
-            local_include_dirs: [
-                "third_party/android_ndk/sources/android/cpufeatures/",
-            ],
-        },
-        host: {
-            srcs: [
-                ":cronet_aml_third_party_zlib_zlib_crc32_simd",
-            ],
-            cflags: [
-                "-DADLER32_SIMD_SSSE3",
-                "-DCRC32_SIMD_SSE42_PCLMUL",
-                "-DCR_SYSROOT_KEY=20220331T153654Z-0",
-                "-DDEFLATE_SLIDE_HASH_SSE2",
-                "-DINFLATE_CHUNK_READ_64LE",
-                "-DINFLATE_CHUNK_SIMD_SSE2",
-                "-DUSE_AURA=1",
-                "-DUSE_OZONE=1",
-                "-DUSE_UDEV",
-                "-DX86_NOT_WINDOWS",
-                "-D_FILE_OFFSET_BITS=64",
-                "-D_LARGEFILE64_SOURCE",
-                "-D_LARGEFILE_SOURCE",
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/zlib:zlib_adler32_simd
-cc_object {
-    name: "cronet_aml_third_party_zlib_zlib_adler32_simd",
-    srcs: [
-        "third_party/zlib/adler32_simd.c",
-    ],
-    host_supported: true,
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DZLIB_DEBUG",
-        "-DZLIB_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_arm: {
-            cflags: [
-                "-DADLER32_SIMD_NEON",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        android_arm64: {
-            cflags: [
-                "-DADLER32_SIMD_NEON",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        android_x86: {
-            cflags: [
-                "-DADLER32_SIMD_SSSE3",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-DX86_NOT_WINDOWS",
-                "-msse3",
-                "-mssse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-DADLER32_SIMD_SSSE3",
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-DX86_NOT_WINDOWS",
-                "-msse3",
-                "-mssse3",
-            ],
-        },
-        host: {
-            cflags: [
-                "-DADLER32_SIMD_SSSE3",
-                "-DCR_SYSROOT_KEY=20220331T153654Z-0",
-                "-DUSE_AURA=1",
-                "-DUSE_OZONE=1",
-                "-DUSE_UDEV",
-                "-DX86_NOT_WINDOWS",
-                "-D_FILE_OFFSET_BITS=64",
-                "-D_LARGEFILE64_SOURCE",
-                "-D_LARGEFILE_SOURCE",
-                "-msse3",
-                "-mssse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/zlib:zlib_arm_crc32
-cc_object {
-    name: "cronet_aml_third_party_zlib_zlib_arm_crc32",
-    srcs: [
-        "third_party/zlib/crc32_simd.c",
-    ],
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DARMV8_OS_ANDROID",
-        "-DCRC32_ARMV8_CRC32",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DHAVE_SYS_UIO_H",
-        "-DZLIB_DEBUG",
-        "-DZLIB_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/zlib/",
-    ],
-    cpp_std: "c++20",
-}
-
-// GN: //third_party/zlib:zlib_common_headers
-cc_object {
-    name: "cronet_aml_third_party_zlib_zlib_common_headers",
-    host_supported: true,
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_arm: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        android_arm64: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        android_x86: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-msse3",
-            ],
-        },
-        host: {
-            cflags: [
-                "-DCR_SYSROOT_KEY=20220331T153654Z-0",
-                "-DUSE_AURA=1",
-                "-DUSE_OZONE=1",
-                "-DUSE_UDEV",
-                "-D_FILE_OFFSET_BITS=64",
-                "-D_LARGEFILE64_SOURCE",
-                "-D_LARGEFILE_SOURCE",
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/zlib:zlib_crc32_simd
-cc_object {
-    name: "cronet_aml_third_party_zlib_zlib_crc32_simd",
-    srcs: [
-        "third_party/zlib/crc32_simd.c",
-        "third_party/zlib/crc_folding.c",
-    ],
-    host_supported: true,
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DCRC32_SIMD_SSE42_PCLMUL",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DZLIB_DEBUG",
-        "-DZLIB_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-        "-mpclmul",
-        "-msse3",
-        "-msse4.2",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        host: {
-            cflags: [
-                "-DCR_SYSROOT_KEY=20220331T153654Z-0",
-                "-DUSE_AURA=1",
-                "-DUSE_OZONE=1",
-                "-DUSE_UDEV",
-                "-D_FILE_OFFSET_BITS=64",
-                "-D_LARGEFILE64_SOURCE",
-                "-D_LARGEFILE_SOURCE",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/zlib:zlib_inflate_chunk_simd
-cc_object {
-    name: "cronet_aml_third_party_zlib_zlib_inflate_chunk_simd",
-    srcs: [
-        "third_party/zlib/contrib/optimizations/inffast_chunk.c",
-        "third_party/zlib/contrib/optimizations/inflate.c",
-    ],
-    host_supported: true,
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DZLIB_DEBUG",
-        "-DZLIB_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-        "third_party/zlib/",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_arm: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_SIMD_NEON",
-            ],
-        },
-        android_arm64: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_READ_64LE",
-                "-DINFLATE_CHUNK_SIMD_NEON",
-            ],
-        },
-        android_x86: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_SIMD_SSE2",
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DHAVE_SYS_UIO_H",
-                "-DINFLATE_CHUNK_READ_64LE",
-                "-DINFLATE_CHUNK_SIMD_SSE2",
-                "-msse3",
-            ],
-        },
-        host: {
-            cflags: [
-                "-DCR_SYSROOT_KEY=20220331T153654Z-0",
-                "-DINFLATE_CHUNK_READ_64LE",
-                "-DINFLATE_CHUNK_SIMD_SSE2",
-                "-DUSE_AURA=1",
-                "-DUSE_OZONE=1",
-                "-DUSE_UDEV",
-                "-D_FILE_OFFSET_BITS=64",
-                "-D_LARGEFILE64_SOURCE",
-                "-D_LARGEFILE_SOURCE",
-                "-msse3",
-            ],
-        },
-    },
-}
-
-// GN: //third_party/zlib:zlib_slide_hash_simd
-cc_object {
-    name: "cronet_aml_third_party_zlib_zlib_slide_hash_simd",
-    host_supported: true,
-    defaults: [
-        "cronet_aml_defaults",
-    ],
-    cflags: [
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
-        "-DZLIB_DEBUG",
-        "-DZLIB_IMPLEMENTATION",
-        "-D_DEBUG",
-        "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
-        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
-        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-    ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
-    ],
-    cpp_std: "c++20",
-    target: {
-        android_arm: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DDEFLATE_SLIDE_HASH_NEON",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        android_arm64: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DDEFLATE_SLIDE_HASH_NEON",
-                "-DHAVE_SYS_UIO_H",
-            ],
-        },
-        android_x86: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DDEFLATE_SLIDE_HASH_SSE2",
-                "-DHAVE_SYS_UIO_H",
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-DANDROID",
-                "-DANDROID_NDK_VERSION_ROLL=r23_1",
-                "-DDEFLATE_SLIDE_HASH_SSE2",
-                "-DHAVE_SYS_UIO_H",
-                "-msse3",
-            ],
-        },
-        host: {
-            cflags: [
-                "-DCR_SYSROOT_KEY=20220331T153654Z-0",
-                "-DDEFLATE_SLIDE_HASH_SSE2",
-                "-DUSE_AURA=1",
-                "-DUSE_OZONE=1",
-                "-DUSE_UDEV",
-                "-D_FILE_OFFSET_BITS=64",
-                "-D_LARGEFILE64_SOURCE",
-                "-D_LARGEFILE_SOURCE",
-                "-msse3",
-            ],
-        },
-    },
-}
-
 // GN: //url:buildflags
 cc_genrule {
     name: "cronet_aml_url_buildflags",
@@ -15377,17 +10559,15 @@
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
         "-DDCHECK_ALWAYS_ON=1",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
         "-DHAVE_SYS_UIO_H",
         "-DIS_URL_IMPL",
         "-D_DEBUG",
         "-D_GNU_SOURCE",
-        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
         "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
-        "-D_LIBCPP_ENABLE_ASSERTIONS_DEFAULT=1",
         "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
         "-D__STDC_CONSTANT_MACROS",
         "-D__STDC_FORMAT_MACROS",
@@ -15400,7 +10580,7 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
         android_x86: {
             cflags: [
@@ -15436,7 +10616,9 @@
          "--input_file " +
          "$(location url/android/java/src/org/chromium/url/IDNStringUtil.java) " +
          "--input_file " +
-         "$(location url/android/java/src/org/chromium/url/Origin.java)",
+         "$(location url/android/java/src/org/chromium/url/Origin.java) " +
+         "--package_prefix " +
+         "android.net.http.internal",
     out: [
         "url/url_jni_headers/IDNStringUtil_jni.h",
         "url/url_jni_headers/Origin_jni.h",
diff --git a/tools/gn2bp/desc_arm.json b/tools/gn2bp/desc_arm.json
index 996b5f5..b59157a 100644
--- a/tools/gn2bp/desc_arm.json
+++ b/tools/gn2bp/desc_arm.json
Binary files differ
diff --git a/tools/gn2bp/desc_arm64.json b/tools/gn2bp/desc_arm64.json
index dd8e800..9881124 100644
--- a/tools/gn2bp/desc_arm64.json
+++ b/tools/gn2bp/desc_arm64.json
Binary files differ
diff --git a/tools/gn2bp/desc_x64.json b/tools/gn2bp/desc_x64.json
index 555f044..3a2ce2a 100644
--- a/tools/gn2bp/desc_x64.json
+++ b/tools/gn2bp/desc_x64.json
Binary files differ
diff --git a/tools/gn2bp/desc_x86.json b/tools/gn2bp/desc_x86.json
index 11e4e95..03bcf2f 100644
--- a/tools/gn2bp/desc_x86.json
+++ b/tools/gn2bp/desc_x86.json
Binary files differ
diff --git a/tools/gn2bp/gen_android_bp b/tools/gn2bp/gen_android_bp
index 58d7cad..dcf8897 100755
--- a/tools/gn2bp/gen_android_bp
+++ b/tools/gn2bp/gen_android_bp
@@ -42,7 +42,7 @@
 # Default targets to translate to the blueprint file.
 default_targets = [
     '//components/cronet/android:cronet',
-    '//components/cronet:cronet_package',
+    '//components/cronet/android:cronet_android_mainline',
 ]
 
 # Defines a custom init_rc argument to be applied to the corresponding output
@@ -93,11 +93,11 @@
 
 # Include directories that will be removed from all targets.
 local_include_dirs_denylist = [
+    'third_party/zlib/',
 ]
 
-android_include_dirs_denylist = [
+experimental_include_dirs_denylist = [
     'third_party/brotli/include/',
-    'third_party/zlib/',
 ]
 
 # Name of the module which settings such as compiler flags for all other
@@ -105,7 +105,7 @@
 defaults_module = module_prefix + 'defaults'
 
 # Location of the project in the Android source tree.
-tree_path = 'external/chromium_org'
+tree_path = 'external/cronet'
 
 # Path for the protobuf sources in the standalone build.
 buildtools_protobuf_src = '//buildtools/protobuf/src'
@@ -142,6 +142,22 @@
             'cronet_aml_crypto_crypto',
         }),
     ],
+    # TODO: fix upstream. Both //base:base and
+    # //base/allocator/partition_allocator:partition_alloc do not create a
+    # dependency on gtest despite using gtest_prod.h.
+    'cronet_aml_base_base': [
+        ('header_libs', {
+            'libgtest_prod_headers',
+        }),
+        ('export_header_lib_headers', {
+            'libgtest_prod_headers',
+        }),
+    ],
+    'cronet_aml_base_allocator_partition_allocator_partition_alloc': [
+        ('header_libs', {
+            'libgtest_prod_headers',
+        }),
+    ],
 }
 
 def enable_brotli(module, arch):
@@ -174,29 +190,34 @@
 builtin_deps = {
     '//buildtools/third_party/libunwind:libunwind':
         lambda m, a: None, # disable libunwind
+    '//net/data/ssl/chrome_root_store:gen_root_store_inc':
+        lambda m, a: None,
     '//net/tools/root_store_tool:root_store_tool':
         lambda m, a: None,
+    '//third_party/zlib:zlib':
+        enable_zlib,
 }
 
-android_deps = {
+experimental_android_deps = {
     '//third_party/brotli:common':
         enable_brotli,
     '//third_party/brotli:dec':
         enable_brotli,
     '//third_party/modp_b64:modp_b64':
         enable_modp_b64,
-    '//third_party/zlib:zlib':
-        enable_zlib,
 }
 
 # Uncomment the following lines to use Android deps rather than their Chromium
 # equivalent:
-#builtin_deps.update(android_deps)
-#local_include_dirs_denylist.extend(android_include_dirs_denylist)
+#builtin_deps.update(experimental_android_deps)
+#local_include_dirs_denylist.extend(experimental_include_dirs_denylist)
 
 # Name of tethering apex module
 tethering_apex = "com.android.tethering"
 
+# Name of cronet api target
+java_api_target_name = "//components/cronet/android:cronet_api_java"
+
 # ----------------------------------------------------------------------------
 # End of configuration.
 # ----------------------------------------------------------------------------
@@ -323,6 +344,7 @@
     self.generated_headers = set()
     self.export_generated_headers = set()
     self.export_static_lib_headers = set()
+    self.export_header_lib_headers = set()
     self.defaults = set()
     self.cflags = set()
     self.include_dirs = set()
@@ -368,6 +390,7 @@
     self.plugins = set()
     self.processor_class = None
     self.sdk_version = None
+    self.javacflags = set()
 
   def to_string(self, output):
     if self.comment:
@@ -393,6 +416,7 @@
     self._output_field(output, 'generated_headers')
     self._output_field(output, 'export_generated_headers')
     self._output_field(output, 'export_static_lib_headers')
+    self._output_field(output, 'export_header_lib_headers')
     self._output_field(output, 'defaults')
     self._output_field(output, 'cflags')
     self._output_field(output, 'include_dirs')
@@ -421,6 +445,7 @@
     self._output_field(output, 'plugins')
     self._output_field(output, 'processor_class')
     self._output_field(output, 'sdk_version')
+    self._output_field(output, 'javacflags')
     if self.rtti:
       self._output_field(output, 'rtti')
 
@@ -508,7 +533,12 @@
 
   def to_string(self, output):
     for m in sorted(self.modules.values(), key=lambda m: m.name):
-      m.to_string(output)
+      if m.type != "cc_object" or m.has_input_files():
+        # Don't print cc_object with empty srcs. These attributes are already
+        # propagated up the tree. Printing them messes the presubmits because
+        # every module is compiled while those targets are not reachable in
+        # a normal compilation path.
+        m.to_string(output)
 
 
 def label_to_module_name(label):
@@ -924,8 +954,7 @@
     return arg
 
   def _sanitize_args(self):
-    self._update_value_arg('--jar_file', self._sanitize_filepath, False)
-    self._update_value_arg('--jar_file', self._add_location_tag, False)
+    self._set_value_arg('--jar_file', '$(location :current_android_jar)', False)
     if self._has_arg('--jar_file'):
       self._append_arg('--javap', '$$(find out/.path -name javap)')
     self._update_value_arg('--output_dir', self._sanitize_filepath)
@@ -933,6 +962,7 @@
     self._delete_value_arg('--prev_output_dir', False)
     self._update_list_arg('--input_file', self._sanitize_filepath)
     self._update_list_arg('--input_file', self._add_location_tag_to_filepath)
+    self._append_arg('--package_prefix', 'android.net.http.internal')
     super()._sanitize_args()
 
   def _sanitize_outputs(self):
@@ -945,6 +975,10 @@
     # android_jar.classes should be part of the tools as it list implicit classes
     # for the script to generate JNI headers.
     tool_files.add("base/android/jni_generator/android_jar.classes")
+
+    # Filter android.jar and add :current_android_jar
+    tool_files = {file if not file.endswith('android.jar') else ':current_android_jar'
+                  for file in tool_files }
     return tool_files
 
 class JniRegistrationGeneratorSanitizer(BaseActionSanitizer):
@@ -959,6 +993,7 @@
     # update_jni_registration_module removes them from the srcs of the module
     # It might be better to remove sources by '--sources-exclusions'
     self._delete_value_arg('--sources-exclusions')
+    self._append_arg('--package_prefix', 'android.net.http.internal')
     super()._sanitize_args()
 
   def get_cmd(self):
@@ -1214,8 +1249,7 @@
   # aosp / soong builds and b) the include directory should already be
   # configured via library dependency.
   module.local_include_dirs.update([gn_utils.label_to_path(d)
-                                 for d in include_dirs
-                                 if not re.match('^//out/.*', d)])
+                                 for d in include_dirs if not d.startswith('//out')])
   # Remove prohibited include directories
   module.local_include_dirs = [d for d in module.local_include_dirs
                                if d not in local_include_dirs_denylist]
@@ -1277,17 +1311,13 @@
 
   blueprint.add_module(module)
   module.init_rc = target_initrc.get(target.name, [])
-  module.srcs.update(
-      gn_utils.label_to_path(src)
-      for src in target.sources
-      if is_supported_source_file(src) and not src.startswith("//out/test"))
+  module.srcs.update(gn_utils.label_to_path(src)
+                     for src in target.sources if is_supported_source_file(src))
 
   # Add arch-specific properties
   for arch_name, arch in target.arch.items():
-    module.target[arch_name].srcs.update(
-      gn_utils.label_to_path(src)
-      for src in arch.sources
-      if is_supported_source_file(src) and not src.startswith("//out/test"))
+    module.target[arch_name].srcs.update(gn_utils.label_to_path(src)
+                                         for src in arch.sources if is_supported_source_file(src))
 
   module.rtti = target.rtti
 
@@ -1453,30 +1483,61 @@
   blueprint.add_module(module)
   return module
 
+def get_java_sources(gn, predicate):
+  java_sources = set()
+  for target_name, sources in gn.java_sources.items():
+    if predicate(target_name):
+      java_sources.update(sources)
+  return java_sources
+
+def get_java_actions(gn, predicate):
+  java_actions = set()
+  for target_name, actions in gn.java_actions.items():
+    if predicate(target_name):
+      java_actions.update(actions)
+  return java_actions
+
+def get_non_api_java_sources(gn):
+  return get_java_sources(gn, lambda name: name != java_api_target_name)
+
+def get_non_api_java_actions(gn):
+  return get_java_actions(gn, lambda name: name != java_api_target_name)
+
+def get_api_java_sources(gn):
+  return get_java_sources(gn, lambda name: name == java_api_target_name)
+
+def get_api_java_actions(gn):
+  return get_java_actions(gn, lambda name: name == java_api_target_name)
+
 def create_java_module(blueprint, gn):
   bp_module_name = module_prefix + 'java'
   module = Module('java_library', bp_module_name, '//gn:java')
-  module.srcs.update([gn_utils.label_to_path(source) for source in gn.java_sources])
+  module.srcs.update([gn_utils.label_to_path(source) for source in get_non_api_java_sources(gn)])
   module.libs = {
     "androidx.annotation_annotation",
     "jsr305",
-    "androidx.core_core-nodeps",
-    "androidx.collection_collection",
     "androidx.annotation_annotation-experimental-nodeps",
-    "android-support-multidex",
     "framework-connectivity.stubs.module_lib",
     "framework-connectivity-t.stubs.module_lib",
     "framework-tethering.stubs.module_lib",
     "framework-wifi.stubs.module_lib",
     "framework-mediaprovider.stubs.module_lib",
   }
+  module.static_libs = {
+    "modules-utils-build_system",
+  }
   module.aidl["include_dirs"] = {"frameworks/base/core/java/"}
   module.aidl["local_include_dirs"] = {"base/android/java/src/"}
   module.sdk_version = "module_current"
   module.apex_available.add(tethering_apex)
-  # TODO: remove following workaround required to make this module visible to make (b/203203405)
-  module.apex_available.add("//apex_available:platform")
-  for dep in gn.java_actions:
+  # TODO: support for this flag is removed upstream in crrev/c/4062652.
+  # Consider reverting this change upstream, or worst-case downstream.  As an
+  # alternative hack, we could rename the generated file to not conflict. This
+  # would be less likely to conflict with upstream changes if the revert is not
+  # accepted.
+  module.javacflags.add("-Aorg.chromium.chrome.skipGenJni")
+  module.javacflags.add("-Apackage_prefix=android.net.http.internal")
+  for dep in get_non_api_java_actions(gn):
     target = gn.get_target(dep)
     if target.script == '//build/android/gyp/gcc_preprocess.py':
       module.srcs.add(':' + create_gcc_preprocess_modules(blueprint, target).name)
@@ -1485,19 +1546,31 @@
   preprocessor_module = create_java_jni_preprocessor(blueprint)
   module.plugins.add(preprocessor_module.name)
   blueprint.add_module(module)
+  return module
+
+def create_java_api_module(blueprint, gn):
+  source_module = Module('filegroup', module_prefix + 'api_sources', java_api_target_name)
+  source_module.srcs.update([gn_utils.label_to_path(source)
+                             for source in get_api_java_sources(gn)])
+  source_module.srcs.update([
+    ':' + create_action_module(blueprint, gn.get_target(dep), 'java_genrule').name
+    for dep in get_api_java_actions(gn)])
+  blueprint.add_module(source_module)
+
+  java_module = Module('java_library', module_prefix + 'api_java', java_api_target_name)
+  java_module.srcs.add(":" + source_module.name)
+  java_module.sdk_version = "module_current"
+  java_module.libs = {
+      "androidx.annotation_annotation",
+    }
+  blueprint.add_module(java_module)
+  return java_module
 
 def update_jni_registration_module(module, gn):
-  # TODO: deny list is in the arg of jni_registration_generator.py. Should not be hardcoded
-  deny_list = [
-    '//base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java',
-    '//base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java',
-    '//base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java',
-    '//base/android/java/src/org/chromium/base/SysUtils.java']
-
   # TODO: java_sources might not contain all the required java files
   module.srcs.update([gn_utils.label_to_path(source)
-                      for source in gn.java_sources
-                      if source.endswith('.java') and source not in deny_list])
+                      for source in get_non_api_java_sources(gn)
+                      if source.endswith('.java')])
 
 def create_blueprint_for_targets(gn, targets):
   """Generate a blueprint for a list of GN targets."""
@@ -1525,9 +1598,11 @@
   # Chromium builds do not add a dependency for headers found inside the
   # sysroot, so they are added globally via defaults.
   defaults.target['android'].header_libs = [
-      'media_ndk_headers',
       'jni_headers',
   ]
+  defaults.target['android'].shared_libs = [
+      'libmediandk'
+  ]
   defaults.target['host'].cflags = [
       # -DANDROID is added by default but target.defines contain -DANDROID if
       # it's required.  So adding -UANDROID to cancel default -DANDROID if it's
@@ -1544,7 +1619,9 @@
   for target in targets:
     create_modules_from_target(blueprint, gn, target)
 
-  create_java_module(blueprint, gn)
+  java_api_module = create_java_api_module(blueprint, gn)
+  java_module = create_java_module(blueprint, gn)
+  java_module.libs.add(java_api_module.name)
   for module in blueprint.modules.values():
     if 'cronet_jni_registration' in module.name:
       update_jni_registration_module(module, gn)
diff --git a/tools/gn2bp/gen_desc_json.sh b/tools/gn2bp/gen_desc_json.sh
new file mode 100755
index 0000000..ed684b3
--- /dev/null
+++ b/tools/gn2bp/gen_desc_json.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+set -x
+
+# Run this script inside a full chromium checkout.
+# TODO: add support for applying local patches.
+
+OUT_PATH="out/cronet"
+
+#######################################
+# Generate desc.json for a specified architecture.
+# Globals:
+#   OUT_PATH
+# Arguments:
+#   target_cpu, string
+#######################################
+function gn_desc() {
+  local -a gn_args=(
+    "target_os = \"android\""
+    "enable_websockets = false"
+    "disable_file_support = true"
+    "disable_brotli_filter = false"
+    "is_component_build = false"
+    "use_crash_key_stubs = true"
+    "use_partition_alloc = false"
+    "include_transport_security_state_preload_list = false"
+    "use_platform_icu_alternatives = true"
+    "default_min_sdk_version = 19"
+    "use_errorprone_java_compiler = true"
+    "enable_reporting = true"
+    "use_hashed_jni_names = true"
+    "treat_warnings_as_errors = false"
+    "enable_base_tracing = false"
+    "is_cronet_build = true"
+  )
+  gn_args+=("target_cpu = \"${1}\"")
+
+  # Only set arm_use_neon on arm architectures to prevent warning from being
+  # written to json output.
+  if [[ "$1" =~ ^arm ]]; then
+    gn_args+=("arm_use_neon = false")
+  fi
+
+  # Configure gn args.
+  gn gen "${OUT_PATH}" --args="${gn_args[*]}"
+
+  # Generate desc.json.
+  local -r out_file="desc_${1}.json"
+  gn desc "${OUT_PATH}" --format=json --all-toolchains "//*" > "${out_file}"
+}
+
+gn_desc x86
+gn_desc x64
+gn_desc arm
+gn_desc arm64
+
diff --git a/tools/gn2bp/gn_utils.py b/tools/gn2bp/gn_utils.py
index 9d732e5..3d709e5 100644
--- a/tools/gn2bp/gn_utils.py
+++ b/tools/gn2bp/gn_utils.py
@@ -20,6 +20,7 @@
 import logging as log
 import os
 import re
+import collections
 
 BUILDFLAGS_TARGET = '//gn:gen_buildflags'
 GEN_VERSION_TARGET = '//src/base:version_gen_h'
@@ -77,7 +78,7 @@
   return name
 
 def _is_java_source(src):
-  return os.path.splitext(src)[1] == '.java' and not src.startswith("//out/test/gen/")
+  return os.path.splitext(src)[1] == '.java' and not src.startswith("//out/")
 
 def is_java_action(script, outputs):
   return (script != "" and script not in JAVA_BANNED_SCRIPTS) and any(
@@ -260,8 +261,8 @@
     self.source_sets = {}
     self.actions = {}
     self.proto_libs = {}
-    self.java_sources = set()
-    self.java_actions = set()
+    self.java_sources = collections.defaultdict(set)
+    self.java_actions = collections.defaultdict(set)
 
   def _get_response_file_contents(self, action_desc):
     # response_file_contents are formatted as:
@@ -307,7 +308,7 @@
 
     return self.all_targets[label_without_toolchain(gn_target_name)]
 
-  def parse_gn_desc(self, gn_desc, gn_target_name, is_java_target = False):
+  def parse_gn_desc(self, gn_desc, gn_target_name, java_group_name=None):
     """Parses a gn desc tree and resolves all target dependencies.
 
         It bubbles up variables from source_set dependencies as described in the
@@ -320,7 +321,8 @@
     type_ = desc['type']
     arch = self._get_arch(desc['toolchain'])
 
-    is_java_target |= self._is_java_group(type_, target_name)
+    if self._is_java_group(type_, target_name):
+      java_group_name = target_name
 
     target = self.all_targets.get(target_name)
     if target is None:
@@ -399,7 +401,7 @@
 
     # Recurse in dependencies.
     for gn_dep_name in desc.get('deps', []):
-      dep = self.parse_gn_desc(gn_desc, gn_dep_name, is_java_target)
+      dep = self.parse_gn_desc(gn_desc, gn_dep_name, java_group_name)
       if dep.type == 'proto_library':
         target.proto_deps.add(dep.name)
         target.transitive_proto_deps.add(dep.name)
@@ -410,6 +412,8 @@
         target.arch[arch].source_set_deps.update(dep.arch[arch].source_set_deps)
         # flatten source_set deps
         if target.is_linker_unit_type():
+          # This ensure that all transitive source set dependencies are
+          # propagated upward to the linker units.
           target.arch[arch].deps.update(target.arch[arch].source_set_deps)
       elif dep.type == 'group':
         target.update(dep, arch)  # Bubble up groups's cflags/ldflags etc.
@@ -447,15 +451,15 @@
         if dep.name.endswith('__compile_java'):
           log.debug('Adding java sources for %s', dep.name)
           java_srcs = [src for src in dep.inputs if _is_java_source(src)]
-          self.java_sources.update(java_srcs)
+          self.java_sources[java_group_name].update(java_srcs)
       if dep.type in ["action"] and target.type == "java_group":
         # //base:base_java_aidl generates srcjar from .aidl files. But java_library in soong can
         # directly have .aidl files in srcs. So adding .aidl files to the java_sources.
         # TODO: Find a better way/place to do this.
         if dep.name == '//base:base_java_aidl':
-          self.java_sources.update(dep.arch[arch].sources)
+          self.java_sources[java_group_name].update(dep.arch[arch].sources)
         else:
-          self.java_actions.add(dep.name)
+          self.java_actions[java_group_name].add(dep.name)
     return target
 
   def get_proto_exports(self, proto_desc):