Merge "add TRANSPORT_THREAD to NetworkCapabilities"
diff --git a/Cronet/Android.bp b/Cronet/Android.bp
deleted file mode 100644
index 3ce88ef..0000000
--- a/Cronet/Android.bp
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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.
-
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_import {
-    name: "cronet_impl_native_java",
-    jars: ["prebuilt/cronet_impl_native_java.jar"],
-    visibility: ["//visibility:private"],
-    apex_available: ["com.android.tethering"],
-    min_sdk_version: "29",
-}
-
-java_import {
-    name: "cronet_impl_common_java",
-    jars: ["prebuilt/cronet_impl_common_java.jar"],
-    visibility: ["//visibility:private"],
-    apex_available: ["com.android.tethering"],
-    min_sdk_version: "29",
-}
-
-java_import {
-    name: "cronet_impl_platform_java",
-    jars: ["prebuilt/cronet_impl_platform_java.jar"],
-    visibility: ["//visibility:private"],
-    apex_available: ["com.android.tethering"],
-    min_sdk_version: "29",
-}
-
-cc_prebuilt_library_shared {
-    name: "libcronet.107.0.5284.2",
-    shared_libs: [
-        "libandroid",
-        "libc",
-        "libdl",
-        "liblog",
-        "libm",
-    ],
-    stl: "libc++_static",
-    target: {
-        android_arm64: {
-            srcs: ["prebuilt/libs/arm64-v8a/libcronet.107.0.5284.2.so"],
-        },
-        android_arm: {
-            srcs: ["prebuilt/libs/armeabi-v7a/libcronet.107.0.5284.2.so"],
-        },
-        android_x86_64: {
-            srcs: ["prebuilt/libs/x86_64/libcronet.107.0.5284.2.so"],
-        },
-        android_x86: {
-            srcs: ["prebuilt/libs/x86/libcronet.107.0.5284.2.so"],
-        },
-    },
-    // These are already stripped, and restripping them just issues diagnostics.
-    strip: {
-        none: true,
-    },
-    apex_available: ["com.android.tethering"],
-    min_sdk_version: "29",
-}
-
-genrule {
-    name: "cronet_api-src",
-    srcs: ["prebuilt/cronet_api-src.jar"],
-    cmd: "cp $(in) $(out)",
-    out: [
-        "cronet_api-src.srcjar",
-    ],
-}
-
-java_sdk_library {
-    name: "framework-cronet",
-    defaults: ["framework-module-defaults"],
-    srcs: [
-        ":cronet_api-src",
-    ],
-    libs: [
-        "androidx.annotation_annotation",
-    ],
-    static_libs: [
-        "androidx.core_core-nodeps",
-        "cronet_impl_common_java",
-        "cronet_impl_native_java",
-        "cronet_impl_platform_java",
-    ],
-    apex_available: ["com.android.tethering"],
-    jarjar_rules: "jarjar-rules.txt",
-    unsafe_ignore_missing_latest_api: true,
-    dist_group: "android",
-    // cronet is used as a shared library.
-    shared_library: true,
-    exclude_kotlinc_generated_files: true,
-}
diff --git a/Cronet/AndroidManifest.xml b/Cronet/AndroidManifest.xml
deleted file mode 100644
index c6471ed..0000000
--- a/Cronet/AndroidManifest.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="com.android.net.http"
-  android:versionCode="11"
-  android:versionName="R-initial">
-</manifest>
diff --git a/Cronet/TEST_MAPPING b/Cronet/TEST_MAPPING
deleted file mode 100644
index b1f3088..0000000
--- a/Cronet/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "CtsCronetTestCases"
-    }
-  ]
-}
diff --git a/Cronet/apex/Android.bp b/Cronet/apex/Android.bp
deleted file mode 100644
index 180dafb..0000000
--- a/Cronet/apex/Android.bp
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.
-
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// CronetApexDefaults uses apex_defaults cronet_apex_defaults specifies. cronet_apex_defaults
-// could be "CronetApexDefaultsEnabled" or "CronetApexDefaultsDisabled" depending on the branch.
-cronet_apex_defaults = "CronetApexDefaultsEnabled"
-// This is a placeholder comment to avoid merge conflicts
-// as cronet_apex_defaults may have different values
-// depending on the branch
-
-apex_defaults {
-    name: "CronetApexDefaults",
-    defaults: [cronet_apex_defaults],
-}
-
-apex_defaults {
-    name: "CronetApexDefaultsEnabled",
-    jni_libs: ["libcronet.107.0.5284.2"],
-    java_libs: ["framework-cronet"],
-    arch: {
-        riscv64: {
-            // TODO: remove this when there is a riscv64 libcronet
-            exclude_jni_libs: ["libcronet.107.0.5284.2"],
-        },
-    },
-}
-
-apex_defaults {
-    name: "CronetApexDefaultsDisabled",
-}
-
-// TODO: Remove cronet apex after com.android.cronet is removed from PRODUCT_PACKAGES
-apex {
-    name: "com.android.cronet",
-    key: "com.android.cronet.key",
-    updatable: false,
-    manifest: "manifest.json",
-}
-
-apex_key {
-    name: "com.android.cronet.key",
-    public_key: "com.android.cronet.avbpubkey",
-    private_key: "com.android.cronet.pem",
-}
diff --git a/Cronet/apex/AndroidManifest.xml b/Cronet/apex/AndroidManifest.xml
deleted file mode 100644
index 650badc..0000000
--- a/Cronet/apex/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="com.android.cronet">
-  <!-- APEX does not have classes.dex -->
-  <application android:hasCode="false" />
-  <uses-sdk
-      android:minSdkVersion="29"
-  />
-</manifest>
diff --git a/Cronet/apex/com.android.cronet.avbpubkey b/Cronet/apex/com.android.cronet.avbpubkey
deleted file mode 100644
index 38aebe0..0000000
--- a/Cronet/apex/com.android.cronet.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/Cronet/apex/com.android.cronet.pem b/Cronet/apex/com.android.cronet.pem
deleted file mode 100644
index 438653f..0000000
--- a/Cronet/apex/com.android.cronet.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKAIBAAKCAgEAqpxkMMK57w+fzxLcwF+mEQEbKrDFWXYHL697tv8DBu/aL2tM
-LRHiKFdov0Fsnup++bd9oojI+6qyAyJh4I8nvzKc4onM0eXL++0FPZuiTv6a6r7K
-wyn+NVT2X/0yr2Hs5NL1rKXFmJPAfMoRCW9vQdi5xMlM9QN8mNaqSWddKtrQM3yC
-HDLy2zZd7MlQ1UTnmDqGCG0AVtuM34X0v1o0wAL7UwNdzOARtmnuWzcL5vBwAJg8
-eXFZH5Pt5rITxbU+eYw/V+/sUYyI0Anrj4GG+oyWQxgdxz+FwdpSAt14xtw5IDl7
-pTYqEIm+TQKnWe6NzVWfI89s2nh85hgOSgugfpS4symbfbZd4qNSOcHGQTB1ssvf
-vdYGF1WRFA20VEEOMzTMYsvcfModKNVCpibzHu/SYDIJGL0JyJWu2eIE+mrn3lLD
-nwDZ2P39YyVNpritEkbk5qugaLh9mIFqAD4L4niYLu/AtYq+CXzd7yroM2ycleRq
-JRNsCIUx3A/Z5vKx7IJaMb7Pwap3DAe3u3/2L9NCL6oo074Rf7fh5xkDF4Dua3Gg
-kPw+k183jAQECHORstdVlgVZlMxPif4lxQ8uCHJWxyDsgShPgzMtEjJyrJJQyDon
-X8pN4xqb+WX30XNYBK5sp7x6mc8w4rdAGExhUSdmTS0J/lcfar6A6/j/yg8CAwEA
-AQKCAgAiYafTJ7q+kWB8I2n3Ho9hx95IqRzsHVvvYSbGRve+MyG+App0TrFLvemu
-+SlBkTILcs3Prk8KYGjFNu2QimjRIAr7oBd1iSClYSt4Md/wmWBwxAgqclD3QGry
-Bx1quIo7xsOZikKar9PPkg0C4MED/P/ax1JJ4ez/A+uHJVxiIXxpk8LImf/U60zc
-RemTQPKG++w80HKMDmyCMwWSdkRBGZi6Luh9O/51yz0shphQbs2zYPp24r+6HF6J
-6gMQCalQZ1Hwj7oI6RA9FHKzFcA0x5YUaUy+9W8oFK4IQ8duE70zYEIplhO+B3Qh
-ItLEzc0nvwR1+/wMvtE0sU5X36X06AFhkcpjyAdmNVMiG91KGrZqruOufrOQu4VE
-njJ5VEUvWOr+6inZDWIdT3NQvwJCZkT4Vvn9WBAoKM8pkpfhY5HTGq4ttX7McHjF
-p7YBFbHRpzO+OfSwM7f/xq2WLcjOKgsFgv17CUo7KQo1rqWPD/4IKJKW5n6dzDwX
-RRF4dehUMYK2UNAbcN9S8O8nJGcJfb76FExjZtGLrhlDgawLmu71bbq5afot/IQ9
-JuB4KxG59t2JAHGNgM7WfFvcL1Zp1D+kzDEHYKYkyDJh3qB7Tw+StlAQFSQjNBX/
-c1I6DUl68rSHOc2LF4oK8ID1oe/URMg2YoaLlF8un2nGZBfwGQKCAQEA20Ie5hBC
-H8W1vTtyI4jOdn/h11RL8UuLN0xtXYunYCzD4+gAEKsAShbhKnvINThZaoxQ2sxy
-9EB+2Ob8R9muYAxR4Eu4tDBWedYmJEl74MflLMFnIrtFIKy4F54zk7J6uNG3cHRo
-yTpoIcmK101xzz1Ed9Dd0XL6rpegnWIuVlWV4slGAf1l3h6pycfx+HCYcCboz6Nq
-JMA0ioKY0fgz5q+mb7IIObN8JjGdLeBQtNh3fcXby08AT/03psKhjgBsbuyTs7s7
-E3n+jxJ3p4xHP/psU3D/HgKWewp48AJNHY8MLY+Kp0KNoQMSQKHKqsiluGTCKLTJ
-sCWg/2c8xf728wKCAQEAxzNdZ54e6WXexMMIsGoH+wVknTHiizuxN4ZqzY/nCM0M
-9heooChfMAFrq8XMC/6MXgiy5rBhl3H12HlG4S6cq3J07MsMR0N+sUFEobuZURB4
-+CbEBebmXx1kymC6FrRG4JuKZWbQ8AKpfd28QO7x915safeq6FA8cILJn4oqBGqQ
-Y8TzMKtuaCzQGoBjSgiMpx1fo9Stl7+dpGiPNsnQEG+SEsXxKoZweJPsuK8G+ZgB
-8YARajLwFfgfsCNp/8fXjA98BYM8eSxURa7USUyCmY4hU3WIGG5qc0/C69Fl35ex
-YZG7XQo1DxW/+gWsdUbAFbI4y+iJ8SRpsFxtFYifdQKCAQA5DiW4PHbYibxXN8bl
-1E3VrEV6oSb57WyWwT6cXyD49+0pu095BuaWYQnK4lcg8j7iaQ0JQraPNNFNZB42
-HEEyIUKVGV9BFGsMXVujibPAtIPAd7t84DqG3Csziillv8YLnhccHk6+PoKmeCm3
-CSIaiZjtjN6MCF2PXUmgatIgCTltwG6FSgleGaCZL3yZ58LjPFzM23tdgN6rRHy7
-9tiaqQ6odi2JxlkCH1sFex/FT6cYhYpCh5ZPOldm/7LGnvmYi9uLo6cl1FMXq/iT
-Ev/feC0EMZ1Rk97QudLqsc6baIQEvxuXlswAICp5wyBX/MqTBzU3HoR1X/VbQOQh
-qc1dAoIBACLjNhqtsNBDzS480krDZz5phWOalwi3naQR4Ka760S5VOnM3vWd3H31
-4bul2sTHAiJ994c7oPv7M4mERAuwNDQ6yYunTDE2+vtkaPbCemmeLvGXKIG4HOTP
-qxVet3i+fiNcWnLD/Rfr/29R5GSi9LHUUbyFaeNiGhPCdDmC4zT+zOcMWWNOwvlv
-z8q0ba9LrAaguF1jJDwNjTh8L4jy84PNZpHvJPvDq/MSRUVbMieInd6EBYjJ/w55
-9GLO8QOhJnkbRSdaAr9eKixCIF/uDHmEUQXi8cEFpZMohwTyGZt9X82szlnPLdfE
-gWjykW/AwmeKXTQpN++J5xDCP0CkOvkCggEBAND4wviHue/+bqY9R5EAIDIZn6kx
-VCK9roebvGjq/Az5AM7IiyUQRANv+6CmeIlXCRBMbaAtgQxhvW5UodA1livgVuzR
-ElF7Br3wfikZ34oWY0Qu8fZI0ru4syAoTiGpaUPJJgStYi76dqne15usTRk/MvwP
-tJzqpkWUYcmNv3g/w92Wr1nIJYXlPKrANSSppRg0P/CAPOHkPxLF0RwC5yIZzC5C
-hiTXSE9AwCFllMRKInnbhUdy/L+xUL6mAbGVvD/DHE7Q2xmPSsdEX5nTZkhEnW/L
-TLLgbsy2+8ouvMJCSNaMq77jq7iCIMTogEfA5GX0UO2Kjf4pnjREOzNQg4I=
------END RSA PRIVATE KEY-----
diff --git a/Cronet/apex/com.android.cronet.pk8 b/Cronet/apex/com.android.cronet.pk8
deleted file mode 100644
index a63d761..0000000
--- a/Cronet/apex/com.android.cronet.pk8
+++ /dev/null
Binary files differ
diff --git a/Cronet/apex/com.android.cronet.x509.pem b/Cronet/apex/com.android.cronet.x509.pem
deleted file mode 100644
index c9cd874..0000000
--- a/Cronet/apex/com.android.cronet.x509.pem
+++ /dev/null
@@ -1,35 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGIzCCBAugAwIBAgIUKEbkVLro9rIJE3M71D8sgUIngUIwDQYJKoZIhvcNAQEL
-BQAwgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMRswGQYDVQQDDBJjb20uYW5kcm9pZC5jcm9uZXQxIjAgBgkqhkiG9w0BCQEW
-E2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMTkxMjA1MDcwOTIxWhgPNDc1NzEwMzEw
-NzA5MjFaMIGfMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
-A1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwH
-QW5kcm9pZDEbMBkGA1UEAwwSY29tLmFuZHJvaWQuY3JvbmV0MSIwIAYJKoZIhvcN
-AQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
-MIICCgKCAgEAwNXIHR2BeZl/R7tOXgC3KK71rrtK98zucfrNBNp/rUiFqiN527P4
-HLW+CAwnFJGLLzHhSbXiZLXyLS7FfPuMeiULUsv1mIVEVwVhtPvbodxwh5szxlVe
-iVf1WkIV90n2tZojTnhMsiEPt0EBWriPJstdO264snqg+oY9Dktxk4tXtTah/rUI
-KWPHeB0SWQMXZTKb30CVVHZfpG/HCXjUlVLx+14/X56EGi8fxd13q5c56qAybx73
-i6+Sm3+F/jcivDpATuPluvcPaZ4Tel9Nz5NjqjycyXBXh8f8azpN1GkJkltE116W
-ZT1iVIJoDAd540UXhW+TpjTeaEH5OeDOWorQM6nE1N9FMiyReprU7tz+HVmyD44Z
-ah43whi3gmwyjgzscW2Z0xGpgVoHgfz/RyBg5+w6p5AGPR0sewv6zr9HvQhpJsoj
-pl+HD9xcrdGb2yMiwm8RuH9dGW0Nos6p1LiXsxg6VBic3N7S+MGXo/dXdX39tkad
-tD+lNskJUJqyx70ynQtRI66YicyxsFv0BImBC+eGECT3hCgyyxnlvTAeRsVsEWtV
-Z+Xwf5M53/8uXkqGal7cC1bHEkG+0zsR8cc0U+22Nif9HQNIrsjEnybOlP6erV/M
-8yX9umVwDz5QlVKCYJFQOq+awSqR9KD9VX3xIRu8kB6aPtB4A7q3828CAwEAAaNT
-MFEwHQYDVR0OBBYEFBQBcdf/bfLa3knW1ukCOFOt++FtMB8GA1UdIwQYMBaAFBQB
-cdf/bfLa3knW1ukCOFOt++FtMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
-BQADggIBALG0r81xb6NwaGCF79SeDecbnDE1MbQ2+cRt+eU/Wl2SI2oQqbaa/WP7
-k3vsZvsBFI6r+ZBiKizpbT/N1Fx8pcoH7rsL0MoZRXaCZY6kQJLZN6AAvXEo4NR0
-p01zDvGibVk3z87R98IJHlDPU3NrljxxMCsaUxFEAjae4eS4j8G2TFm6DsTVTeqy
-zveh4NdZFsZSyUN8blChFC/7TytlizeSGNlXLMx8e/VAcxIw+wQPWLk5pNnk3TXu
-HcqwAryW/lt46+iVeTpF4ylFqYyab6Vmf9Vp6+HVatg7YkErJACeoeN4eRv6DfeY
-slMqa2i+W+veVAGP4VApg7iZE5RnNPPHn/80yATKAe0/AztoZpQWZ5g1IAnpCISg
-k65FHVhbkcKdjNQePOGwjictq21KaYFrbXfIwqpejxSqQdLMne02Dj/2kv0dU1jV
-JG9YxVWIpobauYD5mmZvN6PTYJWGQRAsIFFyWfhvnEiohGmVLNEQ3uRaue0yNMXc
-V2t8B81/jNGXwi06qxmjCMnMhucSCSFl2a2V5oiDEcVj4YbaJ+CEJPdopMhQwqab
-EgTkJBeEXoPFenToSIprL/YiuBNvvPETyTYN+hAXh3P7MSeWewkgGhpZhuyzT8F0
-vEo+nt5WhRWl0pEVLFLiOOXR+/LAB3aqrPEdd0NXvxiCb/QaZnCp
------END CERTIFICATE-----
diff --git a/Cronet/apex/manifest.json b/Cronet/apex/manifest.json
deleted file mode 100644
index 0301e9f..0000000
--- a/Cronet/apex/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.cronet",
-  "version": 1
-}
diff --git a/Cronet/api/current.txt b/Cronet/api/current.txt
deleted file mode 100644
index 21779bc..0000000
--- a/Cronet/api/current.txt
+++ /dev/null
@@ -1,175 +0,0 @@
-// Signature format: 2.0
-package org.chromium.net {
-
-  public abstract class CallbackException extends org.chromium.net.CronetException {
-    ctor protected CallbackException(String, Throwable);
-  }
-
-  public abstract class CronetEngine {
-    ctor public CronetEngine();
-    method public abstract java.net.URLStreamHandlerFactory createURLStreamHandlerFactory();
-    method public abstract byte[] getGlobalMetricsDeltas();
-    method public abstract String getVersionString();
-    method public abstract org.chromium.net.UrlRequest.Builder newUrlRequestBuilder(String, org.chromium.net.UrlRequest.Callback, java.util.concurrent.Executor);
-    method public abstract java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
-    method public abstract void shutdown();
-    method public abstract void startNetLogToFile(String, boolean);
-    method public abstract void stopNetLog();
-  }
-
-  public static class CronetEngine.Builder {
-    ctor public CronetEngine.Builder(android.content.Context);
-    method public org.chromium.net.CronetEngine.Builder addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.util.Date);
-    method public org.chromium.net.CronetEngine.Builder addQuicHint(String, int, int);
-    method public org.chromium.net.CronetEngine build();
-    method public org.chromium.net.CronetEngine.Builder enableBrotli(boolean);
-    method public org.chromium.net.CronetEngine.Builder enableHttp2(boolean);
-    method public org.chromium.net.CronetEngine.Builder enableHttpCache(int, long);
-    method public org.chromium.net.CronetEngine.Builder enablePublicKeyPinningBypassForLocalTrustAnchors(boolean);
-    method public org.chromium.net.CronetEngine.Builder enableQuic(boolean);
-    method public String getDefaultUserAgent();
-    method public org.chromium.net.CronetEngine.Builder setLibraryLoader(org.chromium.net.CronetEngine.Builder.LibraryLoader);
-    method public org.chromium.net.CronetEngine.Builder setStoragePath(String);
-    method public org.chromium.net.CronetEngine.Builder setUserAgent(String);
-    field public static final int HTTP_CACHE_DISABLED = 0; // 0x0
-    field public static final int HTTP_CACHE_DISK = 3; // 0x3
-    field public static final int HTTP_CACHE_DISK_NO_HTTP = 2; // 0x2
-    field public static final int HTTP_CACHE_IN_MEMORY = 1; // 0x1
-  }
-
-  public abstract static class CronetEngine.Builder.LibraryLoader {
-    ctor public CronetEngine.Builder.LibraryLoader();
-    method public abstract void loadLibrary(String);
-  }
-
-  public abstract class CronetException extends java.io.IOException {
-    ctor protected CronetException(String, Throwable);
-  }
-
-  public final class InlineExecutionProhibitedException extends java.util.concurrent.RejectedExecutionException {
-    ctor public InlineExecutionProhibitedException();
-  }
-
-  public abstract class NetworkException extends org.chromium.net.CronetException {
-    ctor protected NetworkException(String, Throwable);
-    method public abstract int getCronetInternalErrorCode();
-    method public abstract int getErrorCode();
-    method public abstract boolean immediatelyRetryable();
-    field public static final int ERROR_ADDRESS_UNREACHABLE = 9; // 0x9
-    field public static final int ERROR_CONNECTION_CLOSED = 5; // 0x5
-    field public static final int ERROR_CONNECTION_REFUSED = 7; // 0x7
-    field public static final int ERROR_CONNECTION_RESET = 8; // 0x8
-    field public static final int ERROR_CONNECTION_TIMED_OUT = 6; // 0x6
-    field public static final int ERROR_HOSTNAME_NOT_RESOLVED = 1; // 0x1
-    field public static final int ERROR_INTERNET_DISCONNECTED = 2; // 0x2
-    field public static final int ERROR_NETWORK_CHANGED = 3; // 0x3
-    field public static final int ERROR_OTHER = 11; // 0xb
-    field public static final int ERROR_QUIC_PROTOCOL_FAILED = 10; // 0xa
-    field public static final int ERROR_TIMED_OUT = 4; // 0x4
-  }
-
-  public abstract class QuicException extends org.chromium.net.NetworkException {
-    ctor protected QuicException(String, Throwable);
-    method public abstract int getQuicDetailedErrorCode();
-  }
-
-  public abstract class UploadDataProvider implements java.io.Closeable {
-    ctor public UploadDataProvider();
-    method public void close() throws java.io.IOException;
-    method public abstract long getLength() throws java.io.IOException;
-    method public abstract void read(org.chromium.net.UploadDataSink, java.nio.ByteBuffer) throws java.io.IOException;
-    method public abstract void rewind(org.chromium.net.UploadDataSink) throws java.io.IOException;
-  }
-
-  public final class UploadDataProviders {
-    method public static org.chromium.net.UploadDataProvider create(java.io.File);
-    method public static org.chromium.net.UploadDataProvider create(android.os.ParcelFileDescriptor);
-    method public static org.chromium.net.UploadDataProvider create(java.nio.ByteBuffer);
-    method public static org.chromium.net.UploadDataProvider create(byte[], int, int);
-    method public static org.chromium.net.UploadDataProvider create(byte[]);
-  }
-
-  public abstract class UploadDataSink {
-    ctor public UploadDataSink();
-    method public abstract void onReadError(Exception);
-    method public abstract void onReadSucceeded(boolean);
-    method public abstract void onRewindError(Exception);
-    method public abstract void onRewindSucceeded();
-  }
-
-  public abstract class UrlRequest {
-    ctor public UrlRequest();
-    method public abstract void cancel();
-    method public abstract void followRedirect();
-    method public abstract void getStatus(org.chromium.net.UrlRequest.StatusListener);
-    method public abstract boolean isDone();
-    method public abstract void read(java.nio.ByteBuffer);
-    method public abstract void start();
-  }
-
-  public abstract static class UrlRequest.Builder {
-    ctor public UrlRequest.Builder();
-    method public abstract org.chromium.net.UrlRequest.Builder addHeader(String, String);
-    method public abstract org.chromium.net.UrlRequest.Builder allowDirectExecutor();
-    method public abstract org.chromium.net.UrlRequest build();
-    method public abstract org.chromium.net.UrlRequest.Builder disableCache();
-    method public abstract org.chromium.net.UrlRequest.Builder setHttpMethod(String);
-    method public abstract org.chromium.net.UrlRequest.Builder setPriority(int);
-    method public abstract org.chromium.net.UrlRequest.Builder setUploadDataProvider(org.chromium.net.UploadDataProvider, java.util.concurrent.Executor);
-    field public static final int REQUEST_PRIORITY_HIGHEST = 4; // 0x4
-    field public static final int REQUEST_PRIORITY_IDLE = 0; // 0x0
-    field public static final int REQUEST_PRIORITY_LOW = 2; // 0x2
-    field public static final int REQUEST_PRIORITY_LOWEST = 1; // 0x1
-    field public static final int REQUEST_PRIORITY_MEDIUM = 3; // 0x3
-  }
-
-  public abstract static class UrlRequest.Callback {
-    ctor public UrlRequest.Callback();
-    method public void onCanceled(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo);
-    method public abstract void onFailed(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, org.chromium.net.CronetException);
-    method public abstract void onReadCompleted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, java.nio.ByteBuffer) throws java.lang.Exception;
-    method public abstract void onRedirectReceived(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, String) throws java.lang.Exception;
-    method public abstract void onResponseStarted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo) throws java.lang.Exception;
-    method public abstract void onSucceeded(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo);
-  }
-
-  public static class UrlRequest.Status {
-    field public static final int CONNECTING = 10; // 0xa
-    field public static final int DOWNLOADING_PAC_FILE = 5; // 0x5
-    field public static final int ESTABLISHING_PROXY_TUNNEL = 8; // 0x8
-    field public static final int IDLE = 0; // 0x0
-    field public static final int INVALID = -1; // 0xffffffff
-    field public static final int READING_RESPONSE = 14; // 0xe
-    field public static final int RESOLVING_HOST = 9; // 0x9
-    field public static final int RESOLVING_HOST_IN_PAC_FILE = 7; // 0x7
-    field public static final int RESOLVING_PROXY_FOR_URL = 6; // 0x6
-    field public static final int SENDING_REQUEST = 12; // 0xc
-    field public static final int SSL_HANDSHAKE = 11; // 0xb
-    field public static final int WAITING_FOR_AVAILABLE_SOCKET = 2; // 0x2
-    field public static final int WAITING_FOR_CACHE = 4; // 0x4
-    field public static final int WAITING_FOR_DELEGATE = 3; // 0x3
-    field public static final int WAITING_FOR_RESPONSE = 13; // 0xd
-    field public static final int WAITING_FOR_STALLED_SOCKET_POOL = 1; // 0x1
-  }
-
-  public abstract static class UrlRequest.StatusListener {
-    ctor public UrlRequest.StatusListener();
-    method public abstract void onStatus(int);
-  }
-
-  public abstract class UrlResponseInfo {
-    ctor public UrlResponseInfo();
-    method public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> getAllHeaders();
-    method public abstract java.util.List<java.util.Map.Entry<java.lang.String,java.lang.String>> getAllHeadersAsList();
-    method public abstract int getHttpStatusCode();
-    method public abstract String getHttpStatusText();
-    method public abstract String getNegotiatedProtocol();
-    method public abstract String getProxyServer();
-    method public abstract long getReceivedByteCount();
-    method public abstract String getUrl();
-    method public abstract java.util.List<java.lang.String> getUrlChain();
-    method public abstract boolean wasCached();
-  }
-
-}
-
diff --git a/Cronet/api/lint-baseline.txt b/Cronet/api/lint-baseline.txt
deleted file mode 100644
index 0e2f25b..0000000
--- a/Cronet/api/lint-baseline.txt
+++ /dev/null
@@ -1,263 +0,0 @@
-// Baseline format: 1.0
-AcronymName: org.chromium.net.CronetEngine#createURLStreamHandlerFactory():
-    Acronyms should not be capitalized in method names: was `createURLStreamHandlerFactory`, should this be `createUrlStreamHandlerFactory`?
-
-
-AndroidUri: org.chromium.net.CronetEngine#createURLStreamHandlerFactory():
-    Use android.net.Uri instead of java.net.URL (method org.chromium.net.CronetEngine.createURLStreamHandlerFactory())
-AndroidUri: org.chromium.net.CronetEngine#openConnection(java.net.URL):
-    Use android.net.Uri instead of java.net.URL (method org.chromium.net.CronetEngine.openConnection(java.net.URL))
-AndroidUri: org.chromium.net.CronetEngine#openConnection(java.net.URL) parameter #0:
-    Use android.net.Uri instead of java.net.URL (parameter url in org.chromium.net.CronetEngine.openConnection(java.net.URL url))
-
-
-BuilderSetStyle: org.chromium.net.CronetEngine.Builder#enableBrotli(boolean):
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method org.chromium.net.CronetEngine.Builder.enableBrotli(boolean)
-BuilderSetStyle: org.chromium.net.CronetEngine.Builder#enableHttp2(boolean):
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method org.chromium.net.CronetEngine.Builder.enableHttp2(boolean)
-BuilderSetStyle: org.chromium.net.CronetEngine.Builder#enableHttpCache(int, long):
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method org.chromium.net.CronetEngine.Builder.enableHttpCache(int,long)
-BuilderSetStyle: org.chromium.net.CronetEngine.Builder#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean):
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method org.chromium.net.CronetEngine.Builder.enablePublicKeyPinningBypassForLocalTrustAnchors(boolean)
-BuilderSetStyle: org.chromium.net.CronetEngine.Builder#enableQuic(boolean):
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method org.chromium.net.CronetEngine.Builder.enableQuic(boolean)
-BuilderSetStyle: org.chromium.net.UrlRequest.Builder#allowDirectExecutor():
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method org.chromium.net.UrlRequest.Builder.allowDirectExecutor()
-BuilderSetStyle: org.chromium.net.UrlRequest.Builder#disableCache():
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method org.chromium.net.UrlRequest.Builder.disableCache()
-
-
-ExecutorRegistration: org.chromium.net.UrlRequest#getStatus(org.chromium.net.UrlRequest.StatusListener):
-    Registration methods should have overload that accepts delivery Executor: `getStatus`
-
-
-GenericException: org.chromium.net.UrlRequest.Callback#onReadCompleted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, java.nio.ByteBuffer):
-    Methods must not throw generic exceptions (`java.lang.Exception`)
-GenericException: org.chromium.net.UrlRequest.Callback#onRedirectReceived(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, String):
-    Methods must not throw generic exceptions (`java.lang.Exception`)
-GenericException: org.chromium.net.UrlRequest.Callback#onResponseStarted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo):
-    Methods must not throw generic exceptions (`java.lang.Exception`)
-
-
-GetterOnBuilder: org.chromium.net.CronetEngine.Builder#getDefaultUserAgent():
-    Getter should be on the built object, not the builder: method org.chromium.net.CronetEngine.Builder.getDefaultUserAgent()
-
-
-ListenerInterface: org.chromium.net.UrlRequest.StatusListener:
-    Listeners should be an interface, or otherwise renamed Callback: StatusListener
-
-
-ListenerLast: org.chromium.net.CronetEngine#newUrlRequestBuilder(String, org.chromium.net.UrlRequest.Callback, java.util.concurrent.Executor) parameter #2:
-    Listeners should always be at end of argument list (method `newUrlRequestBuilder`)
-
-
-MissingGetterMatchingBuilder: org.chromium.net.CronetEngine.Builder#addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.util.Date):
-    org.chromium.net.CronetEngine does not declare a `getPublicKeyPinss()` method matching method org.chromium.net.CronetEngine.Builder.addPublicKeyPins(String,java.util.Set<byte[]>,boolean,java.util.Date)
-MissingGetterMatchingBuilder: org.chromium.net.CronetEngine.Builder#addQuicHint(String, int, int):
-    org.chromium.net.CronetEngine does not declare a `getQuicHints()` method matching method org.chromium.net.CronetEngine.Builder.addQuicHint(String,int,int)
-MissingGetterMatchingBuilder: org.chromium.net.CronetEngine.Builder#setLibraryLoader(org.chromium.net.CronetEngine.Builder.LibraryLoader):
-    org.chromium.net.CronetEngine does not declare a `getLibraryLoader()` method matching method org.chromium.net.CronetEngine.Builder.setLibraryLoader(org.chromium.net.CronetEngine.Builder.LibraryLoader)
-MissingGetterMatchingBuilder: org.chromium.net.CronetEngine.Builder#setStoragePath(String):
-    org.chromium.net.CronetEngine does not declare a `getStoragePath()` method matching method org.chromium.net.CronetEngine.Builder.setStoragePath(String)
-MissingGetterMatchingBuilder: org.chromium.net.CronetEngine.Builder#setUserAgent(String):
-    org.chromium.net.CronetEngine does not declare a `getUserAgent()` method matching method org.chromium.net.CronetEngine.Builder.setUserAgent(String)
-MissingGetterMatchingBuilder: org.chromium.net.UrlRequest.Builder#addHeader(String, String):
-    org.chromium.net.UrlRequest does not declare a `getHeaders()` method matching method org.chromium.net.UrlRequest.Builder.addHeader(String,String)
-MissingGetterMatchingBuilder: org.chromium.net.UrlRequest.Builder#setHttpMethod(String):
-    org.chromium.net.UrlRequest does not declare a `getHttpMethod()` method matching method org.chromium.net.UrlRequest.Builder.setHttpMethod(String)
-MissingGetterMatchingBuilder: org.chromium.net.UrlRequest.Builder#setPriority(int):
-    org.chromium.net.UrlRequest does not declare a `getPriority()` method matching method org.chromium.net.UrlRequest.Builder.setPriority(int)
-MissingGetterMatchingBuilder: org.chromium.net.UrlRequest.Builder#setUploadDataProvider(org.chromium.net.UploadDataProvider, java.util.concurrent.Executor):
-    org.chromium.net.UrlRequest does not declare a `getUploadDataProvider()` method matching method org.chromium.net.UrlRequest.Builder.setUploadDataProvider(org.chromium.net.UploadDataProvider,java.util.concurrent.Executor)
-
-
-MissingNullability: org.chromium.net.CallbackException#CallbackException(String, Throwable) parameter #0:
-    Missing nullability on parameter `message` in method `CallbackException`
-MissingNullability: org.chromium.net.CallbackException#CallbackException(String, Throwable) parameter #1:
-    Missing nullability on parameter `cause` in method `CallbackException`
-MissingNullability: org.chromium.net.CronetEngine#createURLStreamHandlerFactory():
-    Missing nullability on method `createURLStreamHandlerFactory` return
-MissingNullability: org.chromium.net.CronetEngine#getGlobalMetricsDeltas():
-    Missing nullability on method `getGlobalMetricsDeltas` return
-MissingNullability: org.chromium.net.CronetEngine#getVersionString():
-    Missing nullability on method `getVersionString` return
-MissingNullability: org.chromium.net.CronetEngine#newUrlRequestBuilder(String, org.chromium.net.UrlRequest.Callback, java.util.concurrent.Executor):
-    Missing nullability on method `newUrlRequestBuilder` return
-MissingNullability: org.chromium.net.CronetEngine#newUrlRequestBuilder(String, org.chromium.net.UrlRequest.Callback, java.util.concurrent.Executor) parameter #0:
-    Missing nullability on parameter `url` in method `newUrlRequestBuilder`
-MissingNullability: org.chromium.net.CronetEngine#newUrlRequestBuilder(String, org.chromium.net.UrlRequest.Callback, java.util.concurrent.Executor) parameter #1:
-    Missing nullability on parameter `callback` in method `newUrlRequestBuilder`
-MissingNullability: org.chromium.net.CronetEngine#newUrlRequestBuilder(String, org.chromium.net.UrlRequest.Callback, java.util.concurrent.Executor) parameter #2:
-    Missing nullability on parameter `executor` in method `newUrlRequestBuilder`
-MissingNullability: org.chromium.net.CronetEngine#openConnection(java.net.URL):
-    Missing nullability on method `openConnection` return
-MissingNullability: org.chromium.net.CronetEngine#openConnection(java.net.URL) parameter #0:
-    Missing nullability on parameter `url` in method `openConnection`
-MissingNullability: org.chromium.net.CronetEngine#startNetLogToFile(String, boolean) parameter #0:
-    Missing nullability on parameter `fileName` in method `startNetLogToFile`
-MissingNullability: org.chromium.net.CronetEngine.Builder#Builder(android.content.Context) parameter #0:
-    Missing nullability on parameter `context` in method `Builder`
-MissingNullability: org.chromium.net.CronetEngine.Builder#addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.util.Date):
-    Missing nullability on method `addPublicKeyPins` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.util.Date) parameter #0:
-    Missing nullability on parameter `hostName` in method `addPublicKeyPins`
-MissingNullability: org.chromium.net.CronetEngine.Builder#addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.util.Date) parameter #1:
-    Missing nullability on parameter `pinsSha256` in method `addPublicKeyPins`
-MissingNullability: org.chromium.net.CronetEngine.Builder#addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.util.Date) parameter #3:
-    Missing nullability on parameter `expirationDate` in method `addPublicKeyPins`
-MissingNullability: org.chromium.net.CronetEngine.Builder#addQuicHint(String, int, int):
-    Missing nullability on method `addQuicHint` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#addQuicHint(String, int, int) parameter #0:
-    Missing nullability on parameter `host` in method `addQuicHint`
-MissingNullability: org.chromium.net.CronetEngine.Builder#build():
-    Missing nullability on method `build` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#enableBrotli(boolean):
-    Missing nullability on method `enableBrotli` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#enableHttp2(boolean):
-    Missing nullability on method `enableHttp2` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#enableHttpCache(int, long):
-    Missing nullability on method `enableHttpCache` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean):
-    Missing nullability on method `enablePublicKeyPinningBypassForLocalTrustAnchors` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#enableQuic(boolean):
-    Missing nullability on method `enableQuic` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#getDefaultUserAgent():
-    Missing nullability on method `getDefaultUserAgent` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#setLibraryLoader(org.chromium.net.CronetEngine.Builder.LibraryLoader):
-    Missing nullability on method `setLibraryLoader` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#setLibraryLoader(org.chromium.net.CronetEngine.Builder.LibraryLoader) parameter #0:
-    Missing nullability on parameter `loader` in method `setLibraryLoader`
-MissingNullability: org.chromium.net.CronetEngine.Builder#setStoragePath(String):
-    Missing nullability on method `setStoragePath` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#setStoragePath(String) parameter #0:
-    Missing nullability on parameter `value` in method `setStoragePath`
-MissingNullability: org.chromium.net.CronetEngine.Builder#setUserAgent(String):
-    Missing nullability on method `setUserAgent` return
-MissingNullability: org.chromium.net.CronetEngine.Builder#setUserAgent(String) parameter #0:
-    Missing nullability on parameter `userAgent` in method `setUserAgent`
-MissingNullability: org.chromium.net.CronetEngine.Builder.LibraryLoader#loadLibrary(String) parameter #0:
-    Missing nullability on parameter `libName` in method `loadLibrary`
-MissingNullability: org.chromium.net.CronetException#CronetException(String, Throwable) parameter #0:
-    Missing nullability on parameter `message` in method `CronetException`
-MissingNullability: org.chromium.net.CronetException#CronetException(String, Throwable) parameter #1:
-    Missing nullability on parameter `cause` in method `CronetException`
-MissingNullability: org.chromium.net.NetworkException#NetworkException(String, Throwable) parameter #0:
-    Missing nullability on parameter `message` in method `NetworkException`
-MissingNullability: org.chromium.net.NetworkException#NetworkException(String, Throwable) parameter #1:
-    Missing nullability on parameter `cause` in method `NetworkException`
-MissingNullability: org.chromium.net.QuicException#QuicException(String, Throwable) parameter #0:
-    Missing nullability on parameter `message` in method `QuicException`
-MissingNullability: org.chromium.net.QuicException#QuicException(String, Throwable) parameter #1:
-    Missing nullability on parameter `cause` in method `QuicException`
-MissingNullability: org.chromium.net.UploadDataProvider#read(org.chromium.net.UploadDataSink, java.nio.ByteBuffer) parameter #0:
-    Missing nullability on parameter `uploadDataSink` in method `read`
-MissingNullability: org.chromium.net.UploadDataProvider#read(org.chromium.net.UploadDataSink, java.nio.ByteBuffer) parameter #1:
-    Missing nullability on parameter `byteBuffer` in method `read`
-MissingNullability: org.chromium.net.UploadDataProvider#rewind(org.chromium.net.UploadDataSink) parameter #0:
-    Missing nullability on parameter `uploadDataSink` in method `rewind`
-MissingNullability: org.chromium.net.UploadDataProviders#create(android.os.ParcelFileDescriptor):
-    Missing nullability on method `create` return
-MissingNullability: org.chromium.net.UploadDataProviders#create(android.os.ParcelFileDescriptor) parameter #0:
-    Missing nullability on parameter `fd` in method `create`
-MissingNullability: org.chromium.net.UploadDataProviders#create(byte[]):
-    Missing nullability on method `create` return
-MissingNullability: org.chromium.net.UploadDataProviders#create(byte[]) parameter #0:
-    Missing nullability on parameter `data` in method `create`
-MissingNullability: org.chromium.net.UploadDataProviders#create(byte[], int, int):
-    Missing nullability on method `create` return
-MissingNullability: org.chromium.net.UploadDataProviders#create(byte[], int, int) parameter #0:
-    Missing nullability on parameter `data` in method `create`
-MissingNullability: org.chromium.net.UploadDataProviders#create(java.io.File):
-    Missing nullability on method `create` return
-MissingNullability: org.chromium.net.UploadDataProviders#create(java.io.File) parameter #0:
-    Missing nullability on parameter `file` in method `create`
-MissingNullability: org.chromium.net.UploadDataProviders#create(java.nio.ByteBuffer):
-    Missing nullability on method `create` return
-MissingNullability: org.chromium.net.UploadDataProviders#create(java.nio.ByteBuffer) parameter #0:
-    Missing nullability on parameter `buffer` in method `create`
-MissingNullability: org.chromium.net.UploadDataSink#onReadError(Exception) parameter #0:
-    Missing nullability on parameter `exception` in method `onReadError`
-MissingNullability: org.chromium.net.UploadDataSink#onRewindError(Exception) parameter #0:
-    Missing nullability on parameter `exception` in method `onRewindError`
-MissingNullability: org.chromium.net.UrlRequest#getStatus(org.chromium.net.UrlRequest.StatusListener) parameter #0:
-    Missing nullability on parameter `listener` in method `getStatus`
-MissingNullability: org.chromium.net.UrlRequest#read(java.nio.ByteBuffer) parameter #0:
-    Missing nullability on parameter `buffer` in method `read`
-MissingNullability: org.chromium.net.UrlRequest.Builder#addHeader(String, String):
-    Missing nullability on method `addHeader` return
-MissingNullability: org.chromium.net.UrlRequest.Builder#addHeader(String, String) parameter #0:
-    Missing nullability on parameter `header` in method `addHeader`
-MissingNullability: org.chromium.net.UrlRequest.Builder#addHeader(String, String) parameter #1:
-    Missing nullability on parameter `value` in method `addHeader`
-MissingNullability: org.chromium.net.UrlRequest.Builder#allowDirectExecutor():
-    Missing nullability on method `allowDirectExecutor` return
-MissingNullability: org.chromium.net.UrlRequest.Builder#build():
-    Missing nullability on method `build` return
-MissingNullability: org.chromium.net.UrlRequest.Builder#disableCache():
-    Missing nullability on method `disableCache` return
-MissingNullability: org.chromium.net.UrlRequest.Builder#setHttpMethod(String):
-    Missing nullability on method `setHttpMethod` return
-MissingNullability: org.chromium.net.UrlRequest.Builder#setHttpMethod(String) parameter #0:
-    Missing nullability on parameter `method` in method `setHttpMethod`
-MissingNullability: org.chromium.net.UrlRequest.Builder#setPriority(int):
-    Missing nullability on method `setPriority` return
-MissingNullability: org.chromium.net.UrlRequest.Builder#setUploadDataProvider(org.chromium.net.UploadDataProvider, java.util.concurrent.Executor):
-    Missing nullability on method `setUploadDataProvider` return
-MissingNullability: org.chromium.net.UrlRequest.Builder#setUploadDataProvider(org.chromium.net.UploadDataProvider, java.util.concurrent.Executor) parameter #0:
-    Missing nullability on parameter `uploadDataProvider` in method `setUploadDataProvider`
-MissingNullability: org.chromium.net.UrlRequest.Builder#setUploadDataProvider(org.chromium.net.UploadDataProvider, java.util.concurrent.Executor) parameter #1:
-    Missing nullability on parameter `executor` in method `setUploadDataProvider`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onCanceled(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo) parameter #0:
-    Missing nullability on parameter `request` in method `onCanceled`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onCanceled(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo) parameter #1:
-    Missing nullability on parameter `info` in method `onCanceled`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onFailed(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, org.chromium.net.CronetException) parameter #0:
-    Missing nullability on parameter `request` in method `onFailed`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onFailed(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, org.chromium.net.CronetException) parameter #1:
-    Missing nullability on parameter `info` in method `onFailed`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onFailed(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, org.chromium.net.CronetException) parameter #2:
-    Missing nullability on parameter `error` in method `onFailed`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onReadCompleted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, java.nio.ByteBuffer) parameter #0:
-    Missing nullability on parameter `request` in method `onReadCompleted`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onReadCompleted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, java.nio.ByteBuffer) parameter #1:
-    Missing nullability on parameter `info` in method `onReadCompleted`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onReadCompleted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, java.nio.ByteBuffer) parameter #2:
-    Missing nullability on parameter `byteBuffer` in method `onReadCompleted`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onRedirectReceived(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, String) parameter #0:
-    Missing nullability on parameter `request` in method `onRedirectReceived`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onRedirectReceived(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, String) parameter #1:
-    Missing nullability on parameter `info` in method `onRedirectReceived`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onRedirectReceived(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo, String) parameter #2:
-    Missing nullability on parameter `newLocationUrl` in method `onRedirectReceived`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onResponseStarted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo) parameter #0:
-    Missing nullability on parameter `request` in method `onResponseStarted`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onResponseStarted(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo) parameter #1:
-    Missing nullability on parameter `info` in method `onResponseStarted`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onSucceeded(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo) parameter #0:
-    Missing nullability on parameter `request` in method `onSucceeded`
-MissingNullability: org.chromium.net.UrlRequest.Callback#onSucceeded(org.chromium.net.UrlRequest, org.chromium.net.UrlResponseInfo) parameter #1:
-    Missing nullability on parameter `info` in method `onSucceeded`
-MissingNullability: org.chromium.net.UrlResponseInfo#getAllHeaders():
-    Missing nullability on method `getAllHeaders` return
-MissingNullability: org.chromium.net.UrlResponseInfo#getAllHeadersAsList():
-    Missing nullability on method `getAllHeadersAsList` return
-MissingNullability: org.chromium.net.UrlResponseInfo#getHttpStatusText():
-    Missing nullability on method `getHttpStatusText` return
-MissingNullability: org.chromium.net.UrlResponseInfo#getNegotiatedProtocol():
-    Missing nullability on method `getNegotiatedProtocol` return
-MissingNullability: org.chromium.net.UrlResponseInfo#getProxyServer():
-    Missing nullability on method `getProxyServer` return
-MissingNullability: org.chromium.net.UrlResponseInfo#getUrl():
-    Missing nullability on method `getUrl` return
-MissingNullability: org.chromium.net.UrlResponseInfo#getUrlChain():
-    Missing nullability on method `getUrlChain` return
-
-
-NotCloseable: org.chromium.net.CronetEngine:
-    Classes that release resources (shutdown()) should implement AutoClosable and CloseGuard: class org.chromium.net.CronetEngine
-
-
-StaticFinalBuilder: org.chromium.net.CronetEngine.Builder:
-    Builder must be final: org.chromium.net.CronetEngine.Builder
-StaticFinalBuilder: org.chromium.net.UrlRequest.Builder:
-    Builder must be final: org.chromium.net.UrlRequest.Builder
diff --git a/Cronet/api/module-lib-current.txt b/Cronet/api/module-lib-current.txt
deleted file mode 100644
index d802177..0000000
--- a/Cronet/api/module-lib-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/Cronet/api/system-current.txt b/Cronet/api/system-current.txt
deleted file mode 100644
index d802177..0000000
--- a/Cronet/api/system-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/Cronet/api/test-current.txt b/Cronet/api/test-current.txt
deleted file mode 100644
index d802177..0000000
--- a/Cronet/api/test-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/Cronet/api/test-removed.txt b/Cronet/api/test-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/Cronet/api/test-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/Cronet/jarjar-rules.txt b/Cronet/jarjar-rules.txt
deleted file mode 100644
index 76a799e..0000000
--- a/Cronet/jarjar-rules.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-rule androidx.** com.android.net.http.@0
-rule android.support.** com.android.net.http.@0
-
diff --git a/Cronet/prebuilt/VERSION b/Cronet/prebuilt/VERSION
deleted file mode 100644
index c16ab94..0000000
--- a/Cronet/prebuilt/VERSION
+++ /dev/null
@@ -1,4 +0,0 @@
-MAJOR=80
-MINOR=0
-BUILD=3986
-PATCH=0
diff --git a/Cronet/prebuilt/api_version.txt b/Cronet/prebuilt/api_version.txt
deleted file mode 100644
index 48082f7..0000000
--- a/Cronet/prebuilt/api_version.txt
+++ /dev/null
@@ -1 +0,0 @@
-12
diff --git a/Cronet/prebuilt/cronet_api-src.jar b/Cronet/prebuilt/cronet_api-src.jar
deleted file mode 100644
index 924b877..0000000
--- a/Cronet/prebuilt/cronet_api-src.jar
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/cronet_api.jar b/Cronet/prebuilt/cronet_api.jar
deleted file mode 100644
index 977b28d..0000000
--- a/Cronet/prebuilt/cronet_api.jar
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/cronet_impl_common_java.jar b/Cronet/prebuilt/cronet_impl_common_java.jar
deleted file mode 100644
index fa71bf3..0000000
--- a/Cronet/prebuilt/cronet_impl_common_java.jar
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/cronet_impl_native_java.jar b/Cronet/prebuilt/cronet_impl_native_java.jar
deleted file mode 100644
index 4cdd6f3..0000000
--- a/Cronet/prebuilt/cronet_impl_native_java.jar
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/cronet_impl_platform_java.jar b/Cronet/prebuilt/cronet_impl_platform_java.jar
deleted file mode 100644
index 6d6042f..0000000
--- a/Cronet/prebuilt/cronet_impl_platform_java.jar
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/libs/arm64-v8a/libcronet.107.0.5284.2.so b/Cronet/prebuilt/libs/arm64-v8a/libcronet.107.0.5284.2.so
deleted file mode 100644
index 7f2540a..0000000
--- a/Cronet/prebuilt/libs/arm64-v8a/libcronet.107.0.5284.2.so
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/libs/armeabi-v7a/libcronet.107.0.5284.2.so b/Cronet/prebuilt/libs/armeabi-v7a/libcronet.107.0.5284.2.so
deleted file mode 100644
index 115429a..0000000
--- a/Cronet/prebuilt/libs/armeabi-v7a/libcronet.107.0.5284.2.so
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/libs/x86/libcronet.107.0.5284.2.so b/Cronet/prebuilt/libs/x86/libcronet.107.0.5284.2.so
deleted file mode 100644
index 27923f7..0000000
--- a/Cronet/prebuilt/libs/x86/libcronet.107.0.5284.2.so
+++ /dev/null
Binary files differ
diff --git a/Cronet/prebuilt/libs/x86_64/libcronet.107.0.5284.2.so b/Cronet/prebuilt/libs/x86_64/libcronet.107.0.5284.2.so
deleted file mode 100644
index 803e5cd..0000000
--- a/Cronet/prebuilt/libs/x86_64/libcronet.107.0.5284.2.so
+++ /dev/null
Binary files differ
diff --git a/Cronet/tests/common/Android.bp b/Cronet/tests/common/Android.bp
new file mode 100644
index 0000000..f8bdb08
--- /dev/null
+++ b/Cronet/tests/common/Android.bp
@@ -0,0 +1,39 @@
+// 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.
+//
+
+// Tests in this folder are included both in unit tests and CTS.
+// They must be fast and stable, and exercise public or test APIs.
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// TODO: Consider merging with ConnectivityCoverageTests which is a collection of all
+// Connectivity tests being used for coverage. This will depend on how far we decide to
+// go with merging NetHttp and Tethering targets.
+android_test {
+    name: "NetHttpCoverageTests",
+    defaults: ["CronetTestJavaDefaults"],
+    sdk_version: "test_current",
+    test_suites: ["general-tests", "mts-tethering"],
+    static_libs: [
+        "modules-utils-native-coverage-listener",
+        "CtsNetHttpTestsLib",
+        "NetHttpTestsLibPreJarJar",
+    ],
+    jarjar_rules: ":framework-tethering-jarjar-rules",
+    compile_multilib: "both", // Include both the 32 and 64 bit versions
+}
diff --git a/Cronet/tests/common/AndroidManifest.xml b/Cronet/tests/common/AndroidManifest.xml
new file mode 100644
index 0000000..efe880c
--- /dev/null
+++ b/Cronet/tests/common/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="com.android.net.http.tests.coverage">
+    <!-- NetHttpCoverageTests combines CtsNetHttpTestCases and NetHttpTests targets,
+     so permissions and others are declared in their respective manifests -->
+    <application tools:replace="android:label"
+                 android:label="NetHttp coverage tests">
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.net.http.tests.coverage"
+                     android:label="NetHttp coverage tests">
+    </instrumentation>
+</manifest>
diff --git a/Cronet/tests/common/AndroidTest.xml b/Cronet/tests/common/AndroidTest.xml
new file mode 100644
index 0000000..ca298dd
--- /dev/null
+++ b/Cronet/tests/common/AndroidTest.xml
@@ -0,0 +1,33 @@
+<!--
+  ~ 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.
+  -->
+<configuration description="Runs coverage tests for NetHttp">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="test-file-name" value="NetHttpCoverageTests.apk" />
+        <option name="install-arg" value="-t" />
+    </target_preparer>
+    <option name="test-tag" value="NetHttpCoverageTests" />
+    <!-- Tethering/Connectivity is a SDK 30+ module -->
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.net.http.tests.coverage" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+        <option
+            name="device-listeners"
+            value="com.android.modules.utils.testing.NativeCoverageHackInstrumentationListener" />
+    </test>
+</configuration>
diff --git a/Cronet/tests/cts/Android.bp b/Cronet/tests/cts/Android.bp
index d10c68c..d260694 100644
--- a/Cronet/tests/cts/Android.bp
+++ b/Cronet/tests/cts/Android.bp
@@ -18,31 +18,64 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-android_test {
-    name: "CtsCronetTestCases",
-    compile_multilib: "both", // Include both the 32 and 64 bit versions
-    defaults: ["cts_defaults"],
+// cronet_test_java_defaults can be used to specify a java_defaults target that
+// either enables or disables Cronet tests. This is used to disable Cronet
+// tests on tm-mainline-prod where the required APIs are not present.
+cronet_test_java_defaults = "CronetTestJavaDefaultsEnabled"
+// This is a placeholder comment to avoid merge conflicts
+// as cronet_test_java_defaults may have different values
+// depending on the branch
+
+java_defaults {
+    name: "CronetTestJavaDefaultsEnabled",
+    enabled: true,
+}
+
+java_defaults {
+    name: "CronetTestJavaDefaultsDisabled",
+    enabled: false,
+}
+
+java_defaults {
+    name: "CronetTestJavaDefaults",
+    defaults: [cronet_test_java_defaults],
+}
+
+android_library {
+    name: "CtsNetHttpTestsLib",
     sdk_version: "test_current",
     srcs: [
         "src/**/*.java",
         "src/**/*.kt",
     ],
     static_libs: [
+        "androidx.test.ext.junit",
         "androidx.test.rules",
         "androidx.core_core",
         "ctstestrunner-axt",
         "ctstestserver",
         "junit",
+        "hamcrest-library",
+        "kotlin-test",
     ],
     libs: [
         "android.test.runner",
         "android.test.base",
         "android.test.mock",
         "androidx.annotation_annotation",
-        "framework-cronet",
+        "framework-tethering",
         "org.apache.http.legacy",
     ],
+}
 
+android_test {
+    name: "CtsNetHttpTestCases",
+    defaults: [
+        "cts_defaults",
+        "CronetTestJavaDefaults",
+    ],
+    sdk_version: "test_current",
+    static_libs: ["CtsNetHttpTestsLib"],
     // Tag this as a cts test artifact
     test_suites: [
         "cts",
diff --git a/Cronet/tests/cts/AndroidManifest.xml b/Cronet/tests/cts/AndroidManifest.xml
index 5a92dea..26900b2 100644
--- a/Cronet/tests/cts/AndroidManifest.xml
+++ b/Cronet/tests/cts/AndroidManifest.xml
@@ -25,14 +25,11 @@
 
     <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="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
index 1f6bdb3..e0421fd 100644
--- a/Cronet/tests/cts/AndroidTest.xml
+++ b/Cronet/tests/cts/AndroidTest.xml
@@ -17,19 +17,20 @@
 <configuration description="Config for CTS Cronet test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="networking" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <!-- 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" />
+        <option name="test-file-name" value="CtsNetHttpTestCases.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. -->
+    <!-- Only run CtsNetHttpTestCases 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" />
diff --git a/Cronet/tests/cts/src/android/net/http/cts/CallbackExceptionTest.kt b/Cronet/tests/cts/src/android/net/http/cts/CallbackExceptionTest.kt
new file mode 100644
index 0000000..e17b63f
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/CallbackExceptionTest.kt
@@ -0,0 +1,67 @@
+/*
+ * 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 android.net.http.cts
+
+import android.content.Context
+import android.net.http.CallbackException
+import android.net.http.HttpEngine
+import android.net.http.cts.util.HttpCtsTestServer
+import android.net.http.cts.util.TestUrlRequestCallback
+import android.net.http.cts.util.TestUrlRequestCallback.FailureType
+import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertIs
+import kotlin.test.assertSame
+import kotlin.test.assertTrue
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class CallbackExceptionTest {
+
+    @Test
+    fun testCallbackException_returnsInputParameters() {
+        val message = "failed"
+        val cause = Throwable("exception")
+        val callbackException = object : CallbackException(message, cause) {}
+
+        assertEquals(message, callbackException.message)
+        assertSame(cause, callbackException.cause)
+    }
+
+    @Test
+    fun testCallbackException_thrownFromUrlRequest() {
+        val context: Context = ApplicationProvider.getApplicationContext()
+        val server = HttpCtsTestServer(context)
+        val httpEngine = HttpEngine.Builder(context).build()
+        val callback = TestUrlRequestCallback()
+        callback.setFailure(FailureType.THROW_SYNC, ResponseStep.ON_RESPONSE_STARTED)
+        val request = httpEngine
+            .newUrlRequestBuilder(server.successUrl, callback, callback.executor)
+            .build()
+
+        request.start()
+        callback.blockForDone()
+
+        assertTrue(request.isDone)
+        assertIs<CallbackException>(callback.mError)
+        server.shutdown()
+        httpEngine.shutdown()
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt
new file mode 100644
index 0000000..2701ed0
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt
@@ -0,0 +1,46 @@
+/*
+ * 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 android.net.http.cts
+
+import android.net.http.ConnectionMigrationOptions
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.Test
+import kotlin.test.assertNotNull
+import kotlin.test.assertTrue
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ConnectionMigrationOptionsTest {
+
+    @Test
+    fun testConnectionMigrationOptions_enableDefaultNetworkMigration_returnSetValue() {
+        val options =
+            ConnectionMigrationOptions.Builder().setEnableDefaultNetworkMigration(true).build()
+
+        assertNotNull(options.enableDefaultNetworkMigration)
+        assertTrue(options.enableDefaultNetworkMigration!!)
+    }
+
+    @Test
+    fun testConnectionMigrationOptions_enablePathDegradationMigration_returnSetValue() {
+        val options =
+            ConnectionMigrationOptions.Builder().setEnablePathDegradationMigration(true).build()
+
+        assertNotNull(options.enablePathDegradationMigration)
+        assertTrue(options.enablePathDegradationMigration!!)
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/CronetUrlRequestTest.java b/Cronet/tests/cts/src/android/net/http/cts/CronetUrlRequestTest.java
deleted file mode 100644
index 2898f54..0000000
--- a/Cronet/tests/cts/src/android/net/http/cts/CronetUrlRequestTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.http.cts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-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;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.chromium.net.CronetEngine;
-import org.chromium.net.UrlRequest;
-import org.chromium.net.UrlResponseInfo;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class CronetUrlRequestTest {
-    private static final String TAG = CronetUrlRequestTest.class.getSimpleName();
-
-    @NonNull private CronetEngine mCronetEngine;
-    @NonNull private ConnectivityManager mCm;
-    @NonNull private CronetCtsTestServer mTestServer;
-
-    @Before
-    public void setUp() throws Exception {
-        Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        CronetEngine.Builder builder = new CronetEngine.Builder(context);
-        builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_IN_MEMORY, 100 * 1024)
-                .enableHttp2(true)
-                // .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) {
-        assertTrue(msg + " Excepted " + first + " to be greater than " + second, first > second);
-    }
-
-    private void assertHasTestableNetworks() {
-        assertNotNull("This test requires a working Internet connection", mCm.getActiveNetwork());
-    }
-
-    @Test
-    public void testUrlRequestGet_CompletesSuccessfully() throws Exception {
-        assertHasTestableNetworks();
-        String url = mTestServer.getSuccessUrl();
-        TestUrlRequestCallback callback = new TestUrlRequestCallback();
-        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());
-        assertGreaterThan(
-                "Received byte from " + url + " is 0.", (int) info.getReceivedByteCount(), 0);
-    }
-}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
new file mode 100644
index 0000000..b96e931
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
@@ -0,0 +1,128 @@
+/*
+ * 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 android.net.http.cts
+
+import android.net.http.DnsOptions
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import java.time.Duration
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class DnsOptionsTest {
+
+    @Test
+    fun testDnsOptions_defaultValues() {
+        val options = DnsOptions.Builder().build()
+
+        assertNull(options.persistHostCache)
+        assertNull(options.persistHostCachePeriod)
+        assertNull(options.enableStaleDns)
+        assertNull(options.staleDnsOptions)
+        assertNull(options.useHttpStackDnsResolver)
+        assertNull(options.preestablishConnectionsToStaleDnsResults)
+    }
+
+    @Test
+    fun testDnsOptions_persistHostCache_returnSetValue() {
+        val options = DnsOptions.Builder().setPersistHostCache(true).build()
+
+        assertNotNull(options.persistHostCache)
+        assertTrue(options.persistHostCache!!)
+    }
+
+    @Test
+    fun testDnsOptions_persistHostCachePeriod_returnSetValue() {
+        val period = Duration.ofMillis(12345)
+        val options = DnsOptions.Builder().setPersistHostCachePeriod(period).build()
+
+        assertEquals(period, options.persistHostCachePeriod)
+    }
+
+    @Test
+    fun testDnsOptions_enableStaleDns_returnSetValue() {
+        val options = DnsOptions.Builder().setEnableStaleDns(true).build()
+
+        assertNotNull(options.enableStaleDns)
+        assertTrue(options.enableStaleDns!!)
+    }
+
+    @Test
+    fun testDnsOptions_useHttpStackDnsResolver_returnsSetValue() {
+        val options = DnsOptions.Builder().setUseHttpStackDnsResolver(true).build()
+
+        assertNotNull(options.useHttpStackDnsResolver)
+        assertTrue(options.useHttpStackDnsResolver!!)
+    }
+
+    @Test
+    fun testDnsOptions_preestablishConnectionsToStaleDnsResults_returnsSetValue() {
+        val options = DnsOptions.Builder().setPreestablishConnectionsToStaleDnsResults(true).build()
+
+        assertNotNull(options.preestablishConnectionsToStaleDnsResults)
+        assertTrue(options.preestablishConnectionsToStaleDnsResults!!)
+    }
+
+    @Test
+    fun testStaleDnsOptions_defaultValues() {
+        val options = DnsOptions.StaleDnsOptions.Builder().build()
+
+        assertNull(options.allowCrossNetworkUsage)
+        assertNull(options.freshLookupTimeoutMillis)
+        assertNull(options.maxExpiredDelayMillis)
+        assertNull(options.useStaleOnNameNotResolved)
+    }
+
+    @Test
+    fun testStaleDnsOptions_allowCrossNetworkUsage_returnsSetValue() {
+        val options = DnsOptions.StaleDnsOptions.Builder().setAllowCrossNetworkUsage(true).build()
+
+        assertNotNull(options.allowCrossNetworkUsage)
+        assertTrue(options.allowCrossNetworkUsage!!)
+    }
+
+    @Test
+    fun testStaleDnsOptions_freshLookupTimeout_returnsSetValue() {
+        val duration = Duration.ofMillis(12345)
+        val options = DnsOptions.StaleDnsOptions.Builder().setFreshLookupTimeout(duration).build()
+
+        assertNotNull(options.freshLookupTimeoutMillis)
+        assertEquals(duration.toMillis(), options.freshLookupTimeoutMillis!!)
+    }
+
+    @Test
+    fun testStaleDnsOptions_useStaleOnNameNotResolved_returnsSetValue() {
+        val options =
+                DnsOptions.StaleDnsOptions.Builder().setUseStaleOnNameNotResolved(true).build()
+
+        assertNotNull(options.useStaleOnNameNotResolved)
+        assertTrue(options.useStaleOnNameNotResolved!!)
+    }
+
+    @Test
+    fun testStaleDnsOptions_maxExpiredDelayMillis_returnsSetValue() {
+        val duration = Duration.ofMillis(12345)
+        val options = DnsOptions.StaleDnsOptions.Builder().setMaxExpiredDelay(duration).build()
+
+        assertNotNull(options.maxExpiredDelayMillis)
+        assertEquals(duration.toMillis(), options.maxExpiredDelayMillis!!)
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java b/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
new file mode 100644
index 0000000..8663a67
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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 android.net.http.cts;
+
+import static android.net.http.cts.util.TestUtilsKt.assertOKStatusCode;
+import static android.net.http.cts.util.TestUtilsKt.assumeOKStatusCode;
+import static android.net.http.cts.util.TestUtilsKt.skipIfNoInternetConnection;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.net.http.HttpEngine;
+import android.net.http.UrlRequest;
+import android.net.http.UrlResponseInfo;
+import android.net.http.cts.util.TestUrlRequestCallback;
+import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class HttpEngineTest {
+    private static final String HOST = "source.android.com";
+    private static final String URL = "https://" + HOST;
+
+    private HttpEngine.Builder mEngineBuilder;
+    private TestUrlRequestCallback mCallback;
+    private UrlRequest mRequest;
+    private HttpEngine mEngine;
+
+    @Before
+    public void setUp() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        skipIfNoInternetConnection(context);
+        mEngineBuilder = new HttpEngine.Builder(context);
+        mCallback = new TestUrlRequestCallback();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (mRequest != null) {
+            mRequest.cancel();
+            mCallback.blockForDone();
+        }
+        if (mEngine != null) {
+            mEngine.shutdown();
+        }
+    }
+
+    private boolean isQuic(String negotiatedProtocol) {
+        return negotiatedProtocol.startsWith("http/2+quic") || negotiatedProtocol.startsWith("h3");
+    }
+
+    @Test
+    public void testHttpEngine_Default() throws Exception {
+        mEngine = mEngineBuilder.build();
+        UrlRequest.Builder builder =
+                mEngine.newUrlRequestBuilder(URL, mCallback, mCallback.getExecutor());
+        mRequest = builder.build();
+        mRequest.start();
+
+        // This tests uses a non-hermetic server. Instead of asserting, assume the next callback.
+        // This way, if the request were to fail, the test would just be skipped instead of failing.
+        mCallback.assumeCallback(ResponseStep.ON_SUCCEEDED);
+        UrlResponseInfo info = mCallback.mResponseInfo;
+        assertOKStatusCode(info);
+        assertEquals("h2", info.getNegotiatedProtocol());
+    }
+
+    @Test
+    public void testHttpEngine_DisableHttp2() throws Exception {
+        mEngine = mEngineBuilder.setEnableHttp2(false).build();
+        UrlRequest.Builder builder =
+                mEngine.newUrlRequestBuilder(URL, mCallback, mCallback.getExecutor());
+        mRequest = builder.build();
+        mRequest.start();
+
+        // This tests uses a non-hermetic server. Instead of asserting, assume the next callback.
+        // This way, if the request were to fail, the test would just be skipped instead of failing.
+        mCallback.assumeCallback(ResponseStep.ON_SUCCEEDED);
+        UrlResponseInfo info = mCallback.mResponseInfo;
+        assertOKStatusCode(info);
+        assertEquals("http/1.1", info.getNegotiatedProtocol());
+    }
+
+    @Test
+    public void testHttpEngine_EnableQuic() throws Exception {
+        mEngine = mEngineBuilder.setEnableQuic(true).addQuicHint(HOST, 443, 443).build();
+        // The hint doesn't guarantee that QUIC will win the race, just that it will race TCP.
+        // We send multiple requests to reduce the flakiness of the test.
+        boolean quicWasUsed = false;
+        for (int i = 0; i < 5; i++) {
+            mCallback = new TestUrlRequestCallback();
+            UrlRequest.Builder builder =
+                    mEngine.newUrlRequestBuilder(URL, mCallback, mCallback.getExecutor());
+            mRequest = builder.build();
+            mRequest.start();
+
+            // This tests uses a non-hermetic server. Instead of asserting, assume the next
+            // callback. This way, if the request were to fail, the test would just be skipped
+            // instead of failing.
+            mCallback.assumeCallback(ResponseStep.ON_SUCCEEDED);
+            UrlResponseInfo info = mCallback.mResponseInfo;
+            assumeOKStatusCode(info);
+            quicWasUsed = isQuic(info.getNegotiatedProtocol());
+            if (quicWasUsed) {
+                break;
+            }
+        }
+        assertTrue(quicWasUsed);
+    }
+
+    @Test
+    public void testHttpEngine_GetDefaultUserAgent() throws Exception {
+        assertThat(mEngineBuilder.getDefaultUserAgent(), containsString("AndroidHttpClient"));
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/NetworkExceptionTest.kt b/Cronet/tests/cts/src/android/net/http/cts/NetworkExceptionTest.kt
new file mode 100644
index 0000000..a2611e4
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/NetworkExceptionTest.kt
@@ -0,0 +1,59 @@
+/*
+ * 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 android.net.http.cts
+
+import android.net.http.HttpEngine
+import android.net.http.NetworkException
+import android.net.http.cts.util.TestUrlRequestCallback
+import androidx.test.core.app.ApplicationProvider
+import kotlin.test.assertEquals
+import kotlin.test.assertIs
+import kotlin.test.assertSame
+import kotlin.test.assertTrue
+import org.junit.Test
+
+class NetworkExceptionTest {
+
+    @Test
+    fun testNetworkException_returnsInputParameters() {
+        val message = "failed"
+        val cause = Throwable("thrown")
+        val networkException =
+            object : NetworkException(message, cause) {
+                override fun getErrorCode() = 0
+                override fun isImmediatelyRetryable() = false
+            }
+
+        assertEquals(message, networkException.message)
+        assertSame(cause, networkException.cause)
+    }
+
+    @Test
+    fun testNetworkException_thrownFromUrlRequest() {
+        val httpEngine = HttpEngine.Builder(ApplicationProvider.getApplicationContext()).build()
+        val callback = TestUrlRequestCallback()
+        val request =
+            httpEngine.newUrlRequestBuilder("http://localhost", callback, callback.executor).build()
+
+        request.start()
+        callback.blockForDone()
+
+        assertTrue(request.isDone)
+        assertIs<NetworkException>(callback.mError)
+        httpEngine.shutdown()
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java b/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
new file mode 100644
index 0000000..5256bae
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+package android.net.http.cts;
+
+import static android.net.http.cts.util.TestUtilsKt.assertOKStatusCode;
+import static android.net.http.cts.util.TestUtilsKt.skipIfNoInternetConnection;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import android.content.Context;
+import android.net.http.HttpEngine;
+import android.net.http.UrlRequest;
+import android.net.http.UrlRequest.Status;
+import android.net.http.UrlResponseInfo;
+import android.net.http.cts.util.HttpCtsTestServer;
+import android.net.http.cts.util.TestStatusListener;
+import android.net.http.cts.util.TestUploadDataProvider;
+import android.net.http.cts.util.TestUrlRequestCallback;
+import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class UrlRequestTest {
+    private TestUrlRequestCallback mCallback;
+    private HttpCtsTestServer mTestServer;
+    private HttpEngine mHttpEngine;
+
+    @Before
+    public void setUp() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        skipIfNoInternetConnection(context);
+        HttpEngine.Builder builder = new HttpEngine.Builder(context);
+        mHttpEngine = builder.build();
+        mCallback = new TestUrlRequestCallback();
+        mTestServer = new HttpCtsTestServer(context);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (mHttpEngine != null) {
+            mHttpEngine.shutdown();
+        }
+        if (mTestServer != null) {
+            mTestServer.shutdown();
+        }
+    }
+
+    private UrlRequest.Builder createUrlRequestBuilder(String url) {
+        return mHttpEngine.newUrlRequestBuilder(url, mCallback, mCallback.getExecutor());
+    }
+
+    @Test
+    public void testUrlRequestGet_CompletesSuccessfully() throws Exception {
+        String url = mTestServer.getSuccessUrl();
+        UrlRequest request = createUrlRequestBuilder(url).build();
+        request.start();
+
+        mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+        UrlResponseInfo info = mCallback.mResponseInfo;
+        assertOKStatusCode(info);
+        assertThat("Received byte count must be > 0", info.getReceivedByteCount(), greaterThan(0L));
+    }
+
+    @Test
+    public void testUrlRequestStatus_InvalidBeforeRequestStarts() throws Exception {
+        UrlRequest request = createUrlRequestBuilder(mTestServer.getSuccessUrl()).build();
+        // Calling before request is started should give Status.INVALID,
+        // since the native adapter is not created.
+        TestStatusListener statusListener = new TestStatusListener();
+        request.getStatus(statusListener);
+        statusListener.expectStatus(Status.INVALID);
+    }
+
+    @Test
+    public void testUrlRequestCancel_CancelCalled() throws Exception {
+        UrlRequest request = createUrlRequestBuilder(mTestServer.getSuccessUrl()).build();
+        mCallback.setAutoAdvance(false);
+
+        request.start();
+        mCallback.waitForNextStep();
+        assertSame(mCallback.mResponseStep, ResponseStep.ON_RESPONSE_STARTED);
+
+        request.cancel();
+        mCallback.expectCallback(ResponseStep.ON_CANCELED);
+    }
+
+    @Test
+    public void testUrlRequestPost_EchoRequestBody() throws Exception {
+        String testData = "test";
+        UrlRequest.Builder builder = createUrlRequestBuilder(mTestServer.getEchoBodyUrl());
+
+        TestUploadDataProvider dataProvider = new TestUploadDataProvider(
+                TestUploadDataProvider.SuccessCallbackMode.SYNC, mCallback.getExecutor());
+        dataProvider.addRead(testData.getBytes());
+        builder.setUploadDataProvider(dataProvider, mCallback.getExecutor());
+        builder.addHeader("Content-Type", "text/html");
+        builder.build().start();
+        mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+
+        assertOKStatusCode(mCallback.mResponseInfo);
+        assertEquals(testData, mCallback.mResponseAsString);
+        dataProvider.assertClosed();
+    }
+
+    @Test
+    public void testUrlRequestFail_FailedCalled() throws Exception {
+        createUrlRequestBuilder("http://0.0.0.0:0/").build().start();
+        mCallback.expectCallback(ResponseStep.ON_FAILED);
+    }
+}
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
deleted file mode 100644
index 3ccb571..0000000
--- a/Cronet/tests/cts/src/android/net/http/cts/util/CronetCtsTestServer.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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/android/net/http/cts/util/HttpCtsTestServer.kt b/Cronet/tests/cts/src/android/net/http/cts/util/HttpCtsTestServer.kt
new file mode 100644
index 0000000..5196544
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/HttpCtsTestServer.kt
@@ -0,0 +1,57 @@
+/*
+ * 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
+import java.net.URI
+import org.apache.http.HttpEntityEnclosingRequest
+import org.apache.http.HttpRequest
+import org.apache.http.HttpResponse
+import org.apache.http.HttpStatus
+import org.apache.http.HttpVersion
+import org.apache.http.message.BasicHttpResponse
+
+private const val ECHO_BODY_PATH = "/echo_body"
+
+/** Extends CtsTestServer to handle POST requests and other test specific requests */
+class HttpCtsTestServer(context: Context) : CtsTestServer(context) {
+
+    val echoBodyUrl: String = baseUri + ECHO_BODY_PATH
+    val successUrl: String = getAssetUrl("html/hello_world.html")
+
+    override fun onPost(req: HttpRequest): HttpResponse? {
+        val path = URI.create(req.requestLine.uri).path
+        var response: HttpResponse? = null
+
+        if (path.startsWith(ECHO_BODY_PATH)) {
+            if (req !is HttpEntityEnclosingRequest) {
+                return BasicHttpResponse(
+                    HttpVersion.HTTP_1_0,
+                    HttpStatus.SC_INTERNAL_SERVER_ERROR,
+                    "Expected req to be of type HttpEntityEnclosingRequest but got ${req.javaClass}"
+                )
+            }
+
+            response = BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, null)
+            response.entity = req.entity
+            response.addHeader("Content-Length", req.entity.contentLength.toString())
+        }
+
+        return response
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestStatusListener.kt b/Cronet/tests/cts/src/android/net/http/cts/util/TestStatusListener.kt
new file mode 100644
index 0000000..e526c7d
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestStatusListener.kt
@@ -0,0 +1,38 @@
+/*
+ * 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.net.http.UrlRequest.StatusListener
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import org.junit.Assert.assertSame
+
+private const val TIMEOUT_MS = 12000L
+
+/** Test status listener for requests */
+class TestStatusListener : StatusListener() {
+    private val statusFuture = CompletableFuture<Int>()
+
+    override fun onStatus(status: Int) {
+        statusFuture.complete(status)
+    }
+
+    /** Fails if the expected status is not the returned status */
+    fun expectStatus(expected: Int) {
+        assertSame(expected, statusFuture.get(TIMEOUT_MS, TimeUnit.MILLISECONDS))
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestUploadDataProvider.java b/Cronet/tests/cts/src/android/net/http/cts/util/TestUploadDataProvider.java
new file mode 100644
index 0000000..d047828
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestUploadDataProvider.java
@@ -0,0 +1,294 @@
+/*
+ * 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.net.http.UploadDataProvider;
+import android.net.http.UploadDataSink;
+import android.os.ConditionVariable;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/** An UploadDataProvider implementation used in tests. */
+public class TestUploadDataProvider extends UploadDataProvider {
+    // Indicates whether all success callbacks are synchronous or asynchronous.
+    // Doesn't apply to errors.
+    public enum SuccessCallbackMode {
+        SYNC,
+        ASYNC
+    }
+
+    // Indicates whether failures should throw exceptions, invoke callbacks
+    // synchronously, or invoke callback asynchronously.
+    public enum FailMode {
+        NONE,
+        THROWN,
+        CALLBACK_SYNC,
+        CALLBACK_ASYNC
+    }
+
+    private final ArrayList<byte[]> mReads = new ArrayList<byte[]>();
+    private final SuccessCallbackMode mSuccessCallbackMode;
+    private final Executor mExecutor;
+
+    private boolean mChunked;
+
+    // Index of read to fail on.
+    private int mReadFailIndex = -1;
+    // Indicates how to fail on a read.
+    private FailMode mReadFailMode = FailMode.NONE;
+
+    private FailMode mRewindFailMode = FailMode.NONE;
+
+    private FailMode mLengthFailMode = FailMode.NONE;
+
+    private int mNumReadCalls;
+    private int mNumRewindCalls;
+
+    private int mNextRead;
+    private boolean mStarted;
+    private boolean mReadPending;
+    private boolean mRewindPending;
+    // Used to ensure there are no read/rewind requests after a failure.
+    private boolean mFailed;
+
+    private final AtomicBoolean mClosed = new AtomicBoolean(false);
+    private final ConditionVariable mAwaitingClose = new ConditionVariable(false);
+
+    public TestUploadDataProvider(
+            SuccessCallbackMode successCallbackMode, final Executor executor) {
+        mSuccessCallbackMode = successCallbackMode;
+        mExecutor = executor;
+    }
+
+    // Adds the result to be returned by a successful read request.  The
+    // returned bytes must all fit within the read buffer provided by Cronet.
+    // After a rewind, if there is one, all reads will be repeated.
+    public void addRead(byte[] read) {
+        if (mStarted) {
+            throw new IllegalStateException("Adding bytes after read");
+        }
+        mReads.add(read);
+    }
+
+    public void setReadFailure(int readFailIndex, FailMode readFailMode) {
+        mReadFailIndex = readFailIndex;
+        mReadFailMode = readFailMode;
+    }
+
+    public void setLengthFailure() {
+        mLengthFailMode = FailMode.THROWN;
+    }
+
+    public void setRewindFailure(FailMode rewindFailMode) {
+        mRewindFailMode = rewindFailMode;
+    }
+
+    public void setChunked(boolean chunked) {
+        mChunked = chunked;
+    }
+
+    public int getNumReadCalls() {
+        return mNumReadCalls;
+    }
+
+    public int getNumRewindCalls() {
+        return mNumRewindCalls;
+    }
+
+    /** Returns the cumulative length of all data added by calls to addRead. */
+    @Override
+    public long getLength() throws IOException {
+        if (mClosed.get()) {
+            throw new ClosedChannelException();
+        }
+        if (mLengthFailMode == FailMode.THROWN) {
+            throw new IllegalStateException("Sync length failure");
+        }
+        return getUploadedLength();
+    }
+
+    public long getUploadedLength() {
+        if (mChunked) {
+            return -1;
+        }
+        long length = 0;
+        for (byte[] read : mReads) {
+            length += read.length;
+        }
+        return length;
+    }
+
+    @Override
+    public void read(final UploadDataSink uploadDataSink, final ByteBuffer byteBuffer)
+            throws IOException {
+        int currentReadCall = mNumReadCalls;
+        ++mNumReadCalls;
+        if (mClosed.get()) {
+            throw new ClosedChannelException();
+        }
+        assertIdle();
+
+        if (maybeFailRead(currentReadCall, uploadDataSink)) {
+            mFailed = true;
+            return;
+        }
+
+        mReadPending = true;
+        mStarted = true;
+
+        final boolean finalChunk = (mChunked && mNextRead == mReads.size() - 1);
+        if (mNextRead < mReads.size()) {
+            if ((byteBuffer.limit() - byteBuffer.position()) < mReads.get(mNextRead).length) {
+                throw new IllegalStateException("Read buffer smaller than expected.");
+            }
+            byteBuffer.put(mReads.get(mNextRead));
+            ++mNextRead;
+        } else {
+            throw new IllegalStateException("Too many reads: " + mNextRead);
+        }
+
+        Runnable completeRunnable =
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        mReadPending = false;
+                        uploadDataSink.onReadSucceeded(finalChunk);
+                    }
+                };
+        if (mSuccessCallbackMode == SuccessCallbackMode.SYNC) {
+            completeRunnable.run();
+        } else {
+            mExecutor.execute(completeRunnable);
+        }
+    }
+
+    @Override
+    public void rewind(final UploadDataSink uploadDataSink) throws IOException {
+        ++mNumRewindCalls;
+        if (mClosed.get()) {
+            throw new ClosedChannelException();
+        }
+        assertIdle();
+
+        if (maybeFailRewind(uploadDataSink)) {
+            mFailed = true;
+            return;
+        }
+
+        if (mNextRead == 0) {
+            // Should never try and rewind when rewinding does nothing.
+            throw new IllegalStateException("Unexpected rewind when already at beginning");
+        }
+
+        mRewindPending = true;
+        mNextRead = 0;
+
+        Runnable completeRunnable =
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        mRewindPending = false;
+                        uploadDataSink.onRewindSucceeded();
+                    }
+                };
+        if (mSuccessCallbackMode == SuccessCallbackMode.SYNC) {
+            completeRunnable.run();
+        } else {
+            mExecutor.execute(completeRunnable);
+        }
+    }
+
+    private void assertIdle() {
+        if (mReadPending) {
+            throw new IllegalStateException("Unexpected operation during read");
+        }
+        if (mRewindPending) {
+            throw new IllegalStateException("Unexpected operation during rewind");
+        }
+        if (mFailed) {
+            throw new IllegalStateException("Unexpected operation after failure");
+        }
+    }
+
+    private boolean maybeFailRead(int readIndex, final UploadDataSink uploadDataSink) {
+        if (readIndex != mReadFailIndex) return false;
+
+        switch (mReadFailMode) {
+            case THROWN:
+                throw new IllegalStateException("Thrown read failure");
+            case CALLBACK_SYNC:
+                uploadDataSink.onReadError(new IllegalStateException("Sync read failure"));
+                return true;
+            case CALLBACK_ASYNC:
+                Runnable errorRunnable =
+                        new Runnable() {
+                            @Override
+                            public void run() {
+                                uploadDataSink.onReadError(
+                                        new IllegalStateException("Async read failure"));
+                            }
+                        };
+                mExecutor.execute(errorRunnable);
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private boolean maybeFailRewind(final UploadDataSink uploadDataSink) {
+        switch (mRewindFailMode) {
+            case THROWN:
+                throw new IllegalStateException("Thrown rewind failure");
+            case CALLBACK_SYNC:
+                uploadDataSink.onRewindError(new IllegalStateException("Sync rewind failure"));
+                return true;
+            case CALLBACK_ASYNC:
+                Runnable errorRunnable =
+                        new Runnable() {
+                            @Override
+                            public void run() {
+                                uploadDataSink.onRewindError(
+                                        new IllegalStateException("Async rewind failure"));
+                            }
+                        };
+                mExecutor.execute(errorRunnable);
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (!mClosed.compareAndSet(false, true)) {
+            throw new AssertionError("Closed twice");
+        }
+        mAwaitingClose.open();
+    }
+
+    public void assertClosed() {
+        mAwaitingClose.block(5000);
+        if (!mClosed.get()) {
+            throw new AssertionError("Was not closed");
+        }
+    }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java b/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
index c7143f5..efbcff6 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
@@ -16,23 +16,28 @@
 
 package android.net.http.cts.util;
 
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.core.AnyOf.anyOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeThat;
+import static org.junit.Assume.assumeTrue;
 
+import android.net.http.CallbackException;
+import android.net.http.HttpException;
+import android.net.http.InlineExecutionProhibitedException;
+import android.net.http.UrlRequest;
+import android.net.http.UrlResponseInfo;
 import android.os.ConditionVariable;
 import android.os.StrictMode;
 
-import org.chromium.net.CallbackException;
-import org.chromium.net.CronetException;
-import org.chromium.net.InlineExecutionProhibitedException;
-import org.chromium.net.UrlRequest;
-import org.chromium.net.UrlResponseInfo;
-
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.concurrent.ExecutorService;
@@ -50,7 +55,7 @@
     public ArrayList<UrlResponseInfo> mRedirectResponseInfoList = new ArrayList<>();
     public ArrayList<String> mRedirectUrlList = new ArrayList<>();
     public UrlResponseInfo mResponseInfo;
-    public CronetException mError;
+    public HttpException mError;
 
     public ResponseStep mResponseStep = ResponseStep.NOTHING;
 
@@ -89,7 +94,7 @@
     // Signaled on each step when mAutoAdvance is false.
     private final ConditionVariable mStepBlock = new ConditionVariable();
 
-    // Executor Service for Cronet callbacks.
+    // Executor Service for Http callbacks.
     private final ExecutorService mExecutorService;
     private Thread mExecutorThread;
 
@@ -233,6 +238,19 @@
     }
 
     /**
+     * Waits for a terminal callback to complete execution before skipping the test if the
+     * callback is not the expected one
+     *
+     * @param expectedStep the expected callback step
+     */
+    public void assumeCallback(ResponseStep expectedStep) {
+        if (isTerminalCallback(expectedStep)) {
+            assumeTrue("Did not receive terminal callback before timeout", blockForDone());
+        }
+        assumeThat(expectedStep, equalTo(mResponseStep));
+    }
+
+    /**
      * Blocks the calling thread until one of the final states has been called.
      * This is called before the callback has finished executed.
      */
@@ -273,8 +291,9 @@
             UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
         checkExecutorThread();
         assertFalse(request.isDone());
-        assertTrue(mResponseStep == ResponseStep.NOTHING
-                || mResponseStep == ResponseStep.ON_RECEIVED_REDIRECT);
+        assertThat(mResponseStep, anyOf(
+                equalTo(ResponseStep.NOTHING),
+                equalTo(ResponseStep.ON_RECEIVED_REDIRECT)));
         assertNull(mError);
 
         mResponseStep = ResponseStep.ON_RECEIVED_REDIRECT;
@@ -291,8 +310,9 @@
     public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
         checkExecutorThread();
         assertFalse(request.isDone());
-        assertTrue(mResponseStep == ResponseStep.NOTHING
-                || mResponseStep == ResponseStep.ON_RECEIVED_REDIRECT);
+        assertThat(mResponseStep, anyOf(
+                equalTo(ResponseStep.NOTHING),
+                equalTo(ResponseStep.ON_RECEIVED_REDIRECT)));
         assertNull(mError);
 
         mResponseStep = ResponseStep.ON_RESPONSE_STARTED;
@@ -307,8 +327,9 @@
     public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
         checkExecutorThread();
         assertFalse(request.isDone());
-        assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED
-                || mResponseStep == ResponseStep.ON_READ_COMPLETED);
+        assertThat(mResponseStep, anyOf(
+                equalTo(ResponseStep.ON_RESPONSE_STARTED),
+                equalTo(ResponseStep.ON_READ_COMPLETED)));
         assertNull(mError);
 
         mResponseStep = ResponseStep.ON_READ_COMPLETED;
@@ -334,8 +355,9 @@
     public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
         checkExecutorThread();
         assertTrue(request.isDone());
-        assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED
-                || mResponseStep == ResponseStep.ON_READ_COMPLETED);
+        assertThat(mResponseStep, anyOf(
+                equalTo(ResponseStep.ON_RESPONSE_STARTED),
+                equalTo(ResponseStep.ON_READ_COMPLETED)));
         assertFalse(mOnErrorCalled);
         assertFalse(mOnCanceledCalled);
         assertNull(mError);
@@ -349,7 +371,7 @@
     }
 
     @Override
-    public void onFailed(UrlRequest request, UrlResponseInfo info, CronetException error) {
+    public void onFailed(UrlRequest request, UrlResponseInfo info, HttpException error) {
         // If the failure is because of prohibited direct execution, the test shouldn't fail
         // since the request already did.
         if (error.getCause() instanceof InlineExecutionProhibitedException) {
@@ -358,7 +380,7 @@
         checkExecutorThread();
         assertTrue(request.isDone());
         // Shouldn't happen after success.
-        assertTrue(mResponseStep != ResponseStep.ON_SUCCEEDED);
+        assertNotEquals(ResponseStep.ON_SUCCEEDED, mResponseStep);
         // Should happen at most once for a single request.
         assertFalse(mOnErrorCalled);
         assertFalse(mOnCanceledCalled);
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestUtils.kt b/Cronet/tests/cts/src/android/net/http/cts/util/TestUtils.kt
new file mode 100644
index 0000000..23ec2c8
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestUtils.kt
@@ -0,0 +1,39 @@
+/*
+ * 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 android.net.http.cts.util
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.net.http.UrlResponseInfo
+import org.hamcrest.Matchers.equalTo
+import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeNotNull
+import org.junit.Assume.assumeThat
+
+fun skipIfNoInternetConnection(context: Context) {
+    val connectivityManager = context.getSystemService(ConnectivityManager::class.java)
+    assumeNotNull(
+        "This test requires a working Internet connection", connectivityManager.getActiveNetwork())
+}
+
+fun assertOKStatusCode(info: UrlResponseInfo) {
+    assertEquals("Status code must be 200 OK", 200, info.httpStatusCode)
+}
+
+fun assumeOKStatusCode(info: UrlResponseInfo) {
+    assumeThat("Status code must be 200 OK", info.getHttpStatusCode(), equalTo(200))
+}
diff --git a/Cronet/tests/mts/Android.bp b/Cronet/tests/mts/Android.bp
new file mode 100644
index 0000000..1cabd63
--- /dev/null
+++ b/Cronet/tests/mts/Android.bp
@@ -0,0 +1,48 @@
+// 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_library {
+    name: "NetHttpTestsLibPreJarJar",
+    srcs: [":cronet_aml_javatests_sources"],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "junit",
+    ],
+    libs: [
+        "android.test.base",
+        "framework-tethering-pre-jarjar",
+    ]
+}
+
+android_test {
+     name: "NetHttpTests",
+     defaults: [
+        "CronetTestJavaDefaults",
+        "mts-target-sdk-version-current",
+     ],
+     sdk_version: "test_current",
+     static_libs: ["NetHttpTestsLibPreJarJar"],
+     jarjar_rules: ":framework-tethering-jarjar-rules",
+     test_suites: [
+         "general-tests",
+         "mts-tethering",
+     ],
+}
+
diff --git a/Cronet/tests/mts/AndroidManifest.xml b/Cronet/tests/mts/AndroidManifest.xml
new file mode 100644
index 0000000..62c2060
--- /dev/null
+++ b/Cronet/tests/mts/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.net.http.mts">
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.net.http.mts"
+                     android:label="MTS tests of android.net.http">
+    </instrumentation>
+
+</manifest>
\ No newline at end of file
diff --git a/Cronet/tests/mts/AndroidTest.xml b/Cronet/tests/mts/AndroidTest.xml
new file mode 100644
index 0000000..8cb549e
--- /dev/null
+++ b/Cronet/tests/mts/AndroidTest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<configuration description="Runs NetHttp Mainline Tests.">
+    <!-- Only run tests if the device under test is SDK version 30 or above. -->
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="test-file-name" value="NetHttpTests.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="NetHttpTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.net.http.mts" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+
+    <!-- Only run NetHttpTests 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>
\ No newline at end of file
diff --git a/Cronet/tools/import/copy.bara.sky b/Cronet/tools/import/copy.bara.sky
new file mode 100644
index 0000000..64256a0
--- /dev/null
+++ b/Cronet/tools/import/copy.bara.sky
@@ -0,0 +1,110 @@
+# Copyright 2023 Google Inc. All rights reserved.
+#
+# 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.
+
+common_excludes = [
+    # Exclude all Android build files
+    "**/Android.bp",
+    "**/Android.mk",
+
+    # Exclude existing OWNERS files
+    "**/OWNERS",
+]
+
+cronet_origin_files = glob(
+    include = [
+        "base/**",
+        "build/**",
+        "build/buildflag.h",
+        "chrome/VERSION",
+        "components/cronet/**",
+        "components/grpc_suport/**",
+        "components/metrics/**",
+        "components/nacl/**",
+        "components/prefs/**",
+        "crypto/**",
+        "ipc/**",
+        "net/**",
+        "url/**",
+        "LICENSE",
+    ],
+    exclude = common_excludes + [
+        # Per aosp/2367109
+        "build/android/CheckInstallApk-debug.apk",
+        "build/android/unused_resources/**",
+        "build/linux/**",
+
+        # Per aosp/2374766
+        "components/cronet/ios/**",
+        "components/cronet/native/**",
+
+
+        # Exclude all third-party directories. Those are specified explicitly
+        # below, so no dependency can accidentally creep in.
+        "**/third_party/**",
+    ],
+) + glob(
+    # Explicitly include third-party dependencies.
+    # Note: some third-party dependencies include a third_party folder within
+    # them. So far, this has not become a problem.
+    include = [
+        "base/third_party/cityhash/**",
+        "base/third_party/cityhash_v103/**",
+        "base/third_party/double_conversion/**",
+        "base/third_party/dynamic_annotations/**",
+        "base/third_party/icu/**",
+        "base/third_party/nspr/**",
+        "base/third_party/superfasthash/**",
+        # TODO: we should be able to remove this dependency.
+        "base/third_party/symbolize/**",
+        "base/third_party/valgrind/**",
+        "base/third_party/xdg_user_dirs/**",
+        # Not present in source repo; requires gclient sync.
+        "buildtools/third_party/libc++/**",
+        # Not present in source repo; requires gclient sync.
+        "buildtools/third_party/libc++abi/**",
+        "net/third_party/quiche/**",
+        "net/third_party/uri_template/**",
+        "third_party/abseil-cpp/**",
+        "third_party/android_ndk/sources/android/cpufeatures/**",
+        "third_party/ashmem/**",
+        "third_party/boringssl/**",
+        "third_party/brotli/**",
+        # Not present in source repo; requires gclient sync.
+        "third_party/icu/**",
+        "third_party/libevent/**",
+        "third_party/metrics_proto/**",
+        "third_party/modp_b64/**",
+        "third_party/protobuf/**",
+        "third_party/zlib/**",
+    ],
+    exclude = common_excludes,
+)
+
+core.workflow(
+    name = "import_cronet",
+    authoring = authoring.overwrite("Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com>"),
+    origin = git.origin(
+        url = "rpc://chromium/chromium/src",
+        # Source ref is set by the invoking script.
+        ref = "overwritten-by-script",
+        partial_fetch = True,
+    ),
+    origin_files = cronet_origin_files,
+    destination = git.destination(
+        # The destination URL is set by the invoking script.
+        url = "overwritten/by/script",
+        push = "upstream-import",
+    ),
+    mode = "SQUASH",
+)
diff --git a/Cronet/tools/import/import_cronet.sh b/Cronet/tools/import/import_cronet.sh
new file mode 100755
index 0000000..7642914
--- /dev/null
+++ b/Cronet/tools/import/import_cronet.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# Copyright 2023 Google Inc. All rights reserved.
+#
+# 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.
+
+# Script to invoke copybara locally to import Cronet into Android.
+# Inputs:
+#  Environment:
+#   ANDROID_BUILD_TOP: path the root of the current Android directory.
+#  Arguments:
+#   -l: The last revision that was imported.
+#   -n: The new revision to import.
+
+OPTSTRING=l:n:
+
+usage() {
+    cat <<EOF
+Usage: import_cronet.sh -l last-rev -n new-rev
+EOF
+    exit 1
+}
+
+#######################################
+# Runs the copybara import of Chromium
+# Globals:
+#   ANDROID_BUILD_TOP
+# Arguments:
+#   last_rev, string
+#   new_rev, string
+#######################################
+do_run_copybara() {
+    local _last_rev=$1
+    local _new_rev=$2
+
+    /google/bin/releases/copybara/public/copybara/copybara \
+        --git-destination-url="file://${ANDROID_BUILD_TOP}/external/cronet" \
+        --last-rev "${_last_rev}" \
+        --repo-timeout 3h \
+        "${ANDROID_BUILD_TOP}/packages/modules/Connectivity/Cronet/tools/import/copy.bara.sky" \
+        import_cronet "${_new_rev}"
+}
+
+while getopts $OPTSTRING opt; do
+    case "${opt}" in
+        l) last_rev="${OPTARG}" ;;
+        n) new_rev="${OPTARG}" ;;
+        ?) usage ;;
+        *) echo "'${opt}' '${OPTARG}'"
+    esac
+done
+
+# TODO: Get last-rev from METADATA file.
+# Setting last-rev may only be required for the first commit.
+if [ -z "${last_rev}" ]; then
+    echo "-l argument required"
+    usage
+fi
+
+if [ -z "${new_rev}" ]; then
+    echo "-n argument required"
+    usage
+fi
+
+do_run_copybara "${last_rev}" "${new_rev}"
+
diff --git a/OWNERS_core_networking b/OWNERS_core_networking
index 172670e..6d17476 100644
--- a/OWNERS_core_networking
+++ b/OWNERS_core_networking
@@ -1,4 +1,3 @@
-chenbruce@google.com
 chiachangwang@google.com
 cken@google.com
 huangaaron@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 700a085..4d3ecdf 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -58,12 +58,26 @@
       ]
     },
     {
+      "name": "CtsNetTestCasesMaxTargetSdk33",
+      "options": [
+        {
+          "exclude-annotation": "com.android.testutils.SkipPresubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.RequiresDevice"
+        }
+      ]
+    },
+    {
       "name": "bpf_existence_test"
     },
     {
       "name": "connectivity_native_test"
     },
     {
+      "name": "CtsNetHttpTestCases"
+    },
+    {
       "name": "libclat_test"
     },
     {
@@ -99,6 +113,11 @@
     },
     {
       "name": "FrameworksNetDeflakeTest"
+    },
+    // Run in postsubmit to confirm test passes continously since this is a new test setup
+    // TODO: move tests to presubmit
+    {
+      "name": "NetHttpTests"
     }
   ],
   "mainline-presubmit": [
@@ -135,6 +154,17 @@
         }
       ]
     },
+    {
+      "name": "CtsNetTestCasesMaxTargetSdk33[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+      "options": [
+        {
+          "exclude-annotation": "com.android.testutils.SkipPresubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.RequiresDevice"
+        }
+      ]
+    },
     // Test with APK modules only, in cases where APEX is not supported, or the other modules
     // were simply not updated
     {
diff --git a/Tethering/AndroidManifest.xml b/Tethering/AndroidManifest.xml
index b832e16..6a363b0 100644
--- a/Tethering/AndroidManifest.xml
+++ b/Tethering/AndroidManifest.xml
@@ -43,6 +43,7 @@
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
 
+    <!-- Sending non-protected broadcast from system uid is not allowed. -->
     <protected-broadcast android:name="com.android.server.connectivity.tethering.DISABLE_TETHERING" />
 
     <application
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 8840394..67206cd 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -50,11 +50,40 @@
 // as the above target may have different "enabled" values
 // depending on the branch
 
+// cronet_in_tethering_apex_defaults can be used to specify an apex_defaults target that either
+// enables or disables inclusion of Cronet in the Tethering apex. This is used to disable Cronet
+// on tm-mainline-prod. Note: in order for Cronet APIs to work Cronet must also be enabled
+// by the cronet_java_*_defaults in common/TetheringLib/Android.bp.
+cronet_in_tethering_apex_defaults = "CronetInTetheringApexDefaultsEnabled"
+// This is a placeholder comment to avoid merge conflicts
+// as cronet_apex_defaults may have different values
+// depending on the branch
+
+apex_defaults {
+    name: "CronetInTetheringApexDefaults",
+    defaults: [cronet_in_tethering_apex_defaults],
+}
+
+apex_defaults {
+    name: "CronetInTetheringApexDefaultsEnabled",
+    jni_libs: ["cronet_aml_components_cronet_android_cronet"],
+    arch: {
+        riscv64: {
+            // TODO: remove this when there is a riscv64 libcronet
+            exclude_jni_libs: ["cronet_aml_components_cronet_android_cronet"],
+        },
+    },
+}
+
+apex_defaults {
+    name: "CronetInTetheringApexDefaultsDisabled",
+}
+
 apex {
     name: "com.android.tethering",
     defaults: [
         "ConnectivityApexDefaults",
-        "CronetApexDefaults",
+        "CronetInTetheringApexDefaults",
         "r-launched-apex-module",
     ],
     compile_multilib: "both",
@@ -115,7 +144,6 @@
 
     compat_configs: [
         "connectivity-platform-compat-config",
-        "connectivity-t-platform-compat-config",
     ],
 }
 
@@ -183,6 +211,7 @@
             "android.app.usage",
             "android.nearby",
             "android.net",
+            "android.net.http",
             "android.net.netstats",
             "android.net.util",
         ],
@@ -197,6 +226,8 @@
             "android.nearby.aidl",
             "android.net.apf",
             "android.net.connectivity",
+            "android.net.http.apihelpers",
+            "android.net.http.internal",
             "android.net.netstats.provider",
             "android.net.nsd",
             "android.net.wear",
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index 481557b..4c677d0 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -17,9 +17,22 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// 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"],
+    defaults: [
+        "CronetJavaDefaults",
+        "framework-tethering-defaults",
+    ],
     impl_library_visibility: [
         "//packages/modules/Connectivity/Tethering:__subpackages__",
         "//packages/modules/Connectivity/framework",
@@ -45,24 +58,103 @@
         "//packages/modules/NetworkStack/tests:__subpackages__",
         "//packages/modules/Wifi/service/tests/wifitests",
     ],
-
-    srcs: [":framework-tethering-srcs"],
-    libs: ["framework-connectivity.stubs.module_lib"],
     stub_only_libs: ["framework-connectivity.stubs.module_lib"],
+
+    jarjar_rules: ":framework-tethering-jarjar-rules",
+    installable: true,
+
+    hostdex: true, // for hiddenapi check
+    permitted_packages: ["android.net"],
+}
+
+java_defaults {
+    name: "CronetJavaDefaults",
+    defaults: [cronet_java_defaults],
+}
+
+java_defaults {
+    name: "CronetJavaDefaultsEnabled",
+    srcs: [":cronet_aml_api_sources"],
+    libs: [
+        "androidx.annotation_annotation",
+    ],
+    impl_only_static_libs: [
+        "cronet_aml_java",
+    ],
+    // STOPSHIP(b/265674359): fix all Cronet lint warnings and re-enable lint
+    // directly in framework-tethering
+    lint: {
+         enabled: false,
+    },
+    api_lint: {
+        enabled: false,
+    },
+    api_dir: "cronet_enabled/api",
+}
+
+java_defaults {
+  name: "CronetJavaDefaultsDisabled",
+  lint: { strict_updatability_linting: true },
+}
+
+java_defaults {
+  name: "CronetJavaPrejarjarDefaults",
+  defaults: [cronet_java_prejarjar_defaults],
+}
+
+java_defaults {
+  name: "CronetJavaPrejarjarDefaultsDisabled",
+}
+
+java_defaults {
+  name: "CronetJavaPrejarjarDefaultsEnabled",
+  static_libs: [
+    "cronet_aml_api_java",
+    "cronet_aml_java"
+  ],
+}
+
+java_library {
+  name: "framework-tethering-pre-jarjar",
+  defaults: [
+    "framework-tethering-defaults",
+    "CronetJavaPrejarjarDefaults",
+  ],
+}
+
+java_genrule {
+    name: "framework-tethering-jarjar-rules",
+    tool_files: [
+        ":framework-tethering-pre-jarjar{.jar}",
+        ":framework-tethering.stubs.module_lib{.jar}",
+        "jarjar-excludes.txt",
+    ],
+    tools: [
+        "jarjar-rules-generator",
+    ],
+    out: ["framework_tethering_jarjar_rules.txt"],
+    cmd: "$(location jarjar-rules-generator) " +
+        "$(location :framework-tethering-pre-jarjar{.jar}) " +
+        "--apistubs $(location :framework-tethering.stubs.module_lib{.jar}) " + 
+        "--prefix android.net.http.internal " +
+        "--excludes $(location jarjar-excludes.txt) " +
+        "--output $(out)",
+}
+
+java_defaults {
+    name: "framework-tethering-defaults",
+    defaults: ["framework-module-defaults"],
+    srcs: [
+      ":framework-tethering-srcs"
+    ],
+    libs: ["framework-connectivity.stubs.module_lib"],
     aidl: {
         include_dirs: [
             "packages/modules/Connectivity/framework/aidl-export",
         ],
     },
-
-    jarjar_rules: "jarjar-rules.txt",
-    installable: true,
-
-    hostdex: true, // for hiddenapi check
     apex_available: ["com.android.tethering"],
-    permitted_packages: ["android.net"],
     min_sdk_version: "30",
-    lint: { strict_updatability_linting: true },
 }
 
 filegroup {
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/current.txt b/Tethering/common/TetheringLib/cronet_enabled/api/current.txt
new file mode 100644
index 0000000..777138d
--- /dev/null
+++ b/Tethering/common/TetheringLib/cronet_enabled/api/current.txt
@@ -0,0 +1,269 @@
+// Signature format: 2.0
+package android.net.http {
+
+  public abstract class BidirectionalStream {
+    ctor public BidirectionalStream();
+    method public abstract void cancel();
+    method public abstract void flush();
+    method public abstract boolean isDone();
+    method public abstract void read(java.nio.ByteBuffer);
+    method public abstract void start();
+    method public abstract void write(java.nio.ByteBuffer, boolean);
+  }
+
+  public abstract static class BidirectionalStream.Builder {
+    ctor public BidirectionalStream.Builder();
+    method public abstract android.net.http.BidirectionalStream.Builder addHeader(String, String);
+    method public abstract android.net.http.BidirectionalStream build();
+    method public abstract android.net.http.BidirectionalStream.Builder delayRequestHeadersUntilFirstFlush(boolean);
+    method public abstract android.net.http.BidirectionalStream.Builder setHttpMethod(String);
+    method public abstract android.net.http.BidirectionalStream.Builder setPriority(int);
+    method public abstract android.net.http.BidirectionalStream.Builder setTrafficStatsTag(int);
+    method public abstract android.net.http.BidirectionalStream.Builder setTrafficStatsUid(int);
+    field public static final int STREAM_PRIORITY_HIGHEST = 4; // 0x4
+    field public static final int STREAM_PRIORITY_IDLE = 0; // 0x0
+    field public static final int STREAM_PRIORITY_LOW = 2; // 0x2
+    field public static final int STREAM_PRIORITY_LOWEST = 1; // 0x1
+    field public static final int STREAM_PRIORITY_MEDIUM = 3; // 0x3
+  }
+
+  public abstract static class BidirectionalStream.Callback {
+    ctor public BidirectionalStream.Callback();
+    method public void onCanceled(android.net.http.BidirectionalStream, android.net.http.UrlResponseInfo);
+    method public abstract void onFailed(android.net.http.BidirectionalStream, android.net.http.UrlResponseInfo, android.net.http.HttpException);
+    method public abstract void onReadCompleted(android.net.http.BidirectionalStream, android.net.http.UrlResponseInfo, java.nio.ByteBuffer, boolean);
+    method public abstract void onResponseHeadersReceived(android.net.http.BidirectionalStream, android.net.http.UrlResponseInfo);
+    method public void onResponseTrailersReceived(android.net.http.BidirectionalStream, android.net.http.UrlResponseInfo, android.net.http.UrlResponseInfo.HeaderBlock);
+    method public abstract void onStreamReady(android.net.http.BidirectionalStream);
+    method public abstract void onSucceeded(android.net.http.BidirectionalStream, android.net.http.UrlResponseInfo);
+    method public abstract void onWriteCompleted(android.net.http.BidirectionalStream, android.net.http.UrlResponseInfo, java.nio.ByteBuffer, boolean);
+  }
+
+  public abstract class CallbackException extends android.net.http.HttpException {
+    ctor protected CallbackException(String, Throwable);
+  }
+
+  public class ConnectionMigrationOptions {
+    method @Nullable public Boolean getAllowNonDefaultNetworkUsage();
+    method @Nullable public Boolean getEnableDefaultNetworkMigration();
+    method @Nullable public Boolean getEnablePathDegradationMigration();
+  }
+
+  public static class ConnectionMigrationOptions.Builder {
+    ctor public ConnectionMigrationOptions.Builder();
+    method public android.net.http.ConnectionMigrationOptions build();
+    method public android.net.http.ConnectionMigrationOptions.Builder setAllowNonDefaultNetworkUsage(boolean);
+    method public android.net.http.ConnectionMigrationOptions.Builder setEnableDefaultNetworkMigration(boolean);
+    method public android.net.http.ConnectionMigrationOptions.Builder setEnablePathDegradationMigration(boolean);
+  }
+
+  public final class DnsOptions {
+    method @Nullable public Boolean getEnableStaleDns();
+    method @Nullable public Boolean getPersistHostCache();
+    method @Nullable public java.time.Duration getPersistHostCachePeriod();
+    method @Nullable public Boolean getPreestablishConnectionsToStaleDnsResults();
+    method @Nullable public android.net.http.DnsOptions.StaleDnsOptions getStaleDnsOptions();
+    method @Nullable public Boolean getUseHttpStackDnsResolver();
+  }
+
+  public static final class DnsOptions.Builder {
+    ctor public DnsOptions.Builder();
+    method public android.net.http.DnsOptions build();
+    method public android.net.http.DnsOptions.Builder setEnableStaleDns(boolean);
+    method public android.net.http.DnsOptions.Builder setPersistHostCache(boolean);
+    method public android.net.http.DnsOptions.Builder setPersistHostCachePeriod(java.time.Duration);
+    method public android.net.http.DnsOptions.Builder setPreestablishConnectionsToStaleDnsResults(boolean);
+    method public android.net.http.DnsOptions.Builder setStaleDnsOptions(android.net.http.DnsOptions.StaleDnsOptions);
+    method public android.net.http.DnsOptions.Builder setUseHttpStackDnsResolver(boolean);
+  }
+
+  public static class DnsOptions.StaleDnsOptions {
+    method @Nullable public Boolean getAllowCrossNetworkUsage();
+    method @Nullable public Long getFreshLookupTimeoutMillis();
+    method @Nullable public Long getMaxExpiredDelayMillis();
+    method @Nullable public Boolean getUseStaleOnNameNotResolved();
+  }
+
+  public static final class DnsOptions.StaleDnsOptions.Builder {
+    ctor public DnsOptions.StaleDnsOptions.Builder();
+    method public android.net.http.DnsOptions.StaleDnsOptions build();
+    method public android.net.http.DnsOptions.StaleDnsOptions.Builder setAllowCrossNetworkUsage(boolean);
+    method public android.net.http.DnsOptions.StaleDnsOptions.Builder setFreshLookupTimeout(java.time.Duration);
+    method public android.net.http.DnsOptions.StaleDnsOptions.Builder setMaxExpiredDelay(java.time.Duration);
+    method public android.net.http.DnsOptions.StaleDnsOptions.Builder setUseStaleOnNameNotResolved(boolean);
+  }
+
+  public abstract class HttpEngine {
+    method public void bindToNetwork(@Nullable android.net.Network);
+    method public abstract java.net.URLStreamHandlerFactory createURLStreamHandlerFactory();
+    method public static String getVersionString();
+    method public abstract android.net.http.BidirectionalStream.Builder newBidirectionalStreamBuilder(String, android.net.http.BidirectionalStream.Callback, java.util.concurrent.Executor);
+    method public abstract android.net.http.UrlRequest.Builder newUrlRequestBuilder(String, android.net.http.UrlRequest.Callback, java.util.concurrent.Executor);
+    method public abstract java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
+    method public abstract void shutdown();
+  }
+
+  public static class HttpEngine.Builder {
+    ctor public HttpEngine.Builder(android.content.Context);
+    method public android.net.http.HttpEngine.Builder addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.time.Instant);
+    method public android.net.http.HttpEngine.Builder addQuicHint(String, int, int);
+    method public android.net.http.HttpEngine build();
+    method public String getDefaultUserAgent();
+    method public android.net.http.HttpEngine.Builder setConnectionMigrationOptions(android.net.http.ConnectionMigrationOptions);
+    method public android.net.http.HttpEngine.Builder setDnsOptions(android.net.http.DnsOptions);
+    method public android.net.http.HttpEngine.Builder setEnableBrotli(boolean);
+    method public android.net.http.HttpEngine.Builder setEnableHttp2(boolean);
+    method public android.net.http.HttpEngine.Builder setEnableHttpCache(int, long);
+    method public android.net.http.HttpEngine.Builder setEnablePublicKeyPinningBypassForLocalTrustAnchors(boolean);
+    method public android.net.http.HttpEngine.Builder setEnableQuic(boolean);
+    method public android.net.http.HttpEngine.Builder setQuicOptions(android.net.http.QuicOptions);
+    method public android.net.http.HttpEngine.Builder setStoragePath(String);
+    method public android.net.http.HttpEngine.Builder setUserAgent(String);
+    field public static final int HTTP_CACHE_DISABLED = 0; // 0x0
+    field public static final int HTTP_CACHE_DISK = 3; // 0x3
+    field public static final int HTTP_CACHE_DISK_NO_HTTP = 2; // 0x2
+    field public static final int HTTP_CACHE_IN_MEMORY = 1; // 0x1
+  }
+
+  public class HttpException extends java.io.IOException {
+    ctor public HttpException(String, Throwable);
+  }
+
+  public final class InlineExecutionProhibitedException extends java.util.concurrent.RejectedExecutionException {
+    ctor public InlineExecutionProhibitedException();
+  }
+
+  public abstract class NetworkException extends android.net.http.HttpException {
+    ctor public NetworkException(String, Throwable);
+    method public abstract int getErrorCode();
+    method public abstract boolean isImmediatelyRetryable();
+    field public static final int ERROR_ADDRESS_UNREACHABLE = 9; // 0x9
+    field public static final int ERROR_CONNECTION_CLOSED = 5; // 0x5
+    field public static final int ERROR_CONNECTION_REFUSED = 7; // 0x7
+    field public static final int ERROR_CONNECTION_RESET = 8; // 0x8
+    field public static final int ERROR_CONNECTION_TIMED_OUT = 6; // 0x6
+    field public static final int ERROR_HOSTNAME_NOT_RESOLVED = 1; // 0x1
+    field public static final int ERROR_INTERNET_DISCONNECTED = 2; // 0x2
+    field public static final int ERROR_NETWORK_CHANGED = 3; // 0x3
+    field public static final int ERROR_OTHER = 11; // 0xb
+    field public static final int ERROR_QUIC_PROTOCOL_FAILED = 10; // 0xa
+    field public static final int ERROR_TIMED_OUT = 4; // 0x4
+  }
+
+  public abstract class QuicException extends android.net.http.NetworkException {
+    ctor protected QuicException(String, Throwable);
+  }
+
+  public class QuicOptions {
+    method @Nullable public String getHandshakeUserAgent();
+    method @Nullable public Integer getInMemoryServerConfigsCacheSize();
+    method public java.util.Set<java.lang.String> getQuicHostAllowlist();
+  }
+
+  public static class QuicOptions.Builder {
+    ctor public QuicOptions.Builder();
+    method public android.net.http.QuicOptions.Builder addAllowedQuicHost(String);
+    method public android.net.http.QuicOptions build();
+    method public android.net.http.QuicOptions.Builder setHandshakeUserAgent(String);
+    method public android.net.http.QuicOptions.Builder setIdleConnectionTimeout(java.time.Duration);
+    method public android.net.http.QuicOptions.Builder setInMemoryServerConfigsCacheSize(int);
+  }
+
+  public abstract class UploadDataProvider implements java.io.Closeable {
+    ctor public UploadDataProvider();
+    method public void close() throws java.io.IOException;
+    method public abstract long getLength() throws java.io.IOException;
+    method public abstract void read(android.net.http.UploadDataSink, java.nio.ByteBuffer) throws java.io.IOException;
+    method public abstract void rewind(android.net.http.UploadDataSink) throws java.io.IOException;
+  }
+
+  public abstract class UploadDataSink {
+    ctor public UploadDataSink();
+    method public abstract void onReadError(Exception);
+    method public abstract void onReadSucceeded(boolean);
+    method public abstract void onRewindError(Exception);
+    method public abstract void onRewindSucceeded();
+  }
+
+  public abstract class UrlRequest {
+    method public abstract void cancel();
+    method public abstract void followRedirect();
+    method public abstract void getStatus(android.net.http.UrlRequest.StatusListener);
+    method public abstract boolean isDone();
+    method public abstract void read(java.nio.ByteBuffer);
+    method public abstract void start();
+  }
+
+  public abstract static class UrlRequest.Builder {
+    method public abstract android.net.http.UrlRequest.Builder addHeader(String, String);
+    method public abstract android.net.http.UrlRequest.Builder allowDirectExecutor();
+    method public abstract android.net.http.UrlRequest.Builder bindToNetwork(@Nullable android.net.Network);
+    method public abstract android.net.http.UrlRequest build();
+    method public abstract android.net.http.UrlRequest.Builder disableCache();
+    method public abstract android.net.http.UrlRequest.Builder setHttpMethod(String);
+    method public abstract android.net.http.UrlRequest.Builder setPriority(int);
+    method public abstract android.net.http.UrlRequest.Builder setTrafficStatsTag(int);
+    method public abstract android.net.http.UrlRequest.Builder setTrafficStatsUid(int);
+    method public abstract android.net.http.UrlRequest.Builder setUploadDataProvider(android.net.http.UploadDataProvider, java.util.concurrent.Executor);
+    field public static final int REQUEST_PRIORITY_HIGHEST = 4; // 0x4
+    field public static final int REQUEST_PRIORITY_IDLE = 0; // 0x0
+    field public static final int REQUEST_PRIORITY_LOW = 2; // 0x2
+    field public static final int REQUEST_PRIORITY_LOWEST = 1; // 0x1
+    field public static final int REQUEST_PRIORITY_MEDIUM = 3; // 0x3
+  }
+
+  public abstract static class UrlRequest.Callback {
+    ctor public UrlRequest.Callback();
+    method public void onCanceled(android.net.http.UrlRequest, android.net.http.UrlResponseInfo);
+    method public abstract void onFailed(android.net.http.UrlRequest, android.net.http.UrlResponseInfo, android.net.http.HttpException);
+    method public abstract void onReadCompleted(android.net.http.UrlRequest, android.net.http.UrlResponseInfo, java.nio.ByteBuffer) throws java.lang.Exception;
+    method public abstract void onRedirectReceived(android.net.http.UrlRequest, android.net.http.UrlResponseInfo, String) throws java.lang.Exception;
+    method public abstract void onResponseStarted(android.net.http.UrlRequest, android.net.http.UrlResponseInfo) throws java.lang.Exception;
+    method public abstract void onSucceeded(android.net.http.UrlRequest, android.net.http.UrlResponseInfo);
+  }
+
+  public static class UrlRequest.Status {
+    field public static final int CONNECTING = 10; // 0xa
+    field public static final int DOWNLOADING_PAC_FILE = 5; // 0x5
+    field public static final int ESTABLISHING_PROXY_TUNNEL = 8; // 0x8
+    field public static final int IDLE = 0; // 0x0
+    field public static final int INVALID = -1; // 0xffffffff
+    field public static final int READING_RESPONSE = 14; // 0xe
+    field public static final int RESOLVING_HOST = 9; // 0x9
+    field public static final int RESOLVING_HOST_IN_PAC_FILE = 7; // 0x7
+    field public static final int RESOLVING_PROXY_FOR_URL = 6; // 0x6
+    field public static final int SENDING_REQUEST = 12; // 0xc
+    field public static final int SSL_HANDSHAKE = 11; // 0xb
+    field public static final int WAITING_FOR_AVAILABLE_SOCKET = 2; // 0x2
+    field public static final int WAITING_FOR_CACHE = 4; // 0x4
+    field public static final int WAITING_FOR_DELEGATE = 3; // 0x3
+    field public static final int WAITING_FOR_RESPONSE = 13; // 0xd
+    field public static final int WAITING_FOR_STALLED_SOCKET_POOL = 1; // 0x1
+  }
+
+  public abstract static class UrlRequest.StatusListener {
+    ctor public UrlRequest.StatusListener();
+    method public abstract void onStatus(int);
+  }
+
+  public abstract class UrlResponseInfo {
+    ctor public UrlResponseInfo();
+    method public abstract android.net.http.UrlResponseInfo.HeaderBlock getHeaders();
+    method public abstract int getHttpStatusCode();
+    method public abstract String getHttpStatusText();
+    method public abstract String getNegotiatedProtocol();
+    method public abstract String getProxyServer();
+    method public abstract long getReceivedByteCount();
+    method public abstract String getUrl();
+    method public abstract java.util.List<java.lang.String> getUrlChain();
+    method public abstract boolean wasCached();
+  }
+
+  public abstract static class UrlResponseInfo.HeaderBlock {
+    ctor public UrlResponseInfo.HeaderBlock();
+    method public abstract java.util.List<java.util.Map.Entry<java.lang.String,java.lang.String>> getAsList();
+    method public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> getAsMap();
+  }
+
+}
+
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-current.txt b/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-current.txt
new file mode 100644
index 0000000..460c216
--- /dev/null
+++ b/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-current.txt
@@ -0,0 +1,50 @@
+// Signature format: 2.0
+package android.net {
+
+  public final class TetheringConstants {
+    field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+    field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+    field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+    field public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+    field public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+  }
+
+  public class TetheringManager {
+    ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>);
+    method public int getLastTetherError(@NonNull String);
+    method @NonNull public String[] getTetherableBluetoothRegexs();
+    method @NonNull public String[] getTetherableIfaces();
+    method @NonNull public String[] getTetherableUsbRegexs();
+    method @NonNull public String[] getTetherableWifiRegexs();
+    method @NonNull public String[] getTetheredIfaces();
+    method @NonNull public String[] getTetheringErroredIfaces();
+    method public boolean isTetheringSupported();
+    method public boolean isTetheringSupported(@NonNull String);
+    method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
+    method @Deprecated public int setUsbTethering(boolean);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @Deprecated public int tether(@NonNull String);
+    method @Deprecated public int untether(@NonNull String);
+  }
+
+  public static interface TetheringManager.TetheredInterfaceCallback {
+    method public void onAvailable(@NonNull String);
+    method public void onUnavailable();
+  }
+
+  public static interface TetheringManager.TetheredInterfaceRequest {
+    method public void release();
+  }
+
+  public static interface TetheringManager.TetheringEventCallback {
+    method @Deprecated public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
+  }
+
+  @Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
+  }
+
+}
+
diff --git a/Cronet/api/module-lib-removed.txt b/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-removed.txt
similarity index 100%
rename from Cronet/api/module-lib-removed.txt
rename to Tethering/common/TetheringLib/cronet_enabled/api/module-lib-removed.txt
diff --git a/Cronet/api/removed.txt b/Tethering/common/TetheringLib/cronet_enabled/api/removed.txt
similarity index 100%
rename from Cronet/api/removed.txt
rename to Tethering/common/TetheringLib/cronet_enabled/api/removed.txt
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/system-current.txt b/Tethering/common/TetheringLib/cronet_enabled/api/system-current.txt
new file mode 100644
index 0000000..844ff64
--- /dev/null
+++ b/Tethering/common/TetheringLib/cronet_enabled/api/system-current.txt
@@ -0,0 +1,117 @@
+// Signature format: 2.0
+package android.net {
+
+  public final class TetheredClient implements android.os.Parcelable {
+    ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
+    method public int describeContents();
+    method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
+    method @NonNull public android.net.MacAddress getMacAddress();
+    method public int getTetheringType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
+  }
+
+  public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.LinkAddress getAddress();
+    method @Nullable public String getHostname();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
+  }
+
+  public final class TetheringInterface implements android.os.Parcelable {
+    ctor public TetheringInterface(int, @NonNull String);
+    method public int describeContents();
+    method @NonNull public String getInterface();
+    method public int getType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheringInterface> CREATOR;
+  }
+
+  public class TetheringManager {
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
+    field @Deprecated public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
+    field public static final int CONNECTIVITY_SCOPE_GLOBAL = 1; // 0x1
+    field public static final int CONNECTIVITY_SCOPE_LOCAL = 2; // 0x2
+    field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
+    field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+    field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+    field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+    field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+    field public static final int TETHERING_ETHERNET = 5; // 0x5
+    field public static final int TETHERING_INVALID = -1; // 0xffffffff
+    field public static final int TETHERING_NCM = 4; // 0x4
+    field public static final int TETHERING_USB = 1; // 0x1
+    field public static final int TETHERING_WIFI = 0; // 0x0
+    field public static final int TETHERING_WIFI_P2P = 3; // 0x3
+    field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
+    field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
+    field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
+    field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
+    field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
+    field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
+    field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
+    field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
+    field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+    field public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
+    field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
+    field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
+    field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
+    field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+    field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
+    field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
+    field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
+    field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
+    field public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; // 0x1
+    field public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; // 0x0
+  }
+
+  public static interface TetheringManager.OnTetheringEntitlementResultListener {
+    method public void onTetheringEntitlementResult(int);
+  }
+
+  public static interface TetheringManager.StartTetheringCallback {
+    method public default void onTetheringFailed(int);
+    method public default void onTetheringStarted();
+  }
+
+  public static interface TetheringManager.TetheringEventCallback {
+    method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+    method public default void onError(@NonNull String, int);
+    method public default void onError(@NonNull android.net.TetheringInterface, int);
+    method public default void onLocalOnlyInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+    method public default void onLocalOnlyInterfacesChanged(@NonNull java.util.Set<android.net.TetheringInterface>);
+    method public default void onOffloadStatusChanged(int);
+    method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+    method public default void onTetherableInterfacesChanged(@NonNull java.util.Set<android.net.TetheringInterface>);
+    method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+    method public default void onTetheredInterfacesChanged(@NonNull java.util.Set<android.net.TetheringInterface>);
+    method public default void onTetheringSupported(boolean);
+    method public default void onUpstreamChanged(@Nullable android.net.Network);
+  }
+
+  public static class TetheringManager.TetheringRequest {
+    method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
+    method public int getConnectivityScope();
+    method @Nullable public android.net.LinkAddress getLocalIpv4Address();
+    method public boolean getShouldShowEntitlementUi();
+    method public int getTetheringType();
+    method public boolean isExemptFromEntitlementCheck();
+  }
+
+  public static class TetheringManager.TetheringRequest.Builder {
+    ctor public TetheringManager.TetheringRequest.Builder(int);
+    method @NonNull public android.net.TetheringManager.TetheringRequest build();
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setConnectivityScope(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
+  }
+
+}
+
diff --git a/Cronet/api/system-removed.txt b/Tethering/common/TetheringLib/cronet_enabled/api/system-removed.txt
similarity index 100%
rename from Cronet/api/system-removed.txt
rename to Tethering/common/TetheringLib/cronet_enabled/api/system-removed.txt
diff --git a/Tethering/common/TetheringLib/jarjar-excludes.txt b/Tethering/common/TetheringLib/jarjar-excludes.txt
new file mode 100644
index 0000000..50bc186
--- /dev/null
+++ b/Tethering/common/TetheringLib/jarjar-excludes.txt
@@ -0,0 +1,2 @@
+# Don't touch anything that's already under android.net
+android\.net\..+
\ No newline at end of file
diff --git a/Tethering/common/TetheringLib/jarjar-rules.txt b/Tethering/common/TetheringLib/jarjar-rules.txt
deleted file mode 100644
index e459fad..0000000
--- a/Tethering/common/TetheringLib/jarjar-rules.txt
+++ /dev/null
@@ -1 +0,0 @@
-# jarjar rules for the bootclasspath tethering framework library here
\ No newline at end of file
diff --git a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index c452e55..775c36f 100644
--- a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -88,13 +88,13 @@
     private static final int MIN_RTR_ADV_INTERVAL_SEC = 300;
     private static final int MAX_RTR_ADV_INTERVAL_SEC = 600;
     // In general, router, prefix, and DNS lifetimes are all advised to be
-    // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL.  Here, we double
+    // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL.  Here, we quadruple
     // that to allow for multicast packet loss.
     //
     // This MAX_RTR_ADV_INTERVAL_SEC and DEFAULT_LIFETIME are also consistent
     // with the https://tools.ietf.org/html/rfc7772#section-4 discussion of
     // "approximately 7 RAs per hour".
-    private static final int DEFAULT_LIFETIME = 6 * MAX_RTR_ADV_INTERVAL_SEC;
+    private static final int DEFAULT_LIFETIME = 12 * MAX_RTR_ADV_INTERVAL_SEC;
     // From https://tools.ietf.org/html/rfc4861#section-10 .
     private static final int MIN_DELAY_BETWEEN_RAS_SEC = 3;
     // Both initial and final RAs, but also for changes in RA contents.
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 72f83fa..9f8d9b1 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);
@@ -2179,5 +2243,13 @@
         return mTetherClients;
     }
 
+    // Return map of upstream interface IPv4 address to interface index.
+    // This is used for testing only.
+    @NonNull
+    @VisibleForTesting
+    final HashMap<Inet4Address, Integer> getIpv4UpstreamIndicesForTesting() {
+        return mIpv4UpstreamIndices;
+    }
+
     private static native String[] getBpfCounterNames();
 }
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index b3ec805..2e71fda 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -88,7 +88,6 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.Network;
-import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.TetherStatesParcel;
 import android.net.TetheredClient;
@@ -1203,6 +1202,9 @@
         }
 
         private void handleConnectivityAction(Intent intent) {
+            // CONNECTIVITY_ACTION is not handled since U+ device.
+            if (SdkLevel.isAtLeastU()) return;
+
             final NetworkInfo networkInfo =
                     (NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO);
             if (networkInfo == null
@@ -1853,8 +1855,11 @@
             final Network newUpstream = (ns != null) ? ns.network : null;
             if (mTetherUpstream != newUpstream) {
                 mTetherUpstream = newUpstream;
-                mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream);
-                reportUpstreamChanged(ns);
+                reportUpstreamChanged(mTetherUpstream);
+                // Need to notify capabilities change after upstream network changed because new
+                // network's capabilities should be checked every time.
+                mNotificationUpdater.onUpstreamCapabilitiesChanged(
+                        (ns != null) ? ns.networkCapabilities : null);
             }
         }
 
@@ -2034,6 +2039,11 @@
                     // broadcasts that result in being passed a
                     // TetherMainSM.CMD_UPSTREAM_CHANGED.
                     handleNewUpstreamNetworkState(null);
+
+                    if (SdkLevel.isAtLeastU()) {
+                        // Need to try DUN immediately if Wi-Fi goes down.
+                        chooseUpstreamType(true);
+                    }
                     break;
                 default:
                     mLog.e("Unknown arg1 value: " + arg1);
@@ -2077,6 +2087,7 @@
                 if (mTetherUpstream != null) {
                     mTetherUpstream = null;
                     reportUpstreamChanged(null);
+                    mNotificationUpdater.onUpstreamCapabilitiesChanged(null);
                 }
                 mBpfCoordinator.stopPolling();
             }
@@ -2407,6 +2418,9 @@
 
     /** Unregister tethering event callback */
     void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
+        if (callback == null) {
+            throw new NullPointerException();
+        }
         mHandler.post(() -> {
             mTetheringEventCallbacks.unregister(callback);
         });
@@ -2428,10 +2442,8 @@
         }
     }
 
-    private void reportUpstreamChanged(UpstreamNetworkState ns) {
+    private void reportUpstreamChanged(final Network network) {
         final int length = mTetheringEventCallbacks.beginBroadcast();
-        final Network network = (ns != null) ? ns.network : null;
-        final NetworkCapabilities capabilities = (ns != null) ? ns.networkCapabilities : null;
         try {
             for (int i = 0; i < length; i++) {
                 try {
@@ -2443,9 +2455,6 @@
         } finally {
             mTetheringEventCallbacks.finishBroadcast();
         }
-        // Need to notify capabilities change after upstream network changed because new network's
-        // capabilities should be checked every time.
-        mNotificationUpdater.onUpstreamCapabilitiesChanged(capabilities);
     }
 
     private void reportConfigurationChanged(TetheringConfigurationParcel config) {
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 16c031b..ac2aa7b 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -133,8 +133,6 @@
     private boolean mIsDefaultCellularUpstream;
     // The current system default network (not really used yet).
     private Network mDefaultInternetNetwork;
-    // The current upstream network used for tethering.
-    private Network mTetheringUpstreamNetwork;
     private boolean mPreferTestNetworks;
 
     public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
@@ -191,7 +189,6 @@
         releaseCallback(mListenAllCallback);
         mListenAllCallback = null;
 
-        mTetheringUpstreamNetwork = null;
         mNetworkMap.clear();
     }
 
@@ -342,11 +339,6 @@
         return findFirstDunNetwork(mNetworkMap.values());
     }
 
-    /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */
-    public void setCurrentUpstream(Network upstream) {
-        mTetheringUpstreamNetwork = upstream;
-    }
-
     /** Return local prefixes. */
     public Set<IpPrefix> getLocalPrefixes() {
         return (Set<IpPrefix>) mLocalPrefixes.clone();
diff --git a/Tethering/tests/integration/Android.bp b/Tethering/tests/integration/Android.bp
index 11e3dc0..5e08aba 100644
--- a/Tethering/tests/integration/Android.bp
+++ b/Tethering/tests/integration/Android.bp
@@ -21,8 +21,7 @@
     name: "TetheringIntegrationTestsDefaults",
     defaults: ["framework-connectivity-test-defaults"],
     srcs: [
-        "src/**/*.java",
-        "src/**/*.kt",
+        "base/**/*.java",
     ],
     min_sdk_version: "30",
     static_libs: [
@@ -47,6 +46,16 @@
     ],
 }
 
+android_library {
+    name: "TetheringIntegrationTestsBaseLib",
+    target_sdk_version: "current",
+    platform_apis: true,
+    defaults: ["TetheringIntegrationTestsDefaults"],
+    visibility: [
+        "//packages/modules/Connectivity/Tethering/tests/mts",
+    ]
+}
+
 // Library including tethering integration tests targeting the latest stable SDK.
 // Use with NetworkStackJarJarRules.
 android_library {
@@ -54,6 +63,9 @@
     target_sdk_version: "33",
     platform_apis: true,
     defaults: ["TetheringIntegrationTestsDefaults"],
+    srcs: [
+        "src/**/*.java",
+    ],
     visibility: [
         "//packages/modules/Connectivity/tests/cts/tethering",
         "//packages/modules/Connectivity/tests:__subpackages__",
@@ -68,12 +80,16 @@
     target_sdk_version: "current",
     platform_apis: true,
     defaults: ["TetheringIntegrationTestsDefaults"],
+    srcs: [
+        "src/**/*.java",
+    ],
     visibility: [
         "//packages/modules/Connectivity/tests/cts/tethering",
         "//packages/modules/Connectivity/Tethering/tests/mts",
     ]
 }
 
+// TODO: remove because TetheringIntegrationTests has been covered by ConnectivityCoverageTests.
 android_test {
     name: "TetheringIntegrationTests",
     platform_apis: true,
@@ -81,6 +97,9 @@
     test_suites: [
         "device-tests",
     ],
+    srcs: [
+        "src/**/*.java",
+    ],
     compile_multilib: "both",
     jarjar_rules: ":NetworkStackJarJarRules",
 }
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTestBase.java b/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
similarity index 100%
rename from Tethering/tests/integration/src/android/net/EthernetTetheringTestBase.java
rename to Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
diff --git a/Tethering/tests/integration/src/android/net/TetheringTester.java b/Tethering/tests/integration/base/android/net/TetheringTester.java
similarity index 100%
rename from Tethering/tests/integration/src/android/net/TetheringTester.java
rename to Tethering/tests/integration/base/android/net/TetheringTester.java
diff --git a/Tethering/tests/integration/src/android/net/CtsEthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
similarity index 78%
rename from Tethering/tests/integration/src/android/net/CtsEthernetTetheringTest.java
rename to Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index aea6728..fb4b9fa 100644
--- a/Tethering/tests/integration/src/android/net/CtsEthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -16,7 +16,6 @@
 
 package android.net;
 
-import static android.Manifest.permission.DUMP;
 import static android.net.InetAddresses.parseNumericAddress;
 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
 import static android.net.TetheringManager.TETHERING_ETHERNET;
@@ -26,7 +25,6 @@
 import static android.system.OsConstants.ICMP_ECHO;
 import static android.system.OsConstants.ICMP_ECHOREPLY;
 import static android.system.OsConstants.IPPROTO_ICMP;
-import static android.system.OsConstants.IPPROTO_UDP;
 
 import static com.android.net.module.util.ConnectivityUtils.isIPv6ULA;
 import static com.android.net.module.util.HexDump.dumpHexString;
@@ -39,39 +37,28 @@
 import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET;
 import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN;
 import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET;
-import static com.android.testutils.DeviceInfoUtils.KVersion;
-import static com.android.testutils.TestPermissionUtil.runAsShell;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
-import android.content.Context;
 import android.net.TetheringManager.TetheringRequest;
 import android.net.TetheringTester.TetheredDevice;
 import android.os.Build;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.VintfRuntimeInfo;
 import android.util.Log;
-import android.util.Pair;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.net.module.util.BpfDump;
 import com.android.net.module.util.Ipv6Utils;
 import com.android.net.module.util.Struct;
-import com.android.net.module.util.bpf.Tether4Key;
-import com.android.net.module.util.bpf.Tether4Value;
-import com.android.net.module.util.bpf.TetherStatsKey;
-import com.android.net.module.util.bpf.TetherStatsValue;
 import com.android.net.module.util.structs.EthernetHeader;
 import com.android.net.module.util.structs.Icmpv4Header;
 import com.android.net.module.util.structs.Ipv4Header;
@@ -79,8 +66,6 @@
 import com.android.net.module.util.structs.UdpHeader;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
-import com.android.testutils.DeviceInfoUtils;
-import com.android.testutils.DumpTestUtils;
 import com.android.testutils.TapPacketReader;
 
 import org.junit.Rule;
@@ -96,9 +81,7 @@
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
@@ -106,34 +89,13 @@
 
 @RunWith(AndroidJUnit4.class)
 @MediumTest
-public class CtsEthernetTetheringTest extends EthernetTetheringTestBase {
+public class EthernetTetheringTest extends EthernetTetheringTestBase {
     @Rule
     public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
 
-    private static final String TAG = CtsEthernetTetheringTest.class.getSimpleName();
-
-    private static final int DUMP_POLLING_MAX_RETRY = 100;
-    private static final int DUMP_POLLING_INTERVAL_MS = 50;
-    // Kernel treats a confirmed UDP connection which active after two seconds as stream mode.
-    // See upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5.
-    private static final int UDP_STREAM_TS_MS = 2000;
-    // Give slack time for waiting UDP stream mode because handling conntrack event in user space
-    // may not in precise time. Used to reduce the flaky rate.
-    private static final int UDP_STREAM_SLACK_MS = 500;
-    // Per RX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
-    private static final int RX_UDP_PACKET_SIZE = 30;
-    private static final int RX_UDP_PACKET_COUNT = 456;
-    // Per TX UDP packet size: ethhdr (14) + iphdr (20) + udphdr (8) + payload (2) = 44 bytes.
-    private static final int TX_UDP_PACKET_SIZE = 44;
-    private static final int TX_UDP_PACKET_COUNT = 123;
+    private static final String TAG = EthernetTetheringTest.class.getSimpleName();
 
     private static final short DNS_PORT = 53;
-
-    private static final String DUMPSYS_TETHERING_RAWMAP_ARG = "bpfRawMap";
-    private static final String DUMPSYS_RAWMAP_ARG_STATS = "--stats";
-    private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
-    private static final String LINE_DELIMITER = "\\n";
-
     private static final short ICMPECHO_CODE = 0x0;
     private static final short ICMPECHO_ID = 0x0;
     private static final short ICMPECHO_SEQ = 0x0;
@@ -529,7 +491,7 @@
     // remote ip              public ip                           private ip
     // 8.8.8.8:443            <Upstream ip>:9876                  <TetheredDevice ip>:9876
     //
-    private void runUdp4Test(boolean verifyBpf) throws Exception {
+    private void runUdp4Test() throws Exception {
         final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
                 toList(TEST_IP4_DNS));
         final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
@@ -549,123 +511,6 @@
         final InetAddress clientIp = tethered.ipv4Addr;
         sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
         sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
-
-        if (verifyBpf) {
-            // Send second UDP packet in original direction.
-            // The BPF coordinator only offloads the ASSURED conntrack entry. The "request + reply"
-            // packets can make status IPS_SEEN_REPLY to be set. Need one more packet to make
-            // conntrack status IPS_ASSURED_BIT to be set. Note the third packet needs to delay
-            // 2 seconds because kernel monitors a UDP connection which still alive after 2 seconds
-            // and apply ASSURED flag.
-            // See kernel upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5 and
-            // nf_conntrack_udp_packet in net/netfilter/nf_conntrack_proto_udp.c
-            Thread.sleep(UDP_STREAM_TS_MS);
-            sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
-
-            // Give a slack time for handling conntrack event in user space.
-            Thread.sleep(UDP_STREAM_SLACK_MS);
-
-            // [1] Verify IPv4 upstream rule map.
-            final HashMap<Tether4Key, Tether4Value> upstreamMap = pollRawMapFromDump(
-                    Tether4Key.class, Tether4Value.class, DUMPSYS_RAWMAP_ARG_UPSTREAM4);
-            assertNotNull(upstreamMap);
-            assertEquals(1, upstreamMap.size());
-
-            final Map.Entry<Tether4Key, Tether4Value> rule =
-                    upstreamMap.entrySet().iterator().next();
-
-            final Tether4Key upstream4Key = rule.getKey();
-            assertEquals(IPPROTO_UDP, upstream4Key.l4proto);
-            assertTrue(Arrays.equals(tethered.ipv4Addr.getAddress(), upstream4Key.src4));
-            assertEquals(LOCAL_PORT, upstream4Key.srcPort);
-            assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(), upstream4Key.dst4));
-            assertEquals(REMOTE_PORT, upstream4Key.dstPort);
-
-            final Tether4Value upstream4Value = rule.getValue();
-            assertTrue(Arrays.equals(tetheringUpstreamIp.getAddress(),
-                    InetAddress.getByAddress(upstream4Value.src46).getAddress()));
-            assertEquals(LOCAL_PORT, upstream4Value.srcPort);
-            assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(),
-                    InetAddress.getByAddress(upstream4Value.dst46).getAddress()));
-            assertEquals(REMOTE_PORT, upstream4Value.dstPort);
-
-            // [2] Verify stats map.
-            // Transmit packets on both direction for verifying stats. Because we only care the
-            // packet count in stats test, we just reuse the existing packets to increaes
-            // the packet count on both direction.
-
-            // Send packets on original direction.
-            for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) {
-                sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester,
-                        false /* is4To6 */);
-            }
-
-            // Send packets on reply direction.
-            for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) {
-                sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
-            }
-
-            // Dump stats map to verify.
-            final HashMap<TetherStatsKey, TetherStatsValue> statsMap = pollRawMapFromDump(
-                    TetherStatsKey.class, TetherStatsValue.class, DUMPSYS_RAWMAP_ARG_STATS);
-            assertNotNull(statsMap);
-            assertEquals(1, statsMap.size());
-
-            final Map.Entry<TetherStatsKey, TetherStatsValue> stats =
-                    statsMap.entrySet().iterator().next();
-
-            // TODO: verify the upstream index in TetherStatsKey.
-
-            final TetherStatsValue statsValue = stats.getValue();
-            assertEquals(RX_UDP_PACKET_COUNT, statsValue.rxPackets);
-            assertEquals(RX_UDP_PACKET_COUNT * RX_UDP_PACKET_SIZE, statsValue.rxBytes);
-            assertEquals(0, statsValue.rxErrors);
-            assertEquals(TX_UDP_PACKET_COUNT, statsValue.txPackets);
-            assertEquals(TX_UDP_PACKET_COUNT * TX_UDP_PACKET_SIZE, statsValue.txBytes);
-            assertEquals(0, statsValue.txErrors);
-        }
-    }
-
-    private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
-        final KVersion current = DeviceInfoUtils.getMajorMinorSubminorVersion(kernelVersion);
-        return current.isInRange(new KVersion(4, 14, 222), new KVersion(4, 19, 0))
-                || current.isInRange(new KVersion(4, 19, 176), new KVersion(5, 4, 0))
-                || current.isAtLeast(new KVersion(5, 4, 98));
-    }
-
-    @Test
-    public void testIsUdpOffloadSupportedByKernel() throws Exception {
-        assertFalse(isUdpOffloadSupportedByKernel("4.14.221"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.14.222"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.16.0"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.18.0"));
-        assertFalse(isUdpOffloadSupportedByKernel("4.19.0"));
-
-        assertFalse(isUdpOffloadSupportedByKernel("4.19.175"));
-        assertTrue(isUdpOffloadSupportedByKernel("4.19.176"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.2.0"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.3.0"));
-        assertFalse(isUdpOffloadSupportedByKernel("5.4.0"));
-
-        assertFalse(isUdpOffloadSupportedByKernel("5.4.97"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.4.98"));
-        assertTrue(isUdpOffloadSupportedByKernel("5.10.0"));
-    }
-
-    private static void assumeKernelSupportBpfOffloadUdpV4() {
-        final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
-        assumeTrue("Kernel version " + kernelVersion + " doesn't support IPv4 UDP BPF offload",
-                isUdpOffloadSupportedByKernel(kernelVersion));
-    }
-
-    @Test
-    public void testKernelSupportBpfOffloadUdpV4() throws Exception {
-        assumeKernelSupportBpfOffloadUdpV4();
-    }
-
-    @Test
-    public void testTetherConfigBpfOffloadEnabled() throws Exception {
-        assumeTrue(isTetherConfigBpfOffloadEnabled());
     }
 
     /**
@@ -674,73 +519,7 @@
      */
     @Test
     public void testTetherUdpV4() throws Exception {
-        runUdp4Test(false /* verifyBpf */);
-    }
-
-    /**
-     * BPF offload IPv4 UDP tethering test. Verify that UDP tethered packets are offloaded by BPF.
-     * Minimum test requirement:
-     * 1. S+ device.
-     * 2. Tethering config enables tethering BPF offload.
-     * 3. Kernel supports IPv4 UDP BPF offload. See #isUdpOffloadSupportedByKernel.
-     *
-     * TODO: consider enabling the test even tethering config disables BPF offload. See b/238288883
-     */
-    @Test
-    @IgnoreUpTo(Build.VERSION_CODES.R)
-    public void testTetherUdpV4_VerifyBpf() throws Exception {
-        assumeTrue("Tethering config disabled BPF offload", isTetherConfigBpfOffloadEnabled());
-        assumeKernelSupportBpfOffloadUdpV4();
-
-        runUdp4Test(true /* verifyBpf */);
-    }
-
-    @NonNull
-    private <K extends Struct, V extends Struct> HashMap<K, V> dumpAndParseRawMap(
-            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
-            throws Exception {
-        final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
-        final String rawMapStr = runAsShell(DUMP, () ->
-                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args));
-        final HashMap<K, V> map = new HashMap<>();
-
-        for (final String line : rawMapStr.split(LINE_DELIMITER)) {
-            final Pair<K, V> rule =
-                    BpfDump.fromBase64EncodedString(keyClass, valueClass, line.trim());
-            map.put(rule.first, rule.second);
-        }
-        return map;
-    }
-
-    @Nullable
-    private <K extends Struct, V extends Struct> HashMap<K, V> pollRawMapFromDump(
-            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
-            throws Exception {
-        for (int retryCount = 0; retryCount < DUMP_POLLING_MAX_RETRY; retryCount++) {
-            final HashMap<K, V> map = dumpAndParseRawMap(keyClass, valueClass, mapArg);
-            if (!map.isEmpty()) return map;
-
-            Thread.sleep(DUMP_POLLING_INTERVAL_MS);
-        }
-
-        fail("Cannot get rules after " + DUMP_POLLING_MAX_RETRY * DUMP_POLLING_INTERVAL_MS + "ms");
-        return null;
-    }
-
-    private boolean isTetherConfigBpfOffloadEnabled() throws Exception {
-        final String dumpStr = runAsShell(DUMP, () ->
-                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short"));
-
-        // BPF offload tether config can be overridden by "config_tether_enable_bpf_offload" in
-        // packages/modules/Connectivity/Tethering/res/values/config.xml. OEM may disable config by
-        // RRO to override the enabled default value. Get the tethering config via dumpsys.
-        // $ dumpsys tethering
-        //   mIsBpfEnabled: true
-        boolean enabled = dumpStr.contains("mIsBpfEnabled: true");
-        if (!enabled) {
-            Log.d(TAG, "BPF offload tether config not enabled: " + dumpStr);
-        }
-        return enabled;
+        runUdp4Test();
     }
 
     @NonNull
diff --git a/Tethering/tests/mts/Android.bp b/Tethering/tests/mts/Android.bp
index ae36499..4f4b03c 100644
--- a/Tethering/tests/mts/Android.bp
+++ b/Tethering/tests/mts/Android.bp
@@ -33,6 +33,7 @@
     ],
 
     static_libs: [
+        "TetheringIntegrationTestsBaseLib",
         "androidx.test.rules",
         // mockito-target-extended-minus-junit4 used in this lib have dependency with
         // jni_libs libdexmakerjvmtiagent and libstaticjvmtiagent.
diff --git a/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java b/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java
new file mode 100644
index 0000000..cb57d13
--- /dev/null
+++ b/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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;
+
+import static android.Manifest.permission.DUMP;
+import static android.system.OsConstants.IPPROTO_UDP;
+
+import static com.android.testutils.DeviceInfoUtils.KVersion;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.TetheringTester.TetheredDevice;
+import android.os.Build;
+import android.os.VintfRuntimeInfo;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.net.module.util.BpfDump;
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
+import com.android.net.module.util.bpf.TetherStatsKey;
+import com.android.net.module.util.bpf.TetherStatsValue;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DeviceInfoUtils;
+import com.android.testutils.DumpTestUtils;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class MtsEthernetTetheringTest extends EthernetTetheringTestBase {
+    @Rule
+    public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
+    private static final String TAG = MtsEthernetTetheringTest.class.getSimpleName();
+
+    private static final int DUMP_POLLING_MAX_RETRY = 100;
+    private static final int DUMP_POLLING_INTERVAL_MS = 50;
+    // Kernel treats a confirmed UDP connection which active after two seconds as stream mode.
+    // See upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5.
+    private static final int UDP_STREAM_TS_MS = 2000;
+    // Give slack time for waiting UDP stream mode because handling conntrack event in user space
+    // may not in precise time. Used to reduce the flaky rate.
+    private static final int UDP_STREAM_SLACK_MS = 500;
+    // Per RX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
+    private static final int RX_UDP_PACKET_SIZE = 30;
+    private static final int RX_UDP_PACKET_COUNT = 456;
+    // Per TX UDP packet size: ethhdr (14) + iphdr (20) + udphdr (8) + payload (2) = 44 bytes.
+    private static final int TX_UDP_PACKET_SIZE = 44;
+    private static final int TX_UDP_PACKET_COUNT = 123;
+
+    private static final String DUMPSYS_TETHERING_RAWMAP_ARG = "bpfRawMap";
+    private static final String DUMPSYS_RAWMAP_ARG_STATS = "--stats";
+    private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
+    private static final String LINE_DELIMITER = "\\n";
+
+    private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
+        final KVersion current = DeviceInfoUtils.getMajorMinorSubminorVersion(kernelVersion);
+        return current.isInRange(new KVersion(4, 14, 222), new KVersion(4, 19, 0))
+                || current.isInRange(new KVersion(4, 19, 176), new KVersion(5, 4, 0))
+                || current.isAtLeast(new KVersion(5, 4, 98));
+    }
+
+    @Test
+    public void testIsUdpOffloadSupportedByKernel() throws Exception {
+        assertFalse(isUdpOffloadSupportedByKernel("4.14.221"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.14.222"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.16.0"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.18.0"));
+        assertFalse(isUdpOffloadSupportedByKernel("4.19.0"));
+
+        assertFalse(isUdpOffloadSupportedByKernel("4.19.175"));
+        assertTrue(isUdpOffloadSupportedByKernel("4.19.176"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.2.0"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.3.0"));
+        assertFalse(isUdpOffloadSupportedByKernel("5.4.0"));
+
+        assertFalse(isUdpOffloadSupportedByKernel("5.4.97"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.4.98"));
+        assertTrue(isUdpOffloadSupportedByKernel("5.10.0"));
+    }
+
+    private static void assumeKernelSupportBpfOffloadUdpV4() {
+        final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
+        assumeTrue("Kernel version " + kernelVersion + " doesn't support IPv4 UDP BPF offload",
+                isUdpOffloadSupportedByKernel(kernelVersion));
+    }
+
+    @Test
+    public void testKernelSupportBpfOffloadUdpV4() throws Exception {
+        assumeKernelSupportBpfOffloadUdpV4();
+    }
+
+    private boolean isTetherConfigBpfOffloadEnabled() throws Exception {
+        final String dumpStr = runAsShell(DUMP, () ->
+                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short"));
+
+        // BPF offload tether config can be overridden by "config_tether_enable_bpf_offload" in
+        // packages/modules/Connectivity/Tethering/res/values/config.xml. OEM may disable config by
+        // RRO to override the enabled default value. Get the tethering config via dumpsys.
+        // $ dumpsys tethering
+        //   mIsBpfEnabled: true
+        boolean enabled = dumpStr.contains("mIsBpfEnabled: true");
+        if (!enabled) {
+            Log.d(TAG, "BPF offload tether config not enabled: " + dumpStr);
+        }
+        return enabled;
+    }
+
+    @Test
+    public void testTetherConfigBpfOffloadEnabled() throws Exception {
+        assumeTrue(isTetherConfigBpfOffloadEnabled());
+    }
+
+    @NonNull
+    private <K extends Struct, V extends Struct> HashMap<K, V> dumpAndParseRawMap(
+            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
+            throws Exception {
+        final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
+        final String rawMapStr = runAsShell(DUMP, () ->
+                DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args));
+        final HashMap<K, V> map = new HashMap<>();
+
+        for (final String line : rawMapStr.split(LINE_DELIMITER)) {
+            final Pair<K, V> rule =
+                    BpfDump.fromBase64EncodedString(keyClass, valueClass, line.trim());
+            map.put(rule.first, rule.second);
+        }
+        return map;
+    }
+
+    @Nullable
+    private <K extends Struct, V extends Struct> HashMap<K, V> pollRawMapFromDump(
+            Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
+            throws Exception {
+        for (int retryCount = 0; retryCount < DUMP_POLLING_MAX_RETRY; retryCount++) {
+            final HashMap<K, V> map = dumpAndParseRawMap(keyClass, valueClass, mapArg);
+            if (!map.isEmpty()) return map;
+
+            Thread.sleep(DUMP_POLLING_INTERVAL_MS);
+        }
+
+        fail("Cannot get rules after " + DUMP_POLLING_MAX_RETRY * DUMP_POLLING_INTERVAL_MS + "ms");
+        return null;
+    }
+
+    // Test network topology:
+    //
+    //         public network (rawip)                 private network
+    //                   |                 UE                |
+    // +------------+    V    +------------+------------+    V    +------------+
+    // |   Sever    +---------+  Upstream  | Downstream +---------+   Client   |
+    // +------------+         +------------+------------+         +------------+
+    // remote ip              public ip                           private ip
+    // 8.8.8.8:443            <Upstream ip>:9876                  <TetheredDevice ip>:9876
+    //
+    private void runUdp4Test() throws Exception {
+        final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
+                toList(TEST_IP4_DNS));
+        final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
+
+        // TODO: remove the connectivity verification for upstream connected notification race.
+        // Because async upstream connected notification can't guarantee the tethering routing is
+        // ready to use. Need to test tethering connectivity before testing.
+        // For short term plan, consider using IPv6 RA to get MAC address because the prefix comes
+        // from upstream. That can guarantee that the routing is ready. Long term plan is that
+        // refactors upstream connected notification from async to sync.
+        probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
+
+        final MacAddress srcMac = tethered.macAddr;
+        final MacAddress dstMac = tethered.routerMacAddr;
+        final InetAddress remoteIp = REMOTE_IP4_ADDR;
+        final InetAddress tetheringUpstreamIp = TEST_IP4_ADDR.getAddress();
+        final InetAddress clientIp = tethered.ipv4Addr;
+        sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
+        sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
+
+        // Send second UDP packet in original direction.
+        // The BPF coordinator only offloads the ASSURED conntrack entry. The "request + reply"
+        // packets can make status IPS_SEEN_REPLY to be set. Need one more packet to make
+        // conntrack status IPS_ASSURED_BIT to be set. Note the third packet needs to delay
+        // 2 seconds because kernel monitors a UDP connection which still alive after 2 seconds
+        // and apply ASSURED flag.
+        // See kernel upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5 and
+        // nf_conntrack_udp_packet in net/netfilter/nf_conntrack_proto_udp.c
+        Thread.sleep(UDP_STREAM_TS_MS);
+        sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
+
+        // Give a slack time for handling conntrack event in user space.
+        Thread.sleep(UDP_STREAM_SLACK_MS);
+
+        // [1] Verify IPv4 upstream rule map.
+        final HashMap<Tether4Key, Tether4Value> upstreamMap = pollRawMapFromDump(
+                Tether4Key.class, Tether4Value.class, DUMPSYS_RAWMAP_ARG_UPSTREAM4);
+        assertNotNull(upstreamMap);
+        assertEquals(1, upstreamMap.size());
+
+        final Map.Entry<Tether4Key, Tether4Value> rule =
+                upstreamMap.entrySet().iterator().next();
+
+        final Tether4Key upstream4Key = rule.getKey();
+        assertEquals(IPPROTO_UDP, upstream4Key.l4proto);
+        assertTrue(Arrays.equals(tethered.ipv4Addr.getAddress(), upstream4Key.src4));
+        assertEquals(LOCAL_PORT, upstream4Key.srcPort);
+        assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(), upstream4Key.dst4));
+        assertEquals(REMOTE_PORT, upstream4Key.dstPort);
+
+        final Tether4Value upstream4Value = rule.getValue();
+        assertTrue(Arrays.equals(tetheringUpstreamIp.getAddress(),
+                InetAddress.getByAddress(upstream4Value.src46).getAddress()));
+        assertEquals(LOCAL_PORT, upstream4Value.srcPort);
+        assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(),
+                InetAddress.getByAddress(upstream4Value.dst46).getAddress()));
+        assertEquals(REMOTE_PORT, upstream4Value.dstPort);
+
+        // [2] Verify stats map.
+        // Transmit packets on both direction for verifying stats. Because we only care the
+        // packet count in stats test, we just reuse the existing packets to increaes
+        // the packet count on both direction.
+
+        // Send packets on original direction.
+        for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) {
+            sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester,
+                    false /* is4To6 */);
+        }
+
+        // Send packets on reply direction.
+        for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) {
+            sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
+        }
+
+        // Dump stats map to verify.
+        final HashMap<TetherStatsKey, TetherStatsValue> statsMap = pollRawMapFromDump(
+                TetherStatsKey.class, TetherStatsValue.class, DUMPSYS_RAWMAP_ARG_STATS);
+        assertNotNull(statsMap);
+        assertEquals(1, statsMap.size());
+
+        final Map.Entry<TetherStatsKey, TetherStatsValue> stats =
+                statsMap.entrySet().iterator().next();
+
+        // TODO: verify the upstream index in TetherStatsKey.
+
+        final TetherStatsValue statsValue = stats.getValue();
+        assertEquals(RX_UDP_PACKET_COUNT, statsValue.rxPackets);
+        assertEquals(RX_UDP_PACKET_COUNT * RX_UDP_PACKET_SIZE, statsValue.rxBytes);
+        assertEquals(0, statsValue.rxErrors);
+        assertEquals(TX_UDP_PACKET_COUNT, statsValue.txPackets);
+        assertEquals(TX_UDP_PACKET_COUNT * TX_UDP_PACKET_SIZE, statsValue.txBytes);
+        assertEquals(0, statsValue.txErrors);
+    }
+
+    /**
+     * BPF offload IPv4 UDP tethering test. Verify that UDP tethered packets are offloaded by BPF.
+     * Minimum test requirement:
+     * 1. S+ device.
+     * 2. Tethering config enables tethering BPF offload.
+     * 3. Kernel supports IPv4 UDP BPF offload. See #isUdpOffloadSupportedByKernel.
+     *
+     * TODO: consider enabling the test even tethering config disables BPF offload. See b/238288883
+     */
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testTetherBpfOffloadUdpV4() throws Exception {
+        assumeTrue("Tethering config disabled BPF offload", isTetherConfigBpfOffloadEnabled());
+        assumeKernelSupportBpfOffloadUdpV4();
+
+        runUdp4Test();
+    }
+}
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..4f32f3c 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -16,6 +16,8 @@
 
 package com.android.networkstack.tethering;
 
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.ROAMING_NO;
@@ -32,6 +34,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 +44,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;
@@ -75,6 +79,7 @@
 import android.app.usage.NetworkStatsManager;
 import android.net.INetd;
 import android.net.InetAddresses;
+import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.MacAddress;
@@ -87,6 +92,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.test.TestLooper;
+import android.util.SparseArray;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -154,11 +160,13 @@
 
     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_XLAT_IFINDEX = 1002;
+    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_XLAT_IFACE = "v4-rmnet0";
     private static final String UPSTREAM_IFACE2 = "wlan0";
 
     private static final MacAddress DOWNSTREAM_MAC = MacAddress.fromString("12:34:56:78:90:ab");
@@ -181,6 +189,10 @@
     private static final Inet4Address PRIVATE_ADDR2 =
             (Inet4Address) InetAddresses.parseNumericAddress("192.168.90.12");
 
+    private static final Inet4Address XLAT_LOCAL_IPV4ADDR =
+            (Inet4Address) InetAddresses.parseNumericAddress("192.0.0.46");
+    private static final IpPrefix NAT64_IP_PREFIX = new IpPrefix("64:ff9b::/96");
+
     // Generally, public port and private port are the same in the NAT conntrack message.
     // TODO: consider using different private port and public port for testing.
     private static final short REMOTE_PORT = (short) 443;
@@ -192,6 +204,10 @@
     private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams(
             UPSTREAM_IFACE, UPSTREAM_IFINDEX, null /* macAddr, rawip */,
             NetworkStackConstants.ETHER_MTU);
+    private static final InterfaceParams UPSTREAM_XLAT_IFACE_PARAMS = new InterfaceParams(
+            UPSTREAM_XLAT_IFACE, UPSTREAM_XLAT_IFINDEX, null /* macAddr, rawip */,
+            NetworkStackConstants.ETHER_MTU - 28
+            /* mtu delta from external/android-clat/clatd.c */);
     private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams(
             UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.fromString("44:55:66:00:00:0c"),
             NetworkStackConstants.ETHER_MTU);
@@ -283,6 +299,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 +324,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 +401,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 +457,10 @@
                         return mElapsedRealtimeNanos;
                     }
 
+                    public int getNetworkInterfaceMtu(@NonNull String iface) {
+                        return mMtu;
+                    }
+
                     @Nullable
                     public IBpfMap<Tether4Key, Tether4Value> getBpfDownstream4Map() {
                         return mBpfDownstream4Map;
@@ -1518,6 +1549,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 +2140,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 +2227,238 @@
 
         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 */);
+    }
+
+    private static LinkProperties buildUpstreamLinkProperties(final String interfaceName,
+            boolean withIPv4, boolean withIPv6, boolean with464xlat) {
+        final LinkProperties prop = new LinkProperties();
+        prop.setInterfaceName(interfaceName);
+
+        if (withIPv4) {
+            // Assign the address no matter what the interface is. It is okay for now because
+            // only single upstream is available.
+            // TODO: consider to assign address by interface once we need to test two or more
+            // BPF supported upstreams or multi upstreams are supported.
+            prop.addLinkAddress(new LinkAddress(PUBLIC_ADDR, 24));
+        }
+
+        if (withIPv6) {
+            // TODO: make this to be constant. Currently, no test who uses this function cares what
+            // the upstream IPv6 address is.
+            prop.addLinkAddress(new LinkAddress("2001:db8::5175:15ca/64"));
+        }
+
+        if (with464xlat) {
+            final String clatInterface = "v4-" + interfaceName;
+            final LinkProperties stackedLink = new LinkProperties();
+            stackedLink.setInterfaceName(clatInterface);
+            stackedLink.addLinkAddress(new LinkAddress(XLAT_LOCAL_IPV4ADDR, 24));
+            prop.addStackedLink(stackedLink);
+            prop.setNat64Prefix(NAT64_IP_PREFIX);
+        }
+
+        return prop;
+    }
+
+    private void verifyIpv4Upstream(
+            @NonNull final HashMap<Inet4Address, Integer> ipv4UpstreamIndices,
+            @NonNull final SparseArray<String> interfaceNames) {
+        assertEquals(1, ipv4UpstreamIndices.size());
+        Integer upstreamIndex = ipv4UpstreamIndices.get(PUBLIC_ADDR);
+        assertNotNull(upstreamIndex);
+        assertEquals(UPSTREAM_IFINDEX, upstreamIndex.intValue());
+        assertEquals(1, interfaceNames.size());
+        assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+    }
+
+    private void verifyUpdateUpstreamNetworkState()
+            throws Exception {
+        final BpfCoordinator coordinator = makeBpfCoordinator();
+        final HashMap<Inet4Address, Integer> ipv4UpstreamIndices =
+                coordinator.getIpv4UpstreamIndicesForTesting();
+        assertTrue(ipv4UpstreamIndices.isEmpty());
+        final SparseArray<String> interfaceNames =
+                coordinator.getInterfaceNamesForTesting();
+        assertEquals(0, interfaceNames.size());
+
+        // Verify the following are added or removed after upstream changes.
+        // - BpfCoordinator#mIpv4UpstreamIndices (for building IPv4 offload rules)
+        // - BpfCoordinator#mInterfaceNames (for updating limit)
+        //
+        // +-------+-------+-----------------------+
+        // | Test  | Up    |       Protocol        |
+        // | Case# | stream+-------+-------+-------+
+        // |       |       | IPv4  | IPv6  | Xlat  |
+        // +-------+-------+-------+-------+-------+
+        // |   1   | Cell  |   O   |       |       |
+        // +-------+-------+-------+-------+-------+
+        // |   2   | Cell  |       |   O   |       |
+        // +-------+-------+-------+-------+-------+
+        // |   3   | Cell  |   O   |   O   |       |
+        // +-------+-------+-------+-------+-------+
+        // |   4   |   -   |       |       |       |
+        // +-------+-------+-------+-------+-------+
+        // |       | Cell  |   O   |       |       |
+        // |       +-------+-------+-------+-------+
+        // |   5   | Cell  |       |   O   |   O   | <-- doesn't support offload (xlat)
+        // |       +-------+-------+-------+-------+
+        // |       | Cell  |   O   |       |       |
+        // +-------+-------+-------+-------+-------+
+        // |   6   | Wifi  |   O   |   O   |       | <-- doesn't support offload (ether ip)
+        // +-------+-------+-------+-------+-------+
+
+        // [1] Mobile IPv4 only
+        coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX, UPSTREAM_IFACE);
+        doReturn(UPSTREAM_IFACE_PARAMS).when(mDeps).getInterfaceParams(UPSTREAM_IFACE);
+        final UpstreamNetworkState mobileIPv4UpstreamState = new UpstreamNetworkState(
+                buildUpstreamLinkProperties(UPSTREAM_IFACE,
+                        true /* IPv4 */, false /* IPv6 */, false /* 464xlat */),
+                new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+                new Network(TEST_NET_ID));
+        coordinator.updateUpstreamNetworkState(mobileIPv4UpstreamState);
+        verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+        // [2] Mobile IPv6 only
+        final UpstreamNetworkState mobileIPv6UpstreamState = new UpstreamNetworkState(
+                buildUpstreamLinkProperties(UPSTREAM_IFACE,
+                        false /* IPv4 */, true /* IPv6 */, false /* 464xlat */),
+                new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+                new Network(TEST_NET_ID));
+        coordinator.updateUpstreamNetworkState(mobileIPv6UpstreamState);
+        assertTrue(ipv4UpstreamIndices.isEmpty());
+        assertEquals(1, interfaceNames.size());
+        assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+
+        // [3] Mobile IPv4 and IPv6
+        final UpstreamNetworkState mobileDualStackUpstreamState = new UpstreamNetworkState(
+                buildUpstreamLinkProperties(UPSTREAM_IFACE,
+                        true /* IPv4 */, true /* IPv6 */, false /* 464xlat */),
+                new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+                new Network(TEST_NET_ID));
+        coordinator.updateUpstreamNetworkState(mobileDualStackUpstreamState);
+        verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+        // [4] Lost upstream
+        coordinator.updateUpstreamNetworkState(null);
+        assertTrue(ipv4UpstreamIndices.isEmpty());
+        assertEquals(1, interfaceNames.size());
+        assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+
+        // [5] verify xlat interface
+        // Expect that xlat interface information isn't added to mapping.
+        doReturn(UPSTREAM_XLAT_IFACE_PARAMS).when(mDeps).getInterfaceParams(
+                UPSTREAM_XLAT_IFACE);
+        final UpstreamNetworkState mobile464xlatUpstreamState = new UpstreamNetworkState(
+                buildUpstreamLinkProperties(UPSTREAM_IFACE,
+                        false /* IPv4 */, true /* IPv6 */, true /* 464xlat */),
+                new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+                new Network(TEST_NET_ID));
+
+        // Need to add a valid IPv4 upstream to verify that xlat interface doesn't support.
+        // Mobile IPv4 only
+        coordinator.updateUpstreamNetworkState(mobileIPv4UpstreamState);
+        verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+        // Mobile IPv6 and xlat
+        // IpServer doesn't add xlat interface mapping via #addUpstreamNameToLookupTable on
+        // S and T devices.
+        coordinator.updateUpstreamNetworkState(mobile464xlatUpstreamState);
+        // Upstream IPv4 address mapping is removed because xlat interface is not supported.
+        assertTrue(ipv4UpstreamIndices.isEmpty());
+        assertEquals(1, interfaceNames.size());
+        assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+
+        // Need to add a valid IPv4 upstream to verify that wifi interface doesn't support.
+        // Mobile IPv4 only
+        coordinator.updateUpstreamNetworkState(mobileIPv4UpstreamState);
+        verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+        // [6] Wifi IPv4 and IPv6
+        // Expect that upstream index map is cleared because ether ip is not supported.
+        coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2, UPSTREAM_IFACE2);
+        doReturn(UPSTREAM_IFACE_PARAMS2).when(mDeps).getInterfaceParams(UPSTREAM_IFACE2);
+        final UpstreamNetworkState wifiDualStackUpstreamState = new UpstreamNetworkState(
+                buildUpstreamLinkProperties(UPSTREAM_IFACE2,
+                        true /* IPv4 */, true /* IPv6 */, false /* 464xlat */),
+                new NetworkCapabilities().addTransportType(TRANSPORT_WIFI),
+                new Network(TEST_NET_ID2));
+        coordinator.updateUpstreamNetworkState(wifiDualStackUpstreamState);
+        assertTrue(ipv4UpstreamIndices.isEmpty());
+        assertEquals(2, interfaceNames.size());
+        assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+        assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX2));
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testUpdateUpstreamNetworkState() throws Exception {
+        verifyUpdateUpstreamNetworkState();
+    }
 }
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/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index a8d886b..79590b7 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -29,6 +29,7 @@
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -82,6 +83,8 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeFalse;
@@ -179,6 +182,7 @@
 import android.util.ArraySet;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -258,6 +262,8 @@
 
     private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
 
+    private static final Network[] NULL_NETWORK = new Network[] {null};
+
     @Mock private ApplicationInfo mApplicationInfo;
     @Mock private Context mContext;
     @Mock private NetworkStatsManager mStatsManager;
@@ -300,6 +306,7 @@
     private MockContentResolver mContentResolver;
     private BroadcastReceiver mBroadcastReceiver;
     private Tethering mTethering;
+    private TestTetheringEventCallback mTetheringEventCallback;
     private PhoneStateListener mPhoneStateListener;
     private InterfaceConfigurationParcel mInterfaceConfiguration;
     private TetheringConfiguration mConfig;
@@ -667,6 +674,7 @@
         verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
         verify(mNetd).registerUnsolicitedEventListener(any());
         verifyDefaultNetworkRequestFiled();
+        mTetheringEventCallback = registerTetheringEventCallback();
 
         final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
                 ArgumentCaptor.forClass(PhoneStateListener.class);
@@ -742,6 +750,16 @@
         return request;
     }
 
+    @NonNull
+    private TestTetheringEventCallback registerTetheringEventCallback() {
+        TestTetheringEventCallback callback = new TestTetheringEventCallback();
+        mTethering.registerTetheringEventCallback(callback);
+        mLooper.dispatchAll();
+        // Pull the first event which is filed immediately after the callback registration.
+        callback.expectUpstreamChanged(NULL_NETWORK);
+        return callback;
+    }
+
     @After
     public void tearDown() {
         mServiceContext.unregisterReceiver(mBroadcastReceiver);
@@ -921,9 +939,9 @@
         // tetherMatchingInterfaces() which starts by fetching all interfaces).
         verify(mNetd, times(1)).interfaceGetList();
 
-        // UpstreamNetworkMonitor should receive selected upstream
+        // Event callback should receive selected upstream
         verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
-        verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
+        mTetheringEventCallback.expectUpstreamChanged(upstreamState.network);
     }
 
     @Test
@@ -1178,7 +1196,7 @@
         verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
         verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
 
-        verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
+        mTetheringEventCallback.expectUpstreamChanged(upstreamState.network);
     }
 
     private void verifyDisableTryCellWhenTetheringStop(InOrder inOrder) {
@@ -1203,14 +1221,14 @@
         mobile.fakeConnect();
         mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
 
         // Switch upstream to wifi.
         wifi.fakeConnect();
         mCm.makeDefaultNetwork(wifi, BROADCAST_FIRST);
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
     }
 
     private void verifyAutomaticUpstreamSelection(boolean configAutomatic) throws Exception {
@@ -1227,30 +1245,30 @@
         // Switch upstreams a few times.
         mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST, doDispatchAll);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
 
         mCm.makeDefaultNetwork(wifi, BROADCAST_FIRST, doDispatchAll);
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
 
         mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
 
         mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
 
         mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST, doDispatchAll);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
 
         // Wifi disconnecting should not have any affect since it's not the current upstream.
         wifi.fakeDisconnect();
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
 
         // Lose and regain upstream.
         assertTrue(mUpstreamNetworkMonitor.getCurrentPreferredUpstream().linkProperties
@@ -1260,13 +1278,13 @@
         mobile.fakeDisconnect();
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+        mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
 
         mobile = new TestNetworkAgent(mCm, buildMobile464xlatUpstreamState());
         mobile.fakeConnect();
         mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST, doDispatchAll);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
 
         // Check the IP addresses to ensure that the upstream is indeed not the same as the previous
         // mobile upstream, even though the netId is (unrealistically) the same.
@@ -1278,13 +1296,13 @@
         mobile.fakeDisconnect();
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+        mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
 
         mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
         mobile.fakeConnect();
         mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST, doDispatchAll);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
 
         assertTrue(mUpstreamNetworkMonitor.getCurrentPreferredUpstream().linkProperties
                 .hasIPv4Address());
@@ -1325,18 +1343,143 @@
         mLooper.dispatchAll();
         mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST, null);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
 
         wifi.fakeConnect();
         mLooper.dispatchAll();
         mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST, null);
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
 
         verifyDisableTryCellWhenTetheringStop(inOrder);
     }
 
+    private void verifyWifiUpstreamAndUnregisterDunCallback(@NonNull final InOrder inOrder,
+            @NonNull final TestNetworkAgent wifi, @NonNull final NetworkCallback currentDunCallack)
+            throws Exception {
+        assertNotNull(currentDunCallack);
+
+        inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
+        inOrder.verify(mCm).unregisterNetworkCallback(eq(currentDunCallack));
+        mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
+    }
+
+    @Nullable
+    private NetworkCallback verifyDunUpstream(@NonNull final InOrder inOrder,
+            @NonNull final TestNetworkAgent dun, final boolean needToRequestNetwork)
+            throws Exception {
+        inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
+        ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
+        NetworkCallback dunNetworkCallback = null;
+        if (needToRequestNetwork) {
+            inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(),
+                    captor.capture());
+            dunNetworkCallback = captor.getValue();
+        }
+        mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
+        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+        dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
+
+        if (needToRequestNetwork) {
+            assertNotNull(dunNetworkCallback);
+        } else {
+            assertNull(dunNetworkCallback);
+        }
+
+        return dunNetworkCallback;
+    }
+
+    // Overall test coverage:
+    // - verifyChooseDunUpstreamByAutomaticMode: common, test#1, test#2
+    // - testChooseDunUpstreamByAutomaticMode_defaultNetworkWifi: test#3, test#4
+    // - testChooseDunUpstreamByAutomaticMode_loseDefaultNetworkWifi: test#5
+    // - testChooseDunUpstreamByAutomaticMode_defaultNetworkCell: test#5, test#7
+    // - testChooseDunUpstreamByAutomaticMode_loseAndRegainDun: test#8
+    // - testChooseDunUpstreamByAutomaticMode_switchDefaultFromWifiToCell: test#9, test#10
+    //
+    // Overall test cases:
+    // +-------+-------+-------+-------+-------+
+    // | Test  | WiFi  | Cellu |  Dun  | Expec |
+    // | Case  |       | alr   |       | ted   |
+    // |   #   |       |       |       | Upstr |
+    // |       |       |       |       | eam   |
+    // +-------+-------+-------+-------+-------+
+    // |   -   |       |       |       |   -   | --+
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |       |   V   |       |   -   |   |
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |       |   V   |   O   |  Dun  |   +-- chooseDunUpstreamTestCommon
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |   V   |   O   |   O   |  WiFi |   |
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |   V   |   O   |       |  WiFi | --+
+    // +-------+-------+-------+-------+-------+
+    // |       |   O   |   V   |       |   -   |
+    // |   1   +-------+-------+-------+-------+
+    // |       |   O   |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |       |   O   |   V   |       |   -   |
+    // |   2   +-------+-------+-------+-------+
+    // |       |   O   |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |   3   |   V   |   O   |       |  WiFi |
+    // +-------+-------+-------+-------+-------+
+    // |   4   |   V   |       |       |  WiFi |
+    // +-------+-------+-------+-------+-------+
+    // |   5   |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |   6   |       |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |   7   |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |       |       |       |       |   -   |
+    // |   8   +-------+-------+-------+-------+
+    // |       |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |       |   V   |       |   O   |  WiFi |
+    // |   9   +-------+-------+-------+-------+
+    // |       |   V   |       |       |  WiFi |
+    // +-------+-------+-------+-------+-------+
+    // |       |   O   |   V   |       |   -   |
+    // |   10  +-------+-------+-------+-------+
+    // |       |   O   |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    //
+    // Annotation:
+    // 1. "V" means that the given network is connected and it is default network.
+    // 2. "O" means that the given network is connected and it is not default network.
+    //
+
+    // Test case:
+    // +-------+-------+-------+-------+-------+
+    // | Test  | WiFi  | Cellu |  Dun  | Expec |
+    // | Case  |       | alr   |       | ted   |
+    // |   #   |       |       |       | Upstr |
+    // |       |       |       |       | eam   |
+    // +-------+-------+-------+-------+-------+
+    // |   -   |       |       |       |   -   | --+
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |       |   V   |       |   -   |   |
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |       |   V   |   O   |  Dun  |   +-- chooseDunUpstreamTestCommon
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |   V   |   O   |   O   |  WiFi |   |
+    // +-------+-------+-------+-------+-------+   |
+    // |   -   |   V   |   O   |       |  WiFi | --+
+    // +-------+-------+-------+-------+-------+
+    // |       |   O   |   V   |       |   -   |
+    // |   1   +-------+-------+-------+-------+
+    // |       |   O   |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |       |   O   |   V   |       |   -   |
+    // |   2   +-------+-------+-------+-------+
+    // |       |   O   |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    //
     private void verifyChooseDunUpstreamByAutomaticMode(boolean configAutomatic) throws Exception {
         // Enable automatic upstream selection.
         TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
@@ -1345,28 +1488,22 @@
         InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
         chooseDunUpstreamTestCommon(configAutomatic, inOrder, mobile, wifi, dun);
 
-        // When default network switch to mobile and wifi is connected (may have low signal),
+        // [1] When default network switch to mobile and wifi is connected (may have low signal),
         // automatic mode would request dun again and choose it as upstream.
         mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
-        ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
-        inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(), any());
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
-        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
-        dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
-        mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+        verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */);
 
-        // Lose and regain upstream again.
+        // [2] Lose and regain upstream again.
+        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
         dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+        mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
         inOrder.verify(mCm, never()).unregisterNetworkCallback(any(NetworkCallback.class));
         dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
 
         verifyDisableTryCellWhenTetheringStop(inOrder);
     }
@@ -1376,12 +1513,245 @@
         verifyChooseDunUpstreamByAutomaticMode(true /* configAutomatic */);
     }
 
+    // testChooseDunUpstreamByAutomaticMode_* doesn't verify configAutomatic:false because no
+    // matter |configAutomatic| set to true or false, the result always be automatic mode. We
+    // just need one test to make sure this behavior. Don't need to test this configuration
+    // in all tests.
     @Test
     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
     public void testChooseDunUpstreamByAutomaticModeWithConfigDisabled() throws Exception {
         verifyChooseDunUpstreamByAutomaticMode(false /* configAutomatic */);
     }
 
+    // Test case:
+    // +-------+-------+-------+-------+-------+
+    // | Test  | WiFi  | Cellu |  Dun  | Expec |
+    // | Case  |       | alr   |       | ted   |
+    // |   #   |       |       |       | Upstr |
+    // |       |       |       |       | eam   |
+    // +-------+-------+-------+-------+-------+
+    // |   -   |   O   |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |   3   |   V   |   O   |       |  WiFi |
+    // +-------+-------+-------+-------+-------+
+    // |   4   |   V   |       |       |  WiFi |
+    // +-------+-------+-------+-------+-------+
+    //
+    // See verifyChooseDunUpstreamByAutomaticMode for the annotation.
+    //
+    @Test
+    public void testChooseDunUpstreamByAutomaticMode_defaultNetworkWifi() throws Exception {
+        TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+        TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+        TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState());
+        final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+        final NetworkCallback dunNetworkCallback1 = setupDunUpstreamTest(
+                true /* configAutomatic */, inOrder);
+
+        // When wifi connected, unregister dun request and choose wifi as upstream.
+        wifi.fakeConnect();
+        mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback1);
+
+        // When default network switch to mobile and wifi is connected (may have low signal),
+        // automatic mode would request dun again and choose it as upstream.
+        mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        final NetworkCallback dunNetworkCallback2 = verifyDunUpstream(inOrder, dun,
+                true /* needToRequestNetwork */);
+
+        // [3] When default network switch to wifi and mobile is still connected,
+        // unregister dun request and choose wifi as upstream.
+        mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback2);
+
+        // [4] When mobile is disconnected, keep wifi as upstream.
+        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+        mobile.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
+
+        verifyDisableTryCellWhenTetheringStop(inOrder);
+    }
+
+    // Test case:
+    // +-------+-------+-------+-------+-------+
+    // | Test  | WiFi  | Cellu |  Dun  | Expec |
+    // | Case  |       | alr   |       | ted   |
+    // |   #   |       |       |       | Upstr |
+    // |       |       |       |       | eam   |
+    // +-------+-------+-------+-------+-------+
+    // |   -   |   V   |       |       |  WiFi |
+    // +-------+-------+-------+-------+-------+
+    // |   5   |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    //
+    // See verifyChooseDunUpstreamByAutomaticMode for the annotation.
+    //
+    @Test
+    public void testChooseDunUpstreamByAutomaticMode_loseDefaultNetworkWifi() throws Exception {
+        TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+        TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState());
+        final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+        final NetworkCallback dunNetworkCallback = setupDunUpstreamTest(
+                true /* configAutomatic */, inOrder);
+
+        // When wifi connected, unregister dun request and choose wifi as upstream.
+        wifi.fakeConnect();
+        mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback);
+
+        // [5] When wifi is disconnected, automatic mode would request dun again and choose it
+        // as upstream.
+        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+        mCm.makeDefaultNetwork(null, CALLBACKS_FIRST, doDispatchAll);
+        wifi.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */);
+
+        verifyDisableTryCellWhenTetheringStop(inOrder);
+    }
+
+    // Test case:
+    // +-------+-------+-------+-------+-------+
+    // | Test  | WiFi  | Cellu |  Dun  | Expec |
+    // | Case  |       | alr   |       | ted   |
+    // |   #   |       |       |       | Upstr |
+    // |       |       |       |       | eam   |
+    // +-------+-------+-------+-------+-------+
+    // |   -   |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |   6   |       |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |   7   |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    //
+    // See verifyChooseDunUpstreamByAutomaticMode for the annotation.
+    //
+    @Test
+    public void testChooseDunUpstreamByAutomaticMode_defaultNetworkCell() throws Exception {
+        TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+        TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState());
+        final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+        setupDunUpstreamTest(true /* configAutomatic */, inOrder);
+
+        // Pretend dun connected and expect choose dun as upstream.
+        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+        dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
+
+        // [6] When mobile is connected and default network switch to mobile, keep dun as upstream.
+        mobile.fakeConnect();
+        mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
+
+        // [7] When mobile is disconnected, keep dun as upstream.
+        mCm.makeDefaultNetwork(null, CALLBACKS_FIRST, doDispatchAll);
+        mobile.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
+
+        verifyDisableTryCellWhenTetheringStop(inOrder);
+    }
+
+    // Test case:
+    // +-------+-------+-------+-------+-------+
+    // | Test  | WiFi  | Cellu |  Dun  | Expec |
+    // | Case  |       | alr   |       | ted   |
+    // |   #   |       |       |       | Upstr |
+    // |       |       |       |       | eam   |
+    // +-------+-------+-------+-------+-------+
+    // |   -   |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |       |       |       |       |   -   |
+    // |   8   +-------+-------+-------+-------+
+    // |       |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    //
+    // See verifyChooseDunUpstreamByAutomaticMode for the annotation.
+    //
+    @Test
+    public void testChooseDunUpstreamByAutomaticMode_loseAndRegainDun() throws Exception {
+        TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState());
+        final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+        setupDunUpstreamTest(true /* configAutomatic */, inOrder);
+
+        // Pretend dun connected and expect choose dun as upstream.
+        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+        dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
+
+        // [8] Lose and regain upstream again.
+        dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        verifyDunUpstream(inOrder, dun, false /* needToRequestNetwork */);
+
+        verifyDisableTryCellWhenTetheringStop(inOrder);
+    }
+
+    // Test case:
+    // +-------+-------+-------+-------+-------+
+    // | Test  | WiFi  | Cellu |  Dun  | Expec |
+    // | Case  |       | alr   |       | ted   |
+    // |   #   |       |       |       | Upstr |
+    // |       |       |       |       | eam   |
+    // +-------+-------+-------+-------+-------+
+    // |   -   |       |       |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    // |       |   V   |       |   O   |  WiFi |
+    // |   9   +-------+-------+-------+-------+
+    // |       |   V   |       |       |  WiFi |
+    // +-------+-------+-------+-------+-------+
+    // |       |   O   |   V   |       |   -   |
+    // |   10  +-------+-------+-------+-------+
+    // |       |   O   |   V   |   O   |  Dun  |
+    // +-------+-------+-------+-------+-------+
+    //
+    // See verifyChooseDunUpstreamByAutomaticMode for the annotation.
+    //
+    @Test
+    public void testChooseDunUpstreamByAutomaticMode_switchDefaultFromWifiToCell()
+            throws Exception {
+        TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+        TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+        TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState());
+        final InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+        final NetworkCallback dunNetworkCallback = setupDunUpstreamTest(
+                true /* configAutomatic */, inOrder);
+
+        // Pretend dun connected and expect choose dun as upstream.
+        final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+        dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
+
+        // [9] When wifi is connected and default network switch to wifi, unregister dun request
+        // and choose wifi as upstream. When dun is disconnected, keep wifi as upstream.
+        wifi.fakeConnect();
+        mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback);
+        dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
+        mLooper.dispatchAll();
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
+
+        // [10] When mobile and mobile are connected and default network switch to mobile
+        // (may have low signal), automatic mode would request dun again and choose it as
+        // upstream.
+        mobile.fakeConnect();
+        mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */);
+
+        verifyDisableTryCellWhenTetheringStop(inOrder);
+    }
+
     @Test
     @IgnoreAfter(Build.VERSION_CODES.TIRAMISU)
     public void testChooseDunUpstreamByLegacyMode() throws Exception {
@@ -1397,7 +1767,7 @@
         mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
         mLooper.dispatchAll();
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
-        inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
         // BUG: when wifi disconnect, the dun request would not be filed again because wifi is
         // no longer be default network which do not have CONNECTIVIY_ACTION broadcast.
         wifi.fakeDisconnect();
@@ -1425,8 +1795,7 @@
         verifyDisableTryCellWhenTetheringStop(inOrder);
     }
 
-    private void chooseDunUpstreamTestCommon(final boolean automatic, InOrder inOrder,
-            TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun) throws Exception {
+    private NetworkCallback setupDunUpstreamTest(final boolean automatic, InOrder inOrder) {
         when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(automatic);
         when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true);
         sendConfigurationChanged();
@@ -1439,31 +1808,36 @@
         inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
         ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
         inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(),
-                captor.capture());
-        final NetworkCallback dunNetworkCallback1 = captor.getValue();
+                captor.capture() /* DUN network callback */);
 
-        // Pretend cellular connected and expect the upstream to be set.
+        return captor.getValue();
+    }
+
+    private void chooseDunUpstreamTestCommon(final boolean automatic, InOrder inOrder,
+            TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun)
+            throws Exception {
+        final NetworkCallback dunNetworkCallback = setupDunUpstreamTest(automatic, inOrder);
+
+        // Pretend cellular connected and expect the upstream to be not set.
         mobile.fakeConnect();
         mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(mobile.networkId);
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
 
         // Pretend dun connected and expect choose dun as upstream.
         final Runnable doDispatchAll = () -> mLooper.dispatchAll();
         dun.fakeConnect(BROADCAST_FIRST, doDispatchAll);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+        mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
 
         // When wifi connected, unregister dun request and choose wifi as upstream.
         wifi.fakeConnect();
         mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
-        inOrder.verify(mCm).unregisterNetworkCallback(eq(dunNetworkCallback1));
-        inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+        verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback);
         dun.fakeDisconnect(BROADCAST_FIRST, doDispatchAll);
         mLooper.dispatchAll();
-        inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+        mTetheringEventCallback.assertNoUpstreamChangeCallback();
     }
 
     private void runNcmTethering() {
@@ -1767,7 +2141,7 @@
                     new ArrayList<Network>(Arrays.asList(networks));
             for (Network upstream : expectedUpstreams) {
                 // throws OOB if no expectations
-                assertEquals(mActualUpstreams.remove(0), upstream);
+                assertEquals(upstream, mActualUpstreams.remove(0));
             }
             assertNoUpstreamChangeCallback();
         }
@@ -1782,14 +2156,14 @@
             for (TetheringConfigurationParcel config : expectedTetherConfig) {
                 // throws OOB if no expectations
                 final TetheringConfigurationParcel actualConfig = mTetheringConfigs.remove(0);
-                assertTetherConfigParcelEqual(actualConfig, config);
+                assertTetherConfigParcelEqual(config, actualConfig);
             }
             assertNoConfigChangeCallback();
         }
 
         public void expectOffloadStatusChanged(final int expectedStatus) {
             assertOffloadStatusChangedCallback();
-            assertEquals(mOffloadStatus.remove(0), new Integer(expectedStatus));
+            assertEquals(Integer.valueOf(expectedStatus), mOffloadStatus.remove(0));
         }
 
         public TetherStatesParcel pollTetherStatesChanged() {
@@ -1880,12 +2254,12 @@
 
         private void assertTetherConfigParcelEqual(@NonNull TetheringConfigurationParcel actual,
                 @NonNull TetheringConfigurationParcel expect) {
-            assertArrayEquals(actual.tetherableUsbRegexs, expect.tetherableUsbRegexs);
-            assertArrayEquals(actual.tetherableWifiRegexs, expect.tetherableWifiRegexs);
-            assertArrayEquals(actual.tetherableBluetoothRegexs, expect.tetherableBluetoothRegexs);
-            assertArrayEquals(actual.legacyDhcpRanges, expect.legacyDhcpRanges);
-            assertArrayEquals(actual.provisioningApp, expect.provisioningApp);
-            assertEquals(actual.provisioningAppNoUi, expect.provisioningAppNoUi);
+            assertArrayEquals(expect.tetherableUsbRegexs, actual.tetherableUsbRegexs);
+            assertArrayEquals(expect.tetherableWifiRegexs, actual.tetherableWifiRegexs);
+            assertArrayEquals(expect.tetherableBluetoothRegexs, actual.tetherableBluetoothRegexs);
+            assertArrayEquals(expect.legacyDhcpRanges, actual.legacyDhcpRanges);
+            assertArrayEquals(expect.provisioningApp, actual.provisioningApp);
+            assertEquals(expect.provisioningAppNoUi, actual.provisioningAppNoUi);
         }
     }
 
@@ -1910,7 +2284,7 @@
         mTethering.registerTetheringEventCallback(callback);
         mLooper.dispatchAll();
         callback.expectTetheredClientChanged(Collections.emptyList());
-        callback.expectUpstreamChanged(new Network[] {null});
+        callback.expectUpstreamChanged(NULL_NETWORK);
         callback.expectConfigurationChanged(
                 mTethering.getTetheringConfiguration().toStableParcelable());
         TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
@@ -1958,7 +2332,7 @@
         tetherState = callback2.pollTetherStatesChanged();
         assertArrayEquals(tetherState.availableList, new TetheringInterface[] {wifiIface});
         mLooper.dispatchAll();
-        callback2.expectUpstreamChanged(new Network[] {null});
+        callback2.expectUpstreamChanged(NULL_NETWORK);
         callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
         callback.assertNoCallback();
     }
@@ -2305,27 +2679,67 @@
     public void testUpstreamNetworkChanged() {
         final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
                 mTetheringDependencies.mUpstreamNetworkMonitorSM;
+        final InOrder inOrder = inOrder(mNotificationUpdater);
+
+        // Gain upstream.
         final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
         initTetheringUpstream(upstreamState);
         stateMachine.chooseUpstreamType(true);
+        mTetheringEventCallback.expectUpstreamChanged(upstreamState.network);
+        inOrder.verify(mNotificationUpdater)
+                .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
 
-        verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(eq(upstreamState.network));
-        verify(mNotificationUpdater, times(1)).onUpstreamCapabilitiesChanged(any());
+        // Set the upstream with the same network ID but different object and the same capability.
+        final UpstreamNetworkState upstreamState2 = buildMobileIPv4UpstreamState();
+        initTetheringUpstream(upstreamState2);
+        stateMachine.chooseUpstreamType(true);
+        // Bug: duplicated upstream change event.
+        mTetheringEventCallback.expectUpstreamChanged(upstreamState2.network);
+        inOrder.verify(mNotificationUpdater)
+                .onUpstreamCapabilitiesChanged(upstreamState2.networkCapabilities);
+
+        // Set the upstream with the same network ID but different object and different capability.
+        final UpstreamNetworkState upstreamState3 = buildMobileIPv4UpstreamState();
+        assertFalse(upstreamState3.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
+        upstreamState3.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
+        initTetheringUpstream(upstreamState3);
+        stateMachine.chooseUpstreamType(true);
+        // Bug: duplicated upstream change event.
+        mTetheringEventCallback.expectUpstreamChanged(upstreamState3.network);
+        inOrder.verify(mNotificationUpdater)
+                .onUpstreamCapabilitiesChanged(upstreamState3.networkCapabilities);
+
+        // Lose upstream.
+        initTetheringUpstream(null);
+        stateMachine.chooseUpstreamType(true);
+        mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
+        inOrder.verify(mNotificationUpdater).onUpstreamCapabilitiesChanged(null);
     }
 
     @Test
     public void testUpstreamCapabilitiesChanged() {
         final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
                 mTetheringDependencies.mUpstreamNetworkMonitorSM;
+        final InOrder inOrder = inOrder(mNotificationUpdater);
         final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
         initTetheringUpstream(upstreamState);
+
         stateMachine.chooseUpstreamType(true);
+        inOrder.verify(mNotificationUpdater)
+                .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
 
         stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
-        // Should have two onUpstreamCapabilitiesChanged().
-        // One is called by reportUpstreamChanged(). One is called by EVENT_ON_CAPABILITIES.
-        verify(mNotificationUpdater, times(2)).onUpstreamCapabilitiesChanged(any());
-        reset(mNotificationUpdater);
+        inOrder.verify(mNotificationUpdater)
+                .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
+
+        // Verify that onUpstreamCapabilitiesChanged is called if current upstream network
+        // capabilities changed.
+        // Expect that capability is changed with new capability VALIDATED.
+        assertFalse(upstreamState.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
+        upstreamState.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
+        stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
+        inOrder.verify(mNotificationUpdater)
+                .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
 
         // Verify that onUpstreamCapabilitiesChanged won't be called if not current upstream network
         // capabilities changed.
@@ -2333,7 +2747,28 @@
                 upstreamState.linkProperties, upstreamState.networkCapabilities,
                 new Network(WIFI_NETID));
         stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState2);
-        verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
+        inOrder.verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
+    }
+
+    @Test
+    public void testUpstreamCapabilitiesChanged_startStopTethering() throws Exception {
+        final TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+
+        // Start USB tethering with no current upstream.
+        prepareUsbTethering();
+        sendUsbBroadcast(true, true, TETHER_USB_RNDIS_FUNCTION);
+
+        // Pretend wifi connected and expect the upstream to be set.
+        wifi.fakeConnect();
+        mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+        mLooper.dispatchAll();
+        verify(mNotificationUpdater).onUpstreamCapabilitiesChanged(
+                wifi.networkCapabilities);
+
+        // Stop tethering.
+        // Expect that TetherModeAliveState#exit sends capabilities change notification to null.
+        runStopUSBTethering();
+        verify(mNotificationUpdater).onUpstreamCapabilitiesChanged(null);
     }
 
     @Test
diff --git a/bpf_progs/bpf_net_helpers.h b/bpf_progs/bpf_net_helpers.h
index c39269e..b7ca3af 100644
--- a/bpf_progs/bpf_net_helpers.h
+++ b/bpf_progs/bpf_net_helpers.h
@@ -21,6 +21,18 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+// bionic kernel uapi linux/udp.h header is munged...
+#define __kernel_udphdr udphdr
+#include <linux/udp.h>
+
+// Offsets from beginning of L4 (TCP/UDP) header
+#define TCP_OFFSET(field) offsetof(struct tcphdr, field)
+#define UDP_OFFSET(field) offsetof(struct udphdr, field)
+
+// Offsets from beginning of L3 (IPv4/IPv6) header
+#define IP4_OFFSET(field) offsetof(struct iphdr, field)
+#define IP6_OFFSET(field) offsetof(struct ipv6hdr, field)
+
 // this returns 0 iff skb->sk is NULL
 static uint64_t (*bpf_get_socket_cookie)(struct __sk_buff* skb) = (void*)BPF_FUNC_get_socket_cookie;
 
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..84da79d 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -46,8 +46,9 @@
 static const bool INGRESS = false;
 static const bool EGRESS = true;
 
-#define IP_PROTO_OFF offsetof(struct iphdr, protocol)
-#define IPV6_PROTO_OFF offsetof(struct ipv6hdr, nexthdr)
+// Used for 'bool enable_tracing'
+static const bool TRACE_ON = true;
+static const bool TRACE_OFF = false;
 
 // offsetof(struct iphdr, ihl) -- but that's a bitfield
 #define IPPROTO_IHL_OFF 0
@@ -60,14 +61,18 @@
 #define TCP_FLAG32_OFF 12
 
 // For maps netd does not need to access
-#define DEFINE_BPF_MAP_NO_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \
-    DEFINE_BPF_MAP_EXT(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, \
-                       AID_ROOT, AID_NET_BW_ACCT, 0060, "fs_bpf_net_shared", "", false)
+#define DEFINE_BPF_MAP_NO_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries)      \
+    DEFINE_BPF_MAP_EXT(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries,              \
+                       AID_ROOT, AID_NET_BW_ACCT, 0060, "fs_bpf_net_shared", "", false, \
+                       BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, /*ignore_on_eng*/false,       \
+                       /*ignore_on_user*/false, /*ignore_on_userdebug*/false)
 
 // For maps netd only needs read only access to
-#define DEFINE_BPF_MAP_RO_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \
-    DEFINE_BPF_MAP_EXT(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, \
-                       AID_ROOT, AID_NET_BW_ACCT, 0460, "fs_bpf_netd_readonly", "", false)
+#define DEFINE_BPF_MAP_RO_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries)         \
+    DEFINE_BPF_MAP_EXT(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries,                 \
+                       AID_ROOT, AID_NET_BW_ACCT, 0460, "fs_bpf_netd_readonly", "", false, \
+                       BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, /*ignore_on_eng*/false,       \
+                       /*ignore_on_user*/false, /*ignore_on_userdebug*/false)
 
 // For maps netd needs to be able to read and write
 #define DEFINE_BPF_MAP_RW_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \
@@ -95,6 +100,19 @@
 /* never actually used from ebpf */
 DEFINE_BPF_MAP_NO_NETD(iface_index_name_map, HASH, uint32_t, IfaceValue, IFACE_INDEX_NAME_MAP_SIZE)
 
+// A single-element configuration array, packet tracing is enabled when 'true'.
+DEFINE_BPF_MAP_EXT(packet_trace_enabled_map, ARRAY, uint32_t, bool, 1,
+                   AID_ROOT, AID_SYSTEM, 0060, "fs_bpf_net_shared", "", false,
+                   BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, /*ignore_on_eng*/false,
+                   /*ignore_on_user*/true, /*ignore_on_userdebug*/false)
+
+// A ring buffer on which packet information is pushed. This map will only be loaded
+// on eng and userdebug devices. User devices won't load this to save memory.
+DEFINE_BPF_RINGBUF_EXT(packet_trace_ringbuf, PacketTrace, PACKET_TRACE_BUF_SIZE,
+                       AID_ROOT, AID_SYSTEM, 0060, "fs_bpf_net_shared", "", false,
+                       BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, /*ignore_on_eng*/false,
+                       /*ignore_on_user*/true, /*ignore_on_userdebug*/false);
+
 // iptables xt_bpf programs need to be usable by both netd and netutils_wrappers
 // selinux contexts, because even non-xt_bpf iptables mutations are implemented as
 // a full table dump, followed by an update in userspace, and then a reload into the kernel,
@@ -109,8 +127,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 +139,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 +214,98 @@
 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 void do_packet_tracing(
+        const struct __sk_buff* const skb, const bool egress, const uint32_t uid,
+        const uint32_t tag, const bool enable_tracing, const unsigned kver) {
+    if (!enable_tracing) return;
+    if (kver < KVER(5, 8, 0)) return;
+
+    uint32_t mapKey = 0;
+    bool* traceConfig = bpf_packet_trace_enabled_map_lookup_elem(&mapKey);
+    if (traceConfig == NULL) return;
+    if (*traceConfig == false) return;
+
+    PacketTrace* pkt = bpf_packet_trace_ringbuf_reserve();
+    if (pkt == NULL) return;
+
+    // Errors from bpf_skb_load_bytes_net are ignored to favor returning something
+    // over returning nothing. In the event of an error, the kernel will fill in
+    // zero for the destination memory. Do not change the default '= 0' below.
+
+    uint8_t proto = 0;
+    uint8_t L4_off = 0;
+    uint8_t ipVersion = 0;
+    if (skb->protocol == htons(ETH_P_IP)) {
+        (void)bpf_skb_load_bytes_net(skb, IP4_OFFSET(protocol), &proto, sizeof(proto), kver);
+        (void)bpf_skb_load_bytes_net(skb, IPPROTO_IHL_OFF, &L4_off, sizeof(L4_off), kver);
+        L4_off = (L4_off & 0x0F) * 4;  // IHL calculation.
+        ipVersion = 4;
+    } else if (skb->protocol == htons(ETH_P_IPV6)) {
+        (void)bpf_skb_load_bytes_net(skb, IP6_OFFSET(nexthdr), &proto, sizeof(proto), kver);
+        L4_off = sizeof(struct ipv6hdr);
+        ipVersion = 6;
+    }
+
+    uint8_t flags = 0;
+    __be16 sport = 0, dport = 0;
+    if (proto == IPPROTO_TCP && L4_off >= 20) {
+        (void)bpf_skb_load_bytes_net(skb, L4_off + TCP_FLAG32_OFF + 1, &flags, sizeof(flags), kver);
+        (void)bpf_skb_load_bytes_net(skb, L4_off + TCP_OFFSET(source), &sport, sizeof(sport), kver);
+        (void)bpf_skb_load_bytes_net(skb, L4_off + TCP_OFFSET(dest), &dport, sizeof(dport), kver);
+    } else if (proto == IPPROTO_UDP && L4_off >= 20) {
+        (void)bpf_skb_load_bytes_net(skb, L4_off + UDP_OFFSET(source), &sport, sizeof(sport), kver);
+        (void)bpf_skb_load_bytes_net(skb, L4_off + UDP_OFFSET(dest), &dport, sizeof(dport), kver);
+    }
+
+    pkt->timestampNs = bpf_ktime_get_boot_ns();
+    pkt->ifindex = skb->ifindex;
+    pkt->length = skb->len;
+
+    pkt->uid = uid;
+    pkt->tag = tag;
+    pkt->sport = sport;
+    pkt->dport = dport;
+
+    pkt->egress = egress;
+    pkt->ipProto = proto;
+    pkt->tcpFlags = flags;
+    pkt->ipVersion = ipVersion;
+
+    bpf_packet_trace_ringbuf_submit(pkt);
+}
+
+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, IP4_OFFSET(protocol), &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 +314,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, IP6_OFFSET(nexthdr), &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 +349,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 +387,14 @@
                                                             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 bool enable_tracing,
+                                                      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 +414,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.
@@ -353,34 +453,51 @@
         key.tag = 0;
     }
 
+    do_packet_tracing(skb, egress, uid, tag, enable_tracing, kver);
     update_stats_with_config(skb, egress, &key, *selectedMap);
     update_app_uid_stats_map(skb, egress, &uid);
     asm("%0 &= 1" : "+r"(match));
     return match;
 }
 
+DEFINE_BPF_PROG_EXT("cgroupskb/ingress/stats$trace", AID_ROOT, AID_SYSTEM,
+                    bpf_cgroup_ingress_trace, KVER(5, 8, 0), KVER_INF,
+                    BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, false,
+                    "fs_bpf_netd_readonly", "", false, true, false)
+(struct __sk_buff* skb) {
+    return bpf_traffic_account(skb, INGRESS, TRACE_ON, KVER(5, 8, 0));
+}
+
 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, TRACE_OFF, 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, TRACE_OFF, KVER_NONE);
+}
+
+DEFINE_BPF_PROG_EXT("cgroupskb/egress/stats$trace", AID_ROOT, AID_SYSTEM,
+                    bpf_cgroup_egress_trace, KVER(5, 8, 0), KVER_INF,
+                    BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, false,
+                    "fs_bpf_netd_readonly", "", false, true, false)
+(struct __sk_buff* skb) {
+    return bpf_traffic_account(skb, EGRESS, TRACE_ON, KVER(5, 8, 0));
 }
 
 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, TRACE_OFF, 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, TRACE_OFF, KVER_NONE);
 }
 
 // WARNING: Android T's non-updatable netd depends on the name of this program.
diff --git a/bpf_progs/netd.h b/bpf_progs/netd.h
index cc88680..be604f9 100644
--- a/bpf_progs/netd.h
+++ b/bpf_progs/netd.h
@@ -69,6 +69,24 @@
     uint64_t tcpTxPackets;
 } Stats;
 
+typedef struct {
+  uint64_t timestampNs;
+  uint32_t ifindex;
+  uint32_t length;
+
+  uint32_t uid;
+  uint32_t tag;
+
+  __be16 sport;
+  __be16 dport;
+
+  bool egress;
+  uint8_t ipProto;
+  uint8_t tcpFlags;
+  uint8_t ipVersion; // 4=IPv4, 6=IPv6, 0=unknown
+} PacketTrace;
+STRUCT_SIZE(PacketTrace, 8+4+4 + 4+4 + 2+2 + 1+1+1+1);
+
 // Since we cannot garbage collect the stats map since device boot, we need to make these maps as
 // large as possible. The maximum size of number of map entries we can have is depend on the rlimit
 // of MEM_LOCK granted to netd. The memory space needed by each map can be calculated by the
@@ -87,7 +105,8 @@
 // dozable_uid_map:     key:  4 bytes, value:  1 bytes, cost:  145216 bytes    =   145Kbytes
 // standby_uid_map:     key:  4 bytes, value:  1 bytes, cost:  145216 bytes    =   145Kbytes
 // powersave_uid_map:   key:  4 bytes, value:  1 bytes, cost:  145216 bytes    =   145Kbytes
-// total:                                                                         4930Kbytes
+// packet_trace_ringbuf:key:  0 bytes, value: 24 bytes, cost:   32768 bytes    =    32Kbytes
+// total:                                                                         4962Kbytes
 // It takes maximum 4.9MB kernel memory space if all maps are full, which requires any devices
 // running this module to have a memlock rlimit to be larger then 5MB. In the old qtaguid module,
 // we don't have a total limit for data entries but only have limitation of tags each uid can have.
@@ -102,6 +121,7 @@
 static const int IFACE_STATS_MAP_SIZE = 1000;
 static const int CONFIGURATION_MAP_SIZE = 2;
 static const int UID_OWNER_MAP_SIZE = 4000;
+static const int PACKET_TRACE_BUF_SIZE = 32 * 1024;
 
 #ifdef __cplusplus
 
@@ -145,6 +165,8 @@
 #define CONFIGURATION_MAP_PATH BPF_NETD_PATH "map_netd_configuration_map"
 #define UID_OWNER_MAP_PATH BPF_NETD_PATH "map_netd_uid_owner_map"
 #define UID_PERMISSION_MAP_PATH BPF_NETD_PATH "map_netd_uid_permission_map"
+#define PACKET_TRACE_RINGBUF_PATH BPF_NETD_PATH "map_netd_packet_trace_ringbuf"
+#define PACKET_TRACE_ENABLED_MAP_PATH BPF_NETD_PATH "map_netd_packet_trace_enabled_map"
 
 #endif // __cplusplus
 
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index d40fad9..7ef20c5 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -164,6 +164,7 @@
     ],
 }
 
+// This rule is not used anymore(b/268440216).
 platform_compat_config {
     name: "connectivity-t-platform-compat-config",
     src: ":framework-connectivity-t",
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
index eb77288..86745d4 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -192,15 +192,20 @@
     method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void discoverServices(@NonNull String, int, @NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.nsd.NsdManager.DiscoveryListener);
     method public void registerService(android.net.nsd.NsdServiceInfo, int, android.net.nsd.NsdManager.RegistrationListener);
     method public void registerService(@NonNull android.net.nsd.NsdServiceInfo, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.nsd.NsdManager.RegistrationListener);
-    method public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener);
-    method public void resolveService(@NonNull android.net.nsd.NsdServiceInfo, @NonNull java.util.concurrent.Executor, @NonNull android.net.nsd.NsdManager.ResolveListener);
+    method public void registerServiceInfoCallback(@NonNull android.net.nsd.NsdServiceInfo, @NonNull java.util.concurrent.Executor, @NonNull android.net.nsd.NsdManager.ServiceInfoCallback);
+    method @Deprecated public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener);
+    method @Deprecated public void resolveService(@NonNull android.net.nsd.NsdServiceInfo, @NonNull java.util.concurrent.Executor, @NonNull android.net.nsd.NsdManager.ResolveListener);
     method public void stopServiceDiscovery(android.net.nsd.NsdManager.DiscoveryListener);
+    method public void stopServiceResolution(@NonNull android.net.nsd.NsdManager.ResolveListener);
     method public void unregisterService(android.net.nsd.NsdManager.RegistrationListener);
+    method public void unregisterServiceInfoCallback(@NonNull android.net.nsd.NsdManager.ServiceInfoCallback);
     field public static final String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
     field public static final String EXTRA_NSD_STATE = "nsd_state";
     field public static final int FAILURE_ALREADY_ACTIVE = 3; // 0x3
+    field public static final int FAILURE_BAD_PARAMETERS = 6; // 0x6
     field public static final int FAILURE_INTERNAL_ERROR = 0; // 0x0
     field public static final int FAILURE_MAX_LIMIT = 4; // 0x4
+    field public static final int FAILURE_OPERATION_NOT_RUNNING = 5; // 0x5
     field public static final int NSD_STATE_DISABLED = 1; // 0x1
     field public static final int NSD_STATE_ENABLED = 2; // 0x2
     field public static final int PROTOCOL_DNS_SD = 1; // 0x1
@@ -223,22 +228,33 @@
   }
 
   public static interface NsdManager.ResolveListener {
+    method public default void onResolutionStopped(@NonNull android.net.nsd.NsdServiceInfo);
     method public void onResolveFailed(android.net.nsd.NsdServiceInfo, int);
     method public void onServiceResolved(android.net.nsd.NsdServiceInfo);
+    method public default void onStopResolutionFailed(@NonNull android.net.nsd.NsdServiceInfo, int);
+  }
+
+  public static interface NsdManager.ServiceInfoCallback {
+    method public void onServiceInfoCallbackRegistrationFailed(int);
+    method public void onServiceInfoCallbackUnregistered();
+    method public void onServiceLost();
+    method public void onServiceUpdated(@NonNull android.net.nsd.NsdServiceInfo);
   }
 
   public final class NsdServiceInfo implements android.os.Parcelable {
     ctor public NsdServiceInfo();
     method public int describeContents();
     method public java.util.Map<java.lang.String,byte[]> getAttributes();
-    method public java.net.InetAddress getHost();
+    method @Deprecated public java.net.InetAddress getHost();
+    method @NonNull public java.util.List<java.net.InetAddress> getHostAddresses();
     method @Nullable public android.net.Network getNetwork();
     method public int getPort();
     method public String getServiceName();
     method public String getServiceType();
     method public void removeAttribute(String);
     method public void setAttribute(String, String);
-    method public void setHost(java.net.InetAddress);
+    method @Deprecated public void setHost(java.net.InetAddress);
+    method public void setHostAddresses(@NonNull java.util.List<java.net.InetAddress>);
     method public void setNetwork(@Nullable android.net.Network);
     method public void setPort(int);
     method public void setServiceName(String);
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..3afa6ef 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.
      *
@@ -254,7 +273,7 @@
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
-            mCloseGuard.open("open");
+            mCloseGuard.open("close");
         }
 
         /** @hide */
@@ -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/IpSecTransform.java b/framework-t/src/android/net/IpSecTransform.java
index 68ae5de..c236b6c 100644
--- a/framework-t/src/android/net/IpSecTransform.java
+++ b/framework-t/src/android/net/IpSecTransform.java
@@ -126,7 +126,7 @@
                 checkResultStatus(status);
                 mResourceId = result.resourceId;
                 Log.d(TAG, "Added Transform with Id " + mResourceId);
-                mCloseGuard.open("build");
+                mCloseGuard.open("close");
             } catch (ServiceSpecificException e) {
                 throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e);
             }
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index c0ae822..4a1632b 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -48,11 +48,11 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
+import android.util.Log;
 
 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;
@@ -71,6 +71,8 @@
  */
 @SystemApi(client = MODULE_LIBRARIES)
 public final class NetworkTemplate implements Parcelable {
+    private static final String TAG = NetworkTemplate.class.getSimpleName();
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "MATCH_" }, value = {
@@ -89,18 +91,6 @@
     public static final int MATCH_WIFI = 4;
     /** Match rule to match ethernet networks. */
     public static final int MATCH_ETHERNET = 5;
-    /**
-     * Match rule to match all cellular networks.
-     *
-     * @hide
-     */
-    public static final int MATCH_MOBILE_WILDCARD = 6;
-    /**
-     * Match rule to match all wifi networks.
-     *
-     * @hide
-     */
-    public static final int MATCH_WIFI_WILDCARD = 7;
     /** Match rule to match bluetooth networks. */
     public static final int MATCH_BLUETOOTH = 8;
     /**
@@ -178,8 +168,6 @@
             case MATCH_MOBILE:
             case MATCH_WIFI:
             case MATCH_ETHERNET:
-            case MATCH_MOBILE_WILDCARD:
-            case MATCH_WIFI_WILDCARD:
             case MATCH_BLUETOOTH:
             case MATCH_PROXY:
             case MATCH_CARRIER:
@@ -259,7 +247,6 @@
     }
 
     private final int mMatchRule;
-    private final String mSubscriberId;
 
     /**
      * Ugh, templates are designed to target a single subscriber, but we might
@@ -280,23 +267,25 @@
     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:
+            // CARRIER templates must always specify a valid subscriber ID.
+            // MOBILE templates can have empty matchSubscriberIds but it must not contain a null
+            // subscriber ID.
             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));
+                }
+                // fall through
+            case MATCH_MOBILE:
+                if (CollectionUtils.contains(matchSubscriberIds, null)) {
+                    throw new IllegalArgumentException("checkValidMatchSubscriberIds list of ids"
+                            + " may not contain null for rule " + getMatchRuleName(matchRule));
                 }
                 return;
             default:
@@ -312,32 +301,48 @@
     @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,
+        // constructor passes METERED_YES for these types.
+        // For backwards compatibility, still accept old wildcard match rules (6 and 7 for
+        // MATCH_{MOBILE,WIFI}_WILDCARD) but convert into functionally equivalent non-wildcard
+        // ones.
+        this(getBackwardsCompatibleMatchRule(matchRule),
+                subscriberId != null ? new String[] { subscriberId } : new String[0],
                 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);
+                getMeterednessForBackwardsCompatibility(matchRule), ROAMING_ALL,
+                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
+        if (matchRule == 6 || matchRule == 7) {
+            Log.e(TAG, "Use MATCH_MOBILE with empty subscriberIds or MATCH_WIFI with empty "
+                    + "wifiNetworkKeys instead of template with matchRule=" + matchRule);
+        }
+    }
+
+    private static int getBackwardsCompatibleMatchRule(int matchRule) {
+        // Backwards compatibility old constants
+        // Old MATCH_MOBILE_WILDCARD
+        if (6 == matchRule) return MATCH_MOBILE;
+        // Old MATCH_WIFI_WILDCARD
+        if (7 == matchRule) return MATCH_WIFI;
+        return matchRule;
+    }
+
+    private static int getMeterednessForBackwardsCompatibility(int matchRule) {
+        if (getBackwardsCompatibleMatchRule(matchRule) == MATCH_MOBILE
+                || matchRule == MATCH_CARRIER) {
+            return METERED_YES;
+        }
+        return METERED_ALL;
     }
 
     /** @hide */
-    public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
-            String[] matchWifiNetworkKeys, int metered, int roaming,
-            int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) {
+    public NetworkTemplate(int matchRule, String[] matchSubscriberIds,
+            String[] matchWifiNetworkKeys, int metered, int roaming, int defaultNetwork,
+            int ratType, int oemManaged) {
         Objects.requireNonNull(matchWifiNetworkKeys);
         Objects.requireNonNull(matchSubscriberIds);
         mMatchRule = matchRule;
-        mSubscriberId = subscriberId;
         mMatchSubscriberIds = matchSubscriberIds;
         mMatchWifiNetworkKeys = matchWifiNetworkKeys;
         mMetered = metered;
@@ -345,8 +350,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.");
@@ -355,7 +359,6 @@
 
     private NetworkTemplate(Parcel in) {
         mMatchRule = in.readInt();
-        mSubscriberId = in.readString();
         mMatchSubscriberIds = in.createStringArray();
         mMatchWifiNetworkKeys = in.createStringArray();
         mMetered = in.readInt();
@@ -363,13 +366,11 @@
         mDefaultNetwork = in.readInt();
         mRatType = in.readInt();
         mOemManaged = in.readInt();
-        mSubscriberIdMatchRule = in.readInt();
     }
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mMatchRule);
-        dest.writeString(mSubscriberId);
         dest.writeStringArray(mMatchSubscriberIds);
         dest.writeStringArray(mMatchWifiNetworkKeys);
         dest.writeInt(mMetered);
@@ -377,7 +378,6 @@
         dest.writeInt(mDefaultNetwork);
         dest.writeInt(mRatType);
         dest.writeInt(mOemManaged);
-        dest.writeInt(mSubscriberIdMatchRule);
     }
 
     @Override
@@ -389,10 +389,6 @@
     public String toString() {
         final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
         builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
-        if (mSubscriberId != null) {
-            builder.append(", subscriberId=").append(
-                    NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
-        }
         if (mMatchSubscriberIds != null) {
             builder.append(", matchSubscriberIds=").append(
                     Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds)));
@@ -414,15 +410,14 @@
         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);
+        return Objects.hash(mMatchRule, Arrays.hashCode(mMatchSubscriberIds),
+                Arrays.hashCode(mMatchWifiNetworkKeys), mMetered, mRoaming, mDefaultNetwork,
+                mRatType, mOemManaged);
     }
 
     @Override
@@ -430,34 +425,24 @@
         if (obj instanceof NetworkTemplate) {
             final NetworkTemplate other = (NetworkTemplate) obj;
             return mMatchRule == other.mMatchRule
-                    && Objects.equals(mSubscriberId, other.mSubscriberId)
                     && mMetered == other.mMetered
                     && mRoaming == other.mRoaming
                     && mDefaultNetwork == other.mDefaultNetwork
                     && mRatType == other.mRatType
                     && mOemManaged == other.mOemManaged
-                    && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
+                    && Arrays.equals(mMatchSubscriberIds, other.mMatchSubscriberIds)
                     && 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;
-        }
-    }
-
+    // TODO(b/270089918): Remove this method after no callers.
     /** @hide */
     public boolean isMatchRuleMobile() {
         switch (mMatchRule) {
             case MATCH_MOBILE:
-            case MATCH_MOBILE_WILDCARD:
+            // Old MATCH_MOBILE_WILDCARD
+            case 6:
                 return true;
             default:
                 return false;
@@ -467,28 +452,22 @@
     /**
      * Get match rule of the template. See {@code MATCH_*}.
      */
-    @UnsupportedAppUsage
     public int getMatchRule() {
-        // Wildcard rules are not exposed. For external callers, convert wildcard rules to
-        // exposed rules before returning.
-        switch (mMatchRule) {
-            case MATCH_MOBILE_WILDCARD:
-                return MATCH_MOBILE;
-            case MATCH_WIFI_WILDCARD:
-                return MATCH_WIFI;
-            default:
-                return mMatchRule;
-        }
+        return mMatchRule;
     }
 
     /**
      * Get subscriber Id of the template.
+     *
+     * @deprecated User should use {@link #getSubscriberIds} instead.
      * @hide
      */
+    @Deprecated
     @Nullable
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.TIRAMISU,
+            publicAlternatives = "Caller should use {@code getSubscriberIds} instead.")
     public String getSubscriberId() {
-        return mSubscriberId;
+        return CollectionUtils.isEmpty(mMatchSubscriberIds) ? null : mMatchSubscriberIds[0];
     }
 
     /**
@@ -575,10 +554,6 @@
                 return matchesWifi(ident);
             case MATCH_ETHERNET:
                 return matchesEthernet(ident);
-            case MATCH_MOBILE_WILDCARD:
-                return matchesMobileWildcard(ident);
-            case MATCH_WIFI_WILDCARD:
-                return matchesWifiWildcard(ident);
             case MATCH_BLUETOOTH:
                 return matchesBluetooth(ident);
             case MATCH_PROXY:
@@ -627,13 +602,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);
     }
 
@@ -659,9 +634,9 @@
             // TODO: consider matching against WiMAX subscriber identity
             return true;
         } else {
-            return ident.mType == TYPE_MOBILE && !CollectionUtils.isEmpty(mMatchSubscriberIds)
-                    && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
-                    && matchesCollapsedRatType(ident);
+            return (CollectionUtils.isEmpty(mMatchSubscriberIds)
+                || CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId))
+                && (ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident));
         }
     }
 
@@ -673,6 +648,8 @@
             case TYPE_WIFI:
                 return matchesSubscriberId(ident.mSubscriberId)
                         && matchesWifiNetworkKey(ident.mWifiNetworkKey);
+            case TYPE_WIFI_P2P:
+                return CollectionUtils.isEmpty(mMatchWifiNetworkKeys);
             default:
                 return false;
         }
@@ -708,24 +685,6 @@
                 || CollectionUtils.contains(mMatchWifiNetworkKeys, ident.mWifiNetworkKey)));
     }
 
-    private boolean matchesMobileWildcard(NetworkIdentity ident) {
-        if (ident.mType == TYPE_WIMAX) {
-            return true;
-        } else {
-            return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident);
-        }
-    }
-
-    private boolean matchesWifiWildcard(NetworkIdentity ident) {
-        switch (ident.mType) {
-            case TYPE_WIFI:
-            case TYPE_WIFI_P2P:
-                return true;
-            default:
-                return false;
-        }
-    }
-
     /**
      * Check if matches Bluetooth network template.
      */
@@ -751,10 +710,6 @@
                 return "WIFI";
             case MATCH_ETHERNET:
                 return "ETHERNET";
-            case MATCH_MOBILE_WILDCARD:
-                return "MOBILE_WILDCARD";
-            case MATCH_WIFI_WILDCARD:
-                return "WIFI_WILDCARD";
             case MATCH_BLUETOOTH:
                 return "BLUETOOTH";
             case MATCH_PROXY:
@@ -802,17 +757,21 @@
         // information. For instances:
         // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network.
         // The TYPE_CARRIER means that the network associate to specific carrier network.
-        if (template.mSubscriberId == null) return template;
 
-        if (CollectionUtils.contains(merged, template.mSubscriberId)) {
+        if (CollectionUtils.isEmpty(template.mMatchSubscriberIds)) return template;
+
+        if (CollectionUtils.contains(merged, template.mMatchSubscriberIds[0])) {
             // Requested template subscriber is part of the merge group; return
             // a template that matches all merged subscribers.
             final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys;
             // TODO: Use NetworkTemplate.Builder to build a template after NetworkTemplate
             // could handle incompatible subscriberIds. See b/217805241.
-            return new NetworkTemplate(template.mMatchRule, merged[0], merged,
+            return new NetworkTemplate(template.mMatchRule, merged,
                     CollectionUtils.isEmpty(matchWifiNetworkKeys)
-                            ? null : matchWifiNetworkKeys[0]);
+                            ? new String[0] : new String[] { matchWifiNetworkKeys[0] },
+                    (template.mMatchRule == MATCH_MOBILE || template.mMatchRule == MATCH_CARRIER)
+                            ? METERED_YES : METERED_ALL,
+                    ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
         }
 
         return template;
@@ -979,10 +938,7 @@
          * @param matchRule the target match rule to be checked.
          */
         private static void assertRequestableMatchRule(final int matchRule) {
-            if (!isKnownMatchRule(matchRule)
-                    || matchRule == MATCH_PROXY
-                    || matchRule == MATCH_MOBILE_WILDCARD
-                    || matchRule == MATCH_WIFI_WILDCARD) {
+            if (!isKnownMatchRule(matchRule) || matchRule == MATCH_PROXY) {
                 throw new IllegalArgumentException("Invalid match rule: "
                         + getMatchRuleName(matchRule));
             }
@@ -1003,20 +959,6 @@
         }
 
         /**
-         * For backward compatibility, deduce match rule to a wildcard match rule
-         * if the Subscriber Ids are empty.
-         */
-        private int getWildcardDeducedMatchRule() {
-            if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) {
-                return MATCH_MOBILE_WILDCARD;
-            } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty()
-                    && mMatchWifiNetworkKeys.isEmpty()) {
-                return MATCH_WIFI_WILDCARD;
-            }
-            return mMatchRule;
-        }
-
-        /**
          * Builds the instance of the NetworkTemplate.
          *
          * @return the built instance of NetworkTemplate.
@@ -1024,14 +966,10 @@
         @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(),
+            return new NetworkTemplate(mMatchRule,
                     mMatchSubscriberIds.toArray(new String[0]),
                     mMatchWifiNetworkKeys.toArray(new String[0]), mMetered, mRoaming,
-                    mDefaultNetwork, mRatType, mOemManaged, subscriberIdMatchRule);
+                    mDefaultNetwork, mRatType, mOemManaged);
         }
     }
 }
diff --git a/framework-t/src/android/net/nsd/INsdManagerCallback.aidl b/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
index 1a262ec..d89bfa9 100644
--- a/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
+++ b/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
@@ -36,4 +36,10 @@
     void onUnregisterServiceSucceeded(int listenerKey);
     void onResolveServiceFailed(int listenerKey, int error);
     void onResolveServiceSucceeded(int listenerKey, in NsdServiceInfo info);
+    void onStopResolutionFailed(int listenerKey, int error);
+    void onStopResolutionSucceeded(int listenerKey);
+    void onServiceInfoCallbackRegistrationFailed(int listenerKey, int error);
+    void onServiceUpdated(int listenerKey, in NsdServiceInfo info);
+    void onServiceUpdatedLost(int listenerKey);
+    void onServiceInfoCallbackUnregistered(int listenerKey);
 }
diff --git a/framework-t/src/android/net/nsd/INsdServiceConnector.aidl b/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
index b06ae55..5533154 100644
--- a/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
+++ b/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
@@ -32,4 +32,7 @@
     void stopDiscovery(int listenerKey);
     void resolveService(int listenerKey, in NsdServiceInfo serviceInfo);
     void startDaemon();
+    void stopResolution(int listenerKey);
+    void registerServiceInfoCallback(int listenerKey, in NsdServiceInfo serviceInfo);
+    void unregisterServiceInfoCallback(int listenerKey);
 }
\ No newline at end of file
diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java
index fb3b1d6..b4f8897 100644
--- a/framework-t/src/android/net/nsd/NsdManager.java
+++ b/framework-t/src/android/net/nsd/NsdManager.java
@@ -16,6 +16,9 @@
 
 package android.net.nsd;
 
+import static android.net.connectivity.ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER;
+
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -23,8 +26,6 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
 import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
@@ -44,6 +45,8 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 
@@ -134,28 +137,6 @@
     private static final boolean DBG = false;
 
     /**
-     * When enabled, apps targeting < Android 12 are considered legacy for
-     * the NSD native daemon.
-     * The platform will only keep the daemon running as long as there are
-     * any legacy apps connected.
-     *
-     * After Android 12, direct communication with the native daemon might not work since the native
-     * daemon won't always stay alive. Using the NSD APIs from NsdManager as the replacement is
-     * recommended.
-     * Another alternative could be bundling your own mdns solutions instead of
-     * depending on the system mdns native daemon.
-     *
-     * This compatibility change applies to Android 13 and later only. To toggle behavior on
-     * Android 12 and Android 12L, use RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS.
-     *
-     * @hide
-     */
-    @ChangeId
-    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
-    // This was a platform change ID with value 191844585L before T
-    public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER = 235355681L;
-
-    /**
      * Broadcast intent action to indicate whether network service discovery is
      * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state
      * information as int.
@@ -230,7 +211,6 @@
 
     /** @hide */
     public static final int DAEMON_CLEANUP                          = 18;
-
     /** @hide */
     public static final int DAEMON_STARTUP                          = 19;
 
@@ -242,6 +222,30 @@
     /** @hide */
     public static final int UNREGISTER_CLIENT                       = 22;
 
+    /** @hide */
+    public static final int MDNS_DISCOVERY_MANAGER_EVENT            = 23;
+
+    /** @hide */
+    public static final int STOP_RESOLUTION                         = 24;
+    /** @hide */
+    public static final int STOP_RESOLUTION_FAILED                  = 25;
+    /** @hide */
+    public static final int STOP_RESOLUTION_SUCCEEDED               = 26;
+
+    /** @hide */
+    public static final int REGISTER_SERVICE_CALLBACK               = 27;
+    /** @hide */
+    public static final int REGISTER_SERVICE_CALLBACK_FAILED        = 28;
+    /** @hide */
+    public static final int SERVICE_UPDATED                         = 29;
+    /** @hide */
+    public static final int SERVICE_UPDATED_LOST                    = 30;
+
+    /** @hide */
+    public static final int UNREGISTER_SERVICE_CALLBACK             = 31;
+    /** @hide */
+    public static final int UNREGISTER_SERVICE_CALLBACK_SUCCEEDED   = 32;
+
     /** Dns based service discovery protocol */
     public static final int PROTOCOL_DNS_SD = 0x0001;
 
@@ -267,6 +271,15 @@
         EVENT_NAMES.put(DAEMON_CLEANUP, "DAEMON_CLEANUP");
         EVENT_NAMES.put(DAEMON_STARTUP, "DAEMON_STARTUP");
         EVENT_NAMES.put(MDNS_SERVICE_EVENT, "MDNS_SERVICE_EVENT");
+        EVENT_NAMES.put(STOP_RESOLUTION, "STOP_RESOLUTION");
+        EVENT_NAMES.put(STOP_RESOLUTION_FAILED, "STOP_RESOLUTION_FAILED");
+        EVENT_NAMES.put(STOP_RESOLUTION_SUCCEEDED, "STOP_RESOLUTION_SUCCEEDED");
+        EVENT_NAMES.put(REGISTER_SERVICE_CALLBACK, "REGISTER_SERVICE_CALLBACK");
+        EVENT_NAMES.put(REGISTER_SERVICE_CALLBACK_FAILED, "REGISTER_SERVICE_CALLBACK_FAILED");
+        EVENT_NAMES.put(SERVICE_UPDATED, "SERVICE_UPDATED");
+        EVENT_NAMES.put(UNREGISTER_SERVICE_CALLBACK, "UNREGISTER_SERVICE_CALLBACK");
+        EVENT_NAMES.put(UNREGISTER_SERVICE_CALLBACK_SUCCEEDED,
+                "UNREGISTER_SERVICE_CALLBACK_SUCCEEDED");
     }
 
     /** @hide */
@@ -592,6 +605,36 @@
         public void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
             sendInfo(RESOLVE_SERVICE_SUCCEEDED, listenerKey, info);
         }
+
+        @Override
+        public void onStopResolutionFailed(int listenerKey, int error) {
+            sendError(STOP_RESOLUTION_FAILED, listenerKey, error);
+        }
+
+        @Override
+        public void onStopResolutionSucceeded(int listenerKey) {
+            sendNoArg(STOP_RESOLUTION_SUCCEEDED, listenerKey);
+        }
+
+        @Override
+        public void onServiceInfoCallbackRegistrationFailed(int listenerKey, int error) {
+            sendError(REGISTER_SERVICE_CALLBACK_FAILED, listenerKey, error);
+        }
+
+        @Override
+        public void onServiceUpdated(int listenerKey, NsdServiceInfo info) {
+            sendInfo(SERVICE_UPDATED, listenerKey, info);
+        }
+
+        @Override
+        public void onServiceUpdatedLost(int listenerKey) {
+            sendNoArg(SERVICE_UPDATED_LOST, listenerKey);
+        }
+
+        @Override
+        public void onServiceInfoCallbackUnregistered(int listenerKey) {
+            sendNoArg(UNREGISTER_SERVICE_CALLBACK_SUCCEEDED, listenerKey);
+        }
     }
 
     /**
@@ -615,6 +658,37 @@
      */
     public static final int FAILURE_MAX_LIMIT                   = 4;
 
+    /**
+     * Indicates that the stop operation failed because it is not running.
+     * This failure is passed with {@link ResolveListener#onStopResolutionFailed}.
+     */
+    public static final int FAILURE_OPERATION_NOT_RUNNING       = 5;
+
+    /**
+     * Indicates that the service has failed to resolve because of bad parameters.
+     *
+     * This failure is passed with
+     * {@link ServiceInfoCallback#onServiceInfoCallbackRegistrationFailed}.
+     */
+    public static final int FAILURE_BAD_PARAMETERS              = 6;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            FAILURE_OPERATION_NOT_RUNNING,
+    })
+    public @interface StopOperationFailureCode {
+    }
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            FAILURE_ALREADY_ACTIVE,
+            FAILURE_BAD_PARAMETERS,
+    })
+    public @interface ResolutionFailureCode {
+    }
+
     /** Interface for callback invocation for service discovery */
     public interface DiscoveryListener {
 
@@ -643,12 +717,97 @@
         public void onServiceUnregistered(NsdServiceInfo serviceInfo);
     }
 
-    /** Interface for callback invocation for service resolution */
+    /**
+     * Callback for use with {@link NsdManager#resolveService} to resolve the service info and use
+     * with {@link NsdManager#stopServiceResolution} to stop resolution.
+     */
     public interface ResolveListener {
 
-        public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode);
+        /**
+         * Called on the internal thread or with an executor passed to
+         * {@link NsdManager#resolveService} to report the resolution was failed with an error.
+         *
+         * A resolution operation would call either onServiceResolved or onResolveFailed once based
+         * on the result.
+         */
+        void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode);
 
-        public void onServiceResolved(NsdServiceInfo serviceInfo);
+        /**
+         * Called on the internal thread or with an executor passed to
+         * {@link NsdManager#resolveService} to report the resolved service info.
+         *
+         * A resolution operation would call either onServiceResolved or onResolveFailed once based
+         * on the result.
+         */
+        void onServiceResolved(NsdServiceInfo serviceInfo);
+
+        /**
+         * Called on the internal thread or with an executor passed to
+         * {@link NsdManager#resolveService} to report the resolution was stopped.
+         *
+         * A stop resolution operation would call either onResolutionStopped or
+         * onStopResolutionFailed once based on the result.
+         */
+        default void onResolutionStopped(@NonNull NsdServiceInfo serviceInfo) { }
+
+        /**
+         * Called once on the internal thread or with an executor passed to
+         * {@link NsdManager#resolveService} to report that stopping resolution failed with an
+         * error.
+         *
+         * A stop resolution operation would call either onResolutionStopped or
+         * onStopResolutionFailed once based on the result.
+         */
+        default void onStopResolutionFailed(@NonNull NsdServiceInfo serviceInfo,
+                @StopOperationFailureCode int errorCode) { }
+    }
+
+    /**
+     * Callback to listen to service info updates.
+     *
+     * For use with {@link NsdManager#registerServiceInfoCallback} to register, and with
+     * {@link NsdManager#unregisterServiceInfoCallback} to stop listening.
+     */
+    public interface ServiceInfoCallback {
+
+        /**
+         * Reports that registering the callback failed with an error.
+         *
+         * Called on the executor passed to {@link NsdManager#registerServiceInfoCallback}.
+         *
+         * onServiceInfoCallbackRegistrationFailed will be called exactly once when the callback
+         * could not be registered. No other callback will be sent in that case.
+         */
+        void onServiceInfoCallbackRegistrationFailed(@ResolutionFailureCode int errorCode);
+
+        /**
+         * Reports updated service info.
+         *
+         * Called on the executor passed to {@link NsdManager#registerServiceInfoCallback}. Any
+         * service updates will be notified via this callback until
+         * {@link NsdManager#unregisterServiceInfoCallback} is called. This will only be called once
+         * the service is found, so may never be called if the service is never present.
+         */
+        void onServiceUpdated(@NonNull NsdServiceInfo serviceInfo);
+
+        /**
+         * Reports when the service that this callback listens to becomes unavailable.
+         *
+         * Called on the executor passed to {@link NsdManager#registerServiceInfoCallback}. The
+         * service may become available again, in which case {@link #onServiceUpdated} will be
+         * called.
+         */
+        void onServiceLost();
+
+        /**
+         * Reports that service info updates have stopped.
+         *
+         * Called on the executor passed to {@link NsdManager#registerServiceInfoCallback}.
+         *
+         * A callback unregistration operation will call onServiceInfoCallbackUnregistered
+         * once. After this, the callback may be reused.
+         */
+        void onServiceInfoCallbackUnregistered();
     }
 
     @VisibleForTesting
@@ -741,6 +900,33 @@
                     executor.execute(() -> ((ResolveListener) listener).onServiceResolved(
                             (NsdServiceInfo) obj));
                     break;
+                case STOP_RESOLUTION_FAILED:
+                    removeListener(key);
+                    executor.execute(() -> ((ResolveListener) listener).onStopResolutionFailed(
+                            ns, errorCode));
+                    break;
+                case STOP_RESOLUTION_SUCCEEDED:
+                    removeListener(key);
+                    executor.execute(() -> ((ResolveListener) listener).onResolutionStopped(
+                            ns));
+                    break;
+                case REGISTER_SERVICE_CALLBACK_FAILED:
+                    removeListener(key);
+                    executor.execute(() -> ((ServiceInfoCallback) listener)
+                            .onServiceInfoCallbackRegistrationFailed(errorCode));
+                    break;
+                case SERVICE_UPDATED:
+                    executor.execute(() -> ((ServiceInfoCallback) listener)
+                            .onServiceUpdated((NsdServiceInfo) obj));
+                    break;
+                case SERVICE_UPDATED_LOST:
+                    executor.execute(() -> ((ServiceInfoCallback) listener).onServiceLost());
+                    break;
+                case UNREGISTER_SERVICE_CALLBACK_SUCCEEDED:
+                    removeListener(key);
+                    executor.execute(() -> ((ServiceInfoCallback) listener)
+                            .onServiceInfoCallbackUnregistered());
+                    break;
                 default:
                     Log.d(TAG, "Ignored " + message);
                     break;
@@ -1052,7 +1238,14 @@
      * @param serviceInfo service to be resolved
      * @param listener to receive callback upon success or failure. Cannot be null.
      * Cannot be in use for an active service resolution.
+     *
+     * @deprecated the returned ServiceInfo may get stale at any time after resolution, including
+     * immediately after the callback is called, and may not contain some service information that
+     * could be delivered later, like additional host addresses. Prefer using
+     * {@link #registerServiceInfoCallback}, which will keep the application up-to-date with the
+     * state of the service.
      */
+    @Deprecated
     public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
         resolveService(serviceInfo, Runnable::run, listener);
     }
@@ -1064,7 +1257,14 @@
      * @param serviceInfo service to be resolved
      * @param executor Executor to run listener callbacks with
      * @param listener to receive callback upon success or failure.
+     *
+     * @deprecated the returned ServiceInfo may get stale at any time after resolution, including
+     * immediately after the callback is called, and may not contain some service information that
+     * could be delivered later, like additional host addresses. Prefer using
+     * {@link #registerServiceInfoCallback}, which will keep the application up-to-date with the
+     * state of the service.
      */
+    @Deprecated
     public void resolveService(@NonNull NsdServiceInfo serviceInfo,
             @NonNull Executor executor, @NonNull ResolveListener listener) {
         checkServiceInfo(serviceInfo);
@@ -1076,6 +1276,85 @@
         }
     }
 
+    /**
+     * Stop service resolution initiated with {@link #resolveService}.
+     *
+     * A successful stop is notified with a call to {@link ResolveListener#onResolutionStopped}.
+     *
+     * <p> Upon failure to stop service resolution for example if resolution is done or the
+     * requester stops resolution repeatedly, the application is notified
+     * {@link ResolveListener#onStopResolutionFailed} with {@link #FAILURE_OPERATION_NOT_RUNNING}
+     *
+     * @param listener This should be a listener object that was passed to {@link #resolveService}.
+     *                 It identifies the resolution that should be stopped and notifies of a
+     *                 successful or unsuccessful stop. Throws {@code IllegalArgumentException} if
+     *                 the listener was not passed to resolveService before.
+     */
+    public void stopServiceResolution(@NonNull ResolveListener listener) {
+        int id = getListenerKey(listener);
+        try {
+            mService.stopResolution(id);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Register a callback to listen for updates to a service.
+     *
+     * An application can listen to a service to continuously monitor availability of given service.
+     * The callback methods will be called on the passed executor. And service updates are sent with
+     * continuous calls to {@link ServiceInfoCallback#onServiceUpdated}.
+     *
+     * This is different from {@link #resolveService} which provides one shot service information.
+     *
+     * <p> An application can listen to a service once a time. It needs to cancel the registration
+     * before registering other callbacks. Upon failure to register a callback for example if
+     * it's a duplicated registration, the application is notified through
+     * {@link ServiceInfoCallback#onServiceInfoCallbackRegistrationFailed} with
+     * {@link #FAILURE_BAD_PARAMETERS} or {@link #FAILURE_ALREADY_ACTIVE}.
+     *
+     * @param serviceInfo the service to receive updates for
+     * @param executor Executor to run callbacks with
+     * @param listener to receive callback upon service update
+     */
+    public void registerServiceInfoCallback(@NonNull NsdServiceInfo serviceInfo,
+            @NonNull Executor executor, @NonNull ServiceInfoCallback listener) {
+        checkServiceInfo(serviceInfo);
+        int key = putListener(listener, executor, serviceInfo);
+        try {
+            mService.registerServiceInfoCallback(key, serviceInfo);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Unregister a callback registered with {@link #registerServiceInfoCallback}.
+     *
+     * A successful unregistration is notified with a call to
+     * {@link ServiceInfoCallback#onServiceInfoCallbackUnregistered}. The same callback can only be
+     * reused after this is called.
+     *
+     * <p>If the callback is not already registered, this will throw with
+     * {@link IllegalArgumentException}.
+     *
+     * @param listener This should be a listener object that was passed to
+     *                 {@link #registerServiceInfoCallback}. It identifies the registration that
+     *                 should be unregistered and notifies of a successful or unsuccessful stop.
+     *                 Throws {@code IllegalArgumentException} if the listener was not passed to
+     *                 {@link #registerServiceInfoCallback} before.
+     */
+    public void unregisterServiceInfoCallback(@NonNull ServiceInfoCallback listener) {
+        // Will throw IllegalArgumentException if the listener is not known
+        int id = getListenerKey(listener);
+        try {
+            mService.unregisterServiceInfoCallback(id);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
     private static void checkListener(Object listener) {
         Objects.requireNonNull(listener, "listener cannot be null");
     }
diff --git a/framework-t/src/android/net/nsd/NsdServiceInfo.java b/framework-t/src/android/net/nsd/NsdServiceInfo.java
index 6438a60..caeecdd 100644
--- a/framework-t/src/android/net/nsd/NsdServiceInfo.java
+++ b/framework-t/src/android/net/nsd/NsdServiceInfo.java
@@ -26,10 +26,14 @@
 import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.net.module.util.InetAddressUtils;
+
 import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -46,7 +50,7 @@
 
     private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<>();
 
-    private InetAddress mHost;
+    private final List<InetAddress> mHostAddresses = new ArrayList<>();
 
     private int mPort;
 
@@ -84,17 +88,32 @@
         mServiceType = s;
     }
 
-    /** Get the host address. The host address is valid for a resolved service. */
+    /**
+     * Get the host address. The host address is valid for a resolved service.
+     *
+     * @deprecated Use {@link #getHostAddresses()} to get the entire list of addresses for the host.
+     */
+    @Deprecated
     public InetAddress getHost() {
-        return mHost;
+        return mHostAddresses.size() == 0 ? null : mHostAddresses.get(0);
     }
 
-    /** Set the host address */
+    /**
+     * Set the host address
+     *
+     * @deprecated Use {@link #setHostAddresses(List)} to set multiple addresses for the host.
+     */
+    @Deprecated
     public void setHost(InetAddress s) {
-        mHost = s;
+        setHostAddresses(Collections.singletonList(s));
     }
 
-    /** Get port number. The port number is valid for a resolved service. */
+    /**
+     * Get port number. The port number is valid for a resolved service.
+     *
+     * The port is valid for all addresses.
+     * @see #getHostAddresses()
+     */
     public int getPort() {
         return mPort;
     }
@@ -105,6 +124,24 @@
     }
 
     /**
+     * Get the host addresses.
+     *
+     * All host addresses are valid for the resolved service.
+     * All addresses share the same port
+     * @see #getPort()
+     */
+    @NonNull
+    public List<InetAddress> getHostAddresses() {
+        return new ArrayList<>(mHostAddresses);
+    }
+
+    /** Set the host addresses */
+    public void setHostAddresses(@NonNull List<InetAddress> addresses) {
+        mHostAddresses.clear();
+        mHostAddresses.addAll(addresses);
+    }
+
+    /**
      * Unpack txt information from a base-64 encoded byte array.
      *
      * @param txtRecordsRawBytes The raw base64 encoded byte array.
@@ -359,7 +396,7 @@
         StringBuilder sb = new StringBuilder();
         sb.append("name: ").append(mServiceName)
                 .append(", type: ").append(mServiceType)
-                .append(", host: ").append(mHost)
+                .append(", hostAddresses: ").append(TextUtils.join(", ", mHostAddresses))
                 .append(", port: ").append(mPort)
                 .append(", network: ").append(mNetwork);
 
@@ -377,12 +414,6 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mServiceName);
         dest.writeString(mServiceType);
-        if (mHost != null) {
-            dest.writeInt(1);
-            dest.writeByteArray(mHost.getAddress());
-        } else {
-            dest.writeInt(0);
-        }
         dest.writeInt(mPort);
 
         // TXT record key/value pairs.
@@ -401,6 +432,10 @@
 
         dest.writeParcelable(mNetwork, 0);
         dest.writeInt(mInterfaceIndex);
+        dest.writeInt(mHostAddresses.size());
+        for (InetAddress address : mHostAddresses) {
+            InetAddressUtils.parcelInetAddress(dest, address, flags);
+        }
     }
 
     /** Implement the Parcelable interface */
@@ -410,13 +445,6 @@
                 NsdServiceInfo info = new NsdServiceInfo();
                 info.mServiceName = in.readString();
                 info.mServiceType = in.readString();
-
-                if (in.readInt() == 1) {
-                    try {
-                        info.mHost = InetAddress.getByAddress(in.createByteArray());
-                    } catch (java.net.UnknownHostException e) {}
-                }
-
                 info.mPort = in.readInt();
 
                 // TXT record key/value pairs.
@@ -432,6 +460,10 @@
                 }
                 info.mNetwork = in.readParcelable(null, Network.class);
                 info.mInterfaceIndex = in.readInt();
+                int size = in.readInt();
+                for (int i = 0; i < size; i++) {
+                    info.mHostAddresses.add(InetAddressUtils.unparcelInetAddress(in));
+                }
                 return info;
             }
 
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 7669e0e..193bd92 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -15,7 +15,7 @@
     method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.LinkProperties getRedactedLinkPropertiesForPackage(@NonNull android.net.LinkProperties, int, @NonNull String);
     method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.NetworkCapabilities getRedactedNetworkCapabilitiesForPackage(@NonNull android.net.NetworkCapabilities, int, @NonNull String);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkAllowList(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkDenyList(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void replaceFirewallChain(int, @NonNull int[]);
@@ -63,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/api/system-current.txt b/framework/api/system-current.txt
index dd3404c..196e023 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -470,7 +470,9 @@
   }
 
   public abstract class SocketKeepalive implements java.lang.AutoCloseable {
+    method public final void start(@IntRange(from=0xa, to=0xe10) int, int, @NonNull android.net.Network);
     field public static final int ERROR_NO_SUCH_SLOT = -33; // 0xffffffdf
+    field public static final int FLAG_AUTOMATIC_ON_OFF = 1; // 0x1
     field public static final int SUCCESS = 0; // 0x0
   }
 
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 60bc68c..7cef58b 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 = {
@@ -1477,6 +1502,22 @@
     }
 
     /**
+     * Temporarily set automaticOnOff keeplaive TCP polling alarm timer to 1 second.
+     *
+     * TODO: Remove this when the TCP polling design is replaced with callback.
+     * @param timeMs The time of expiry, with System.currentTimeMillis() base. The value should be
+     *               set no more than 5 minutes in the future.
+     * @hide
+     */
+    public void setTestLowTcpPollingTimerForKeepalive(long timeMs) {
+        try {
+            mService.setTestLowTcpPollingTimerForKeepalive(timeMs);
+        } 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.
@@ -2188,9 +2229,13 @@
         /** The requested keepalive was successfully started. */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public void onStarted() {}
+        /** The keepalive was resumed after being paused by the system. */
+        public void onResumed() {}
         /** The keepalive was successfully stopped. */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public void onStopped() {}
+        /** The keepalive was paused automatically by the system. */
+        public void onPaused() {}
         /** An error occurred. */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public void onError(int error) {}
@@ -2254,16 +2299,12 @@
         private final ISocketKeepaliveCallback mCallback;
         private final ExecutorService mExecutor;
 
-        private volatile Integer mSlot;
-
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public void stop() {
             try {
                 mExecutor.execute(() -> {
                     try {
-                        if (mSlot != null) {
-                            mService.stopKeepalive(mNetwork, mSlot);
-                        }
+                        mService.stopKeepalive(mCallback);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Error stopping packet keepalive: ", e);
                         throw e.rethrowFromSystemServer();
@@ -2281,11 +2322,10 @@
             mExecutor = Executors.newSingleThreadExecutor();
             mCallback = new ISocketKeepaliveCallback.Stub() {
                 @Override
-                public void onStarted(int slot) {
+                public void onStarted() {
                     final long token = Binder.clearCallingIdentity();
                     try {
                         mExecutor.execute(() -> {
-                            mSlot = slot;
                             callback.onStarted();
                         });
                     } finally {
@@ -2294,11 +2334,22 @@
                 }
 
                 @Override
+                public void onResumed() {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() -> {
+                            callback.onResumed();
+                        });
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+
+                @Override
                 public void onStopped() {
                     final long token = Binder.clearCallingIdentity();
                     try {
                         mExecutor.execute(() -> {
-                            mSlot = null;
                             callback.onStopped();
                         });
                     } finally {
@@ -2308,11 +2359,23 @@
                 }
 
                 @Override
+                public void onPaused() {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() -> {
+                            callback.onPaused();
+                        });
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                    mExecutor.shutdown();
+                }
+
+                @Override
                 public void onError(int error) {
                     final long token = Binder.clearCallingIdentity();
                     try {
                         mExecutor.execute(() -> {
-                            mSlot = null;
                             callback.onError(error);
                         });
                     } finally {
@@ -4838,6 +4901,7 @@
     @RequiresPermission(anyOf = {
             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
             android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
             android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS})
     public void registerSystemDefaultNetworkCallback(@NonNull NetworkCallback networkCallback,
             @NonNull Handler handler) {
@@ -5972,6 +6036,30 @@
     }
 
     /**
+     * Get firewall rule of specified firewall chain on specified uid.
+     *
+     * @param chain target chain.
+     * @param uid   target uid
+     * @return either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
+     * @throws UnsupportedOperationException if called on pre-T devices.
+     * @throws ServiceSpecificException in case of failure, with an error code indicating the
+     *                                  cause of the failure.
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
+    public int getUidFirewallRule(@FirewallChain final int chain, final int uid) {
+        try {
+            return mService.getUidFirewallRule(chain, uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Enables or disables the specified firewall chain.
      *
      * @param chain target chain.
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 7b6e769..1372e9a 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -188,12 +188,12 @@
 
     void startNattKeepaliveWithFd(in Network network, in ParcelFileDescriptor pfd, int resourceId,
             int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr,
-            String dstAddr);
+            String dstAddr, boolean automaticOnOffKeepalives, in Network underpinnedNetwork);
 
     void startTcpKeepalive(in Network network, in ParcelFileDescriptor pfd, int intervalSeconds,
             in ISocketKeepaliveCallback cb);
 
-    void stopKeepalive(in Network network, int slot);
+    void stopKeepalive(in ISocketKeepaliveCallback cb);
 
     String getCaptivePortalServerUrl();
 
@@ -242,6 +242,8 @@
 
     void setUidFirewallRule(int chain, int uid, int rule);
 
+    int getUidFirewallRule(int chain, int uid);
+
     void setFirewallChainEnabled(int chain, boolean enable);
 
     boolean getFirewallChainEnabled(int chain);
@@ -251,4 +253,6 @@
     IBinder getCompanionDeviceManagerProxyService();
 
     void setVpnNetworkPreference(String session, in UidRange[] ranges);
+
+    void setTestLowTcpPollingTimerForKeepalive(long timeMs);
 }
diff --git a/framework/src/android/net/ISocketKeepaliveCallback.aidl b/framework/src/android/net/ISocketKeepaliveCallback.aidl
index 020fbca..0a1de6c 100644
--- a/framework/src/android/net/ISocketKeepaliveCallback.aidl
+++ b/framework/src/android/net/ISocketKeepaliveCallback.aidl
@@ -24,11 +24,15 @@
 oneway interface ISocketKeepaliveCallback
 {
     /** The keepalive was successfully started. */
-    void onStarted(int slot);
+    void onStarted();
     /** The keepalive was successfully stopped. */
     void onStopped();
     /** The keepalive was stopped because of an error. */
     void onError(int error);
     /** The keepalive on a TCP socket was stopped because the socket received data. */
     void onDataReceived();
+    /** The keepalive was paused by the system because it's not necessary right now. */
+    void onPaused();
+    /** The keepalive was resumed by the system after being suspended. */
+    void onResumed();
 }
diff --git a/framework/src/android/net/LinkProperties.java b/framework/src/android/net/LinkProperties.java
index b7ee846..e0926e9 100644
--- a/framework/src/android/net/LinkProperties.java
+++ b/framework/src/android/net/LinkProperties.java
@@ -16,19 +16,18 @@
 
 package android.net;
 
+import static android.net.connectivity.ConnectivityCompatChanges.EXCLUDED_ROUTES;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.CollectionUtils;
 import com.android.net.module.util.LinkPropertiesUtils;
@@ -58,17 +57,6 @@
  *
  */
 public final class LinkProperties implements Parcelable {
-    /**
-     * The {@link #getRoutes()} now can contain excluded as well as included routes. Use
-     * {@link RouteInfo#getType()} to determine route type.
-     *
-     * @hide
-     */
-    @ChangeId
-    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
-    @VisibleForTesting
-    public static final long EXCLUDED_ROUTES = 186082280;
-
     // The interface described by the network link.
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private String mIfaceName;
diff --git a/framework/src/android/net/NattSocketKeepalive.java b/framework/src/android/net/NattSocketKeepalive.java
index 56cc923..a83b5b4 100644
--- a/framework/src/android/net/NattSocketKeepalive.java
+++ b/framework/src/android/net/NattSocketKeepalive.java
@@ -47,13 +47,42 @@
         mResourceId = resourceId;
     }
 
+    /**
+     * Request that keepalive be started with the given {@code intervalSec}.
+     *
+     * When a VPN is running with the network for this keepalive as its underlying network, the
+     * system can monitor the TCP connections on that VPN to determine whether this keepalive is
+     * necessary. To enable this behavior, pass {@link SocketKeepalive#FLAG_AUTOMATIC_ON_OFF} into
+     * the flags. When this is enabled, the system will disable sending keepalive packets when
+     * there are no TCP connections over the VPN(s) running over this network to save battery, and
+     * restart sending them as soon as any TCP connection is opened over one of the VPN networks.
+     * When no VPN is running on top of this network, this flag has no effect, i.e. the keepalives
+     * are always sent with the specified interval.
+     *
+     * Also {@see SocketKeepalive}.
+     *
+     * @param intervalSec The target interval in seconds between keepalive packet transmissions.
+     *                    The interval should be between 10 seconds and 3600 seconds. Otherwise,
+     *                    the supplied {@link Callback} will see a call to
+     *                    {@link Callback#onError(int)} with {@link #ERROR_INVALID_INTERVAL}.
+     * @param flags Flags to enable/disable available options on this keepalive.
+     * @param underpinnedNetwork The underpinned network of this keepalive.
+     *
+     * @hide
+     */
     @Override
-    protected void startImpl(int intervalSec) {
+    protected void startImpl(int intervalSec, int flags, Network underpinnedNetwork) {
+        if (0 != (flags & ~FLAG_AUTOMATIC_ON_OFF)) {
+            throw new IllegalArgumentException("Illegal flag value for "
+                    + this.getClass().getSimpleName() + " : " + flags);
+        }
+        final boolean automaticOnOffKeepalives = 0 != (flags & FLAG_AUTOMATIC_ON_OFF);
         mExecutor.execute(() -> {
             try {
                 mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId,
-                        intervalSec, mCallback,
-                        mSource.getHostAddress(), mDestination.getHostAddress());
+                        intervalSec, mCallback, mSource.getHostAddress(),
+                        mDestination.getHostAddress(), automaticOnOffKeepalives,
+                        underpinnedNetwork);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error starting socket keepalive: ", e);
                 throw e.rethrowFromSystemServer();
@@ -65,9 +94,7 @@
     protected void stopImpl() {
         mExecutor.execute(() -> {
             try {
-                if (mSlot != null) {
-                    mService.stopKeepalive(mNetwork, mSlot);
-                }
+                mService.stopKeepalive(mCallback);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error stopping socket keepalive: ", e);
                 throw e.rethrowFromSystemServer();
diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java
index 1486619..8fe20de 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -281,7 +281,7 @@
      *
      *   arg1 = the hardware slot number of the keepalive to start
      *   arg2 = interval in seconds
-     *   obj = KeepalivePacketData object describing the data to be sent
+     *   obj = AutomaticKeepaliveInfo object
      *
      * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
      * @hide
@@ -291,7 +291,9 @@
     /**
      * Requests that the specified keepalive packet be stopped.
      *
-     * arg1 = hardware slot number of the keepalive to stop.
+     * arg1 = unused
+     * arg2 = error code (SUCCESS)
+     * obj = callback to identify the keepalive
      *
      * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
      * @hide
@@ -483,6 +485,19 @@
      */
     public static final int EVENT_UNREGISTER_AFTER_REPLACEMENT = BASE + 29;
 
+    /**
+     * Sent by AutomaticOnOffKeepaliveTracker periodically (when relevant) to trigger monitor
+     * automatic keepalive request.
+     *
+     * NATT keepalives have an automatic mode where the system only sends keepalive packets when
+     * TCP sockets are open over a VPN. The system will check periodically for presence of
+     * such open sockets, and this message is what triggers the re-evaluation.
+     *
+     * obj = A Binder object associated with the keepalive.
+     * @hide
+     */
+    public static final int CMD_MONITOR_AUTOMATIC_KEEPALIVE = BASE + 30;
+
     private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
         final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
                 config.legacyTypeName, config.legacySubTypeName);
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index a81da22..427eac1 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -18,6 +18,7 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
 import static com.android.net.module.util.BitUtils.appendStringRepresentationOfBitMaskToStringBuilder;
+import static com.android.net.module.util.BitUtils.describeDifferences;
 
 import android.annotation.IntDef;
 import android.annotation.LongDef;
@@ -2076,30 +2077,14 @@
      * Returns a short but human-readable string of updates from an older set of capabilities.
      * @param old the old capabilities to diff from
      * @return a string fit for logging differences, or null if no differences.
-     *         this never returns the empty string.
+     *         this never returns the empty string. See BitUtils#describeDifferences.
      * @hide
      */
     @Nullable
     public String describeCapsDifferencesFrom(@Nullable final NetworkCapabilities old) {
         final long oldCaps = null == old ? 0 : old.mNetworkCapabilities;
-        final long changed = oldCaps ^ mNetworkCapabilities;
-        if (0 == changed) return null;
-        // If the control reaches here, there are changes (additions, removals, or both) so
-        // the code below is guaranteed to add something to the string and can't return "".
-        final long removed = oldCaps & changed;
-        final long added = mNetworkCapabilities & changed;
-        final StringBuilder sb = new StringBuilder();
-        if (0 != removed) {
-            sb.append("-");
-            appendStringRepresentationOfBitMaskToStringBuilder(sb, removed,
-                    NetworkCapabilities::capabilityNameOf, "-");
-        }
-        if (0 != added) {
-            sb.append("+");
-            appendStringRepresentationOfBitMaskToStringBuilder(sb, added,
-                    NetworkCapabilities::capabilityNameOf, "+");
-        }
-        return sb.toString();
+        return describeDifferences(oldCaps, mNetworkCapabilities,
+                NetworkCapabilities::capabilityNameOf);
     }
 
     /**
diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java
index 57cf5e3..311126e 100644
--- a/framework/src/android/net/SocketKeepalive.java
+++ b/framework/src/android/net/SocketKeepalive.java
@@ -16,10 +16,11 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.PRIVILEGED_APPS;
+
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
@@ -63,6 +64,12 @@
     public static final int SUCCESS = 0;
 
     /**
+     * Success when trying to suspend.
+     * @hide
+     */
+    public static final int SUCCESS_PAUSED = 1;
+
+    /**
      * No keepalive. This should only be internally as it indicates There is no keepalive.
      * It should not propagate to applications.
      * @hide
@@ -174,6 +181,27 @@
     public @interface KeepaliveEvent {}
 
     /**
+     * Whether the system automatically toggles keepalive when no TCP connection is open on the VPN.
+     *
+     * If this flag is present, the system will monitor the VPN(s) running on top of the specified
+     * network for open TCP connections. When no such connections are open, it will turn off the
+     * keepalives to conserve battery power. When there is at least one such connection it will
+     * turn on the keepalives to make sure functionality is preserved.
+     *
+     * This only works with {@link NattSocketKeepalive}.
+     * @hide
+     */
+    @SystemApi
+    public static final int FLAG_AUTOMATIC_ON_OFF = 1 << 0;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "FLAG_"}, flag = true, value = {
+            FLAG_AUTOMATIC_ON_OFF
+    })
+    public @interface StartFlags {}
+
+    /**
      * The minimum interval in seconds between keepalive packet transmissions.
      *
      * @hide
@@ -226,9 +254,6 @@
     @NonNull protected final Executor mExecutor;
     /** @hide */
     @NonNull protected final ISocketKeepaliveCallback mCallback;
-    // TODO: remove slot since mCallback could be used to identify which keepalive to stop.
-    /** @hide */
-    @Nullable protected Integer mSlot;
 
     /** @hide */
     public SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
@@ -240,11 +265,10 @@
         mExecutor = executor;
         mCallback = new ISocketKeepaliveCallback.Stub() {
             @Override
-            public void onStarted(int slot) {
+            public void onStarted() {
                 final long token = Binder.clearCallingIdentity();
                 try {
                     mExecutor.execute(() -> {
-                        mSlot = slot;
                         callback.onStarted();
                     });
                 } finally {
@@ -253,11 +277,22 @@
             }
 
             @Override
+            public void onResumed() {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> {
+                        callback.onResumed();
+                    });
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+
+            @Override
             public void onStopped() {
                 final long token = Binder.clearCallingIdentity();
                 try {
                     executor.execute(() -> {
-                        mSlot = null;
                         callback.onStopped();
                     });
                 } finally {
@@ -266,11 +301,22 @@
             }
 
             @Override
+            public void onPaused() {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    executor.execute(() -> {
+                        callback.onPaused();
+                    });
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+
+            @Override
             public void onError(int error) {
                 final long token = Binder.clearCallingIdentity();
                 try {
                     executor.execute(() -> {
-                        mSlot = null;
                         callback.onError(error);
                     });
                 } finally {
@@ -283,7 +329,6 @@
                 final long token = Binder.clearCallingIdentity();
                 try {
                     executor.execute(() -> {
-                        mSlot = null;
                         callback.onDataReceived();
                     });
                 } finally {
@@ -294,13 +339,15 @@
     }
 
     /**
-     * Request that keepalive be started with the given {@code intervalSec}. See
-     * {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an exception
-     * when invoking start or stop of the {@link SocketKeepalive}, a {@link RemoteException} will be
-     * thrown into the {@code executor}. This is typically not important to catch because the remote
-     * party is the system, so if it is not in shape to communicate through binder the system is
-     * probably going down anyway. If the caller cares regardless, it can use a custom
-     * {@link Executor} to catch the {@link RemoteException}.
+     * Request that keepalive be started with the given {@code intervalSec}.
+     *
+     * See {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an
+     * exception when invoking start or stop of the {@link SocketKeepalive}, a
+     * {@link RuntimeException} caused by a {@link RemoteException} will be thrown into the
+     * {@link Executor}. This is typically not important to catch because the remote party is
+     * the system, so if it is not in shape to communicate through binder the system is going
+     * down anyway. If the caller still cares, it can use a custom {@link Executor} to catch the
+     * {@link RuntimeException}.
      *
      * @param intervalSec The target interval in seconds between keepalive packet transmissions.
      *                    The interval should be between 10 seconds and 3600 seconds, otherwise
@@ -308,11 +355,37 @@
      */
     public final void start(@IntRange(from = MIN_INTERVAL_SEC, to = MAX_INTERVAL_SEC)
             int intervalSec) {
-        startImpl(intervalSec);
+        startImpl(intervalSec, 0 /* flags */, null /* underpinnedNetwork */);
+    }
+
+    /**
+     * Request that keepalive be started with the given {@code intervalSec}.
+     *
+     * See {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an
+     * exception when invoking start or stop of the {@link SocketKeepalive}, a
+     * {@link RuntimeException} caused by a {@link RemoteException} will be thrown into the
+     * {@link Executor}. This is typically not important to catch because the remote party is
+     * the system, so if it is not in shape to communicate through binder the system is going
+     * down anyway. If the caller still cares, it can use a custom {@link Executor} to catch the
+     * {@link RuntimeException}.
+     *
+     * @param intervalSec The target interval in seconds between keepalive packet transmissions.
+     *                    The interval should be between 10 seconds and 3600 seconds. Otherwise,
+     *                    the supplied {@link Callback} will see a call to
+     *                    {@link Callback#onError(int)} with {@link #ERROR_INVALID_INTERVAL}.
+     * @param flags Flags to enable/disable available options on this keepalive.
+     * @param underpinnedNetwork The underpinned network of this keepalive.
+     * @hide
+     */
+    @SystemApi(client = PRIVILEGED_APPS)
+    public final void start(@IntRange(from = MIN_INTERVAL_SEC, to = MAX_INTERVAL_SEC)
+            int intervalSec, @StartFlags int flags, @NonNull Network underpinnedNetwork) {
+        startImpl(intervalSec, flags, underpinnedNetwork);
     }
 
     /** @hide */
-    protected abstract void startImpl(int intervalSec);
+    protected abstract void startImpl(int intervalSec, @StartFlags int flags,
+            Network underpinnedNetwork);
 
     /**
      * Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
@@ -346,8 +419,18 @@
     public static class Callback {
         /** The requested keepalive was successfully started. */
         public void onStarted() {}
+        /**
+         * The keepalive was resumed by the system after being suspended.
+         * @hide
+         **/
+        public void onResumed() {}
         /** The keepalive was successfully stopped. */
         public void onStopped() {}
+        /**
+         * The keepalive was paused by the system because it's not necessary right now.
+         * @hide
+         **/
+        public void onPaused() {}
         /** An error occurred. */
         public void onError(@ErrorCode int error) {}
         /** The keepalive on a TCP socket was stopped because the socket received data. This is
diff --git a/framework/src/android/net/TcpSocketKeepalive.java b/framework/src/android/net/TcpSocketKeepalive.java
index 7131784..b548f6d 100644
--- a/framework/src/android/net/TcpSocketKeepalive.java
+++ b/framework/src/android/net/TcpSocketKeepalive.java
@@ -50,7 +50,11 @@
      *   acknowledgement.
      */
     @Override
-    protected void startImpl(int intervalSec) {
+    protected void startImpl(int intervalSec, int flags, Network underpinnedNetwork) {
+        if (0 != flags) {
+            throw new IllegalArgumentException("Illegal flag value for "
+                    + this.getClass().getSimpleName() + " : " + flags);
+        }
         mExecutor.execute(() -> {
             try {
                 mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback);
@@ -65,9 +69,7 @@
     protected void stopImpl() {
         mExecutor.execute(() -> {
             try {
-                if (mSlot != null) {
-                    mService.stopKeepalive(mNetwork, mSlot);
-                }
+                mService.stopKeepalive(mCallback);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error stopping packet keepalive: ", e);
                 throw e.rethrowFromSystemServer();
diff --git a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
new file mode 100644
index 0000000..a166675
--- /dev/null
+++ b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
@@ -0,0 +1,67 @@
+/*
+ * 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.connectivity;
+
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.EnabledSince;
+import android.os.Build;
+
+/**
+ * The class contains all CompatChanges for the Connectivity module.
+ *
+ * <p>This is the centralized place for the CompatChanges used in the Connectivity module.
+ * Putting all the CompatChanges in single place makes it possible to manage them under a single
+ * platform_compat_config.
+ * @hide
+ */
+public final class ConnectivityCompatChanges {
+
+    /**
+     * The {@link android.net.LinkProperties#getRoutes()} now can contain excluded as well as
+     * included routes. Use {@link android.net.RouteInfo#getType()} to determine route type.
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
+    public static final long EXCLUDED_ROUTES = 186082280;
+
+    /**
+     * When enabled, apps targeting < Android 12 are considered legacy for
+     * the NSD native daemon.
+     * The platform will only keep the daemon running as long as there are
+     * any legacy apps connected.
+     *
+     * After Android 12, direct communication with the native daemon might not work since the native
+     * daemon won't always stay alive. Using the NSD APIs from NsdManager as the replacement is
+     * recommended.
+     * Another alternative could be bundling your own mdns solutions instead of
+     * depending on the system mdns native daemon.
+     *
+     * This compatibility change applies to Android 13 and later only. To toggle behavior on
+     * Android 12 and Android 12L, use RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS.
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
+    // This was a platform change ID with value 191844585L before T
+    public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER = 235355681L;
+
+    private ConnectivityCompatChanges() {
+    }
+}
diff --git a/nearby/tests/cts/fastpair/AndroidManifest.xml b/nearby/tests/cts/fastpair/AndroidManifest.xml
index 96e2783..9e1ec70 100644
--- a/nearby/tests/cts/fastpair/AndroidManifest.xml
+++ b/nearby/tests/cts/fastpair/AndroidManifest.xml
@@ -30,7 +30,5 @@
   <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
       android:targetPackage="android.nearby.cts"
       android:label="CTS tests for android.nearby Fast Pair">
-    <meta-data android:name="listener"
-        android:value="com.android.cts.runner.CtsTestRunListener"/>
   </instrumentation>
 </manifest>
diff --git a/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java b/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java
index 86e39dc..8b5ac12 100644
--- a/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java
+++ b/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java
@@ -54,7 +54,7 @@
             @NonNull String specificLog, @NonNull Date startTime) {
         return new Condition<UiDevice, Boolean>() {
             @Override
-            Boolean apply(UiDevice device) {
+            public Boolean apply(UiDevice device) {
                 String logcatLogs;
                 try {
                     logcatLogs = device.executeShellCommand("logcat -v time -v year -d");
diff --git a/service-t/Android.bp b/service-t/Android.bp
index d876166..5bf2973 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -52,6 +52,7 @@
         "framework-connectivity-t-pre-jarjar",
         // TODO: use framework-tethering-pre-jarjar when it is separated from framework-tethering
         "framework-tethering.impl",
+        "framework-wifi",
         "service-connectivity-pre-jarjar",
         "service-nearby-pre-jarjar",
         "ServiceConnectivityResources",
diff --git a/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp b/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
index a3299a7..2dbe771 100644
--- a/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
+++ b/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
@@ -210,7 +210,8 @@
 };
 
 int register_android_server_net_NetworkStatsFactory(JNIEnv* env) {
-    int err = jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsFactory", gMethods,
+    int err = jniRegisterNativeMethods(env,
+            "android/net/connectivity/com/android/server/net/NetworkStatsFactory", gMethods,
             NELEM(gMethods));
     gStringClass = env->FindClass("java/lang/String");
     gStringClass = static_cast<jclass>(env->NewGlobalRef(gStringClass));
diff --git a/service-t/jni/com_android_server_net_NetworkStatsService.cpp b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
index 39cbaf7..dab9d07 100644
--- a/service-t/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
@@ -30,9 +30,11 @@
 
 #include "bpf/BpfUtils.h"
 #include "netdbpf/BpfNetworkStats.h"
+#include "netdbpf/NetworkTraceHandler.h"
 
 using android::bpf::bpfGetUidStats;
 using android::bpf::bpfGetIfaceStats;
+using android::bpf::NetworkTraceHandler;
 
 namespace android {
 
@@ -67,7 +69,7 @@
     }
 }
 
-static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
+static jlong nativeGetTotalStat(JNIEnv* env, jclass clazz, jint type) {
     Stats stats = {};
 
     if (bpfGetIfaceStats(NULL, &stats) == 0) {
@@ -77,7 +79,7 @@
     }
 }
 
-static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
+static jlong nativeGetIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
     ScopedUtfChars iface8(env, iface);
     if (iface8.c_str() == NULL) {
         return UNKNOWN;
@@ -92,7 +94,7 @@
     }
 }
 
-static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
+static jlong nativeGetUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
     Stats stats = {};
 
     if (bpfGetUidStats(uid, &stats) == 0) {
@@ -102,15 +104,21 @@
     }
 }
 
+static void nativeInitNetworkTracing(JNIEnv* env, jclass clazz) {
+    NetworkTraceHandler::InitPerfettoTracing();
+}
+
 static const JNINativeMethod gMethods[] = {
-        {"nativeGetTotalStat", "(I)J", (void*)getTotalStat},
-        {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat},
-        {"nativeGetUidStat", "(II)J", (void*)getUidStat},
+        {"nativeGetTotalStat", "(I)J", (void*)nativeGetTotalStat},
+        {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)nativeGetIfaceStat},
+        {"nativeGetUidStat", "(II)J", (void*)nativeGetUidStat},
+        {"nativeInitNetworkTracing", "()V", (void*)nativeInitNetworkTracing},
 };
 
 int register_android_server_net_NetworkStatsService(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods,
-                                    NELEM(gMethods));
+    return jniRegisterNativeMethods(env,
+            "android/net/connectivity/com/android/server/net/NetworkStatsService", gMethods,
+            NELEM(gMethods));
 }
 
 }
diff --git a/service-t/native/libs/libnetworkstats/Android.bp b/service-t/native/libs/libnetworkstats/Android.bp
index 5b3d314..aa1ee41 100644
--- a/service-t/native/libs/libnetworkstats/Android.bp
+++ b/service-t/native/libs/libnetworkstats/Android.bp
@@ -24,12 +24,19 @@
     host_supported: false,
     header_libs: ["bpf_connectivity_headers"],
     srcs: [
-        "BpfNetworkStats.cpp"
+        "BpfNetworkStats.cpp",
+        "NetworkTraceHandler.cpp",
     ],
     shared_libs: [
         "libbase",
         "liblog",
     ],
+    static_libs: [
+        "libperfetto_client_experimental",
+    ],
+    export_static_lib_headers: [
+        "libperfetto_client_experimental",
+    ],
     export_include_dirs: ["include"],
     cflags: [
         "-Wall",
@@ -54,6 +61,7 @@
     header_libs: ["bpf_connectivity_headers"],
     srcs: [
         "BpfNetworkStatsTest.cpp",
+        "NetworkTraceHandlerTest.cpp",
     ],
     cflags: [
         "-Wall",
@@ -64,10 +72,12 @@
     static_libs: [
         "libgmock",
         "libnetworkstats",
+        "libperfetto_client_experimental",
     ],
     shared_libs: [
         "libbase",
         "liblog",
+        "libandroid_net",
     ],
     compile_multilib: "both",
     multilib: {
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
index 122c2d4..4fbc5f4 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
@@ -247,10 +247,6 @@
     return parseBpfNetworkStatsDevInternal(lines, ifaceStatsMap, ifaceIndexNameMap);
 }
 
-uint64_t combineUidTag(const uid_t uid, const uint32_t tag) {
-    return (uint64_t)uid << 32 | tag;
-}
-
 void groupNetworkStats(std::vector<stats_line>* lines) {
     if (lines->size() <= 1) return;
     std::sort(lines->begin(), lines->end());
diff --git a/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
new file mode 100644
index 0000000..aeadb4a
--- /dev/null
+++ b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "NetworkTrace"
+
+#include "netdbpf/NetworkTraceHandler.h"
+
+#include <arpa/inet.h>
+#include <bpf/BpfUtils.h>
+#include <log/log.h>
+#include <perfetto/config/android/network_trace_config.pbzero.h>
+#include <perfetto/trace/android/network_trace.pbzero.h>
+#include <perfetto/trace/profiling/profile_packet.pbzero.h>
+#include <perfetto/tracing/platform.h>
+#include <perfetto/tracing/tracing.h>
+
+// Note: this is initializing state for a templated Perfetto type that resides
+// in the `perfetto` namespace. This must be defined in the global scope.
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::bpf::NetworkTraceHandler);
+
+namespace android {
+namespace bpf {
+using ::perfetto::protos::pbzero::NetworkPacketEvent;
+using ::perfetto::protos::pbzero::NetworkPacketTraceConfig;
+using ::perfetto::protos::pbzero::TracePacket;
+using ::perfetto::protos::pbzero::TrafficDirection;
+
+// static
+void NetworkTraceHandler::RegisterDataSource() {
+  ALOGD("Registering Perfetto data source");
+  perfetto::DataSourceDescriptor dsd;
+  dsd.set_name("android.network_packets");
+  NetworkTraceHandler::Register(dsd);
+}
+
+// static
+void NetworkTraceHandler::InitPerfettoTracing() {
+  perfetto::TracingInitArgs args = {};
+  args.backends |= perfetto::kSystemBackend;
+  args.enable_system_consumer = false;
+  perfetto::Tracing::Initialize(args);
+  NetworkTraceHandler::RegisterDataSource();
+}
+
+NetworkTraceHandler::NetworkTraceHandler()
+    : NetworkTraceHandler([this](const PacketTrace& pkt) {
+        NetworkTraceHandler::Trace(
+            [this, pkt](NetworkTraceHandler::TraceContext ctx) {
+              Fill(pkt, *ctx.NewTracePacket());
+            });
+      }) {}
+
+void NetworkTraceHandler::OnSetup(const SetupArgs& args) {
+  const std::string& raw = args.config->network_packet_trace_config_raw();
+  NetworkPacketTraceConfig::Decoder config(raw);
+
+  mPollMs = config.poll_ms();
+  if (mPollMs < 100) {
+    ALOGI("poll_ms is missing or below the 100ms minimum. Increasing to 100ms");
+    mPollMs = 100;
+  }
+}
+
+void NetworkTraceHandler::OnStart(const StartArgs&) {
+  if (!Start()) return;
+  mTaskRunner = perfetto::Platform::GetDefaultPlatform()->CreateTaskRunner({});
+  Loop();
+}
+
+void NetworkTraceHandler::OnStop(const StopArgs&) {
+  Stop();
+  mTaskRunner.reset();
+}
+
+void NetworkTraceHandler::Loop() {
+  mTaskRunner->PostDelayedTask([this]() { Loop(); }, mPollMs);
+  ConsumeAll();
+}
+
+void NetworkTraceHandler::Fill(const PacketTrace& src, TracePacket& dst) {
+  dst.set_timestamp(src.timestampNs);
+  auto* event = dst.set_network_packet();
+  event->set_direction(src.egress ? TrafficDirection::DIR_EGRESS
+                                  : TrafficDirection::DIR_INGRESS);
+  event->set_length(src.length);
+  event->set_uid(src.uid);
+  event->set_tag(src.tag);
+
+  event->set_local_port(src.egress ? ntohs(src.sport) : ntohs(src.dport));
+  event->set_remote_port(src.egress ? ntohs(src.dport) : ntohs(src.sport));
+
+  event->set_ip_proto(src.ipProto);
+  event->set_tcp_flags(src.tcpFlags);
+
+  char ifname[IF_NAMESIZE] = {};
+  if (if_indextoname(src.ifindex, ifname) == ifname) {
+    event->set_interface(std::string(ifname));
+  } else {
+    event->set_interface("error");
+  }
+}
+
+bool NetworkTraceHandler::Start() {
+  ALOGD("Starting datasource");
+
+  auto status = mConfigurationMap.init(PACKET_TRACE_ENABLED_MAP_PATH);
+  if (!status.ok()) {
+    ALOGW("Failed to bind config map: %s", status.error().message().c_str());
+    return false;
+  }
+
+  auto rb = BpfRingbuf<PacketTrace>::Create(PACKET_TRACE_RINGBUF_PATH);
+  if (!rb.ok()) {
+    ALOGW("Failed to create ringbuf: %s", rb.error().message().c_str());
+    return false;
+  }
+
+  mRingBuffer = std::move(*rb);
+
+  auto res = mConfigurationMap.writeValue(0, true, BPF_ANY);
+  if (!res.ok()) {
+    ALOGW("Failed to enable tracing: %s", res.error().message().c_str());
+    return false;
+  }
+
+  return true;
+}
+
+bool NetworkTraceHandler::Stop() {
+  ALOGD("Stopping datasource");
+
+  auto res = mConfigurationMap.writeValue(0, false, BPF_ANY);
+  if (!res.ok()) {
+    ALOGW("Failed to disable tracing: %s", res.error().message().c_str());
+    return false;
+  }
+
+  mRingBuffer.reset();
+
+  return true;
+}
+
+bool NetworkTraceHandler::ConsumeAll() {
+  if (mRingBuffer == nullptr) {
+    ALOGW("Tracing is not active");
+    return false;
+  }
+
+  base::Result<int> ret = mRingBuffer->ConsumeAll(mCallback);
+  if (!ret.ok()) {
+    ALOGW("Failed to poll ringbuf: %s", ret.error().message().c_str());
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace bpf
+}  // namespace android
diff --git a/service-t/native/libs/libnetworkstats/NetworkTraceHandlerTest.cpp b/service-t/native/libs/libnetworkstats/NetworkTraceHandlerTest.cpp
new file mode 100644
index 0000000..560194f
--- /dev/null
+++ b/service-t/native/libs/libnetworkstats/NetworkTraceHandlerTest.cpp
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+
+#include <android-base/unique_fd.h>
+#include <android/multinetwork.h>
+#include <arpa/inet.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <inttypes.h>
+#include <net/if.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <vector>
+
+#include "netdbpf/NetworkTraceHandler.h"
+
+using ::testing::AllOf;
+using ::testing::AnyOf;
+using ::testing::Each;
+using ::testing::Eq;
+using ::testing::Field;
+using ::testing::Test;
+
+namespace android {
+namespace bpf {
+
+__be16 bindAndListen(int s) {
+  sockaddr_in sin = {.sin_family = AF_INET};
+  socklen_t len = sizeof(sin);
+  if (bind(s, (sockaddr*)&sin, sizeof(sin))) return 0;
+  if (listen(s, 1)) return 0;
+  if (getsockname(s, (sockaddr*)&sin, &len)) return 0;
+  return sin.sin_port;
+}
+
+// This takes tcp flag constants from the standard library and makes them usable
+// with the flags we get from BPF. The standard library flags are big endian
+// whereas the BPF flags are reported in host byte order. BPF also trims the
+// flags down to the 8 single-bit flag bits (fin, syn, rst, etc).
+constexpr inline uint8_t FlagToHost(__be32 be_unix_flags) {
+  return ntohl(be_unix_flags) >> 16;
+}
+
+// Pretty prints all fields for a list of packets (useful for debugging).
+struct PacketPrinter {
+  const std::vector<PacketTrace>& data;
+  static constexpr char kTcpFlagNames[] = "FSRPAUEC";
+
+  friend std::ostream& operator<<(std::ostream& os, const PacketPrinter& d) {
+    os << "Packet count: " << d.data.size();
+    for (const PacketTrace& info : d.data) {
+      os << "\nifidx=" << info.ifindex;
+      os << ", len=" << info.length;
+      os << ", uid=" << info.uid;
+      os << ", tag=" << info.tag;
+      os << ", sport=" << info.sport;
+      os << ", dport=" << info.dport;
+      os << ", direction=" << (info.egress ? "egress" : "ingress");
+      os << ", proto=" << static_cast<int>(info.ipProto);
+      os << ", ip=" << static_cast<int>(info.ipVersion);
+      os << ", flags=";
+      for (int i = 0; i < 8; i++) {
+        os << ((info.tcpFlags & (1 << i)) ? kTcpFlagNames[i] : '.');
+      }
+    }
+    return os;
+  }
+};
+
+class NetworkTraceHandlerTest : public testing::Test {
+ protected:
+  void SetUp() {
+    if (access(PACKET_TRACE_RINGBUF_PATH, R_OK)) {
+      GTEST_SKIP() << "Network tracing is not enabled/loaded on this build.";
+    }
+    if (sizeof(void*) != 8) {
+      GTEST_SKIP() << "Network tracing requires 64-bit build.";
+    }
+  }
+};
+
+TEST_F(NetworkTraceHandlerTest, PollWhileInactive) {
+  NetworkTraceHandler handler([&](const PacketTrace& pkt) {});
+
+  // One succeed after start and before stop.
+  EXPECT_FALSE(handler.ConsumeAll());
+  ASSERT_TRUE(handler.Start());
+  EXPECT_TRUE(handler.ConsumeAll());
+  ASSERT_TRUE(handler.Stop());
+  EXPECT_FALSE(handler.ConsumeAll());
+}
+
+TEST_F(NetworkTraceHandlerTest, TraceTcpSession) {
+  __be16 server_port = 0;
+  std::vector<PacketTrace> packets;
+
+  // Record all packets with the bound address and current uid. This callback is
+  // involked only within ConsumeAll, at which point the port should have
+  // already been filled in and all packets have been processed.
+  NetworkTraceHandler handler([&](const PacketTrace& pkt) {
+    if (pkt.sport != server_port && pkt.dport != server_port) return;
+    if (pkt.uid != getuid()) return;
+    packets.push_back(pkt);
+  });
+
+  ASSERT_TRUE(handler.Start());
+  const uint32_t kClientTag = 2468;
+  const uint32_t kServerTag = 1357;
+
+  // Go through a typical connection sequence between two v4 sockets using tcp.
+  // This covers connection handshake, shutdown, and one data packet.
+  {
+    android::base::unique_fd clientsocket(socket(AF_INET, SOCK_STREAM, 0));
+    ASSERT_NE(-1, clientsocket) << "Failed to open client socket";
+    ASSERT_EQ(android_tag_socket(clientsocket, kClientTag), 0);
+
+    android::base::unique_fd serversocket(socket(AF_INET, SOCK_STREAM, 0));
+    ASSERT_NE(-1, serversocket) << "Failed to open server socket";
+    ASSERT_EQ(android_tag_socket(serversocket, kServerTag), 0);
+
+    server_port = bindAndListen(serversocket);
+    ASSERT_NE(0, server_port) << "Can't bind to server port";
+
+    sockaddr_in addr = {.sin_family = AF_INET, .sin_port = server_port};
+    ASSERT_EQ(0, connect(clientsocket, (sockaddr*)&addr, sizeof(addr)))
+        << "connect to loopback failed: " << strerror(errno);
+
+    int accepted = accept(serversocket, nullptr, nullptr);
+    ASSERT_NE(-1, accepted) << "accept connection failed: " << strerror(errno);
+
+    const char data[] = "abcdefghijklmnopqrstuvwxyz";
+    EXPECT_EQ(send(clientsocket, data, sizeof(data), 0), sizeof(data))
+        << "failed to send message: " << strerror(errno);
+
+    char buff[100] = {};
+    EXPECT_EQ(recv(accepted, buff, sizeof(buff), 0), sizeof(data))
+        << "failed to receive message: " << strerror(errno);
+
+    EXPECT_EQ(std::string(data), std::string(buff));
+  }
+
+  ASSERT_TRUE(handler.ConsumeAll());
+  ASSERT_TRUE(handler.Stop());
+
+  // There are 12 packets in total (6 messages: each seen by client & server):
+  // 1. Client connects to server with syn
+  // 2. Server responds with syn ack
+  // 3. Client responds with ack
+  // 4. Client sends data with psh ack
+  // 5. Server acks the data packet
+  // 6. Client closes connection with fin ack
+  ASSERT_EQ(packets.size(), 12) << PacketPrinter{packets};
+
+  // All packets should be TCP packets.
+  EXPECT_THAT(packets, Each(Field(&PacketTrace::ipProto, Eq(IPPROTO_TCP))));
+
+  // Packet 1: client requests connection with server.
+  EXPECT_EQ(packets[0].egress, 1) << PacketPrinter{packets};
+  EXPECT_EQ(packets[0].dport, server_port) << PacketPrinter{packets};
+  EXPECT_EQ(packets[0].tag, kClientTag) << PacketPrinter{packets};
+  EXPECT_EQ(packets[0].tcpFlags, FlagToHost(TCP_FLAG_SYN))
+      << PacketPrinter{packets};
+
+  // Packet 2: server receives request from client.
+  EXPECT_EQ(packets[1].egress, 0) << PacketPrinter{packets};
+  EXPECT_EQ(packets[1].dport, server_port) << PacketPrinter{packets};
+  EXPECT_EQ(packets[1].tag, kServerTag) << PacketPrinter{packets};
+  EXPECT_EQ(packets[1].tcpFlags, FlagToHost(TCP_FLAG_SYN))
+      << PacketPrinter{packets};
+
+  // Packet 3: server replies back with syn ack.
+  EXPECT_EQ(packets[2].egress, 1) << PacketPrinter{packets};
+  EXPECT_EQ(packets[2].sport, server_port) << PacketPrinter{packets};
+  EXPECT_EQ(packets[2].tcpFlags, FlagToHost(TCP_FLAG_SYN | TCP_FLAG_ACK))
+      << PacketPrinter{packets};
+
+  // Packet 4: client receives the server's syn ack.
+  EXPECT_EQ(packets[3].egress, 0) << PacketPrinter{packets};
+  EXPECT_EQ(packets[3].sport, server_port) << PacketPrinter{packets};
+  EXPECT_EQ(packets[3].tcpFlags, FlagToHost(TCP_FLAG_SYN | TCP_FLAG_ACK))
+      << PacketPrinter{packets};
+}
+
+}  // namespace bpf
+}  // namespace android
diff --git a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
new file mode 100644
index 0000000..c257aa0
--- /dev/null
+++ b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+
+#pragma once
+
+#include <perfetto/base/task_runner.h>
+#include <perfetto/tracing.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "bpf/BpfMap.h"
+#include "bpf/BpfRingbuf.h"
+
+// For PacketTrace struct definition
+#include "netd.h"
+
+namespace android {
+namespace bpf {
+
+class NetworkTraceHandler : public perfetto::DataSource<NetworkTraceHandler> {
+ public:
+  // Registers this DataSource.
+  static void RegisterDataSource();
+
+  // Connects to the system Perfetto daemon and registers the trace handler.
+  static void InitPerfettoTracing();
+
+  // Initialize with the default Perfetto callback.
+  NetworkTraceHandler();
+
+  // Testonly: initialize with a callback capable of intercepting data.
+  NetworkTraceHandler(std::function<void(const PacketTrace&)> callback)
+      : mCallback(std::move(callback)) {}
+
+  // Testonly: standalone functions without perfetto dependency.
+  bool Start();
+  bool Stop();
+  bool ConsumeAll();
+
+  // perfetto::DataSource overrides:
+  void OnSetup(const SetupArgs&) override;
+  void OnStart(const StartArgs&) override;
+  void OnStop(const StopArgs&) override;
+
+  // Convert a PacketTrace into a Perfetto trace packet.
+  void Fill(const PacketTrace& src,
+            ::perfetto::protos::pbzero::TracePacket& dst);
+
+ private:
+  void Loop();
+
+  // How often to poll the ring buffer, defined by the trace config.
+  uint32_t mPollMs;
+
+  // The function to process PacketTrace, typically a Perfetto sink.
+  std::function<void(const PacketTrace&)> mCallback;
+
+  // The BPF ring buffer handle.
+  std::unique_ptr<BpfRingbuf<PacketTrace>> mRingBuffer;
+
+  // The packet tracing config map (really a 1-element array).
+  BpfMap<uint32_t, bool> mConfigurationMap;
+
+  // This must be the last member, causing it to be the first deleted. If it is
+  // not, members required for callbacks can be deleted before it's stopped.
+  std::unique_ptr<perfetto::base::TaskRunner> mTaskRunner;
+};
+
+}  // namespace bpf
+}  // namespace android
diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
index 6cee08a..a884840 100644
--- a/service-t/src/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -17,6 +17,8 @@
 package com.android.server;
 
 import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.NETWORK_SETTINGS;
+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 +38,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;
@@ -63,6 +66,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
+import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.BinderUtils;
 import com.android.net.module.util.NetdUtils;
 import com.android.net.module.util.PermissionUtils;
@@ -100,6 +104,7 @@
 
     private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
     private static final InetAddress INADDR_ANY;
+    private static final InetAddress IN6ADDR_ANY;
 
     @VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
 
@@ -108,6 +113,8 @@
     static {
         try {
             INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
+            IN6ADDR_ANY = InetAddress.getByAddress(
+                    new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
         } catch (UnknownHostException e) {
             throw new RuntimeException(e);
         }
@@ -590,14 +597,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 +633,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() {
@@ -961,11 +1018,13 @@
     private final class EncapSocketRecord extends OwnedResourceRecord {
         private FileDescriptor mSocket;
         private final int mPort;
+        private final int mFamily;  // TODO: what about IPV6_ADDRFORM?
 
-        EncapSocketRecord(int resourceId, FileDescriptor socket, int port) {
+        EncapSocketRecord(int resourceId, FileDescriptor socket, int port, int family) {
             super(resourceId);
             mSocket = socket;
             mPort = port;
+            mFamily = family;
         }
 
         /** always guarded by IpSecService#this */
@@ -986,6 +1045,10 @@
             return mSocket;
         }
 
+        public int getFamily() {
+            return mFamily;
+        }
+
         @Override
         protected ResourceTracker getResourceTracker() {
             return getUserRecord().mSocketQuotaTracker;
@@ -1158,15 +1221,16 @@
      * and re-binding, during which the system could *technically* hand that port out to someone
      * else.
      */
-    private int bindToRandomPort(FileDescriptor sockFd) throws IOException {
+    private int bindToRandomPort(FileDescriptor sockFd, int family, InetAddress localAddr)
+            throws IOException {
         for (int i = MAX_PORT_BIND_ATTEMPTS; i > 0; i--) {
             try {
-                FileDescriptor probeSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-                Os.bind(probeSocket, INADDR_ANY, 0);
+                FileDescriptor probeSocket = Os.socket(family, SOCK_DGRAM, IPPROTO_UDP);
+                Os.bind(probeSocket, localAddr, 0);
                 int port = ((InetSocketAddress) Os.getsockname(probeSocket)).getPort();
                 Os.close(probeSocket);
                 Log.v(TAG, "Binding to port " + port);
-                Os.bind(sockFd, INADDR_ANY, port);
+                Os.bind(sockFd, localAddr, port);
                 return port;
             } catch (ErrnoException e) {
                 // Someone miraculously claimed the port just after we closed probeSocket.
@@ -1208,6 +1272,19 @@
     @Override
     public synchronized IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, IBinder binder)
             throws RemoteException {
+        // Experimental support for IPv6 UDP encap.
+        final int family;
+        final InetAddress localAddr;
+        if (SdkLevel.isAtLeastU() && port >= 65536) {
+            PermissionUtils.enforceNetworkStackPermissionOr(mContext, NETWORK_SETTINGS);
+            port -= 65536;
+            family = AF_INET6;
+            localAddr = IN6ADDR_ANY;
+        } else {
+            family = AF_INET;
+            localAddr = INADDR_ANY;
+        }
+
         if (port != 0 && (port < FREE_PORT_MIN || port > PORT_MAX)) {
             throw new IllegalArgumentException(
                     "Specified port number must be a valid non-reserved UDP port");
@@ -1226,7 +1303,7 @@
 
             FileDescriptor sockFd = null;
             try {
-                sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+                sockFd = Os.socket(family, SOCK_DGRAM, IPPROTO_UDP);
                 pFd = ParcelFileDescriptor.dup(sockFd);
             } finally {
                 IoUtils.closeQuietly(sockFd);
@@ -1243,15 +1320,16 @@
             mNetd.ipSecSetEncapSocketOwner(pFd, callingUid);
             if (port != 0) {
                 Log.v(TAG, "Binding to port " + port);
-                Os.bind(pFd.getFileDescriptor(), INADDR_ANY, port);
+                Os.bind(pFd.getFileDescriptor(), localAddr, port);
             } else {
-                port = bindToRandomPort(pFd.getFileDescriptor());
+                port = bindToRandomPort(pFd.getFileDescriptor(), family, localAddr);
             }
 
             userRecord.mEncapSocketRecords.put(
                     resourceId,
                     new RefcountedResource<EncapSocketRecord>(
-                            new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port),
+                            new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port,
+                                    family),
                             binder));
             return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port,
                     pFd.getFileDescriptor());
@@ -1528,6 +1606,7 @@
      */
     private void checkIpSecConfig(IpSecConfig config) {
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+        EncapSocketRecord encapSocketRecord = null;
 
         switch (config.getEncapType()) {
             case IpSecTransform.ENCAP_NONE:
@@ -1535,7 +1614,7 @@
             case IpSecTransform.ENCAP_ESPINUDP:
             case IpSecTransform.ENCAP_ESPINUDP_NON_IKE:
                 // Retrieve encap socket record; will throw IllegalArgumentException if not found
-                userRecord.mEncapSocketRecords.getResourceOrThrow(
+                encapSocketRecord = userRecord.mEncapSocketRecords.getResourceOrThrow(
                         config.getEncapSocketResourceId());
 
                 int port = config.getEncapRemotePort();
@@ -1589,10 +1668,9 @@
                             + ") have different address families.");
         }
 
-        // Throw an error if UDP Encapsulation is not used in IPv4.
-        if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) {
+        if (encapSocketRecord != null && encapSocketRecord.getFamily() != destinationFamily) {
             throw new IllegalArgumentException(
-                    "UDP Encapsulation is not supported for this address family");
+                    "UDP encapsulation socket and destination address families must match");
         }
 
         switch (config.getMode()) {
@@ -1630,6 +1708,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 +1812,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 +1909,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 +1996,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/NetworkStatsServiceInitializer.java b/service-t/src/com/android/server/NetworkStatsServiceInitializer.java
index 0ea126a..82a4fbd 100644
--- a/service-t/src/com/android/server/NetworkStatsServiceInitializer.java
+++ b/service-t/src/com/android/server/NetworkStatsServiceInitializer.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.net.TrafficStats;
+import android.os.Build;
 import android.util.Log;
 
 import com.android.modules.utils.build.SdkLevel;
@@ -46,6 +47,15 @@
                     /* allowIsolated= */ false);
             TrafficStats.init(getContext());
         }
+
+        // The following code registers the Perfetto Network Trace Handler on non-user builds.
+        // The enhanced tracing is intended to be used for debugging and diagnosing issues. This
+        // is conditional on the build type rather than `isDebuggable` to match the system_server
+        // selinux rules which only allow the Perfetto connection under the same circumstances.
+        if (SdkLevel.isAtLeastU() && !Build.TYPE.equals("user")) {
+            Log.i(TAG, "Initializing network tracing hooks");
+            NetworkStatsService.nativeInitNetworkTracing();
+        }
     }
 
     @Override
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index 1226eea..4ad39e1 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -17,12 +17,17 @@
 package com.android.server;
 
 import static android.net.ConnectivityManager.NETID_UNSET;
+import static android.net.nsd.NsdManager.MDNS_DISCOVERY_MANAGER_EVENT;
 import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.INetd;
+import android.net.InetAddresses;
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.mdns.aidl.DiscoveryInfo;
@@ -39,18 +44,29 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
-import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.net.module.util.DeviceConfigUtils;
 import com.android.net.module.util.PermissionUtils;
+import com.android.server.connectivity.mdns.ExecutorProvider;
+import com.android.server.connectivity.mdns.MdnsAdvertiser;
+import com.android.server.connectivity.mdns.MdnsDiscoveryManager;
+import com.android.server.connectivity.mdns.MdnsMultinetworkSocketClient;
+import com.android.server.connectivity.mdns.MdnsSearchOptions;
+import com.android.server.connectivity.mdns.MdnsServiceBrowserListener;
+import com.android.server.connectivity.mdns.MdnsServiceInfo;
+import com.android.server.connectivity.mdns.MdnsSocketClientBase;
+import com.android.server.connectivity.mdns.MdnsSocketProvider;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -58,7 +74,17 @@
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Network Service Discovery Service handles remote service discovery operation requests by
@@ -69,8 +95,22 @@
 public class NsdService extends INsdManager.Stub {
     private static final String TAG = "NsdService";
     private static final String MDNS_TAG = "mDnsConnector";
+    /**
+     * Enable discovery using the Java DiscoveryManager, instead of the legacy mdnsresponder
+     * implementation.
+     */
+    private static final String MDNS_DISCOVERY_MANAGER_VERSION = "mdns_discovery_manager_version";
+    private static final String LOCAL_DOMAIN_NAME = "local";
+    // Max label length as per RFC 1034/1035
+    private static final int MAX_LABEL_LENGTH = 63;
 
-    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    /**
+     * Enable advertising using the Java MdnsAdvertiser, instead of the legacy mdnsresponder
+     * implementation.
+     */
+    private static final String MDNS_ADVERTISER_VERSION = "mdns_advertiser_version";
+
+    public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     private static final long CLEANUP_DELAY_MS = 10000;
     private static final int IFACE_IDX_ANY = 0;
 
@@ -78,10 +118,21 @@
     private final NsdStateMachine mNsdStateMachine;
     private final MDnsManager mMDnsManager;
     private final MDnsEventCallback mMDnsEventCallback;
-    // WARNING : Accessing this value in any thread is not safe, it must only be changed in the
+    @NonNull
+    private final Dependencies mDeps;
+    @NonNull
+    private final MdnsMultinetworkSocketClient mMdnsSocketClient;
+    @NonNull
+    private final MdnsDiscoveryManager mMdnsDiscoveryManager;
+    @NonNull
+    private final MdnsSocketProvider mMdnsSocketProvider;
+    @NonNull
+    private final MdnsAdvertiser mAdvertiser;
+    // WARNING : Accessing these values in any thread is not safe, it must only be changed in the
     // state machine thread. If change this outside state machine, it will need to introduce
     // synchronization.
     private boolean mIsDaemonStarted = false;
+    private boolean mIsMonitoringSocketsStarted = false;
 
     /**
      * Clients receiving asynchronous messages
@@ -98,6 +149,110 @@
     // The count of the connected legacy clients.
     private int mLegacyClientCount = 0;
 
+    private static class MdnsListener implements MdnsServiceBrowserListener {
+        protected final int mClientId;
+        protected final int mTransactionId;
+        @NonNull
+        protected final NsdServiceInfo mReqServiceInfo;
+        @NonNull
+        protected final String mListenedServiceType;
+
+        MdnsListener(int clientId, int transactionId, @NonNull NsdServiceInfo reqServiceInfo,
+                @NonNull String listenedServiceType) {
+            mClientId = clientId;
+            mTransactionId = transactionId;
+            mReqServiceInfo = reqServiceInfo;
+            mListenedServiceType = listenedServiceType;
+        }
+
+        @NonNull
+        public String getListenedServiceType() {
+            return mListenedServiceType;
+        }
+
+        @Override
+        public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) { }
+
+        @Override
+        public void onServiceUpdated(@NonNull MdnsServiceInfo serviceInfo) { }
+
+        @Override
+        public void onServiceRemoved(@NonNull MdnsServiceInfo serviceInfo) { }
+
+        @Override
+        public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo) { }
+
+        @Override
+        public void onServiceNameRemoved(@NonNull MdnsServiceInfo serviceInfo) { }
+
+        @Override
+        public void onSearchStoppedWithError(int error) { }
+
+        @Override
+        public void onSearchFailedToStart() { }
+
+        @Override
+        public void onDiscoveryQuerySent(@NonNull List<String> subtypes, int transactionId) { }
+
+        @Override
+        public void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode) { }
+    }
+
+    private class DiscoveryListener extends MdnsListener {
+
+        DiscoveryListener(int clientId, int transactionId, @NonNull NsdServiceInfo reqServiceInfo,
+                @NonNull String listenServiceType) {
+            super(clientId, transactionId, reqServiceInfo, listenServiceType);
+        }
+
+        @Override
+        public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo) {
+            mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+                    NsdManager.SERVICE_FOUND,
+                    new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
+        }
+
+        @Override
+        public void onServiceNameRemoved(@NonNull MdnsServiceInfo serviceInfo) {
+            mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+                    NsdManager.SERVICE_LOST,
+                    new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
+        }
+    }
+
+    private class ResolutionListener extends MdnsListener {
+
+        ResolutionListener(int clientId, int transactionId, @NonNull NsdServiceInfo reqServiceInfo,
+                @NonNull String listenServiceType) {
+            super(clientId, transactionId, reqServiceInfo, listenServiceType);
+        }
+
+        @Override
+        public void onServiceFound(MdnsServiceInfo serviceInfo) {
+            mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+                    NsdManager.RESOLVE_SERVICE_SUCCEEDED,
+                    new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
+        }
+    }
+
+    /**
+     * Data class of mdns service callback information.
+     */
+    private static class MdnsEvent {
+        final int mClientId;
+        @NonNull
+        final String mRequestedServiceType;
+        @NonNull
+        final MdnsServiceInfo mMdnsServiceInfo;
+
+        MdnsEvent(int clientId, @NonNull String requestedServiceType,
+                @NonNull MdnsServiceInfo mdnsServiceInfo) {
+            mClientId = clientId;
+            mRequestedServiceType = requestedServiceType;
+            mMdnsServiceInfo = mdnsServiceInfo;
+        }
+    }
+
     private class NsdStateMachine extends StateMachine {
 
         private final DefaultState mDefaultState = new DefaultState();
@@ -148,6 +303,24 @@
             this.removeMessages(NsdManager.DAEMON_CLEANUP);
         }
 
+        private void maybeStartMonitoringSockets() {
+            if (mIsMonitoringSocketsStarted) {
+                if (DBG) Log.d(TAG, "Socket monitoring is already started.");
+                return;
+            }
+
+            mMdnsSocketProvider.startMonitoringSockets();
+            mIsMonitoringSocketsStarted = true;
+        }
+
+        private void maybeStopMonitoringSocketsIfNoActiveRequest() {
+            if (!mIsMonitoringSocketsStarted) return;
+            if (isAnyRequestActive()) return;
+
+            mMdnsSocketProvider.stopMonitoringSockets();
+            mIsMonitoringSocketsStarted = false;
+        }
+
         NsdStateMachine(String name, Handler handler) {
             super(name, handler);
             addState(mDefaultState);
@@ -180,10 +353,11 @@
                         cInfo = mClients.remove(connector);
                         if (cInfo != null) {
                             cInfo.expungeAllRequests();
-                            if (cInfo.isLegacy()) {
+                            if (cInfo.isPreSClient()) {
                                 mLegacyClientCount -= 1;
                             }
                         }
+                        maybeStopMonitoringSocketsIfNoActiveRequest();
                         maybeScheduleStop();
                         break;
                     case NsdManager.DISCOVER_SERVICES:
@@ -221,6 +395,20 @@
                                     clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
                         break;
+                    case NsdManager.STOP_RESOLUTION:
+                        cInfo = getClientInfoForReply(msg);
+                        if (cInfo != null) {
+                            cInfo.onStopResolutionFailed(
+                                    clientId, NsdManager.FAILURE_OPERATION_NOT_RUNNING);
+                        }
+                        break;
+                    case NsdManager.REGISTER_SERVICE_CALLBACK:
+                        cInfo = getClientInfoForReply(msg);
+                        if (cInfo != null) {
+                            cInfo.onServiceInfoCallbackRegistrationFailed(
+                                    clientId, NsdManager.FAILURE_BAD_PARAMETERS);
+                        }
+                        break;
                     case NsdManager.DAEMON_CLEANUP:
                         maybeStopDaemon();
                         break;
@@ -230,7 +418,7 @@
                         cInfo = getClientInfoForReply(msg);
                         if (cInfo != null) {
                             cancelStop();
-                            cInfo.setLegacy();
+                            cInfo.setPreSClient();
                             mLegacyClientCount += 1;
                             maybeStartDaemon();
                         }
@@ -262,26 +450,99 @@
             }
 
             private boolean requestLimitReached(ClientInfo clientInfo) {
-                if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
+                if (clientInfo.mClientRequests.size() >= ClientInfo.MAX_LIMIT) {
                     if (DBG) Log.d(TAG, "Exceeded max outstanding requests " + clientInfo);
                     return true;
                 }
                 return false;
             }
 
-            private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) {
-                clientInfo.mClientIds.put(clientId, globalId);
-                clientInfo.mClientRequests.put(clientId, what);
+            private void storeLegacyRequestMap(int clientId, int globalId, ClientInfo clientInfo,
+                    int what) {
+                clientInfo.mClientRequests.put(clientId, new LegacyClientRequest(globalId, what));
                 mIdToClientInfoMap.put(globalId, clientInfo);
                 // Remove the cleanup event because here comes a new request.
                 cancelStop();
             }
 
+            private void storeAdvertiserRequestMap(int clientId, int globalId,
+                    ClientInfo clientInfo) {
+                clientInfo.mClientRequests.put(clientId, new AdvertiserClientRequest(globalId));
+                mIdToClientInfoMap.put(globalId, clientInfo);
+            }
+
             private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
-                clientInfo.mClientIds.delete(clientId);
-                clientInfo.mClientRequests.delete(clientId);
+                final ClientRequest existing = clientInfo.mClientRequests.get(clientId);
+                if (existing == null) return;
+                clientInfo.mClientRequests.remove(clientId);
                 mIdToClientInfoMap.remove(globalId);
-                maybeScheduleStop();
+
+                if (existing instanceof LegacyClientRequest) {
+                    maybeScheduleStop();
+                } else {
+                    maybeStopMonitoringSocketsIfNoActiveRequest();
+                }
+            }
+
+            private void storeDiscoveryManagerRequestMap(int clientId, int globalId,
+                    MdnsListener listener, ClientInfo clientInfo) {
+                clientInfo.mClientRequests.put(clientId,
+                        new DiscoveryManagerRequest(globalId, listener));
+                mIdToClientInfoMap.put(globalId, clientInfo);
+            }
+
+            private void clearRegisteredServiceInfo(ClientInfo clientInfo) {
+                clientInfo.mRegisteredService = null;
+                clientInfo.mClientIdForServiceUpdates = 0;
+            }
+
+            /**
+             * Check the given service type is valid and construct it to a service type
+             * which can use for discovery / resolution service.
+             *
+             * <p> The valid service type should be 2 labels, or 3 labels if the query is for a
+             * subtype (see RFC6763 7.1). Each label is up to 63 characters and must start with an
+             * underscore; they are alphanumerical characters or dashes or underscore, except the
+             * last one that is just alphanumerical. The last label must be _tcp or _udp.
+             *
+             * @param serviceType the request service type for discovery / resolution service
+             * @return constructed service type or null if the given service type is invalid.
+             */
+            @Nullable
+            private String constructServiceType(String serviceType) {
+                if (TextUtils.isEmpty(serviceType)) return null;
+
+                final Pattern serviceTypePattern = Pattern.compile(
+                        "^(_[a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]\\.)?"
+                                + "(_[a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]\\._(?:tcp|udp))$");
+                final Matcher matcher = serviceTypePattern.matcher(serviceType);
+                if (!matcher.matches()) return null;
+                return matcher.group(1) == null
+                        ? serviceType
+                        : matcher.group(1) + "_sub." + matcher.group(2);
+            }
+
+            /**
+             * Truncate a service name to up to 63 UTF-8 bytes.
+             *
+             * See RFC6763 4.1.1: service instance names are UTF-8 and up to 63 bytes. Truncating
+             * names used in registerService follows historical behavior (see mdnsresponder
+             * handle_regservice_request).
+             */
+            @NonNull
+            private String truncateServiceName(@NonNull String originalName) {
+                // UTF-8 is at most 4 bytes per character; return early in the common case where
+                // the name can't possibly be over the limit given its string length.
+                if (originalName.length() <= MAX_LABEL_LENGTH / 4) return originalName;
+
+                final Charset utf8 = StandardCharsets.UTF_8;
+                final CharsetEncoder encoder = utf8.newEncoder();
+                final ByteBuffer out = ByteBuffer.allocate(MAX_LABEL_LENGTH);
+                // encode will write as many characters as possible to the out buffer, and just
+                // return an overflow code if there were too many characters (no need to check the
+                // return code here, this method truncates the name on purpose).
+                encoder.encode(CharBuffer.wrap(originalName), out, true /* endOfInput */);
+                return new String(out.array(), 0, out.position(), utf8);
             }
 
             @Override
@@ -291,7 +552,7 @@
                 final int clientId = msg.arg2;
                 final ListenerArgs args;
                 switch (msg.what) {
-                    case NsdManager.DISCOVER_SERVICES:
+                    case NsdManager.DISCOVER_SERVICES: {
                         if (DBG) Log.d(TAG, "Discover services");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
@@ -309,22 +570,46 @@
                             break;
                         }
 
-                        maybeStartDaemon();
+                        final NsdServiceInfo info = args.serviceInfo;
                         id = getUniqueId();
-                        if (discoverServices(id, args.serviceInfo)) {
-                            if (DBG) {
-                                Log.d(TAG, "Discover " + msg.arg2 + " " + id
-                                        + args.serviceInfo.getServiceType());
+                        if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)) {
+                            final String serviceType = constructServiceType(info.getServiceType());
+                            if (serviceType == null) {
+                                clientInfo.onDiscoverServicesFailed(clientId,
+                                        NsdManager.FAILURE_INTERNAL_ERROR);
+                                break;
                             }
-                            storeRequestMap(clientId, id, clientInfo, msg.what);
-                            clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo);
+
+                            final String listenServiceType = serviceType + ".local";
+                            maybeStartMonitoringSockets();
+                            final MdnsListener listener =
+                                    new DiscoveryListener(clientId, id, info, listenServiceType);
+                            final MdnsSearchOptions options = MdnsSearchOptions.newBuilder()
+                                    .setNetwork(info.getNetwork())
+                                    .setIsPassiveMode(true)
+                                    .build();
+                            mMdnsDiscoveryManager.registerListener(
+                                    listenServiceType, listener, options);
+                            storeDiscoveryManagerRequestMap(clientId, id, listener, clientInfo);
+                            clientInfo.onDiscoverServicesStarted(clientId, info);
                         } else {
-                            stopServiceDiscovery(id);
-                            clientInfo.onDiscoverServicesFailed(clientId,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
+                            maybeStartDaemon();
+                            if (discoverServices(id, info)) {
+                                if (DBG) {
+                                    Log.d(TAG, "Discover " + msg.arg2 + " " + id
+                                            + info.getServiceType());
+                                }
+                                storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
+                                clientInfo.onDiscoverServicesStarted(clientId, info);
+                            } else {
+                                stopServiceDiscovery(id);
+                                clientInfo.onDiscoverServicesFailed(clientId,
+                                        NsdManager.FAILURE_INTERNAL_ERROR);
+                            }
                         }
                         break;
-                    case NsdManager.STOP_DISCOVERY:
+                    }
+                    case NsdManager.STOP_DISCOVERY: {
                         if (DBG) Log.d(TAG, "Stop service discovery");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
@@ -336,22 +621,34 @@
                             break;
                         }
 
-                        try {
-                            id = clientInfo.mClientIds.get(clientId);
-                        } catch (NullPointerException e) {
-                            clientInfo.onStopDiscoveryFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+                        if (request == null) {
+                            Log.e(TAG, "Unknown client request in STOP_DISCOVERY");
                             break;
                         }
-                        removeRequestMap(clientId, id, clientInfo);
-                        if (stopServiceDiscovery(id)) {
+                        id = request.mGlobalId;
+                        // Note isMdnsDiscoveryManagerEnabled may have changed to false at this
+                        // point, so this needs to check the type of the original request to
+                        // unregister instead of looking at the flag value.
+                        if (request instanceof DiscoveryManagerRequest) {
+                            final MdnsListener listener =
+                                    ((DiscoveryManagerRequest) request).mListener;
+                            mMdnsDiscoveryManager.unregisterListener(
+                                    listener.getListenedServiceType(), listener);
+                            removeRequestMap(clientId, id, clientInfo);
                             clientInfo.onStopDiscoverySucceeded(clientId);
                         } else {
-                            clientInfo.onStopDiscoveryFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            removeRequestMap(clientId, id, clientInfo);
+                            if (stopServiceDiscovery(id)) {
+                                clientInfo.onStopDiscoverySucceeded(clientId);
+                            } else {
+                                clientInfo.onStopDiscoveryFailed(
+                                        clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            }
                         }
                         break;
-                    case NsdManager.REGISTER_SERVICE:
+                    }
+                    case NsdManager.REGISTER_SERVICE: {
                         if (DBG) Log.d(TAG, "Register service");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
@@ -369,19 +666,40 @@
                             break;
                         }
 
-                        maybeStartDaemon();
                         id = getUniqueId();
-                        if (registerService(id, args.serviceInfo)) {
-                            if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
-                            storeRequestMap(clientId, id, clientInfo, msg.what);
-                            // Return success after mDns reports success
+                        if (mDeps.isMdnsAdvertiserEnabled(mContext)) {
+                            final NsdServiceInfo serviceInfo = args.serviceInfo;
+                            final String serviceType = serviceInfo.getServiceType();
+                            final String registerServiceType = constructServiceType(serviceType);
+                            if (registerServiceType == null) {
+                                Log.e(TAG, "Invalid service type: " + serviceType);
+                                clientInfo.onRegisterServiceFailed(clientId,
+                                        NsdManager.FAILURE_INTERNAL_ERROR);
+                                break;
+                            }
+                            serviceInfo.setServiceType(registerServiceType);
+                            serviceInfo.setServiceName(truncateServiceName(
+                                    serviceInfo.getServiceName()));
+
+                            maybeStartMonitoringSockets();
+                            mAdvertiser.addService(id, serviceInfo);
+                            storeAdvertiserRequestMap(clientId, id, clientInfo);
                         } else {
-                            unregisterService(id);
-                            clientInfo.onRegisterServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            maybeStartDaemon();
+                            if (registerService(id, args.serviceInfo)) {
+                                if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
+                                storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
+                                // Return success after mDns reports success
+                            } else {
+                                unregisterService(id);
+                                clientInfo.onRegisterServiceFailed(
+                                        clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            }
+
                         }
                         break;
-                    case NsdManager.UNREGISTER_SERVICE:
+                    }
+                    case NsdManager.UNREGISTER_SERVICE: {
                         if (DBG) Log.d(TAG, "unregister service");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
@@ -392,16 +710,31 @@
                             Log.e(TAG, "Unknown connector in unregistration");
                             break;
                         }
-                        id = clientInfo.mClientIds.get(clientId);
+                        final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+                        if (request == null) {
+                            Log.e(TAG, "Unknown client request in UNREGISTER_SERVICE");
+                            break;
+                        }
+                        id = request.mGlobalId;
                         removeRequestMap(clientId, id, clientInfo);
-                        if (unregisterService(id)) {
+
+                        // Note isMdnsAdvertiserEnabled may have changed to false at this point,
+                        // so this needs to check the type of the original request to unregister
+                        // instead of looking at the flag value.
+                        if (request instanceof AdvertiserClientRequest) {
+                            mAdvertiser.removeService(id);
                             clientInfo.onUnregisterServiceSucceeded(clientId);
                         } else {
-                            clientInfo.onUnregisterServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            if (unregisterService(id)) {
+                                clientInfo.onUnregisterServiceSucceeded(clientId);
+                            } else {
+                                clientInfo.onUnregisterServiceFailed(
+                                        clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            }
                         }
                         break;
-                    case NsdManager.RESOLVE_SERVICE:
+                    }
+                    case NsdManager.RESOLVE_SERVICE: {
                         if (DBG) Log.d(TAG, "Resolve service");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
@@ -413,8 +746,88 @@
                             break;
                         }
 
-                        if (clientInfo.mResolvedService != null) {
-                            clientInfo.onResolveServiceFailed(
+                        final NsdServiceInfo info = args.serviceInfo;
+                        id = getUniqueId();
+                        if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)) {
+                            final String serviceType = constructServiceType(info.getServiceType());
+                            if (serviceType == null) {
+                                clientInfo.onResolveServiceFailed(clientId,
+                                        NsdManager.FAILURE_INTERNAL_ERROR);
+                                break;
+                            }
+                            final String resolveServiceType = serviceType + ".local";
+
+                            maybeStartMonitoringSockets();
+                            final MdnsListener listener =
+                                    new ResolutionListener(clientId, id, info, resolveServiceType);
+                            final MdnsSearchOptions options = MdnsSearchOptions.newBuilder()
+                                    .setNetwork(info.getNetwork())
+                                    .setIsPassiveMode(true)
+                                    .build();
+                            mMdnsDiscoveryManager.registerListener(
+                                    resolveServiceType, listener, options);
+                            storeDiscoveryManagerRequestMap(clientId, id, listener, clientInfo);
+                        } else {
+                            if (clientInfo.mResolvedService != null) {
+                                clientInfo.onResolveServiceFailed(
+                                        clientId, NsdManager.FAILURE_ALREADY_ACTIVE);
+                                break;
+                            }
+
+                            maybeStartDaemon();
+                            if (resolveService(id, args.serviceInfo)) {
+                                clientInfo.mResolvedService = new NsdServiceInfo();
+                                storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
+                            } else {
+                                clientInfo.onResolveServiceFailed(
+                                        clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            }
+                        }
+                        break;
+                    }
+                    case NsdManager.STOP_RESOLUTION: {
+                        if (DBG) Log.d(TAG, "Stop service resolution");
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
+                        // If the binder death notification for a INsdManagerCallback was received
+                        // before any calls are received by NsdService, the clientInfo would be
+                        // cleared and cause NPE. Add a null check here to prevent this corner case.
+                        if (clientInfo == null) {
+                            Log.e(TAG, "Unknown connector in stop resolution");
+                            break;
+                        }
+
+                        final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+                        if (request == null) {
+                            Log.e(TAG, "Unknown client request in STOP_RESOLUTION");
+                            break;
+                        }
+                        id = request.mGlobalId;
+                        removeRequestMap(clientId, id, clientInfo);
+                        if (stopResolveService(id)) {
+                            clientInfo.onStopResolutionSucceeded(clientId);
+                        } else {
+                            clientInfo.onStopResolutionFailed(
+                                    clientId, NsdManager.FAILURE_OPERATION_NOT_RUNNING);
+                        }
+                        clientInfo.mResolvedService = null;
+                        // TODO: Implement the stop resolution with MdnsDiscoveryManager.
+                        break;
+                    }
+                    case NsdManager.REGISTER_SERVICE_CALLBACK:
+                        if (DBG) Log.d(TAG, "Register a service callback");
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
+                        // If the binder death notification for a INsdManagerCallback was received
+                        // before any calls are received by NsdService, the clientInfo would be
+                        // cleared and cause NPE. Add a null check here to prevent this corner case.
+                        if (clientInfo == null) {
+                            Log.e(TAG, "Unknown connector in callback registration");
+                            break;
+                        }
+
+                        if (clientInfo.mRegisteredService != null) {
+                            clientInfo.onServiceInfoCallbackRegistrationFailed(
                                     clientId, NsdManager.FAILURE_ALREADY_ACTIVE);
                             break;
                         }
@@ -422,24 +835,70 @@
                         maybeStartDaemon();
                         id = getUniqueId();
                         if (resolveService(id, args.serviceInfo)) {
-                            clientInfo.mResolvedService = new NsdServiceInfo();
-                            storeRequestMap(clientId, id, clientInfo, msg.what);
+                            clientInfo.mRegisteredService = new NsdServiceInfo();
+                            clientInfo.mClientIdForServiceUpdates = clientId;
+                            storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
                         } else {
-                            clientInfo.onResolveServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            clientInfo.onServiceInfoCallbackRegistrationFailed(
+                                    clientId, NsdManager.FAILURE_BAD_PARAMETERS);
                         }
                         break;
+                    case NsdManager.UNREGISTER_SERVICE_CALLBACK: {
+                        if (DBG) Log.d(TAG, "Unregister a service callback");
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
+                        // If the binder death notification for a INsdManagerCallback was received
+                        // before any calls are received by NsdService, the clientInfo would be
+                        // cleared and cause NPE. Add a null check here to prevent this corner case.
+                        if (clientInfo == null) {
+                            Log.e(TAG, "Unknown connector in callback unregistration");
+                            break;
+                        }
+
+                        final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+                        if (request == null) {
+                            Log.e(TAG, "Unknown client request in STOP_RESOLUTION");
+                            break;
+                        }
+                        id = request.mGlobalId;
+                        removeRequestMap(clientId, id, clientInfo);
+                        if (stopResolveService(id)) {
+                            clientInfo.onServiceInfoCallbackUnregistered(clientId);
+                        } else {
+                            Log.e(TAG, "Failed to unregister service info callback");
+                        }
+                        clearRegisteredServiceInfo(clientInfo);
+                        break;
+                    }
                     case MDNS_SERVICE_EVENT:
                         if (!handleMDnsServiceEvent(msg.arg1, msg.arg2, msg.obj)) {
                             return NOT_HANDLED;
                         }
                         break;
+                    case MDNS_DISCOVERY_MANAGER_EVENT:
+                        if (!handleMdnsDiscoveryManagerEvent(msg.arg1, msg.arg2, msg.obj)) {
+                            return NOT_HANDLED;
+                        }
+                        break;
                     default:
                         return NOT_HANDLED;
                 }
                 return HANDLED;
             }
 
+            private void notifyResolveFailedResult(boolean isListenedToUpdates, int clientId,
+                    ClientInfo clientInfo, int error) {
+                if (isListenedToUpdates) {
+                    clientInfo.onServiceInfoCallbackRegistrationFailed(clientId, error);
+                    clearRegisteredServiceInfo(clientInfo);
+                } else {
+                    // The resolve API always returned FAILURE_INTERNAL_ERROR on error; keep it
+                    // for backwards compatibility.
+                    clientInfo.onResolveServiceFailed(clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                    clientInfo.mResolvedService = null;
+                }
+            }
+
             private boolean handleMDnsServiceEvent(int code, int id, Object obj) {
                 NsdServiceInfo servInfo;
                 ClientInfo clientInfo = mIdToClientInfoMap.get(id);
@@ -474,6 +933,12 @@
                             // interfaces that do not have an associated Network.
                             break;
                         }
+                        if (foundNetId == INetd.DUMMY_NET_ID) {
+                            // Ignore services on the dummy0 interface: they are only seen when
+                            // discovering locally advertised services, and are not reachable
+                            // through that interface.
+                            break;
+                        }
                         setServiceNetworkForCallback(servInfo, info.netId, info.interfaceIdx);
                         clientInfo.onServiceFound(clientId, servInfo);
                         break;
@@ -490,6 +955,8 @@
                         // found services on the same interface index and their network at the time
                         setServiceNetworkForCallback(servInfo, lostNetId, info.interfaceIdx);
                         clientInfo.onServiceLost(clientId, servInfo);
+                        // TODO: also support registered service lost when not discovering
+                        clientInfo.maybeNotifyRegisteredServiceLost(servInfo);
                         break;
                     }
                     case IMDnsEventListener.SERVICE_DISCOVERY_FAILED:
@@ -526,10 +993,15 @@
                         String rest = fullName.substring(index);
                         String type = rest.replace(".local.", "");
 
-                        clientInfo.mResolvedService.setServiceName(name);
-                        clientInfo.mResolvedService.setServiceType(type);
-                        clientInfo.mResolvedService.setPort(info.port);
-                        clientInfo.mResolvedService.setTxtRecords(info.txtRecord);
+                        final boolean isListenedToUpdates =
+                                clientId == clientInfo.mClientIdForServiceUpdates;
+                        final NsdServiceInfo serviceInfo = isListenedToUpdates
+                                ? clientInfo.mRegisteredService : clientInfo.mResolvedService;
+
+                        serviceInfo.setServiceName(name);
+                        serviceInfo.setServiceType(type);
+                        serviceInfo.setPort(info.port);
+                        serviceInfo.setTxtRecords(info.txtRecord);
                         // Network will be added after SERVICE_GET_ADDR_SUCCESS
 
                         stopResolveService(id);
@@ -537,11 +1009,11 @@
 
                         final int id2 = getUniqueId();
                         if (getAddrInfo(id2, info.hostname, info.interfaceIdx)) {
-                            storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
+                            storeLegacyRequestMap(clientId, id2, clientInfo,
+                                    NsdManager.RESOLVE_SERVICE);
                         } else {
-                            clientInfo.onResolveServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                            clientInfo.mResolvedService = null;
+                            notifyResolveFailedResult(isListenedToUpdates, clientId, clientInfo,
+                                    NsdManager.FAILURE_BAD_PARAMETERS);
                         }
                         break;
                     }
@@ -549,17 +1021,17 @@
                         /* NNN resolveId errorCode */
                         stopResolveService(id);
                         removeRequestMap(clientId, id, clientInfo);
-                        clientInfo.mResolvedService = null;
-                        clientInfo.onResolveServiceFailed(
-                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        notifyResolveFailedResult(
+                                clientId == clientInfo.mClientIdForServiceUpdates,
+                                clientId, clientInfo, NsdManager.FAILURE_BAD_PARAMETERS);
                         break;
                     case IMDnsEventListener.SERVICE_GET_ADDR_FAILED:
                         /* NNN resolveId errorCode */
                         stopGetAddrInfo(id);
                         removeRequestMap(clientId, id, clientInfo);
-                        clientInfo.mResolvedService = null;
-                        clientInfo.onResolveServiceFailed(
-                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        notifyResolveFailedResult(
+                                clientId == clientInfo.mClientIdForServiceUpdates,
+                                clientId, clientInfo, NsdManager.FAILURE_BAD_PARAMETERS);
                         break;
                     case IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS: {
                         /* NNN resolveId hostname ttl addr interfaceIdx netId */
@@ -576,19 +1048,126 @@
                         // If the resolved service is on an interface without a network, consider it
                         // as a failure: it would not be usable by apps as they would need
                         // privileged permissions.
-                        if (netId != NETID_UNSET && serviceHost != null) {
-                            clientInfo.mResolvedService.setHost(serviceHost);
-                            setServiceNetworkForCallback(clientInfo.mResolvedService,
-                                    netId, info.interfaceIdx);
-                            clientInfo.onResolveServiceSucceeded(
-                                    clientId, clientInfo.mResolvedService);
+                        if (clientId == clientInfo.mClientIdForServiceUpdates) {
+                            if (netId != NETID_UNSET && serviceHost != null) {
+                                setServiceNetworkForCallback(clientInfo.mRegisteredService,
+                                        netId, info.interfaceIdx);
+                                final List<InetAddress> addresses =
+                                        clientInfo.mRegisteredService.getHostAddresses();
+                                addresses.add(serviceHost);
+                                clientInfo.mRegisteredService.setHostAddresses(addresses);
+                                clientInfo.onServiceUpdated(
+                                        clientId, clientInfo.mRegisteredService);
+                            } else {
+                                stopGetAddrInfo(id);
+                                removeRequestMap(clientId, id, clientInfo);
+                                clearRegisteredServiceInfo(clientInfo);
+                                clientInfo.onServiceInfoCallbackRegistrationFailed(
+                                        clientId, NsdManager.FAILURE_BAD_PARAMETERS);
+                            }
                         } else {
+                            if (netId != NETID_UNSET && serviceHost != null) {
+                                clientInfo.mResolvedService.setHost(serviceHost);
+                                setServiceNetworkForCallback(clientInfo.mResolvedService,
+                                        netId, info.interfaceIdx);
+                                clientInfo.onResolveServiceSucceeded(
+                                        clientId, clientInfo.mResolvedService);
+                            } else {
+                                clientInfo.onResolveServiceFailed(
+                                        clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                            }
+                            stopGetAddrInfo(id);
+                            removeRequestMap(clientId, id, clientInfo);
+                            clientInfo.mResolvedService = null;
+                        }
+                        break;
+                    }
+                    default:
+                        return false;
+                }
+                return true;
+            }
+
+            private NsdServiceInfo buildNsdServiceInfoFromMdnsEvent(final MdnsEvent event) {
+                final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo;
+                final String serviceType = event.mRequestedServiceType;
+                final String serviceName = serviceInfo.getServiceInstanceName();
+                final NsdServiceInfo servInfo = new NsdServiceInfo(serviceName, serviceType);
+                final Network network = serviceInfo.getNetwork();
+                setServiceNetworkForCallback(
+                        servInfo,
+                        network == null ? NETID_UNSET : network.netId,
+                        serviceInfo.getInterfaceIndex());
+                return servInfo;
+            }
+
+            private boolean handleMdnsDiscoveryManagerEvent(
+                    int transactionId, int code, Object obj) {
+                final ClientInfo clientInfo = mIdToClientInfoMap.get(transactionId);
+                if (clientInfo == null) {
+                    Log.e(TAG, String.format(
+                            "id %d for %d has no client mapping", transactionId, code));
+                    return false;
+                }
+
+                final MdnsEvent event = (MdnsEvent) obj;
+                final int clientId = event.mClientId;
+                final NsdServiceInfo info = buildNsdServiceInfoFromMdnsEvent(event);
+                if (DBG) {
+                    Log.d(TAG, String.format("MdnsDiscoveryManager event code=%s transactionId=%d",
+                            NsdManager.nameOf(code), transactionId));
+                }
+                switch (code) {
+                    case NsdManager.SERVICE_FOUND:
+                        clientInfo.onServiceFound(clientId, info);
+                        break;
+                    case NsdManager.SERVICE_LOST:
+                        clientInfo.onServiceLost(clientId, info);
+                        break;
+                    case NsdManager.RESOLVE_SERVICE_SUCCEEDED: {
+                        final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+                        if (request == null) {
+                            Log.e(TAG, "Unknown client request in RESOLVE_SERVICE_SUCCEEDED");
+                            break;
+                        }
+                        final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo;
+                        // Add '.' in front of the service type that aligns with historical behavior
+                        info.setServiceType("." + event.mRequestedServiceType);
+                        info.setPort(serviceInfo.getPort());
+
+                        Map<String, String> attrs = serviceInfo.getAttributes();
+                        for (Map.Entry<String, String> kv : attrs.entrySet()) {
+                            final String key = kv.getKey();
+                            try {
+                                info.setAttribute(key, serviceInfo.getAttributeAsBytes(key));
+                            } catch (IllegalArgumentException e) {
+                                Log.e(TAG, "Invalid attribute", e);
+                            }
+                        }
+                        try {
+                            if (serviceInfo.getIpv4Address() != null) {
+                                info.setHost(InetAddresses.parseNumericAddress(
+                                        serviceInfo.getIpv4Address()));
+                            } else {
+                                info.setHost(InetAddresses.parseNumericAddress(
+                                        serviceInfo.getIpv6Address()));
+                            }
+                            clientInfo.onResolveServiceSucceeded(clientId, info);
+                        } catch (IllegalArgumentException e) {
+                            Log.wtf(TAG, "Invalid address in RESOLVE_SERVICE_SUCCEEDED", e);
                             clientInfo.onResolveServiceFailed(
                                     clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
-                        stopGetAddrInfo(id);
-                        removeRequestMap(clientId, id, clientInfo);
-                        clientInfo.mResolvedService = null;
+
+                        // Unregister the listener immediately like IMDnsEventListener design
+                        if (!(request instanceof DiscoveryManagerRequest)) {
+                            Log.wtf(TAG, "non-DiscoveryManager request in DiscoveryManager event");
+                            break;
+                        }
+                        final MdnsListener listener = ((DiscoveryManagerRequest) request).mListener;
+                        mMdnsDiscoveryManager.unregisterListener(
+                                listener.getListenedServiceType(), listener);
+                        removeRequestMap(clientId, transactionId, clientInfo);
                         break;
                     }
                     default:
@@ -650,12 +1229,79 @@
 
     @VisibleForTesting
     NsdService(Context ctx, Handler handler, long cleanupDelayMs) {
+        this(ctx, handler, cleanupDelayMs, new Dependencies());
+    }
+
+    @VisibleForTesting
+    NsdService(Context ctx, Handler handler, long cleanupDelayMs, Dependencies deps) {
         mCleanupDelayMs = cleanupDelayMs;
         mContext = ctx;
         mNsdStateMachine = new NsdStateMachine(TAG, handler);
         mNsdStateMachine.start();
         mMDnsManager = ctx.getSystemService(MDnsManager.class);
         mMDnsEventCallback = new MDnsEventCallback(mNsdStateMachine);
+        mDeps = deps;
+
+        mMdnsSocketProvider = deps.makeMdnsSocketProvider(ctx, handler.getLooper());
+        mMdnsSocketClient =
+                new MdnsMultinetworkSocketClient(handler.getLooper(), mMdnsSocketProvider);
+        mMdnsDiscoveryManager =
+                deps.makeMdnsDiscoveryManager(new ExecutorProvider(), mMdnsSocketClient);
+        handler.post(() -> mMdnsSocketClient.setCallback(mMdnsDiscoveryManager));
+        mAdvertiser = deps.makeMdnsAdvertiser(handler.getLooper(), mMdnsSocketProvider,
+                new AdvertiserCallback());
+    }
+
+    /**
+     * Dependencies of NsdService, for injection in tests.
+     */
+    @VisibleForTesting
+    public static class Dependencies {
+        /**
+         * Check whether the MdnsDiscoveryManager feature is enabled.
+         *
+         * @param context The global context information about an app environment.
+         * @return true if the MdnsDiscoveryManager feature is enabled.
+         */
+        public boolean isMdnsDiscoveryManagerEnabled(Context context) {
+            return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
+                    MDNS_DISCOVERY_MANAGER_VERSION, false /* defaultEnabled */);
+        }
+
+        /**
+         * Check whether the MdnsAdvertiser feature is enabled.
+         *
+         * @param context The global context information about an app environment.
+         * @return true if the MdnsAdvertiser feature is enabled.
+         */
+        public boolean isMdnsAdvertiserEnabled(Context context) {
+            return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
+                    MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
+        }
+
+        /**
+         * @see MdnsDiscoveryManager
+         */
+        public MdnsDiscoveryManager makeMdnsDiscoveryManager(
+                ExecutorProvider executorProvider, MdnsSocketClientBase socketClient) {
+            return new MdnsDiscoveryManager(executorProvider, socketClient);
+        }
+
+        /**
+         * @see MdnsAdvertiser
+         */
+        public MdnsAdvertiser makeMdnsAdvertiser(
+                @NonNull Looper looper, @NonNull MdnsSocketProvider socketProvider,
+                @NonNull MdnsAdvertiser.AdvertiserCallback cb) {
+            return new MdnsAdvertiser(looper, socketProvider, cb);
+        }
+
+        /**
+         * @see MdnsSocketProvider
+         */
+        public MdnsSocketProvider makeMdnsSocketProvider(Context context, Looper looper) {
+            return new MdnsSocketProvider(context, looper);
+        }
     }
 
     public static NsdService create(Context context) {
@@ -708,6 +1354,49 @@
         }
     }
 
+    private class AdvertiserCallback implements MdnsAdvertiser.AdvertiserCallback {
+        @Override
+        public void onRegisterServiceSucceeded(int serviceId, NsdServiceInfo registeredInfo) {
+            final ClientInfo clientInfo = getClientInfoOrLog(serviceId);
+            if (clientInfo == null) return;
+
+            final int clientId = getClientIdOrLog(clientInfo, serviceId);
+            if (clientId < 0) return;
+
+            // onRegisterServiceSucceeded only has the service name in its info. This aligns with
+            // historical behavior.
+            final NsdServiceInfo cbInfo = new NsdServiceInfo(registeredInfo.getServiceName(), null);
+            clientInfo.onRegisterServiceSucceeded(clientId, cbInfo);
+        }
+
+        @Override
+        public void onRegisterServiceFailed(int serviceId, int errorCode) {
+            final ClientInfo clientInfo = getClientInfoOrLog(serviceId);
+            if (clientInfo == null) return;
+
+            final int clientId = getClientIdOrLog(clientInfo, serviceId);
+            if (clientId < 0) return;
+
+            clientInfo.onRegisterServiceFailed(clientId, errorCode);
+        }
+
+        private ClientInfo getClientInfoOrLog(int serviceId) {
+            final ClientInfo clientInfo = mIdToClientInfoMap.get(serviceId);
+            if (clientInfo == null) {
+                Log.e(TAG, String.format("Callback for service %d has no client", serviceId));
+            }
+            return clientInfo;
+        }
+
+        private int getClientIdOrLog(@NonNull ClientInfo info, int serviceId) {
+            final int clientId = info.getClientId(serviceId);
+            if (clientId < 0) {
+                Log.e(TAG, String.format("Client ID not found for service %d", serviceId));
+            }
+            return clientId;
+        }
+    }
+
     @Override
     public INsdServiceConnector connect(INsdManagerCallback cb) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService");
@@ -763,6 +1452,26 @@
         }
 
         @Override
+        public void stopResolution(int listenerKey) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.STOP_RESOLUTION, 0, listenerKey, new ListenerArgs(this, null)));
+        }
+
+        @Override
+        public void registerServiceInfoCallback(int listenerKey, NsdServiceInfo serviceInfo) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.REGISTER_SERVICE_CALLBACK, 0, listenerKey,
+                    new ListenerArgs(this, serviceInfo)));
+        }
+
+        @Override
+        public void unregisterServiceInfoCallback(int listenerKey) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.UNREGISTER_SERVICE_CALLBACK, 0, listenerKey,
+                    new ListenerArgs(this, null)));
+        }
+
+        @Override
         public void startDaemon() {
             mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
                     NsdManager.DAEMON_STARTUP, new ListenerArgs(this, null)));
@@ -903,6 +1612,39 @@
         mNsdStateMachine.dump(fd, pw, args);
     }
 
+    private abstract static class ClientRequest {
+        private final int mGlobalId;
+
+        private ClientRequest(int globalId) {
+            mGlobalId = globalId;
+        }
+    }
+
+    private static class LegacyClientRequest extends ClientRequest {
+        private final int mRequestCode;
+
+        private LegacyClientRequest(int globalId, int requestCode) {
+            super(globalId);
+            mRequestCode = requestCode;
+        }
+    }
+
+    private static class AdvertiserClientRequest extends ClientRequest {
+        private AdvertiserClientRequest(int globalId) {
+            super(globalId);
+        }
+    }
+
+    private static class DiscoveryManagerRequest extends ClientRequest {
+        @NonNull
+        private final MdnsListener mListener;
+
+        private DiscoveryManagerRequest(int globalId, @NonNull MdnsListener listener) {
+            super(globalId);
+            mListener = listener;
+        }
+    }
+
     /* Information tracked per client */
     private class ClientInfo {
 
@@ -911,14 +1653,16 @@
         /* Remembers a resolved service until getaddrinfo completes */
         private NsdServiceInfo mResolvedService;
 
-        /* A map from client id to unique id sent to mDns */
-        private final SparseIntArray mClientIds = new SparseIntArray();
-
-        /* A map from client id to the type of the request we had received */
-        private final SparseIntArray mClientRequests = new SparseIntArray();
+        /* A map from client-side ID (listenerKey) to the request */
+        private final SparseArray<ClientRequest> mClientRequests = new SparseArray<>();
 
         // The target SDK of this client < Build.VERSION_CODES.S
-        private boolean mIsLegacy = false;
+        private boolean mIsPreSClient = false;
+
+        /*** The service that is registered to listen to its updates */
+        private NsdServiceInfo mRegisteredService;
+        /*** The client id that listen to updates */
+        private int mClientIdForServiceUpdates;
 
         private ClientInfo(INsdManagerCallback cb) {
             mCb = cb;
@@ -929,38 +1673,59 @@
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("mResolvedService ").append(mResolvedService).append("\n");
-            sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
-            for(int i = 0; i< mClientIds.size(); i++) {
-                int clientID = mClientIds.keyAt(i);
-                sb.append("clientId ").append(clientID).
-                    append(" mDnsId ").append(mClientIds.valueAt(i)).
-                    append(" type ").append(mClientRequests.get(clientID)).append("\n");
+            sb.append("mIsLegacy ").append(mIsPreSClient).append("\n");
+            for (int i = 0; i < mClientRequests.size(); i++) {
+                int clientID = mClientRequests.keyAt(i);
+                sb.append("clientId ")
+                        .append(clientID)
+                        .append(" mDnsId ").append(mClientRequests.valueAt(i).mGlobalId)
+                        .append(" type ").append(
+                                mClientRequests.valueAt(i).getClass().getSimpleName())
+                        .append("\n");
             }
             return sb.toString();
         }
 
-        private boolean isLegacy() {
-            return mIsLegacy;
+        private boolean isPreSClient() {
+            return mIsPreSClient;
         }
 
-        private void setLegacy() {
-            mIsLegacy = true;
+        private void setPreSClient() {
+            mIsPreSClient = true;
         }
 
         // Remove any pending requests from the global map when we get rid of a client,
         // and send cancellations to the daemon.
         private void expungeAllRequests() {
-            int globalId, clientId, i;
             // TODO: to keep handler responsive, do not clean all requests for that client at once.
-            for (i = 0; i < mClientIds.size(); i++) {
-                clientId = mClientIds.keyAt(i);
-                globalId = mClientIds.valueAt(i);
+            for (int i = 0; i < mClientRequests.size(); i++) {
+                final int clientId = mClientRequests.keyAt(i);
+                final ClientRequest request = mClientRequests.valueAt(i);
+                final int globalId = request.mGlobalId;
                 mIdToClientInfoMap.remove(globalId);
                 if (DBG) {
                     Log.d(TAG, "Terminating client-ID " + clientId
                             + " global-ID " + globalId + " type " + mClientRequests.get(clientId));
                 }
-                switch (mClientRequests.get(clientId)) {
+
+                if (request instanceof DiscoveryManagerRequest) {
+                    final MdnsListener listener =
+                            ((DiscoveryManagerRequest) request).mListener;
+                    mMdnsDiscoveryManager.unregisterListener(
+                            listener.getListenedServiceType(), listener);
+                    continue;
+                }
+
+                if (request instanceof AdvertiserClientRequest) {
+                    mAdvertiser.removeService(globalId);
+                    continue;
+                }
+
+                if (!(request instanceof LegacyClientRequest)) {
+                    throw new IllegalStateException("Unknown request type: " + request.getClass());
+                }
+
+                switch (((LegacyClientRequest) request).mRequestCode) {
                     case NsdManager.DISCOVER_SERVICES:
                         stopServiceDiscovery(globalId);
                         break;
@@ -974,18 +1739,31 @@
                         break;
                 }
             }
-            mClientIds.clear();
             mClientRequests.clear();
         }
 
-        // mClientIds is a sparse array of listener id -> mDnsClient id.  For a given mDnsClient id,
-        // return the corresponding listener id.  mDnsClient id is also called a global id.
+        // mClientRequests is a sparse array of listener id -> ClientRequest.  For a given
+        // mDnsClient id, return the corresponding listener id.  mDnsClient id is also called a
+        // global id.
         private int getClientId(final int globalId) {
-            int idx = mClientIds.indexOfValue(globalId);
-            if (idx < 0) {
-                return idx;
+            for (int i = 0; i < mClientRequests.size(); i++) {
+                if (mClientRequests.valueAt(i).mGlobalId == globalId) {
+                    return mClientRequests.keyAt(i);
+                }
             }
-            return mClientIds.keyAt(idx);
+            return -1;
+        }
+
+        private void maybeNotifyRegisteredServiceLost(@NonNull NsdServiceInfo info) {
+            if (mRegisteredService == null) return;
+            if (!Objects.equals(mRegisteredService.getServiceName(), info.getServiceName())) return;
+            // Resolved services have a leading dot appended at the beginning of their type, but in
+            // discovered info it's at the end
+            if (!Objects.equals(
+                    mRegisteredService.getServiceType() + ".", "." + info.getServiceType())) {
+                return;
+            }
+            onServiceUpdatedLost(mClientIdForServiceUpdates);
         }
 
         void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
@@ -1083,5 +1861,53 @@
                 Log.e(TAG, "Error calling onResolveServiceSucceeded", e);
             }
         }
+
+        void onStopResolutionFailed(int listenerKey, int error) {
+            try {
+                mCb.onStopResolutionFailed(listenerKey, error);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onStopResolutionFailed", e);
+            }
+        }
+
+        void onStopResolutionSucceeded(int listenerKey) {
+            try {
+                mCb.onStopResolutionSucceeded(listenerKey);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onStopResolutionSucceeded", e);
+            }
+        }
+
+        void onServiceInfoCallbackRegistrationFailed(int listenerKey, int error) {
+            try {
+                mCb.onServiceInfoCallbackRegistrationFailed(listenerKey, error);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onServiceInfoCallbackRegistrationFailed", e);
+            }
+        }
+
+        void onServiceUpdated(int listenerKey, NsdServiceInfo info) {
+            try {
+                mCb.onServiceUpdated(listenerKey, info);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onServiceUpdated", e);
+            }
+        }
+
+        void onServiceUpdatedLost(int listenerKey) {
+            try {
+                mCb.onServiceUpdatedLost(listenerKey);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onServiceUpdatedLost", e);
+            }
+        }
+
+        void onServiceInfoCallbackUnregistered(int listenerKey) {
+            try {
+                mCb.onServiceInfoCallbackUnregistered(listenerKey);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onServiceInfoCallbackUnregistered", e);
+            }
+        }
     }
 }
diff --git a/service/mdns/com/android/server/connectivity/mdns/ConnectivityMonitor.java b/service-t/src/com/android/server/connectivity/mdns/ConnectivityMonitor.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/ConnectivityMonitor.java
rename to service-t/src/com/android/server/connectivity/mdns/ConnectivityMonitor.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/ConnectivityMonitorWithConnectivityManager.java b/service-t/src/com/android/server/connectivity/mdns/ConnectivityMonitorWithConnectivityManager.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/ConnectivityMonitorWithConnectivityManager.java
rename to service-t/src/com/android/server/connectivity/mdns/ConnectivityMonitorWithConnectivityManager.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
similarity index 67%
rename from service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
rename to service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
index f7871f3..fdd1478 100644
--- a/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
+++ b/service-t/src/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/ExecutorProvider.java b/service-t/src/com/android/server/connectivity/mdns/ExecutorProvider.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/ExecutorProvider.java
rename to service-t/src/com/android/server/connectivity/mdns/ExecutorProvider.java
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
new file mode 100644
index 0000000..977478a
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
@@ -0,0 +1,474 @@
+/*
+ * 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.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.util.List;
+import java.util.Map;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+/**
+ * MdnsAdvertiser manages advertising services per {@link com.android.server.NsdService} requests.
+ *
+ * All methods except the constructor must be called on the looper thread.
+ */
+public class MdnsAdvertiser {
+    private static final String TAG = MdnsAdvertiser.class.getSimpleName();
+    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 (any(mAllAdvertisers, (k, 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) {
+            if (DBG) {
+                Log.v(TAG, "Found conflict, restarted probing for service " + serviceId);
+            }
+
+            final Registration registration = mRegistrations.get(serviceId);
+            if (registration == null) return;
+            if (registration.mNotifiedRegistrationSuccess) {
+                // TODO: consider notifying clients that the service is no longer registered with
+                // the old name (back to probing). The legacy implementation did not send any
+                // callback though; it only sent onServiceRegistered after re-probing finishes
+                // (with the old, conflicting, actually not used name as argument... The new
+                // implementation will send callbacks with the new name).
+                registration.mNotifiedRegistrationSuccess = false;
+
+                // The service was done probing, just reset it to probing state (RFC6762 9.)
+                forAllAdvertisers(a -> a.restartProbingForConflict(serviceId));
+                return;
+            }
+
+            // Conflict was found during probing; rename once to find a name that has no conflict
+            registration.updateForConflict(
+                    registration.makeNewServiceInfoForConflict(1 /* renameCount */),
+                    1 /* renameCount */);
+
+            // Keep renaming if the new name conflicts in local registrations
+            updateRegistrationUntilNoConflict((net, adv) -> adv.hasRegistration(registration),
+                    registration);
+
+            // Update advertisers to use the new name
+            forAllAdvertisers(a -> a.renameServiceForConflict(
+                    serviceId, registration.getServiceInfo()));
+        }
+
+        @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);
+        }
+    };
+
+    private boolean hasAnyConflict(
+            @NonNull BiPredicate<Network, InterfaceAdvertiserRequest> applicableAdvertiserFilter,
+            @NonNull NsdServiceInfo newInfo) {
+        return any(mAdvertiserRequests, (network, adv) ->
+                applicableAdvertiserFilter.test(network, adv) && adv.hasConflict(newInfo));
+    }
+
+    private void updateRegistrationUntilNoConflict(
+            @NonNull BiPredicate<Network, InterfaceAdvertiserRequest> applicableAdvertiserFilter,
+            @NonNull Registration registration) {
+        int renameCount = 0;
+        NsdServiceInfo newInfo = registration.getServiceInfo();
+        while (hasAnyConflict(applicableAdvertiserFilter, newInfo)) {
+            renameCount++;
+            newInfo = registration.makeNewServiceInfoForConflict(renameCount);
+        }
+        registration.updateForConflict(newInfo, renameCount);
+    }
+
+    /**
+     * 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;
+        }
+
+        /**
+         * Return whether this {@link InterfaceAdvertiserRequest} has the given registration.
+         */
+        boolean hasRegistration(@NonNull Registration registration) {
+            return mPendingRegistrations.indexOfValue(registration) >= 0;
+        }
+
+        /**
+         * Return whether using the proposed new {@link NsdServiceInfo} to add a registration would
+         * cause a conflict in this {@link InterfaceAdvertiserRequest}.
+         */
+        boolean hasConflict(@NonNull NsdServiceInfo newInfo) {
+            return getConflictingService(newInfo) >= 0;
+        }
+
+        /**
+         * 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;
+        }
+
+        /**
+         * Add a service.
+         *
+         * Conflicts must be checked via {@link #getConflictingService} before attempting to add.
+         */
+        void addService(int id, Registration registration) {
+            mPendingRegistrations.put(id, registration);
+            for (int i = 0; i < mAdvertisers.size(); i++) {
+                try {
+                    mAdvertisers.valueAt(i).addService(id, registration.getServiceInfo());
+                } catch (NameConflictException e) {
+                    Log.wtf(TAG, "Name conflict adding services that should have unique names", e);
+                }
+            }
+        }
+
+        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.
+         *
+         * @param newInfo New service info to use.
+         * @param renameCount How many renames were done before reaching the current name.
+         */
+        private void updateForConflict(@NonNull NsdServiceInfo newInfo, int renameCount) {
+            mConflictCount += renameCount;
+            mServiceInfo = newInfo;
+        }
+
+        /**
+         * Make a new service name for the registration, 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.
+         *
+         * @param renameCount How much to increase the number suffix for this conflict.
+         */
+        @NonNull
+        public NsdServiceInfo makeNewServiceInfoForConflict(int renameCount) {
+            // 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 + renameCount + 1) + ")");
+            newInfo.setServiceType(mServiceInfo.getServiceType());
+            for (Map.Entry<String, byte[]> attr : mServiceInfo.getAttributes().entrySet()) {
+                newInfo.setAttribute(attr.getKey(),
+                        attr.getValue() == null ? null : new String(attr.getValue()));
+            }
+            newInfo.setHost(mServiceInfo.getHost());
+            newInfo.setPort(mServiceInfo.getPort());
+            newInfo.setNetwork(mServiceInfo.getNetwork());
+            // interfaceIndex is not set when registering
+            return newInfo;
+        }
+
+        @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);
+        }
+
+        final Network network = service.getNetwork();
+        final Registration registration = new Registration(service);
+        final BiPredicate<Network, InterfaceAdvertiserRequest> checkConflictFilter;
+        if (network == null) {
+            // If registering on all networks, no advertiser must have conflicts
+            checkConflictFilter = (net, adv) -> true;
+        } else {
+            // If registering on one network, the matching network advertiser and the one for all
+            // networks must not have conflicts
+            checkConflictFilter = (net, adv) -> net == null || network.equals(net);
+        }
+
+        updateRegistrationUntilNoConflict(checkConflictFilter, registration);
+
+        InterfaceAdvertiserRequest advertiser = mAdvertiserRequests.get(network);
+        if (advertiser == null) {
+            advertiser = new InterfaceAdvertiserRequest(network);
+            mAdvertiserRequests.put(network, advertiser);
+        }
+        advertiser.addService(id, registration);
+        mRegistrations.put(id, registration);
+    }
+
+    /**
+     * 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 static <K, V> boolean any(@NonNull ArrayMap<K, V> map,
+            @NonNull BiPredicate<K, V> predicate) {
+        for (int i = 0; i < map.size(); i++) {
+            if (predicate.test(map.keyAt(i), map.valueAt(i))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void forAllAdvertisers(@NonNull Consumer<MdnsInterfaceAdvertiser> consumer) {
+        any(mAllAdvertisers, (socket, advertiser) -> {
+            consumer.accept(advertiser);
+            return false;
+        });
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsAnnouncer.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAnnouncer.java
similarity index 61%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsAnnouncer.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsAnnouncer.java
index 91e08a8..27fc945 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsAnnouncer.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAnnouncer.java
@@ -22,52 +22,58 @@
 
 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.
  *
  * This allows maintaining other hosts' caches up-to-date. See RFC6762 8.3.
  */
-public class MdnsAnnouncer extends MdnsPacketRepeater<MdnsAnnouncer.AnnouncementInfo> {
+public class MdnsAnnouncer extends MdnsPacketRepeater<MdnsAnnouncer.BaseAnnouncementInfo> {
     private static final long ANNOUNCEMENT_INITIAL_DELAY_MS = 1000L;
     @VisibleForTesting
     static final int ANNOUNCEMENT_COUNT = 8;
 
+    // Matches delay and GoodbyeCount used by the legacy implementation
+    private static final long EXIT_DELAY_MS = 2000L;
+    private static final int EXIT_COUNT = 3;
+
     @NonNull
     private final String mLogTag;
 
-    static class AnnouncementInfo implements MdnsPacketRepeater.Request {
+    /** Base class for announcement requests to send with {@link MdnsAnnouncer}. */
+    public abstract static class BaseAnnouncementInfo implements MdnsPacketRepeater.Request {
+        private final int mServiceId;
         @NonNull
         private final MdnsPacket mPacket;
-        @NonNull
-        private final Supplier<Iterable<SocketAddress>> mDestinationsSupplier;
 
-        AnnouncementInfo(List<MdnsRecord> announcedRecords, List<MdnsRecord> additionalRecords,
-                Supplier<Iterable<SocketAddress>> destinationsSupplier) {
-            // Records to announce (as answers)
-            // Records to place in the "Additional records", with NSEC negative responses
-            // to mark records that have been verified unique
+        protected BaseAnnouncementInfo(int serviceId, @NonNull List<MdnsRecord> announcedRecords,
+                @NonNull List<MdnsRecord> additionalRecords) {
+            mServiceId = serviceId;
             final int flags = 0x8400; // Response, authoritative (rfc6762 18.4)
             mPacket = new MdnsPacket(flags,
                     Collections.emptyList() /* questions */,
                     announcedRecords,
                     Collections.emptyList() /* authorityRecords */,
                     additionalRecords);
-            mDestinationsSupplier = destinationsSupplier;
+        }
+
+        public int getServiceId() {
+            return mServiceId;
         }
 
         @Override
         public MdnsPacket getPacket(int index) {
             return mPacket;
         }
+    }
 
-        @Override
-        public Iterable<SocketAddress> getDestinations(int index) {
-            return mDestinationsSupplier.get();
+    /** Announcement request to send with {@link MdnsAnnouncer}. */
+    public static class AnnouncementInfo extends BaseAnnouncementInfo {
+        AnnouncementInfo(int serviceId, List<MdnsRecord> announcedRecords,
+                List<MdnsRecord> additionalRecords) {
+            super(serviceId, announcedRecords, additionalRecords);
         }
 
         @Override
@@ -82,9 +88,26 @@
         }
     }
 
+    /** Service exit announcement request to send with {@link MdnsAnnouncer}. */
+    public static class ExitAnnouncementInfo extends BaseAnnouncementInfo {
+        ExitAnnouncementInfo(int serviceId, List<MdnsRecord> announcedRecords) {
+            super(serviceId, announcedRecords, Collections.emptyList() /* additionalRecords */);
+        }
+
+        @Override
+        public long getDelayMs(int nextIndex) {
+            return EXIT_DELAY_MS;
+        }
+
+        @Override
+        public int getNumSends() {
+            return EXIT_COUNT;
+        }
+    }
+
     public MdnsAnnouncer(@NonNull String interfaceTag, @NonNull Looper looper,
             @NonNull MdnsReplySender replySender,
-            @Nullable PacketRepeaterCallback<AnnouncementInfo> cb) {
+            @Nullable PacketRepeaterCallback<BaseAnnouncementInfo> cb) {
         super(looper, replySender, cb);
         mLogTag = MdnsAnnouncer.class.getSimpleName() + "/" + interfaceTag;
     }
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsAnyRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAnyRecord.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsAnyRecord.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsAnyRecord.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsConfigs.java b/service-t/src/com/android/server/connectivity/mdns/MdnsConfigs.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsConfigs.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsConfigs.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsConstants.java b/service-t/src/com/android/server/connectivity/mdns/MdnsConstants.java
similarity index 97%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsConstants.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsConstants.java
index 396be5f..f0e1717 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsConstants.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsConstants.java
@@ -37,6 +37,7 @@
     public static final int FLAGS_QUERY = 0x0000;
     public static final int FLAGS_RESPONSE_MASK = 0xF80F;
     public static final int FLAGS_RESPONSE = 0x8000;
+    public static final int FLAG_TRUNCATED = 0x0200;
     public static final int QCLASS_INTERNET = 0x0001;
     public static final int QCLASS_UNICAST = 0x8000;
     public static final String SUBTYPE_LABEL = "_sub";
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
similarity index 89%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
index 0f3c23a..cc6b98b 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
+++ b/service-t/src/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/MdnsInetAddressRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
new file mode 100644
index 0000000..c616e01
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
@@ -0,0 +1,344 @@
+/*
+ * 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.net.module.util.HexDump;
+import com.android.server.connectivity.mdns.MdnsAnnouncer.BaseAnnouncementInfo;
+import com.android.server.connectivity.mdns.MdnsPacketRepeater.PacketRepeaterCallback;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.List;
+
+/**
+ * A class that handles advertising services on a {@link MdnsInterfaceSocket} tied to an interface.
+ */
+public class MdnsInterfaceAdvertiser implements MulticastPacketReader.PacketHandler {
+    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<BaseAnnouncementInfo> {
+        @Override
+        public void onSent(int index, @NonNull BaseAnnouncementInfo info) {
+            mRecordRepository.onAdvertisementSent(info.getServiceId());
+        }
+
+        @Override
+        public void onFinished(@NonNull BaseAnnouncementInfo info) {
+            if (info instanceof MdnsAnnouncer.ExitAnnouncementInfo) {
+                mRecordRepository.removeService(info.getServiceId());
+
+                if (mRecordRepository.getServicesCount() == 0) {
+                    destroyNow();
+                }
+            }
+        }
+    }
+
+    /**
+     * 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 String interfaceTag, @NonNull Looper looper,
+                @NonNull MdnsInterfaceSocket socket, @NonNull byte[] packetCreationBuffer) {
+            return new MdnsReplySender(interfaceTag, looper, socket, packetCreationBuffer);
+        }
+
+        /** @see MdnsAnnouncer */
+        public MdnsAnnouncer makeMdnsAnnouncer(@NonNull String interfaceTag, @NonNull Looper looper,
+                @NonNull MdnsReplySender replySender,
+                @Nullable PacketRepeaterCallback<MdnsAnnouncer.BaseAnnouncementInfo> 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(logTag, 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() {
+        mSocket.addPacketHandler(this);
+    }
+
+    /**
+     * 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) {
+        if (!mRecordRepository.hasActiveService(id)) return;
+        mProber.stop(id);
+        mAnnouncer.stop(id);
+        final MdnsAnnouncer.ExitAnnouncementInfo 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);
+        }
+        mReplySender.cancelAll();
+        mSocket.removePacketHandler(this);
+        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) {
+        final MdnsProber.ProbingInfo probingInfo = mRecordRepository.setServiceProbing(serviceId);
+        if (probingInfo == null) return;
+
+        mProber.restartForConflict(probingInfo);
+    }
+
+    /**
+     * Rename a service following a conflict found on the network, and restart probing.
+     *
+     * If the service was not registered on this {@link MdnsInterfaceAdvertiser}, this is a no-op.
+     */
+    public void renameServiceForConflict(int serviceId, NsdServiceInfo newInfo) {
+        final MdnsProber.ProbingInfo probingInfo = mRecordRepository.renameServiceForConflict(
+                serviceId, newInfo);
+        if (probingInfo == null) return;
+
+        mProber.restartForConflict(probingInfo);
+    }
+
+    /**
+     * 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);
+    }
+
+    @Override
+    public void handlePacket(byte[] recvbuf, int length, InetSocketAddress src) {
+        final MdnsPacket packet;
+        try {
+            packet = MdnsPacket.parse(new MdnsPacketReader(recvbuf, length));
+        } catch (MdnsPacket.ParseException e) {
+            Log.e(mTag, "Error parsing mDNS packet", e);
+            if (DBG) {
+                Log.v(
+                        mTag, "Packet: " + HexDump.toHexString(recvbuf, 0, length));
+            }
+            return;
+        }
+
+        if (DBG) {
+            Log.v(mTag,
+                    "Parsed packet with " + packet.questions.size() + " questions, "
+                            + packet.answers.size() + " answers, "
+                            + packet.authorityRecords.size() + " authority, "
+                            + packet.additionalRecords.size() + " additional from " + src);
+        }
+
+        for (int conflictServiceId : mRecordRepository.getConflictingServices(packet)) {
+            mCbHandler.post(() -> mCb.onServiceConflict(this, conflictServiceId));
+        }
+
+        // Even in case of conflict, add replies for other services. But in general conflicts would
+        // happen when the incoming packet has answer records (not a question), so there will be no
+        // answer. One exception is simultaneous probe tiebreaking (rfc6762 8.2), in which case the
+        // conflicting service is still probing and won't reply either.
+        final MdnsRecordRepository.ReplyInfo answers = mRecordRepository.getReply(packet, src);
+
+        if (answers == null) return;
+        mReplySender.queueReply(answers);
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
similarity index 66%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
index 6090415..119c7a8 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
+++ b/service-t/src/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,40 @@
         }
     }
 
-    /*** 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);
+    }
+
+    /**
+     * Remove a handler added via {@link #addPacketHandler}. If the handler is not present, this is
+     * a no-op.
+     */
+    public void removePacketHandler(@NonNull MulticastPacketReader.PacketHandler handler) {
+        mPacketReader.removePacketHandler(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-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
new file mode 100644
index 0000000..d959065
--- /dev/null
+++ b/service-t/src/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/MdnsNsecRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsNsecRecord.java
similarity index 87%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsNsecRecord.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsNsecRecord.java
index 06fdd5e..6ec2f99 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsNsecRecord.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsNsecRecord.java
@@ -17,12 +17,14 @@
 package com.android.server.connectivity.mdns;
 
 import android.net.DnsResolver;
+import android.text.TextUtils;
 
 import com.android.net.module.util.CollectionUtils;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * A mDNS "NSEC" record, used in particular for negative responses (RFC6762 6.1).
@@ -140,4 +142,30 @@
         writer.writeUInt8(bytesInBlock);
         writer.writeBytes(bytes);
     }
+
+    @Override
+    public String toString() {
+        return "NSEC: NextDomain: " + TextUtils.join(".", mNextDomain)
+                + " Types " + Arrays.toString(mTypes);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(),
+                Arrays.hashCode(mNextDomain), Arrays.hashCode(mTypes));
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+        if (!(other instanceof MdnsNsecRecord)) {
+            return false;
+        }
+
+        return super.equals(other)
+                && Arrays.equals(mNextDomain, ((MdnsNsecRecord) other).mNextDomain)
+                && Arrays.equals(mTypes, ((MdnsNsecRecord) other).mTypes);
+    }
 }
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsPacket.java b/service-t/src/com/android/server/connectivity/mdns/MdnsPacket.java
new file mode 100644
index 0000000..27002b9
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsPacket.java
@@ -0,0 +1,231 @@
+/*
+ * 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.util.Log;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A class holding data that can be included in a mDNS packet.
+ */
+public class MdnsPacket {
+    private static final String TAG = MdnsPacket.class.getSimpleName();
+
+    public final int flags;
+    @NonNull
+    public final List<MdnsRecord> questions;
+    @NonNull
+    public final List<MdnsRecord> answers;
+    @NonNull
+    public final List<MdnsRecord> authorityRecords;
+    @NonNull
+    public final List<MdnsRecord> additionalRecords;
+
+    MdnsPacket(int flags,
+            @NonNull List<MdnsRecord> questions,
+            @NonNull List<MdnsRecord> answers,
+            @NonNull List<MdnsRecord> authorityRecords,
+            @NonNull List<MdnsRecord> additionalRecords) {
+        this.flags = flags;
+        this.questions = Collections.unmodifiableList(questions);
+        this.answers = Collections.unmodifiableList(answers);
+        this.authorityRecords = Collections.unmodifiableList(authorityRecords);
+        this.additionalRecords = Collections.unmodifiableList(additionalRecords);
+    }
+
+    /**
+     * Exception thrown on parse errors.
+     */
+    public static class ParseException extends IOException {
+        public final int code;
+
+        public ParseException(int code, @NonNull String message, @Nullable Throwable cause) {
+            super(message, cause);
+            this.code = code;
+        }
+    }
+
+    /**
+     * Parse the packet in the provided {@link MdnsPacketReader}.
+     */
+    @NonNull
+    public static MdnsPacket parse(@NonNull MdnsPacketReader reader) throws ParseException {
+        final int flags;
+        try {
+            reader.readUInt16(); // transaction ID (not used)
+            flags = reader.readUInt16();
+        } catch (EOFException e) {
+            throw new ParseException(MdnsResponseErrorCode.ERROR_END_OF_FILE,
+                    "Reached the end of the mDNS response unexpectedly.", e);
+        }
+        return parseRecordsSection(reader, flags);
+    }
+
+    /**
+     * Parse the records section of a mDNS packet in the provided {@link MdnsPacketReader}.
+     *
+     * The records section starts with the questions count, just after the packet flags.
+     */
+    public static MdnsPacket parseRecordsSection(@NonNull MdnsPacketReader reader, int flags)
+            throws ParseException {
+        try {
+            final int numQuestions = reader.readUInt16();
+            final int numAnswers = reader.readUInt16();
+            final int numAuthority = reader.readUInt16();
+            final int numAdditional = reader.readUInt16();
+
+            final ArrayList<MdnsRecord> questions = parseRecords(reader, numQuestions, true);
+            final ArrayList<MdnsRecord> answers = parseRecords(reader, numAnswers, false);
+            final ArrayList<MdnsRecord> authority = parseRecords(reader, numAuthority, false);
+            final ArrayList<MdnsRecord> additional = parseRecords(reader, numAdditional, false);
+
+            return new MdnsPacket(flags, questions, answers, authority, additional);
+        } catch (EOFException e) {
+            throw new ParseException(MdnsResponseErrorCode.ERROR_END_OF_FILE,
+                    "Reached the end of the mDNS response unexpectedly.", e);
+        }
+    }
+
+    private static ArrayList<MdnsRecord> parseRecords(@NonNull MdnsPacketReader reader, int count,
+            boolean isQuestion)
+            throws ParseException {
+        final ArrayList<MdnsRecord> records = new ArrayList<>(count);
+        for (int i = 0; i < count; ++i) {
+            final MdnsRecord record = parseRecord(reader, isQuestion);
+            if (record != null) {
+                records.add(record);
+            }
+        }
+        return records;
+    }
+
+    @Nullable
+    private static MdnsRecord parseRecord(@NonNull MdnsPacketReader reader, boolean isQuestion)
+            throws ParseException {
+        String[] name;
+        try {
+            name = reader.readLabels();
+        } catch (IOException e) {
+            throw new ParseException(MdnsResponseErrorCode.ERROR_READING_RECORD_NAME,
+                    "Failed to read labels from mDNS response.", e);
+        }
+
+        final int type;
+        try {
+            type = reader.readUInt16();
+        } catch (EOFException e) {
+            throw new ParseException(MdnsResponseErrorCode.ERROR_END_OF_FILE,
+                    "Reached the end of the mDNS response unexpectedly.", e);
+        }
+
+        switch (type) {
+            case MdnsRecord.TYPE_A: {
+                try {
+                    return new MdnsInetAddressRecord(name, MdnsRecord.TYPE_A, reader, isQuestion);
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_READING_A_RDATA,
+                            "Failed to read A record from mDNS response.", e);
+                }
+            }
+
+            case MdnsRecord.TYPE_AAAA: {
+                try {
+                    return new MdnsInetAddressRecord(name,
+                            MdnsRecord.TYPE_AAAA, reader, isQuestion);
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_READING_AAAA_RDATA,
+                            "Failed to read AAAA record from mDNS response.", e);
+                }
+            }
+
+            case MdnsRecord.TYPE_PTR: {
+                try {
+                    return new MdnsPointerRecord(name, reader, isQuestion);
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_READING_PTR_RDATA,
+                            "Failed to read PTR record from mDNS response.", e);
+                }
+            }
+
+            case MdnsRecord.TYPE_SRV: {
+                try {
+                    return new MdnsServiceRecord(name, reader, isQuestion);
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_READING_SRV_RDATA,
+                            "Failed to read SRV record from mDNS response.", e);
+                }
+            }
+
+            case MdnsRecord.TYPE_TXT: {
+                try {
+                    return new MdnsTextRecord(name, reader, isQuestion);
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_READING_TXT_RDATA,
+                            "Failed to read TXT record from mDNS response.", e);
+                }
+            }
+
+            case MdnsRecord.TYPE_NSEC: {
+                try {
+                    return new MdnsNsecRecord(name, reader, isQuestion);
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_READING_NSEC_RDATA,
+                            "Failed to read NSEC record from mDNS response.", e);
+                }
+            }
+
+            case MdnsRecord.TYPE_ANY: {
+                try {
+                    return new MdnsAnyRecord(name, reader);
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_READING_ANY_RDATA,
+                            "Failed to read TYPE_ANY record from mDNS response.", e);
+                }
+            }
+
+            default: {
+                try {
+                    if (MdnsAdvertiser.DBG) {
+                        Log.i(TAG, "Skipping parsing of record of unhandled type " + type);
+                    }
+                    skipMdnsRecord(reader, isQuestion);
+                    return null;
+                } catch (IOException e) {
+                    throw new ParseException(MdnsResponseErrorCode.ERROR_SKIPPING_UNKNOWN_RECORD,
+                            "Failed to skip mDNS record.", e);
+                }
+            }
+        }
+    }
+
+    private static void skipMdnsRecord(@NonNull MdnsPacketReader reader, boolean isQuestion)
+            throws IOException {
+        reader.skip(2); // Skip the class
+        if (isQuestion) return;
+        // Skip TTL and data
+        reader.skip(4);
+        int dataLength = reader.readUInt16();
+        reader.skip(dataLength);
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsPacketReader.java b/service-t/src/com/android/server/connectivity/mdns/MdnsPacketReader.java
similarity index 97%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsPacketReader.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsPacketReader.java
index 856a2cd..aa38844 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsPacketReader.java
+++ b/service-t/src/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-t/src/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
similarity index 88%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
index 015dbd8..4c385da 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsPacketRepeater.java
@@ -16,6 +16,9 @@
 
 package com.android.server.connectivity.mdns;
 
+import static com.android.server.connectivity.mdns.MdnsRecordRepository.IPV4_ADDR;
+import static com.android.server.connectivity.mdns.MdnsRecordRepository.IPV6_ADDR;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Handler;
@@ -24,7 +27,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 +35,10 @@
  */
 public abstract class MdnsPacketRepeater<T extends MdnsPacketRepeater.Request> {
     private static final boolean DBG = MdnsAdvertiser.DBG;
+    private static final InetSocketAddress[] ALL_ADDRS = new InetSocketAddress[] {
+            IPV4_ADDR, IPV6_ADDR
+    };
+
     @NonNull
     private final MdnsReplySender mReplySender;
     @NonNull
@@ -70,12 +77,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 +111,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 ID " + msg.what);
             }
-            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/MdnsPacketWriter.java b/service-t/src/com/android/server/connectivity/mdns/MdnsPacketWriter.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsPacketWriter.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsPacketWriter.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsPointerRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsPointerRecord.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsProber.java b/service-t/src/com/android/server/connectivity/mdns/MdnsProber.java
similarity index 84%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsProber.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsProber.java
index db7049e..669b323 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsProber.java
+++ b/service-t/src/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.
@@ -35,37 +33,32 @@
  * TODO: implement receiving replies and handling conflicts.
  */
 public class MdnsProber extends MdnsPacketRepeater<MdnsProber.ProbingInfo> {
+    private static final long CONFLICT_RETRY_DELAY_MS = 5_000L;
     @NonNull
     private final String mLogTag;
 
     public MdnsProber(@NonNull String interfaceTag, @NonNull Looper looper,
             @NonNull MdnsReplySender replySender,
             @NonNull PacketRepeaterCallback<ProbingInfo> cb) {
-        // 3 packets as per https://datatracker.ietf.org/doc/html/rfc6762#section-8.1
         super(looper, replySender, cb);
         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
@@ -153,4 +140,18 @@
     private void startProbing(@NonNull ProbingInfo info, long delay) {
         startSending(info.getServiceId(), info, delay);
     }
+
+    /**
+     * Restart probing with new service info as a conflict was found.
+     */
+    public void restartForConflict(@NonNull ProbingInfo newInfo) {
+        stop(newInfo.getServiceId());
+
+        /* RFC 6762 8.1: "If fifteen conflicts occur within any ten-second period, then the host
+        MUST wait at least five seconds before each successive additional probe attempt. [...]
+        For very simple devices, a valid way to comply with this requirement is to always wait
+        five seconds after any failed probe attempt before trying again. */
+        // TODO: count 15 conflicts in 10s instead of waiting for 5s every time
+        startProbing(newInfo, CONFLICT_RETRY_DELAY_MS);
+    }
 }
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
similarity index 99%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsRecord.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
index 00871ea..bcee9d1 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsRecord.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
@@ -45,6 +45,7 @@
     private static final int FLAG_CACHE_FLUSH = 0x8000;
 
     public static final long RECEIPT_TIME_NOT_SENT = 0L;
+    public static final int CLASS_ANY = 0x00ff;
 
     /** Status indicating that the record is current. */
     public static final int STATUS_OK = 0;
@@ -317,4 +318,4 @@
             return (recordType * 31) + Arrays.hashCode(recordName);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java b/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java
new file mode 100644
index 0000000..e975ab4
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java
@@ -0,0 +1,885 @@
+/*
+ * 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.annotation.TargetApi;
+import android.net.LinkAddress;
+import android.net.nsd.NsdServiceInfo;
+import android.os.Build;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.util.ArraySet;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.HexDump;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Random;
+import java.util.Set;
+import java.util.TreeMap;
+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.
+ */
+@TargetApi(Build.VERSION_CODES.TIRAMISU) // Allow calling T+ APIs; this is only loaded on T+
+public class MdnsRecordRepository {
+    // RFC6762 p.15
+    private static final long MIN_MULTICAST_REPLY_INTERVAL_MS = 1_000L;
+
+    // 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 };
+
+    public static final InetSocketAddress IPV6_ADDR = new InetSocketAddress(
+            MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
+    public static final InetSocketAddress IPV4_ADDR = new InetSocketAddress(
+            MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT);
+
+    @NonNull
+    private final Random mDelayGenerator = new Random();
+    // Map of service unique ID -> records for service
+    @NonNull
+    private final SparseArray<ServiceRegistration> mServices = new SparseArray<>();
+    @NonNull
+    private final List<RecordInfo<?>> mGeneralRecords = new ArrayList<>();
+    @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;
+
+        /**
+         * Last time (as per SystemClock.elapsedRealtime) when advertised via multicast, 0 if never
+         */
+        public long lastAdvertisedTimeMs;
+
+        /**
+         * Last time (as per SystemClock.elapsedRealtime) when sent via unicast or multicast,
+         * 0 if never
+         */
+        public long lastSentTimeMs;
+
+        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) {
+        mGeneralRecords.clear();
+        for (LinkAddress addr : newAddresses) {
+            final String[] revDnsAddr = getReverseDnsAddress(addr.getAddress());
+            mGeneralRecords.add(new RecordInfo<>(
+                    null /* serviceInfo */,
+                    new MdnsPointerRecord(
+                            revDnsAddr,
+                            0L /* receiptTimeMillis */,
+                            true /* cacheFlush */,
+                            NAME_RECORDS_TTL_MILLIS,
+                            mDeviceHostname),
+                    false /* sharedName */, false /* probing */));
+
+            mGeneralRecords.add(new RecordInfo<>(
+                    null /* serviceInfo */,
+                    new MdnsInetAddressRecord(
+                            mDeviceHostname,
+                            0L /* receiptTimeMillis */,
+                            true /* cacheFlush */,
+                            NAME_RECORDS_TTL_MILLIS,
+                            addr.getAddress()),
+                    false /* sharedName */, false /* probing */));
+        }
+    }
+
+    /**
+     * 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.ExitAnnouncementInfo exitService(int id) {
+        final ServiceRegistration registration = mServices.get(id);
+        if (registration == null) return null;
+        if (registration.exiting) return null;
+
+        // Send exit (TTL 0) for the PTR record, if the record was sent (in particular don't send
+        // if still probing)
+        if (registration.ptrRecord.lastSentTimeMs == 0L) {
+            return null;
+        }
+
+        registration.exiting = true;
+        final MdnsPointerRecord expiredRecord = new MdnsPointerRecord(
+                registration.ptrRecord.record.getName(),
+                0L /* receiptTimeMillis */,
+                true /* cacheFlush */,
+                0L /* ttlMillis */,
+                registration.ptrRecord.record.getPointer());
+
+        // Exit should be skipped if the record is still advertised by another service, but that
+        // would be a conflict (2 service registrations with the same service name), so it would
+        // not have been allowed by the repository.
+        return new MdnsAnnouncer.ExitAnnouncementInfo(id, Collections.singletonList(expiredRecord));
+    }
+
+    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;
+    }
+
+    /**
+     * Info about a reply to be sent.
+     */
+    public static class ReplyInfo {
+        @NonNull
+        public final List<MdnsRecord> answers;
+        @NonNull
+        public final List<MdnsRecord> additionalAnswers;
+        public final long sendDelayMs;
+        @NonNull
+        public final InetSocketAddress destination;
+
+        public ReplyInfo(
+                @NonNull List<MdnsRecord> answers,
+                @NonNull List<MdnsRecord> additionalAnswers,
+                long sendDelayMs,
+                @NonNull InetSocketAddress destination) {
+            this.answers = answers;
+            this.additionalAnswers = additionalAnswers;
+            this.sendDelayMs = sendDelayMs;
+            this.destination = destination;
+        }
+
+        @Override
+        public String toString() {
+            return "{ReplyInfo to " + destination + ", answers: " + answers.size()
+                    + ", additionalAnswers: " + additionalAnswers.size()
+                    + ", sendDelayMs " + sendDelayMs + "}";
+        }
+    }
+
+    /**
+     * Get the reply to send to an incoming packet.
+     *
+     * @param packet The incoming packet.
+     * @param src The source address of the incoming packet.
+     */
+    @Nullable
+    public ReplyInfo getReply(MdnsPacket packet, InetSocketAddress src) {
+        final long now = SystemClock.elapsedRealtime();
+        final boolean replyUnicast = (packet.flags & MdnsConstants.QCLASS_UNICAST) != 0;
+        final ArrayList<MdnsRecord> additionalAnswerRecords = new ArrayList<>();
+        final ArrayList<RecordInfo<?>> answerInfo = new ArrayList<>();
+        for (MdnsRecord question : packet.questions) {
+            // Add answers from general records
+            addReplyFromService(question, mGeneralRecords, null /* servicePtrRecord */,
+                    null /* serviceSrvRecord */, null /* serviceTxtRecord */, replyUnicast, now,
+                    answerInfo, additionalAnswerRecords);
+
+            // Add answers from each service
+            for (int i = 0; i < mServices.size(); i++) {
+                final ServiceRegistration registration = mServices.valueAt(i);
+                if (registration.exiting) continue;
+                addReplyFromService(question, registration.allRecords, registration.ptrRecord,
+                        registration.srvRecord, registration.txtRecord, replyUnicast, now,
+                        answerInfo, additionalAnswerRecords);
+            }
+        }
+
+        if (answerInfo.size() == 0 && additionalAnswerRecords.size() == 0) {
+            return null;
+        }
+
+        // Determine the send delay
+        final long delayMs;
+        if ((packet.flags & MdnsConstants.FLAG_TRUNCATED) != 0) {
+            // RFC 6762 6.: 400-500ms delay if TC bit is set
+            delayMs = 400L + mDelayGenerator.nextInt(100);
+        } else if (packet.questions.size() > 1
+                || CollectionUtils.any(answerInfo, a -> a.isSharedName)) {
+            // 20-120ms if there may be responses from other hosts (not a fully owned
+            // name) (RFC 6762 6.), or if there are multiple questions (6.3).
+            // TODO: this should be 0 if this is a probe query ("can be distinguished from a
+            // normal query by the fact that a probe query contains a proposed record in the
+            // Authority Section that answers the question" in 6.), and the reply is for a fully
+            // owned record.
+            delayMs = 20L + mDelayGenerator.nextInt(100);
+        } else {
+            delayMs = 0L;
+        }
+
+        // Determine the send destination
+        final InetSocketAddress dest;
+        if (replyUnicast) {
+            dest = src;
+        } else if (src.getAddress() instanceof Inet4Address) {
+            dest = IPV4_ADDR;
+        } else {
+            dest = IPV6_ADDR;
+        }
+
+        // Build the list of answer records from their RecordInfo
+        final ArrayList<MdnsRecord> answerRecords = new ArrayList<>(answerInfo.size());
+        for (RecordInfo<?> info : answerInfo) {
+            // TODO: consider actual packet send delay after response aggregation
+            info.lastSentTimeMs = now + delayMs;
+            if (!replyUnicast) {
+                info.lastAdvertisedTimeMs = info.lastSentTimeMs;
+            }
+            answerRecords.add(info.record);
+        }
+
+        return new ReplyInfo(answerRecords, additionalAnswerRecords, delayMs, dest);
+    }
+
+    /**
+     * Add answers and additional answers for a question, from a ServiceRegistration.
+     */
+    private void addReplyFromService(@NonNull MdnsRecord question,
+            @NonNull List<RecordInfo<?>> serviceRecords,
+            @Nullable RecordInfo<MdnsPointerRecord> servicePtrRecord,
+            @Nullable RecordInfo<MdnsServiceRecord> serviceSrvRecord,
+            @Nullable RecordInfo<MdnsTextRecord> serviceTxtRecord,
+            boolean replyUnicast, long now, @NonNull List<RecordInfo<?>> answerInfo,
+            @NonNull List<MdnsRecord> additionalAnswerRecords) {
+        boolean hasDnsSdPtrRecordAnswer = false;
+        boolean hasDnsSdSrvRecordAnswer = false;
+        boolean hasFullyOwnedNameMatch = false;
+        boolean hasKnownAnswer = false;
+
+        final int answersStartIndex = answerInfo.size();
+        for (RecordInfo<?> info : serviceRecords) {
+            if (info.isProbing) continue;
+
+             /* RFC6762 6.: the record name must match the question name, the record rrtype
+             must match the question qtype unless the qtype is "ANY" (255) or the rrtype is
+             "CNAME" (5), and the record rrclass must match the question qclass unless the
+             qclass is "ANY" (255) */
+            if (!Arrays.equals(info.record.getName(), question.getName())) continue;
+            hasFullyOwnedNameMatch |= !info.isSharedName;
+
+            // The repository does not store CNAME records
+            if (question.getType() != MdnsRecord.TYPE_ANY
+                    && question.getType() != info.record.getType()) {
+                continue;
+            }
+            if (question.getRecordClass() != MdnsRecord.CLASS_ANY
+                    && question.getRecordClass() != info.record.getRecordClass()) {
+                continue;
+            }
+
+            hasKnownAnswer = true;
+            hasDnsSdPtrRecordAnswer |= (info == servicePtrRecord);
+            hasDnsSdSrvRecordAnswer |= (info == serviceSrvRecord);
+
+            // TODO: responses to probe queries should bypass this check and only ensure the
+            // reply is sent 250ms after the last sent time (RFC 6762 p.15)
+            if (!replyUnicast && info.lastAdvertisedTimeMs > 0L
+                    && now - info.lastAdvertisedTimeMs < MIN_MULTICAST_REPLY_INTERVAL_MS) {
+                continue;
+            }
+
+            // TODO: Don't reply if in known answers of the querier (7.1) if TTL is > half
+
+            answerInfo.add(info);
+        }
+
+        // RFC6762 6.1:
+        // "Any time a responder receives a query for a name for which it has verified exclusive
+        // ownership, for a type for which that name has no records, the responder MUST [...]
+        // respond asserting the nonexistence of that record"
+        if (hasFullyOwnedNameMatch && !hasKnownAnswer) {
+            additionalAnswerRecords.add(new MdnsNsecRecord(
+                    question.getName(),
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    // TODO: RFC6762 6.1: "In general, the TTL given for an NSEC record SHOULD
+                    // be the same as the TTL that the record would have had, had it existed."
+                    NAME_RECORDS_TTL_MILLIS,
+                    question.getName(),
+                    new int[] { question.getType() }));
+        }
+
+        // No more records to add if no answer
+        if (answerInfo.size() == answersStartIndex) return;
+
+        final List<RecordInfo<?>> additionalAnswerInfo = new ArrayList<>();
+        // RFC6763 12.1: if including PTR record, include the SRV and TXT records it names
+        if (hasDnsSdPtrRecordAnswer) {
+            if (serviceTxtRecord != null) {
+                additionalAnswerInfo.add(serviceTxtRecord);
+            }
+            if (serviceSrvRecord != null) {
+                additionalAnswerInfo.add(serviceSrvRecord);
+            }
+        }
+
+        // RFC6763 12.1&.2: if including PTR or SRV record, include the address records it names
+        if (hasDnsSdPtrRecordAnswer || hasDnsSdSrvRecordAnswer) {
+            for (RecordInfo<?> record : mGeneralRecords) {
+                if (record.record instanceof MdnsInetAddressRecord) {
+                    additionalAnswerInfo.add(record);
+                }
+            }
+        }
+
+        for (RecordInfo<?> info : additionalAnswerInfo) {
+            additionalAnswerRecords.add(info.record);
+        }
+
+        // RFC6762 6.1: negative responses
+        addNsecRecordsForUniqueNames(additionalAnswerRecords,
+                answerInfo.listIterator(answersStartIndex),
+                additionalAnswerInfo.listIterator());
+    }
+
+    /**
+     * Add NSEC records indicating that the response records are unique.
+     *
+     * Following RFC6762 6.1:
+     * "On receipt of a question for a particular name, rrtype, and rrclass, for which a responder
+     * does have one or more unique answers, the responder MAY also include an NSEC record in the
+     * Additional Record Section indicating the nonexistence of other rrtypes for that name and
+     * rrclass."
+     * @param destinationList List to add the NSEC records to.
+     * @param answerRecords Lists of answered records based on which to add NSEC records (typically
+     *                      answer and additionalAnswer sections)
+     */
+    @SafeVarargs
+    private static void addNsecRecordsForUniqueNames(
+            List<MdnsRecord> destinationList,
+            Iterator<RecordInfo<?>>... answerRecords) {
+        // Group unique records by name. Use a TreeMap with comparator as arrays don't implement
+        // equals / hashCode.
+        final Map<String[], List<MdnsRecord>> nsecByName = new TreeMap<>(Arrays::compare);
+        // But keep the list of names in added order, otherwise records would be sorted in
+        // alphabetical order instead of the order of the original records, which would look like
+        // inconsistent behavior depending on service name.
+        final List<String[]> namesInAddedOrder = new ArrayList<>();
+        for (Iterator<RecordInfo<?>> answers : answerRecords) {
+            addNonSharedRecordsToMap(answers, nsecByName, namesInAddedOrder);
+        }
+
+        for (String[] nsecName : namesInAddedOrder) {
+            final List<MdnsRecord> entryRecords = nsecByName.get(nsecName);
+            long minTtl = Long.MAX_VALUE;
+            final Set<Integer> types = new ArraySet<>(entryRecords.size());
+            for (MdnsRecord record : entryRecords) {
+                if (minTtl > record.getTtl()) minTtl = record.getTtl();
+                types.add(record.getType());
+            }
+
+            destinationList.add(new MdnsNsecRecord(
+                    nsecName,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    minTtl,
+                    nsecName,
+                    CollectionUtils.toIntArray(types)));
+        }
+    }
+
+    /**
+     * Add non-shared records to a map listing them by record name, and to a list of names that
+     * remembers the adding order.
+     *
+     * In the destination map records are grouped by name; so the map has one key per record name,
+     * and the values are the lists of different records that share the same name.
+     * @param records Records to scan.
+     * @param dest Map to add the records to.
+     * @param namesInAddedOrder List of names to add the names in order, keeping the first
+     *                          occurrence of each name.
+     */
+    private static void addNonSharedRecordsToMap(
+            Iterator<RecordInfo<?>> records,
+            Map<String[], List<MdnsRecord>> dest,
+            List<String[]> namesInAddedOrder) {
+        while (records.hasNext()) {
+            final RecordInfo<?> record = records.next();
+            if (record.isSharedName) continue;
+            final List<MdnsRecord> recordsForName = dest.computeIfAbsent(record.record.name,
+                    key -> {
+                        namesInAddedOrder.add(key);
+                        return new ArrayList<>();
+                    });
+            recordsForName.add(record.record);
+        }
+    }
+
+    /**
+     * 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 {
+
+        final ServiceRegistration registration = mServices.get(probeSuccessInfo.getServiceId());
+        if (registration == null) throw new IOException(
+                "Service is not registered: " + probeSuccessInfo.getServiceId());
+        registration.setProbing(false);
+
+        final ArrayList<MdnsRecord> answers = new ArrayList<>();
+        final ArrayList<MdnsRecord> additionalAnswers = new ArrayList<>();
+
+        // Interface address records in general records
+        for (RecordInfo<?> record : mGeneralRecords) {
+            answers.add(record.record);
+        }
+
+        // All service records
+        for (RecordInfo<?> info : registration.allRecords) {
+            answers.add(info.record);
+        }
+
+        addNsecRecordsForUniqueNames(additionalAnswers,
+                mGeneralRecords.iterator(), registration.allRecords.iterator());
+
+        return new MdnsAnnouncer.AnnouncementInfo(probeSuccessInfo.getServiceId(),
+                answers, additionalAnswers);
+    }
+
+    /**
+     * Get the service IDs of services conflicting with a received packet.
+     */
+    public Set<Integer> getConflictingServices(MdnsPacket packet) {
+        // Avoid allocating a new set for each incoming packet: use an empty set by default.
+        Set<Integer> conflicting = Collections.emptySet();
+        for (MdnsRecord record : packet.answers) {
+            for (int i = 0; i < mServices.size(); i++) {
+                final ServiceRegistration registration = mServices.valueAt(i);
+                if (registration.exiting) continue;
+
+                // Only look for conflicts in service name, as a different service name can be used
+                // if there is a conflict, but there is nothing actionable if any other conflict
+                // happens. In fact probing is only done for the service name in the SRV record.
+                // This means only SRV and TXT records need to be checked.
+                final RecordInfo<MdnsServiceRecord> srvRecord = registration.srvRecord;
+                if (!Arrays.equals(record.getName(), srvRecord.record.getName())) continue;
+
+                // As per RFC6762 9., it's fine if the "conflict" is an identical record with same
+                // data.
+                if (record instanceof MdnsServiceRecord) {
+                    final MdnsServiceRecord local = srvRecord.record;
+                    final MdnsServiceRecord other = (MdnsServiceRecord) record;
+                    // Note "equals" does not consider TTL or receipt time, as intended here
+                    if (Objects.equals(local, other)) {
+                        continue;
+                    }
+                }
+
+                if (record instanceof MdnsTextRecord) {
+                    final MdnsTextRecord local = registration.txtRecord.record;
+                    final MdnsTextRecord other = (MdnsTextRecord) record;
+                    if (Objects.equals(local, other)) {
+                        continue;
+                    }
+                }
+
+                if (conflicting.size() == 0) {
+                    // Conflict was found: use a mutable set
+                    conflicting = new ArraySet<>();
+                }
+                final int serviceId = mServices.keyAt(i);
+                conflicting.add(serviceId);
+            }
+        }
+
+        return conflicting;
+    }
+
+    /**
+     * (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;
+    }
+
+    /**
+     * Return whether the repository has an active (non-exiting) service for the given ID.
+     */
+    public boolean hasActiveService(int serviceId) {
+        final ServiceRegistration registration = mServices.get(serviceId);
+        if (registration == null) return false;
+
+        return !registration.exiting;
+    }
+
+    /**
+     * Rename a service to the newly provided info, following a conflict.
+     *
+     * If the specified service does not exist, this returns null.
+     */
+    @Nullable
+    public MdnsProber.ProbingInfo renameServiceForConflict(int serviceId, NsdServiceInfo newInfo) {
+        if (!mServices.contains(serviceId)) return null;
+
+        final ServiceRegistration newService = new ServiceRegistration(
+                mDeviceHostname, newInfo);
+        mServices.put(serviceId, newService);
+        return makeProbingInfo(serviceId, newService.srvRecord.record);
+    }
+
+    /**
+     * Called when {@link MdnsAdvertiser} sent an advertisement for the given service.
+     */
+    public void onAdvertisementSent(int serviceId) {
+        final ServiceRegistration registration = mServices.get(serviceId);
+        if (registration == null) return;
+
+        final long now = SystemClock.elapsedRealtime();
+        for (RecordInfo<?> record : registration.allRecords) {
+            record.lastSentTimeMs = now;
+            record.lastAdvertisedTimeMs = now;
+        }
+    }
+
+    /**
+     * Compute:
+     * 2001:db8::1 --> 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.0.1.0.0.2.ip6.arpa
+     *
+     * Or:
+     * 192.0.2.123 --> 123.2.0.192.in-addr.arpa
+     */
+    @VisibleForTesting
+    public static String[] getReverseDnsAddress(@NonNull InetAddress addr) {
+        // xxx.xxx.xxx.xxx.in-addr.arpa (up to 28 characters)
+        // or 32 hex characters separated by dots + .ip6.arpa
+        final byte[] addrBytes = addr.getAddress();
+        final List<String> out = new ArrayList<>();
+        if (addr instanceof Inet4Address) {
+            for (int i = addrBytes.length - 1; i >= 0; i--) {
+                out.add(String.valueOf(Byte.toUnsignedInt(addrBytes[i])));
+            }
+            out.add("in-addr");
+        } else {
+            final String hexAddr = HexDump.toHexString(addrBytes);
+
+            for (int i = hexAddr.length() - 1; i >= 0; i--) {
+                out.add(String.valueOf(hexAddr.charAt(i)));
+            }
+            out.add("ip6");
+        }
+        out.add("arpa");
+
+        return out.toArray(new String[0]);
+    }
+
+    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-t/src/com/android/server/connectivity/mdns/MdnsReplySender.java b/service-t/src/com/android/server/connectivity/mdns/MdnsReplySender.java
new file mode 100644
index 0000000..f1389ca
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsReplySender.java
@@ -0,0 +1,153 @@
+/*
+ * 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.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.server.connectivity.mdns.MdnsRecordRepository.ReplyInfo;
+
+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.util.Collections;
+
+/**
+ * A class that handles sending mDNS replies to a {@link MulticastSocket}, possibly queueing them
+ * to be sent after some delay.
+ *
+ * TODO: implement sending after a delay, combining queued replies and duplicate answer suppression
+ */
+public class MdnsReplySender {
+    private static final boolean DBG = MdnsAdvertiser.DBG;
+    private static final int MSG_SEND = 1;
+
+    private final String mLogTag;
+    @NonNull
+    private final MdnsInterfaceSocket mSocket;
+    @NonNull
+    private final Handler mHandler;
+    @NonNull
+    private final byte[] mPacketCreationBuffer;
+
+    public MdnsReplySender(@NonNull String interfaceTag, @NonNull Looper looper,
+            @NonNull MdnsInterfaceSocket socket, @NonNull byte[] packetCreationBuffer) {
+        mHandler = new SendHandler(looper);
+        mLogTag = MdnsReplySender.class.getSimpleName() + "/" +  interfaceTag;
+        mSocket = socket;
+        mPacketCreationBuffer = packetCreationBuffer;
+    }
+
+    /**
+     * Queue a reply to be sent when its send delay expires.
+     */
+    public void queueReply(@NonNull ReplyInfo reply) {
+        ensureRunningOnHandlerThread(mHandler);
+        // TODO: implement response aggregation (RFC 6762 6.4)
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SEND, reply), reply.sendDelayMs);
+
+        if (DBG) {
+            Log.v(mLogTag, "Scheduling " + reply);
+        }
+    }
+
+    /**
+     * Send a packet immediately.
+     *
+     * Must be called on the looper thread used by the {@link MdnsReplySender}.
+     */
+    public void sendNow(@NonNull MdnsPacket packet, @NonNull InetSocketAddress destination)
+            throws IOException {
+        ensureRunningOnHandlerThread(mHandler);
+        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);
+
+        writer.writeUInt16(0); // Transaction ID (advertisement: 0)
+        writer.writeUInt16(packet.flags); // Response, authoritative (rfc6762 18.4)
+        writer.writeUInt16(packet.questions.size()); // questions count
+        writer.writeUInt16(packet.answers.size()); // answers count
+        writer.writeUInt16(packet.authorityRecords.size()); // authority entries count
+        writer.writeUInt16(packet.additionalRecords.size()); // additional records count
+
+        for (MdnsRecord record : packet.questions) {
+            // Questions do not have TTL or data
+            record.writeHeaderFields(writer);
+        }
+        for (MdnsRecord record : packet.answers) {
+            record.write(writer, 0L);
+        }
+        for (MdnsRecord record : packet.authorityRecords) {
+            record.write(writer, 0L);
+        }
+        for (MdnsRecord record : packet.additionalRecords) {
+            record.write(writer, 0L);
+        }
+
+        final int len = writer.getWritePosition();
+        final byte[] outBuffer = new byte[len];
+        System.arraycopy(mPacketCreationBuffer, 0, outBuffer, 0, len);
+
+        mSocket.send(new DatagramPacket(outBuffer, 0, len, destination));
+    }
+
+    /**
+     * Cancel all pending sends.
+     */
+    public void cancelAll() {
+        ensureRunningOnHandlerThread(mHandler);
+        mHandler.removeMessages(MSG_SEND);
+    }
+
+    private class SendHandler extends Handler {
+        SendHandler(@NonNull Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(@NonNull Message msg) {
+            final ReplyInfo replyInfo = (ReplyInfo) msg.obj;
+            if (DBG) Log.v(mLogTag, "Sending " + replyInfo);
+
+            final int flags = 0x8400; // Response, authoritative (rfc6762 18.4)
+            final MdnsPacket packet = new MdnsPacket(flags,
+                    Collections.emptyList() /* questions */,
+                    replyInfo.answers,
+                    Collections.emptyList() /* authorityRecords */,
+                    replyInfo.additionalAnswers);
+
+            try {
+                sendNow(packet, replyInfo.destination);
+            } catch (IOException e) {
+                Log.e(mLogTag, "Error sending MDNS response", e);
+            }
+        }
+    }
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsResponse.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsResponse.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
similarity index 66%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
index 7cf84f6..82da2e4 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
@@ -24,11 +24,9 @@
 import com.android.server.connectivity.mdns.util.MdnsLogger;
 
 import java.io.EOFException;
-import java.io.IOException;
 import java.net.DatagramPacket;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.LinkedList;
 import java.util.List;
 
 /** A class that decodes mDNS responses from UDP packets. */
@@ -48,12 +46,6 @@
         this.serviceType = serviceType;
     }
 
-    private static void skipMdnsRecord(MdnsPacketReader reader) throws IOException {
-        reader.skip(2 + 4); // skip the class and TTL
-        int dataLength = reader.readUInt16();
-        reader.skip(dataLength);
-    }
-
     private static MdnsResponse findResponseWithPointer(
             List<MdnsResponse> responses, String[] pointer) {
         if (responses != null) {
@@ -101,9 +93,26 @@
      */
     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);
+    }
 
-        List<MdnsRecord> records;
+    /**
+     * 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);
+
+        final MdnsPacket mdnsPacket;
         try {
             reader.readUInt16(); // transaction ID (not used)
             int flags = reader.readUInt16();
@@ -111,111 +120,25 @@
                 return MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE;
             }
 
-            int numQuestions = reader.readUInt16();
-            int numAnswers = reader.readUInt16();
-            int numAuthority = reader.readUInt16();
-            int numRecords = reader.readUInt16();
-
-            LOGGER.log(String.format(
-                    "num questions: %d, num answers: %d, num authority: %d, num records: %d",
-                    numQuestions, numAnswers, numAuthority, numRecords));
-
-            if (numAnswers < 1) {
+            mdnsPacket = MdnsPacket.parseRecordsSection(reader, flags);
+            if (mdnsPacket.answers.size() < 1) {
                 return MdnsResponseErrorCode.ERROR_NO_ANSWERS;
             }
-
-            records = new LinkedList<>();
-
-            for (int i = 0; i < (numAnswers + numAuthority + numRecords); ++i) {
-                String[] name;
-                try {
-                    name = reader.readLabels();
-                } catch (IOException e) {
-                    LOGGER.e("Failed to read labels from mDNS response.", e);
-                    return MdnsResponseErrorCode.ERROR_READING_RECORD_NAME;
-                }
-                int type = reader.readUInt16();
-
-                switch (type) {
-                    case MdnsRecord.TYPE_A: {
-                        try {
-                            records.add(new MdnsInetAddressRecord(name, MdnsRecord.TYPE_A, reader));
-                        } catch (IOException e) {
-                            LOGGER.e("Failed to read A record from mDNS response.", e);
-                            return MdnsResponseErrorCode.ERROR_READING_A_RDATA;
-                        }
-                        break;
-                    }
-
-                    case MdnsRecord.TYPE_AAAA: {
-                        try {
-                            // AAAA should only contain the IPv6 address.
-                            MdnsInetAddressRecord record =
-                                    new MdnsInetAddressRecord(name, MdnsRecord.TYPE_AAAA, reader);
-                            if (record.getInet6Address() != null) {
-                                records.add(record);
-                            }
-                        } catch (IOException e) {
-                            LOGGER.e("Failed to read AAAA record from mDNS response.", e);
-                            return MdnsResponseErrorCode.ERROR_READING_AAAA_RDATA;
-                        }
-                        break;
-                    }
-
-                    case MdnsRecord.TYPE_PTR: {
-                        try {
-                            records.add(new MdnsPointerRecord(name, reader));
-                        } catch (IOException e) {
-                            LOGGER.e("Failed to read PTR record from mDNS response.", e);
-                            return MdnsResponseErrorCode.ERROR_READING_PTR_RDATA;
-                        }
-                        break;
-                    }
-
-                    case MdnsRecord.TYPE_SRV: {
-                        if (name.length == 4) {
-                            try {
-                                records.add(new MdnsServiceRecord(name, reader));
-                            } catch (IOException e) {
-                                LOGGER.e("Failed to read SRV record from mDNS response.", e);
-                                return MdnsResponseErrorCode.ERROR_READING_SRV_RDATA;
-                            }
-                        } else {
-                            try {
-                                skipMdnsRecord(reader);
-                            } catch (IOException e) {
-                                LOGGER.e("Failed to skip SVR record from mDNS response.", e);
-                                return MdnsResponseErrorCode.ERROR_SKIPPING_SRV_RDATA;
-                            }
-                        }
-                        break;
-                    }
-
-                    case MdnsRecord.TYPE_TXT: {
-                        try {
-                            records.add(new MdnsTextRecord(name, reader));
-                        } catch (IOException e) {
-                            LOGGER.e("Failed to read TXT record from mDNS response.", e);
-                            return MdnsResponseErrorCode.ERROR_READING_TXT_RDATA;
-                        }
-                        break;
-                    }
-
-                    default: {
-                        try {
-                            skipMdnsRecord(reader);
-                        } catch (IOException e) {
-                            LOGGER.e("Failed to skip mDNS record.", e);
-                            return MdnsResponseErrorCode.ERROR_SKIPPING_UNKNOWN_RECORD;
-                        }
-                    }
-                }
-            }
         } catch (EOFException e) {
             LOGGER.e("Reached the end of the mDNS response unexpectedly.", e);
             return MdnsResponseErrorCode.ERROR_END_OF_FILE;
+        } catch (MdnsPacket.ParseException e) {
+            LOGGER.e(e.getMessage(), e);
+            return e.code;
         }
 
+        final ArrayList<MdnsRecord> records = new ArrayList<>(
+                mdnsPacket.questions.size() + mdnsPacket.answers.size()
+                        + mdnsPacket.authorityRecords.size() + mdnsPacket.additionalRecords.size());
+        records.addAll(mdnsPacket.answers);
+        records.addAll(mdnsPacket.authorityRecords);
+        records.addAll(mdnsPacket.additionalRecords);
+
         // The response records are structured in a hierarchy, where some records reference
         // others, as follows:
         //
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java
similarity index 92%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java
index fcf9058..73a7e3a 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseErrorCode.java
+++ b/service-t/src/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/MdnsSearchOptions.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSearchOptions.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsSearchOptions.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsSearchOptions.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceInfo.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsServiceInfo.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsServiceRecord.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
similarity index 96%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index 538f376..d26fbdb 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service-t/src/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-t/src/com/android/server/connectivity/mdns/MdnsSocket.java
similarity index 97%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsSocket.java
index 64c4495..5fd1354 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
+++ b/service-t/src/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-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
similarity index 98%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
index 6a321d1..907687e 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
+++ b/service-t/src/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-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
new file mode 100644
index 0000000..23504a0
--- /dev/null
+++ b/service-t/src/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-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
similarity index 85%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsSocketProvider.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
index b8c324e..9298852 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketProvider.java
+++ b/service-t/src/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/MdnsTextRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsTextRecord.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsTextRecord.java
rename to service-t/src/com/android/server/connectivity/mdns/MdnsTextRecord.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java b/service-t/src/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java
rename to service-t/src/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java
diff --git a/service-t/src/com/android/server/connectivity/mdns/MulticastPacketReader.java b/service-t/src/com/android/server/connectivity/mdns/MulticastPacketReader.java
new file mode 100644
index 0000000..b597f0a
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/MulticastPacketReader.java
@@ -0,0 +1,120 @@
+/*
+ * 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);
+    }
+
+    /**
+     * Remove a packet handler added via {@link #addPacketHandler}. If the handler was not set,
+     * this is a no-op.
+     */
+    public void removePacketHandler(@NonNull PacketHandler handler) {
+        ensureRunningOnHandlerThread(mHandler);
+        mPacketHandlers.remove(handler);
+    }
+}
+
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/NameConflictException.java
similarity index 64%
rename from service/mdns/com/android/server/connectivity/mdns/MdnsAdvertiser.java
rename to service-t/src/com/android/server/connectivity/mdns/NameConflictException.java
index dee78fd..c123d02 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsAdvertiser.java
+++ b/service-t/src/com/android/server/connectivity/mdns/NameConflictException.java
@@ -16,14 +16,15 @@
 
 package com.android.server.connectivity.mdns;
 
-import android.util.Log;
-
 /**
- * MdnsAdvertiser manages advertising services per {@link com.android.server.NsdService} requests.
- *
- * TODO: implement
+ * An exception thrown when a service name conflicts with an existing service.
  */
-public class MdnsAdvertiser {
-    private static final String TAG = MdnsAdvertiser.class.getSimpleName();
-    public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+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/mdns/com/android/server/connectivity/mdns/NetworkInterfaceWrapper.java b/service-t/src/com/android/server/connectivity/mdns/NetworkInterfaceWrapper.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/NetworkInterfaceWrapper.java
rename to service-t/src/com/android/server/connectivity/mdns/NetworkInterfaceWrapper.java
diff --git a/service/mdns/com/android/server/connectivity/mdns/util/MdnsLogger.java b/service-t/src/com/android/server/connectivity/mdns/util/MdnsLogger.java
similarity index 100%
rename from service/mdns/com/android/server/connectivity/mdns/util/MdnsLogger.java
rename to service-t/src/com/android/server/connectivity/mdns/util/MdnsLogger.java
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index 0605abe..eed9aeb 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -469,9 +469,7 @@
             // TODO: Update this logic to only do a restart if required. Although a restart may
             //  be required due to the capabilities or ipConfiguration values, not all
             //  capabilities changes require a restart.
-            if (mIpClient != null) {
-                restart();
-            }
+            maybeRestart();
         }
 
         boolean isRestricted() {
@@ -491,10 +489,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) {
@@ -540,7 +547,7 @@
                 // Send a callback in case a provisioning request was in progress.
                 return;
             }
-            restart();
+            maybeRestart();
         }
 
         private void ensureRunningOnEthernetHandlerThread() {
@@ -573,7 +580,7 @@
             // If there is a better network, that will become default and apps
             // will be able to use internet. If ethernet gets connected again,
             // and has backhaul connectivity, it will become default.
-            restart();
+            maybeRestart();
         }
 
         /** Returns true if state has been modified */
@@ -635,20 +642,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) {
@@ -661,8 +654,16 @@
                         .build();
         }
 
-        void restart() {
-            if (DBG) Log.d(TAG, "reconnecting Ethernet");
+        void maybeRestart() {
+            if (mIpClient == null) {
+                // If maybeRestart() is called from a provisioning failure, it is
+                // possible that link disappeared in the meantime. In that
+                // case, stop() has already been called and IpClient should not
+                // get restarted to prevent a provisioning failure loop.
+                Log.i(TAG, String.format("maybeRestart() called on stopped interface %s", name));
+                return;
+            }
+            if (DBG) Log.d(TAG, "restart IpClient");
             stop();
             start();
         }
diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java
index 8161f50..e0abdf1 100644
--- a/service-t/src/com/android/server/net/NetworkStatsFactory.java
+++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java
@@ -200,16 +200,6 @@
     }
 
     /**
-     * Parse and return interface-level summary {@link NetworkStats} measured
-     * using {@code /proc/net/dev} style hooks, which may include non IP layer
-     * traffic. Values monotonically increase since device boot, and may include
-     * details about inactive interfaces.
-     */
-    public NetworkStats readNetworkStatsSummaryDev() throws IOException {
-        return mDeps.getNetworkStatsDev();
-    }
-
-    /**
      * Parse and return interface-level summary {@link NetworkStats}. Designed
      * to return only IP layer traffic. Values monotonically increase since
      * device boot, and may include details about inactive interfaces.
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index cf53002..9176ec2 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;
@@ -333,13 +339,11 @@
             }
         }
 
-        Config getDevConfig();
         Config getXtConfig();
         Config getUidConfig();
         Config getUidTagConfig();
 
         long getGlobalAlertBytes(long def);
-        long getDevPersistBytes(long def);
         long getXtPersistBytes(long def);
         long getUidPersistBytes(long def);
         long getUidTagPersistBytes(long def);
@@ -389,8 +393,6 @@
     private final Semaphore mStatsProviderSem = new Semaphore(0, true);
 
     @GuardedBy("mStatsLock")
-    private NetworkStatsRecorder mDevRecorder;
-    @GuardedBy("mStatsLock")
     private NetworkStatsRecorder mXtRecorder;
     @GuardedBy("mStatsLock")
     private NetworkStatsRecorder mUidRecorder;
@@ -526,8 +528,23 @@
                 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)
+                                    .setDeferUntilActive(true)
+                                    .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;
                 }
             }
@@ -844,8 +861,6 @@
             mSystemReady = true;
 
             // create data recorders along with historical rotators
-            mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false, mStatsDir,
-                    true /* wipeOnError */);
             mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false, mStatsDir,
                     true /* wipeOnError */);
             mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false, mStatsDir,
@@ -943,7 +958,6 @@
         final long currentTime = mClock.millis();
 
         // persist any pending stats
-        mDevRecorder.forcePersistLocked(currentTime);
         mXtRecorder.forcePersistLocked(currentTime);
         mUidRecorder.forcePersistLocked(currentTime);
         mUidTagRecorder.forcePersistLocked(currentTime);
@@ -1010,8 +1024,17 @@
             Log.i(TAG, "Starting import : attempts " + attempts + "/" + targetAttempts);
         }
 
+        // Still create a legacy dev recorder locally but the service doesn't really use it.
+        // This is for backward compatibility where the OEMs might call readPlatformCollection to
+        // perform proprietary operations and relying on the side-effects to complete the follow-up
+        // import process.
+        final NetworkStatsSettings.Config devConfig =
+                new NetworkStatsSettings.Config(HOUR_IN_MILLIS,
+                15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
+        final NetworkStatsRecorder devRecorder = buildRecorder(PREFIX_DEV, devConfig,
+                false, mStatsDir, true /* wipeOnError */);
         final MigrationInfo[] migrations = new MigrationInfo[]{
-                new MigrationInfo(mDevRecorder), new MigrationInfo(mXtRecorder),
+                new MigrationInfo(devRecorder), new MigrationInfo(mXtRecorder),
                 new MigrationInfo(mUidRecorder), new MigrationInfo(mUidTagRecorder)
         };
 
@@ -1021,9 +1044,10 @@
             final File legacyBaseDir = mDeps.getLegacyStatsDir();
             // Set wipeOnError flag false so the recorder won't damage persistent data if reads
             // failed and calling deleteAll.
+            // Set DEV legacy recorder as null since the DEV recorder has been removed.
+            // Thus it doesn't need to build DEV legacy recorder for comparing with imported data.
             legacyRecorders = new NetworkStatsRecorder[]{
-                buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false, legacyBaseDir,
-                        false /* wipeOnError */),
+                null /* dev Recorder */,
                 buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false, legacyBaseDir,
                         false /* wipeOnError */),
                 buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false, legacyBaseDir,
@@ -1040,7 +1064,6 @@
             // commit any data to disk until all are read.
             for (int i = 0; i < migrations.length; i++) {
                 final MigrationInfo migration = migrations[i];
-
                 // Read the collection from platform code, and set fallbacks counter if throws
                 // for better debugging.
                 try {
@@ -1074,6 +1097,7 @@
 
             // Find the latest end time.
             for (final MigrationInfo migration : migrations) {
+                if (PREFIX_DEV.equals(migration.recorder.getCookie())) continue;
                 final long migrationEnd = migration.collection.getEndMillis();
                 if (migrationEnd > migrationEndTime) migrationEndTime = migrationEnd;
             }
@@ -1090,7 +1114,8 @@
             for (final MigrationInfo migration : migrations) {
                 migration.imported = true;
                 migration.recorder.removeDataBefore(migrationEndTime);
-                if (migration.collection.isEmpty()) continue;
+                if (migration.collection.isEmpty()
+                        || PREFIX_DEV.equals(migration.recorder.getCookie())) continue;
                 migration.recorder.importCollectionLocked(migration.collection);
             }
 
@@ -1113,6 +1138,7 @@
             if (migrationEndTime > Long.MIN_VALUE) {
                 try {
                     for (final MigrationInfo migration : migrations) {
+                        if (PREFIX_DEV.equals(migration.recorder.getCookie())) continue;
                         if (migration.imported) {
                             migration.recorder.removeDataBefore(migrationEndTime);
                         }
@@ -1123,6 +1149,7 @@
                     // framework will reboot, and if there are remaining tries, the migration
                     // process will retry, which is fine because it's idempotent.
                     for (final MigrationInfo migration : migrations) {
+                        if (PREFIX_DEV.equals(migration.recorder.getCookie())) continue;
                         migration.recorder.recoverAndDeleteData();
                     }
                 }
@@ -1176,11 +1203,14 @@
     /**
      * Compare imported data with the data returned by legacy recorders.
      *
-     * @return true if the data matches, false if the data does not match or throw with exceptions.
+     * @return true if the data matches or if {@code legacyRecorder} is null, false if the data
+     * does not match or throw with exceptions.
      */
     private boolean compareImportedToLegacyStats(@NonNull MigrationInfo migration,
-            @NonNull NetworkStatsRecorder legacyRecorder) {
+            @Nullable NetworkStatsRecorder legacyRecorder) {
         final NetworkStatsCollection legacyStats;
+        // Skip the recorder that doesn't need to be compared.
+        if (legacyRecorder == null) return true;
         try {
             legacyStats = legacyRecorder.getOrLoadCompleteLocked();
         } catch (Throwable e) {
@@ -1834,7 +1864,6 @@
 
             updatePersistThresholdsLocked();
 
-            mDevRecorder.maybePersistLocked(currentTime);
             mXtRecorder.maybePersistLocked(currentTime);
             mUidRecorder.maybePersistLocked(currentTime);
             mUidTagRecorder.maybePersistLocked(currentTime);
@@ -1950,7 +1979,6 @@
      */
     @GuardedBy("mStatsLock")
     private void updatePersistThresholdsLocked() {
-        mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
         mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
         mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
         mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
@@ -2230,30 +2258,23 @@
     @GuardedBy("mStatsLock")
     private void recordSnapshotLocked(long currentTime) throws RemoteException {
         // snapshot and record current counters; read UID stats first to
-        // avoid over counting dev stats.
+        // avoid over counting xt stats.
         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid");
         final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
         Trace.traceEnd(TRACE_TAG_NETWORK);
         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
         final NetworkStats xtSnapshot = readNetworkStatsSummaryXt();
         Trace.traceEnd(TRACE_TAG_NETWORK);
-        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
-        final NetworkStats devSnapshot = readNetworkStatsSummaryDev();
-        Trace.traceEnd(TRACE_TAG_NETWORK);
 
-        // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data
-        // from stats providers that isn't already counted by dev and XT stats.
+        // Snapshot for xt stats from all custom stats providers. Counts per-interface data
+        // from stats providers that isn't already counted by XT stats.
         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider");
         final NetworkStats providersnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
         Trace.traceEnd(TRACE_TAG_NETWORK);
         xtSnapshot.combineAllValues(providersnapshot);
-        devSnapshot.combineAllValues(providersnapshot);
 
-        // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
+        // For xt, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
         // can't be reattributed to responsible apps.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
-        mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
         Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
         mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
         Trace.traceEnd(TRACE_TAG_NETWORK);
@@ -2333,13 +2354,11 @@
         // persist any pending data depending on requested flags
         Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]");
         if (persistForce) {
-            mDevRecorder.forcePersistLocked(currentTime);
             mXtRecorder.forcePersistLocked(currentTime);
             mUidRecorder.forcePersistLocked(currentTime);
             mUidTagRecorder.forcePersistLocked(currentTime);
         } else {
             if (persistNetwork) {
-                mDevRecorder.maybePersistLocked(currentTime);
                 mXtRecorder.maybePersistLocked(currentTime);
             }
             if (persistUid) {
@@ -2396,33 +2415,49 @@
         final long currentTime = mClock.millis();
 
         NetworkTemplate template;
-        NetworkStats.Entry devTotal;
         NetworkStats.Entry xtTotal;
         NetworkStats.Entry uidTotal;
 
         // collect mobile sample
         template = new NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build();
-        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
 
-        EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
-                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
-                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
-                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
-                currentTime);
+        if (SdkLevel.isAtLeastU()) {
+            EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
+                    xtTotal.rxBytes, xtTotal.txBytes, xtTotal.rxPackets, xtTotal.txPackets,
+                    uidTotal.rxBytes, uidTotal.txBytes, uidTotal.rxPackets, uidTotal.txPackets,
+                    currentTime);
+        } else {
+            // To keep the format of event log, here replaces the value of DevRecorder with the
+            // value of XtRecorder because they have the same content in old design.
+            EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
+                    xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+                    xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+                    uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
+                    currentTime);
+        }
 
         // collect wifi sample
         template = new NetworkTemplate.Builder(MATCH_WIFI).build();
-        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
 
-        EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
-                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
-                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
-                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
-                currentTime);
+        if (SdkLevel.isAtLeastU()) {
+            EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
+                    xtTotal.rxBytes, xtTotal.txBytes, xtTotal.rxPackets, xtTotal.txPackets,
+                    uidTotal.rxBytes, uidTotal.txBytes, uidTotal.rxPackets, uidTotal.txPackets,
+                    currentTime);
+        } else {
+            // To keep the format of event log, here replaces the value of DevRecorder with the
+            // value of XtRecorder because they have the same content in old design.
+            EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
+                    xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+                    xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+                    uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
+                    currentTime);
+
+        }
     }
 
     // deleteKernelTagData can ignore ENOENT; otherwise we should log an error
@@ -2721,7 +2756,12 @@
 
             pw.println("Dev stats:");
             pw.increaseIndent();
-            mDevRecorder.dumpLocked(pw, fullHistory);
+            pw.println("Pending bytes: ");
+            if (fullHistory) {
+                pw.println("Complete history:");
+            } else {
+                pw.println("History since boot:");
+            }
             pw.decreaseIndent();
 
             pw.println("Xt stats:");
@@ -2781,7 +2821,6 @@
                 mActiveIfaces);
         dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES,
                 mActiveUidIfaces);
-        mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
         mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
         mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
         mUidTagRecorder.dumpDebugLocked(proto,
@@ -2797,7 +2836,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.
@@ -2916,14 +2955,6 @@
                 });
     }
 
-    private NetworkStats readNetworkStatsSummaryDev() {
-        try {
-            return mStatsFactory.readNetworkStatsSummaryDev();
-        } catch (IOException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
     private NetworkStats readNetworkStatsSummaryXt() {
         try {
             return mStatsFactory.readNetworkStatsSummaryXt();
@@ -3232,12 +3263,8 @@
             return false;
         }
         @Override
-        public Config getDevConfig() {
-            return new Config(HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
-        }
-        @Override
         public Config getXtConfig() {
-            return getDevConfig();
+            return new Config(HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
         }
         @Override
         public Config getUidConfig() {
@@ -3248,10 +3275,6 @@
             return new Config(2 * HOUR_IN_MILLIS, 5 * DAY_IN_MILLIS, 15 * DAY_IN_MILLIS);
         }
         @Override
-        public long getDevPersistBytes(long def) {
-            return def;
-        }
-        @Override
         public long getXtPersistBytes(long def) {
             return def;
         }
@@ -3268,4 +3291,7 @@
     private static native long nativeGetTotalStat(int type);
     private static native long nativeGetIfaceStat(String iface, int type);
     private static native long nativeGetUidStat(int uid, int type);
+
+    /** Initializes and registers the Perfetto Network Trace data source */
+    public static native void nativeInitNetworkTracing();
 }
diff --git a/service/Android.bp b/service/Android.bp
index b7ddc8a..1523af9 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -195,26 +195,6 @@
     ],
 }
 
-// TODO: Remove this temporary library and put code into module when test coverage is enough.
-java_library {
-    name: "service-mdns",
-    sdk_version: "system_server_current",
-    min_sdk_version: "30",
-    srcs: [
-        "mdns/**/*.java",
-    ],
-    libs: [
-        "framework-annotations-lib",
-        "framework-connectivity-pre-jarjar",
-        "framework-tethering",
-        "framework-wifi",
-        "service-connectivity-pre-jarjar",
-    ],
-    visibility: [
-        "//packages/modules/Connectivity/tests:__subpackages__",
-    ],
-}
-
 java_library {
     name: "service-connectivity-protos",
     sdk_version: "system_current",
diff --git a/service/ServiceConnectivityResources/res/values-mcc310-mnc590/config.xml b/service/ServiceConnectivityResources/res/values-mcc310-mnc590/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc310-mnc590/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc310-mnc599/config.xml b/service/ServiceConnectivityResources/res/values-mcc310-mnc599/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc310-mnc599/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc270/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc270/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc270/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc280/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc280/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc280/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
deleted file mode 100644
index 7e7025f..0000000
--- a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<!-- Configuration values for ConnectivityService
-     DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources
-     Overlay package following the overlayable.xml configuration in the same directory:
-     https://source.android.com/devices/architecture/rros -->
-<resources>
-    <!-- Whether the device should automatically switch away from Wi-Fi networks that lose
-         Internet access. Actual device behaviour is controlled by
-         Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
-    <integer translatable="false" name="config_networkAvoidBadWifi">0</integer>
-</resources>
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/jarjar-excludes.txt b/service/jarjar-excludes.txt
index b0d6763..7bd3862 100644
--- a/service/jarjar-excludes.txt
+++ b/service/jarjar-excludes.txt
@@ -1,9 +1,3 @@
 # Classes loaded by SystemServer via their hardcoded name, so they can't be jarjared
 com\.android\.server\.ConnectivityServiceInitializer(\$.+)?
 com\.android\.server\.NetworkStatsServiceInitializer(\$.+)?
-
-# Do not jarjar com.android.server, as several unit tests fail because they lose
-# package-private visibility between jarjared and non-jarjared classes.
-# TODO: fix the tests and also jarjar com.android.server, or at least only exclude a package that
-# is specific to the module like com.android.server.connectivity
-com\.android\.server\..+
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index 05f50b0..77cffda 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -236,7 +236,7 @@
 // clang-format on
 
 int register_com_android_server_BpfNetMaps(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "com/android/server/BpfNetMaps",
+    return jniRegisterNativeMethods(env, "android/net/connectivity/com/android/server/BpfNetMaps",
                                     gMethods, NELEM(gMethods));
 }
 
diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
index bd74d54..7aeecfa 100644
--- a/service/jni/com_android_server_TestNetworkService.cpp
+++ b/service/jni/com_android_server_TestNetworkService.cpp
@@ -151,8 +151,9 @@
 };
 
 int register_com_android_server_TestNetworkService(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "com/android/server/TestNetworkService", gMethods,
-                                    NELEM(gMethods));
+    return jniRegisterNativeMethods(env,
+            "android/net/connectivity/com/android/server/TestNetworkService", gMethods,
+            NELEM(gMethods));
 }
 
 }; // namespace android
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 18d2311..5b42659 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <linux/if_packet.h>
 #include <linux/if_tun.h>
 #include <linux/ioctl.h>
 #include <log/log.h>
@@ -36,9 +37,6 @@
 #include "libclat/clatutils.h"
 #include "nativehelper/scoped_utf_chars.h"
 
-// Sync from system/netd/include/netid_client.h
-#define MARK_UNSET 0u
-
 // Sync from system/netd/server/NetdConstants.h
 #define __INT_STRLEN(i) sizeof(#i)
 #define _INT_STRLEN(i) __INT_STRLEN(i)
@@ -184,6 +182,12 @@
         throwIOException(env, "packet socket failed", errno);
         return -1;
     }
+    int on = 1;
+    if (setsockopt(sock, SOL_PACKET, PACKET_AUXDATA, &on, sizeof(on))) {
+        throwIOException(env, "packet socket auxdata enablement failed", errno);
+        close(sock);
+        return -1;
+    }
     return sock;
 }
 
@@ -197,7 +201,7 @@
     }
 
     // TODO: check the mark validation
-    if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) {
+    if (setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) {
         throwIOException(env, "could not set mark on raw socket", errno);
         close(sock);
         return -1;
@@ -473,8 +477,9 @@
 };
 
 int register_com_android_server_connectivity_ClatCoordinator(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "com/android/server/connectivity/ClatCoordinator",
-                                    gMethods, NELEM(gMethods));
+    return jniRegisterNativeMethods(env,
+            "android/net/connectivity/com/android/server/connectivity/ClatCoordinator",
+            gMethods, NELEM(gMethods));
 }
 
 };  // namespace android
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsPacket.java b/service/mdns/com/android/server/connectivity/mdns/MdnsPacket.java
deleted file mode 100644
index eae084a..0000000
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsPacket.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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 java.util.Collections;
-import java.util.List;
-
-/**
- * A class holding data that can be included in a mDNS packet.
- */
-public class MdnsPacket {
-    public final int flags;
-    public final List<MdnsRecord> questions;
-    public final List<MdnsRecord> answers;
-    public final List<MdnsRecord> authorityRecords;
-    public final List<MdnsRecord> additionalRecords;
-
-    MdnsPacket(int flags,
-            List<MdnsRecord> questions,
-            List<MdnsRecord> answers,
-            List<MdnsRecord> authorityRecords,
-            List<MdnsRecord> additionalRecords) {
-        this.flags = flags;
-        this.questions = Collections.unmodifiableList(questions);
-        this.answers = Collections.unmodifiableList(answers);
-        this.authorityRecords = Collections.unmodifiableList(authorityRecords);
-        this.additionalRecords = Collections.unmodifiableList(additionalRecords);
-    }
-}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsReplySender.java b/service/mdns/com/android/server/connectivity/mdns/MdnsReplySender.java
deleted file mode 100644
index 1fdbc5c..0000000
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsReplySender.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.os.Looper;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.MulticastSocket;
-import java.net.SocketAddress;
-
-/**
- * A class that handles sending mDNS replies to a {@link MulticastSocket}, possibly queueing them
- * to be sent after some delay.
- *
- * TODO: implement sending after a delay, combining queued replies and duplicate answer suppression
- */
-public class MdnsReplySender {
-    @NonNull
-    private final MulticastSocket mSocket;
-    @NonNull
-    private final Looper mLooper;
-    @NonNull
-    private final byte[] mPacketCreationBuffer;
-
-    public MdnsReplySender(@NonNull Looper looper,
-            @NonNull MulticastSocket socket, @NonNull byte[] packetCreationBuffer) {
-        mLooper = looper;
-        mSocket = socket;
-        mPacketCreationBuffer = packetCreationBuffer;
-    }
-
-    /**
-     * Send a packet immediately.
-     *
-     * Must be called on the looper thread used by the {@link MdnsReplySender}.
-     */
-    public void sendNow(@NonNull MdnsPacket packet, @NonNull SocketAddress destination)
-            throws IOException {
-        if (Thread.currentThread() != mLooper.getThread()) {
-            throw new IllegalStateException("sendNow must be called in the handler thread");
-        }
-
-        // TODO: support packets over size (send in multiple packets with TC bit set)
-        final MdnsPacketWriter writer = new MdnsPacketWriter(mPacketCreationBuffer);
-
-        writer.writeUInt16(0); // Transaction ID (advertisement: 0)
-        writer.writeUInt16(packet.flags); // Response, authoritative (rfc6762 18.4)
-        writer.writeUInt16(packet.questions.size()); // questions count
-        writer.writeUInt16(packet.answers.size()); // answers count
-        writer.writeUInt16(packet.authorityRecords.size()); // authority entries count
-        writer.writeUInt16(packet.additionalRecords.size()); // additional records count
-
-        for (MdnsRecord record : packet.questions) {
-            // Questions do not have TTL or data
-            record.writeHeaderFields(writer);
-        }
-        for (MdnsRecord record : packet.answers) {
-            record.write(writer, 0L);
-        }
-        for (MdnsRecord record : packet.authorityRecords) {
-            record.write(writer, 0L);
-        }
-        for (MdnsRecord record : packet.additionalRecords) {
-            record.write(writer, 0L);
-        }
-
-        final int len = writer.getWritePosition();
-        final byte[] outBuffer = new byte[len];
-        System.arraycopy(mPacketCreationBuffer, 0, outBuffer, 0, len);
-
-        mSocket.send(new DatagramPacket(outBuffer, 0, len, destination));
-    }
-}
diff --git a/service/native/libs/libclat/clatutils.cpp b/service/native/libs/libclat/clatutils.cpp
index be86612..c6a9781 100644
--- a/service/native/libs/libclat/clatutils.cpp
+++ b/service/native/libs/libclat/clatutils.cpp
@@ -29,13 +29,6 @@
 #include "checksum.h"
 }
 
-// Sync from external/android-clat/clatd.h
-#define MAXMTU 65536
-#define PACKETLEN (MAXMTU + sizeof(struct tun_pi))
-
-// Sync from system/netd/include/netid_client.h.
-#define MARK_UNSET 0u
-
 namespace android {
 namespace net {
 namespace clat {
@@ -132,7 +125,7 @@
 
     // Socket's mark affects routing decisions (network selection)
     // An fwmark is necessary for clat to bypass the VPN during initialization.
-    if ((mark != MARK_UNSET) && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
+    if (setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
         int ret = errno;
         ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(errno));
         close(s);
@@ -180,7 +173,7 @@
     }
 
     // Socket's mark affects routing decisions (network selection)
-    if ((mark != MARK_UNSET) && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
+    if (setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
         int ret = errno;
         ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(errno));
         close(s);
@@ -235,7 +228,7 @@
     // Compare it against the first four bytes of our IPv6 address, in host byte order (BPF loads
     // are always in host byte order). If it matches, continue with next instruction (JMP 0). If it
     // doesn't match, jump ahead to statement that returns 0 (ignore packet). Repeat for the other
-    // three words of the IPv6 address, and if they all match, return PACKETLEN (accept packet).
+    // three words of the IPv6 address, and if they all match, return full packet (accept packet).
         BPF_STMT(BPF_LD  | BPF_W   | BPF_ABS,  24),
         BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    htonl(ipv6[0]), 0, 7),
         BPF_STMT(BPF_LD  | BPF_W   | BPF_ABS,  28),
@@ -244,7 +237,7 @@
         BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    htonl(ipv6[2]), 0, 3),
         BPF_STMT(BPF_LD  | BPF_W   | BPF_ABS,  36),
         BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    htonl(ipv6[3]), 0, 1),
-        BPF_STMT(BPF_RET | BPF_K,              PACKETLEN),
+        BPF_STMT(BPF_RET | BPF_K,              0xFFFFFFFF),
         BPF_STMT(BPF_RET | BPF_K,              0),
     };
     // clang-format on
diff --git a/service/proguard.flags b/service/proguard.flags
index 864a28b..cf25f05 100644
--- a/service/proguard.flags
+++ b/service/proguard.flags
@@ -7,7 +7,7 @@
     *;
 }
 
--keepclassmembers class com.android.server.**,android.net.**,com.android.networkstack.** {
+-keepclassmembers class android.net.**,com.android.networkstack.** {
     static final % POLICY_*;
     static final % NOTIFY_TYPE_*;
     static final % TRANSPORT_*;
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index bce9f53..b4fce37 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);
 
@@ -720,6 +721,31 @@
     }
 
     /**
+     * Get firewall rule of specified firewall chain on specified uid.
+     *
+     * @param childChain target chain
+     * @param uid        target uid
+     * @return either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
+     * @throws UnsupportedOperationException if called on pre-T devices.
+     * @throws ServiceSpecificException in case of failure, with an error code indicating the
+     *                                  cause of the failure.
+     */
+    public int getUidRule(final int childChain, final int uid) {
+        throwIfPreT("isUidChainEnabled is not available on pre-T devices");
+
+        final long match = getMatchByFirewallChain(childChain);
+        final boolean isAllowList = isFirewallAllowList(childChain);
+        try {
+            final UidOwnerValue uidMatch = sUidOwnerMap.getValue(new S32(uid));
+            final boolean isMatchEnabled = uidMatch != null && (uidMatch.rule & match) != 0;
+            return isMatchEnabled == isAllowList ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY;
+        } catch (ErrnoException e) {
+            throw new ServiceSpecificException(e.errno,
+                    "Unable to get uid rule status: " + Os.strerror(e.errno));
+        }
+    }
+
+    /**
      * Add ingress interface filtering rules to a list of UIDs
      *
      * For a given uid, once a filtering rule is added, the kernel will only allow packets from the
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 004b4d2..e32ea8f 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -107,6 +107,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
 import android.app.AppOpsManager;
 import android.app.BroadcastOptions;
@@ -242,6 +243,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,7 +265,13 @@
 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.AutomaticOnOffKeepaliveTracker;
+import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive;
 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
 import com.android.server.connectivity.ClatCoordinator;
 import com.android.server.connectivity.ConnectivityFlags;
@@ -372,6 +381,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;
 
@@ -397,8 +410,7 @@
 
     private final MockableSystemProperties mSystemProperties;
 
-    @VisibleForTesting
-    protected final PermissionMonitor mPermissionMonitor;
+    private final PermissionMonitor mPermissionMonitor;
 
     @VisibleForTesting
     final RequestInfoPerUidCounter mNetworkRequestCounter;
@@ -754,6 +766,11 @@
     private static final int EVENT_SET_VPN_NETWORK_PREFERENCE = 59;
 
     /**
+     * Event to use low TCP polling timer used in automatic on/off keepalive temporarily.
+     */
+    private static final int EVENT_SET_LOW_TCP_POLLING_UNTIL = 60;
+
+    /**
      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
      * should be shown.
      */
@@ -771,6 +788,12 @@
     private static final long MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS = 5 * 60 * 1000L;
 
     /**
+     * The maximum alive time to decrease TCP polling timer in automatic on/off keepalive for
+     * testing.
+     */
+    private static final long MAX_TEST_LOW_TCP_POLLING_UNTIL_MS = 5 * 60 * 1000L;
+
+    /**
      * The priority of the tc police rate limiter -- smaller value is higher priority.
      * This value needs to be coordinated with PRIO_CLAT, PRIO_TETHER4, and PRIO_TETHER6.
      */
@@ -833,7 +856,7 @@
 
     private final LocationPermissionChecker mLocationPermissionChecker;
 
-    private final KeepaliveTracker mKeepaliveTracker;
+    private final AutomaticOnOffKeepaliveTracker mKeepaliveTracker;
     private final QosCallbackTracker mQosCallbackTracker;
     private final NetworkNotificationManager mNotifier;
     private final LingerMonitor mLingerMonitor;
@@ -1293,6 +1316,14 @@
         }
 
         /**
+         * @see AutomaticOnOffKeepaliveTracker
+         */
+        public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(
+                @NonNull Context c, @NonNull Handler h) {
+            return new AutomaticOnOffKeepaliveTracker(c, h);
+        }
+
+        /**
          * @see BatteryStatsManager
          */
         public void reportNetworkInterfaceForTransports(Context context, String iface,
@@ -1411,6 +1442,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) {
@@ -1545,7 +1586,7 @@
         mSettingsObserver = new SettingsObserver(mContext, mHandler);
         registerSettingsCallbacks();
 
-        mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler);
+        mKeepaliveTracker = mDeps.makeAutomaticOnOffKeepaliveTracker(mContext, mHandler);
         mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager);
         mQosCallbackTracker = new QosCallbackTracker(mHandler, mNetworkRequestCounter);
 
@@ -2841,9 +2882,10 @@
                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
     }
 
-    private void enforceSettingsOrUseRestrictedNetworksPermission() {
+    private void enforceSettingsOrSetupWizardOrUseRestrictedNetworksPermission() {
         enforceAnyPermissionOf(mContext,
                 android.Manifest.permission.NETWORK_SETTINGS,
+                android.Manifest.permission.NETWORK_SETUP_WIZARD,
                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
                 Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS);
     }
@@ -3017,6 +3059,8 @@
         sendStickyBroadcast(makeGeneralIntent(info, bcastType));
     }
 
+    // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
+    @SuppressLint("NewApi")
     // TODO: Set the mini sdk to 31 and remove @TargetApi annotation when b/205923322 is addressed.
     @TargetApi(Build.VERSION_CODES.S)
     private void sendStickyBroadcast(Intent intent) {
@@ -3037,6 +3081,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);
             }
@@ -3048,6 +3093,33 @@
         }
     }
 
+    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));
+            optsShim.setDeferUntilActive(true);
+        } 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.
      */
@@ -4366,6 +4438,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);
@@ -4800,6 +4875,7 @@
                 }
             }
         }
+
         nri.mPerUidCounter.decrementCount(nri.mUid);
         mNetworkRequestInfoLogs.log("RELEASE " + nri);
         checkNrisConsistency(nri);
@@ -4945,6 +5021,22 @@
                 mHandler.obtainMessage(EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL, timeMs));
     }
 
+    @Override
+    public void setTestLowTcpPollingTimerForKeepalive(long timeMs) {
+        enforceSettingsPermission();
+        if (!Build.isDebuggable()) {
+            throw new IllegalStateException("Is not supported in non-debuggable build");
+        }
+
+        if (timeMs > System.currentTimeMillis() + MAX_TEST_LOW_TCP_POLLING_UNTIL_MS) {
+            throw new IllegalArgumentException("Argument should not exceed "
+                    + MAX_TEST_LOW_TCP_POLLING_UNTIL_MS + "ms from now");
+        }
+
+        mHandler.sendMessage(
+                mHandler.obtainMessage(EVENT_SET_LOW_TCP_POLLING_UNTIL, timeMs));
+    }
+
     private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
         if (DBG) log("handleSetAcceptUnvalidated network=" + network +
                 " accept=" + accept + " always=" + always);
@@ -5493,12 +5585,45 @@
                     mKeepaliveTracker.handleStartKeepalive(msg);
                     break;
                 }
+                case NetworkAgent.CMD_MONITOR_AUTOMATIC_KEEPALIVE: {
+                    final AutomaticOnOffKeepalive ki =
+                            mKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj);
+                    if (null == ki) return; // The callback was unregistered before the alarm fired
+
+                    final Network underpinnedNetwork = ki.getUnderpinnedNetwork();
+                    final Network network = ki.getNetwork();
+                    boolean networkFound = false;
+                    boolean underpinnedNetworkFound = false;
+                    for (NetworkAgentInfo n : mNetworkAgentInfos) {
+                        if (n.network.equals(network)) networkFound = true;
+                        if (n.everConnected() && n.network.equals(underpinnedNetwork)) {
+                            underpinnedNetworkFound = true;
+                        }
+                    }
+
+                    // If the network no longer exists, then the keepalive should have been
+                    // cleaned up already. There is no point trying to resume keepalives.
+                    if (!networkFound) return;
+
+                    if (underpinnedNetworkFound) {
+                        mKeepaliveTracker.handleMonitorAutomaticKeepalive(ki,
+                                underpinnedNetwork.netId);
+                    } else {
+                        // If no underpinned network, then make sure the keepalive is running.
+                        mKeepaliveTracker.handleMaybeResumeKeepalive(ki);
+                    }
+                    break;
+                }
                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
                 case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: {
-                    NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
-                    int slot = msg.arg1;
-                    int reason = msg.arg2;
-                    mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
+                    final AutomaticOnOffKeepalive ki = mKeepaliveTracker.getKeepaliveForBinder(
+                            (IBinder) msg.obj);
+                    if (ki == null) {
+                        Log.e(TAG, "Attempt to stop an already stopped keepalive");
+                        return;
+                    }
+                    final int reason = msg.arg2;
+                    mKeepaliveTracker.handleStopKeepalive(ki, reason);
                     break;
                 }
                 case EVENT_REPORT_NETWORK_CONNECTIVITY: {
@@ -5553,6 +5678,11 @@
                 case EVENT_SET_VPN_NETWORK_PREFERENCE:
                     handleSetVpnNetworkPreference((VpnNetworkPreferenceInfo) msg.obj);
                     break;
+                case EVENT_SET_LOW_TCP_POLLING_UNTIL: {
+                    final long time = ((Long) msg.obj).longValue();
+                    mKeepaliveTracker.handleSetTestLowTcpPollingTimer(time);
+                    break;
+                }
             }
         }
     }
@@ -6166,12 +6296,14 @@
         if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
         }
+        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);
@@ -6717,7 +6849,7 @@
                 enforceAccessPermission();
                 break;
             case TRACK_SYSTEM_DEFAULT:
-                enforceSettingsOrUseRestrictedNetworksPermission();
+                enforceSettingsOrSetupWizardOrUseRestrictedNetworksPermission();
                 networkCapabilities = new NetworkCapabilities(defaultNc);
                 break;
             case BACKGROUND_REQUEST:
@@ -8430,6 +8562,8 @@
         // else not handled
     }
 
+    // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
+    @SuppressLint("NewApi")
     private void sendIntent(PendingIntent pendingIntent, Intent intent) {
         mPendingIntentWakeLock.acquire();
         try {
@@ -8688,6 +8822,78 @@
         }
     }
 
+    /**
+     * 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() {
+        // Netd command is not implemented before U.
+        if (!SdkLevel.isAtLeastU()) return;
+
+        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?
+            Log.wtf(TAG, "Unexpected ServiceSpecificException", e);
+        } catch (RemoteException e) {
+            // Netd died. This will cause a runtime restart anyway.
+            Log.wtf(TAG, "Unexpected RemoteException", e);
+        }
+    }
+
     private void makeDefaultNetwork(@Nullable final NetworkAgentInfo newDefaultNetwork) {
         try {
             if (null != newDefaultNetwork) {
@@ -9320,6 +9526,7 @@
             networkAgent.setCreated();
             networkAgent.onNetworkCreated();
             updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
+            updateProfileAllowedNetworks();
         }
 
         if (!networkAgent.everConnected() && state == NetworkInfo.State.CONNECTED) {
@@ -9665,20 +9872,24 @@
         enforceKeepalivePermission();
         mKeepaliveTracker.startNattKeepalive(
                 getNetworkAgentInfoForNetwork(network), null /* fd */,
-                intervalSeconds, cb,
-                srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
+                intervalSeconds, cb, srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT,
+                // Keep behavior of the deprecated method as it is. Set automaticOnOffKeepalives to
+                // false and set the underpinned network to null because there is no way and no
+                // plan to configure automaticOnOffKeepalives or underpinnedNetwork in this
+                // deprecated method.
+                false /* automaticOnOffKeepalives */, null /* underpinnedNetwork */);
     }
 
     @Override
     public void startNattKeepaliveWithFd(Network network, ParcelFileDescriptor pfd, int resourceId,
             int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
-            String dstAddr) {
+            String dstAddr, boolean automaticOnOffKeepalives, Network underpinnedNetwork) {
         try {
             final FileDescriptor fd = pfd.getFileDescriptor();
             mKeepaliveTracker.startNattKeepalive(
                     getNetworkAgentInfoForNetwork(network), fd, resourceId,
-                    intervalSeconds, cb,
-                    srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
+                    intervalSeconds, cb, srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT,
+                    automaticOnOffKeepalives, underpinnedNetwork);
         } finally {
             // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks.
             // startNattKeepalive calls Os.dup(fd) before returning, so we can close immediately.
@@ -9706,9 +9917,10 @@
     }
 
     @Override
-    public void stopKeepalive(Network network, int slot) {
+    public void stopKeepalive(@NonNull final ISocketKeepaliveCallback cb) {
         mHandler.sendMessage(mHandler.obtainMessage(
-                NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, slot, SocketKeepalive.SUCCESS, network));
+                NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, 0, SocketKeepalive.SUCCESS,
+                Objects.requireNonNull(cb).asBinder()));
     }
 
     @Override
@@ -10856,6 +11068,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;
@@ -10865,6 +11078,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.
@@ -10898,7 +11114,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");
@@ -11011,6 +11228,7 @@
         removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_PROFILE);
         addPerAppDefaultNetworkRequests(
                 createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences));
+        updateProfileAllowedNetworks();
 
         // Finally, rematch.
         rematchAllNetworksAndRequests();
@@ -11534,6 +11752,12 @@
         }
     }
 
+    @Override
+    public int getUidFirewallRule(final int chain, final int uid) {
+        enforceNetworkStackOrSettingsPermission();
+        return mBpfNetMaps.getUidRule(chain, uid);
+    }
+
     private int getFirewallRuleType(int chain, int rule) {
         final int defaultRule;
         switch (chain) {
diff --git a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
new file mode 100644
index 0000000..9f9b496
--- /dev/null
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -0,0 +1,791 @@
+/*
+ * 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;
+
+import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
+import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
+import static android.net.SocketKeepalive.SUCCESS_PAUSED;
+import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.SOL_SOCKET;
+import static android.system.OsConstants.SO_SNDTIMEO;
+
+import static com.android.net.module.util.netlink.NetlinkConstants.NLMSG_DONE;
+import static com.android.net.module.util.netlink.NetlinkConstants.SOCKDIAG_MSG_HEADER_SIZE;
+import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
+import static com.android.net.module.util.netlink.NetlinkUtils.IO_TIMEOUT_MS;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AlarmManager;
+import android.content.Context;
+import android.net.INetd;
+import android.net.ISocketKeepaliveCallback;
+import android.net.MarkMaskParcel;
+import android.net.Network;
+import android.net.NetworkAgent;
+import android.net.SocketKeepalive.InvalidSocketException;
+import android.os.FileUtils;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructTimeval;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.BinderUtils;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.DeviceConfigUtils;
+import com.android.net.module.util.HexDump;
+import com.android.net.module.util.SocketUtils;
+import com.android.net.module.util.netlink.InetDiagMessage;
+import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.NetlinkUtils;
+import com.android.net.module.util.netlink.StructNlAttr;
+
+import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.SocketException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Manages automatic on/off socket keepalive requests.
+ *
+ * Provides methods to stop and start automatic keepalive requests, and keeps track of keepalives
+ * across all networks. This class is tightly coupled to ConnectivityService. It is not
+ * thread-safe and its handle* methods must be called only from the ConnectivityService handler
+ * thread.
+ */
+public class AutomaticOnOffKeepaliveTracker {
+    private static final String TAG = "AutomaticOnOffKeepaliveTracker";
+    private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET6, AF_INET};
+    private static final String EXTRA_BINDER_TOKEN = "token";
+    private static final long DEFAULT_TCP_POLLING_INTERVAL_MS = 120_000L;
+    private static final long LOW_TCP_POLLING_INTERVAL_MS = 1_000L;
+    private static final String AUTOMATIC_ON_OFF_KEEPALIVE_VERSION =
+            "automatic_on_off_keepalive_version";
+    /**
+     * States for {@code #AutomaticOnOffKeepalive}.
+     *
+     * If automatic mode is off for this keepalive, the state is STATE_ALWAYS_ON and it stays
+     * so for the entire lifetime of this object.
+     *
+     * If enabled, a new AutomaticOnOffKeepalive starts with STATE_ENABLED. The system will monitor
+     * the TCP sockets on VPN networks running on top of the specified network, and turn off
+     * keepalive if there is no TCP socket any of the VPN networks. Conversely, it will turn
+     * keepalive back on if any TCP socket is open on any of the VPN networks.
+     *
+     * When there is no TCP socket on any of the VPN networks, the state becomes STATE_SUSPENDED.
+     * The {@link KeepaliveTracker.KeepaliveInfo} object is kept to remember the parameters so it
+     * is possible to resume keepalive later with the same parameters.
+     *
+     * When the system detects some TCP socket is open on one of the VPNs while in STATE_SUSPENDED,
+     * this AutomaticOnOffKeepalive goes to STATE_ENABLED again.
+     *
+     * When finishing keepalive, this object is deleted.
+     */
+    private static final int STATE_ENABLED = 0;
+    private static final int STATE_SUSPENDED = 1;
+    private static final int STATE_ALWAYS_ON = 2;
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "STATE_" }, value = {
+            STATE_ENABLED,
+            STATE_SUSPENDED,
+            STATE_ALWAYS_ON
+    })
+    private @interface AutomaticOnOffState {}
+
+    @NonNull
+    private final Handler mConnectivityServiceHandler;
+    @NonNull
+    private final KeepaliveTracker mKeepaliveTracker;
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final AlarmManager mAlarmManager;
+
+    /**
+     * The {@code inetDiagReqV2} messages for different IP family.
+     *
+     *   Key: Ip family type.
+     * Value: Bytes array represent the {@code inetDiagReqV2}.
+     *
+     * This should only be accessed in the connectivity service handler thread.
+     */
+    private final SparseArray<byte[]> mSockDiagMsg = new SparseArray<>();
+    private final Dependencies mDependencies;
+    private final INetd mNetd;
+    /**
+     * Keeps track of automatic on/off keepalive requests.
+     * This should be only updated in ConnectivityService handler thread.
+     */
+    private final ArrayList<AutomaticOnOffKeepalive> mAutomaticOnOffKeepalives = new ArrayList<>();
+    // TODO: Remove this when TCP polling design is replaced with callback.
+    private long mTestLowTcpPollingTimerUntilMs = 0;
+
+    /**
+     * Information about a managed keepalive.
+     *
+     * The keepalive in mKi is managed by this object. This object can be in one of three states
+     * (in mAutomatiOnOffState) :
+     * • STATE_ALWAYS_ON : this keepalive is always on
+     * • STATE_ENABLED : this keepalive is currently on, and monitored for possibly being turned
+     *                   off if no TCP socket is open on the VPN.
+     * • STATE_SUSPENDED : this keepalive is currently off, and monitored for possibly being
+     *                     resumed if a TCP socket is open on the VPN.
+     * See the documentation for the states for more detail.
+     */
+    public class AutomaticOnOffKeepalive implements IBinder.DeathRecipient {
+        @NonNull
+        private final KeepaliveTracker.KeepaliveInfo mKi;
+        @NonNull
+        private final ISocketKeepaliveCallback mCallback;
+        @Nullable
+        private final FileDescriptor mFd;
+        @Nullable
+        private final AlarmManager.OnAlarmListener mAlarmListener;
+        @AutomaticOnOffState
+        private int mAutomaticOnOffState;
+        @Nullable
+        private final Network mUnderpinnedNetwork;
+
+        AutomaticOnOffKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki,
+                final boolean autoOnOff, @NonNull Context context,
+                @Nullable Network underpinnedNetwork)
+                throws InvalidSocketException {
+            this.mKi = Objects.requireNonNull(ki);
+            mCallback = ki.mCallback;
+            mUnderpinnedNetwork = underpinnedNetwork;
+            if (autoOnOff && mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+                    true /* defaultEnabled */)) {
+                mAutomaticOnOffState = STATE_ENABLED;
+                if (null == ki.mFd) {
+                    throw new IllegalArgumentException("fd can't be null with automatic "
+                            + "on/off keepalives");
+                }
+                try {
+                    mFd = Os.dup(ki.mFd);
+                } catch (ErrnoException e) {
+                    Log.e(TAG, "Cannot dup fd: ", e);
+                    throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
+                }
+                mAlarmListener = () -> mConnectivityServiceHandler.obtainMessage(
+                        NetworkAgent.CMD_MONITOR_AUTOMATIC_KEEPALIVE, mCallback.asBinder())
+                        .sendToTarget();
+            } else {
+                mAutomaticOnOffState = STATE_ALWAYS_ON;
+                // A null fd is acceptable in KeepaliveInfo for backward compatibility of
+                // PacketKeepalive API, but it must never happen with automatic keepalives.
+                // TODO : remove mFd from KeepaliveInfo or from this class.
+                mFd = ki.mFd;
+                mAlarmListener = null;
+            }
+        }
+
+        @VisibleForTesting
+        public ISocketKeepaliveCallback getCallback() {
+            return mCallback;
+        }
+
+        public Network getNetwork() {
+            return mKi.getNai().network;
+        }
+
+        @Nullable
+        public Network getUnderpinnedNetwork() {
+            return mUnderpinnedNetwork;
+        }
+
+        public boolean match(Network network, int slot) {
+            return mKi.getNai().network().equals(network) && mKi.getSlot() == slot;
+        }
+
+        @Override
+        public void binderDied() {
+            mConnectivityServiceHandler.post(() -> cleanupAutoOnOffKeepalive(this));
+        }
+
+        /** Close this automatic on/off keepalive */
+        public void close() {
+            // Close the duplicated fd that maintains the lifecycle of socket. If this fd was
+            // not duplicated this is a no-op.
+            FileUtils.closeQuietly(mFd);
+        }
+
+        private String getAutomaticOnOffStateName(int state) {
+            switch (state) {
+                case STATE_ENABLED:
+                    return "STATE_ENABLED";
+                case STATE_SUSPENDED:
+                    return "STATE_SUSPENDED";
+                case STATE_ALWAYS_ON:
+                    return "STATE_ALWAYS_ON";
+                default:
+                    Log.e(TAG, "Get unexpected state:" + state);
+                    return Integer.toString(state);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "AutomaticOnOffKeepalive [ "
+                    + mKi
+                    + ", state=" + getAutomaticOnOffStateName(mAutomaticOnOffState)
+                    + " ]";
+        }
+    }
+
+    public AutomaticOnOffKeepaliveTracker(@NonNull Context context, @NonNull Handler handler) {
+        this(context, handler, new Dependencies(context));
+    }
+
+    @VisibleForTesting
+    public AutomaticOnOffKeepaliveTracker(@NonNull Context context, @NonNull Handler handler,
+            @NonNull Dependencies dependencies) {
+        mContext = Objects.requireNonNull(context);
+        mDependencies = Objects.requireNonNull(dependencies);
+        mConnectivityServiceHandler = Objects.requireNonNull(handler);
+        mNetd = mDependencies.getNetd();
+        mKeepaliveTracker = mDependencies.newKeepaliveTracker(
+                mContext, mConnectivityServiceHandler);
+
+        mAlarmManager = mDependencies.getAlarmManager(context);
+    }
+
+    private void startTcpPollingAlarm(@NonNull final AlarmManager.OnAlarmListener listener) {
+        final long triggerAtMillis =
+                SystemClock.elapsedRealtime() + getTcpPollingInterval();
+        // Setup a non-wake up alarm.
+        mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, null /* tag */,
+                listener, mConnectivityServiceHandler);
+    }
+
+    /**
+     * Determine if any state transition is needed for the specific automatic keepalive.
+     */
+    public void handleMonitorAutomaticKeepalive(@NonNull final AutomaticOnOffKeepalive ki,
+            final int vpnNetId) {
+        // Might happen if the automatic keepalive was removed by the app just as the alarm fires.
+        if (!mAutomaticOnOffKeepalives.contains(ki)) return;
+        if (STATE_ALWAYS_ON == ki.mAutomaticOnOffState) {
+            throw new IllegalStateException("Should not monitor non-auto keepalive");
+        }
+
+        handleMonitorTcpConnections(ki, vpnNetId);
+    }
+
+    /**
+     * Determine if disable or re-enable keepalive is needed or not based on TCP sockets status.
+     */
+    private void handleMonitorTcpConnections(@NonNull AutomaticOnOffKeepalive ki, int vpnNetId) {
+        // Might happen if the automatic keepalive was removed by the app just as the alarm fires.
+        if (!mAutomaticOnOffKeepalives.contains(ki)) return;
+        if (STATE_ALWAYS_ON == ki.mAutomaticOnOffState) {
+            throw new IllegalStateException("Should not monitor non-auto keepalive");
+        }
+        if (!isAnyTcpSocketConnected(vpnNetId)) {
+            // No TCP socket exists. Stop keepalive if ENABLED, and remain SUSPENDED if currently
+            // SUSPENDED.
+            if (ki.mAutomaticOnOffState == STATE_ENABLED) {
+                ki.mAutomaticOnOffState = STATE_SUSPENDED;
+                handlePauseKeepalive(ki.mKi);
+            }
+        } else {
+            handleMaybeResumeKeepalive(ki);
+        }
+        // TODO: listen to socket status instead of periodically check.
+        startTcpPollingAlarm(ki.mAlarmListener);
+    }
+
+    /**
+     * Resume an auto on/off keepalive, unless it's already resumed
+     * @param autoKi the keepalive to resume
+     */
+    public void handleMaybeResumeKeepalive(@NonNull AutomaticOnOffKeepalive autoKi) {
+        // Might happen if the automatic keepalive was removed by the app just as the alarm fires.
+        if (!mAutomaticOnOffKeepalives.contains(autoKi)) return;
+        if (STATE_ALWAYS_ON == autoKi.mAutomaticOnOffState) {
+            throw new IllegalStateException("Should not resume non-auto keepalive");
+        }
+        if (autoKi.mAutomaticOnOffState == STATE_ENABLED) return;
+        KeepaliveTracker.KeepaliveInfo newKi;
+        try {
+            // Get fd from AutomaticOnOffKeepalive since the fd in the original
+            // KeepaliveInfo should be closed.
+            newKi = autoKi.mKi.withFd(autoKi.mFd);
+        } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) {
+            Log.e(TAG, "Fail to construct keepalive", e);
+            mKeepaliveTracker.notifyErrorCallback(autoKi.mCallback, ERROR_INVALID_SOCKET);
+            return;
+        }
+        autoKi.mAutomaticOnOffState = STATE_ENABLED;
+        handleResumeKeepalive(newKi);
+    }
+
+    /**
+     * Find the AutomaticOnOffKeepalive associated with a given callback.
+     * @return the keepalive associated with this callback, or null if none
+     */
+    @Nullable
+    public AutomaticOnOffKeepalive getKeepaliveForBinder(@NonNull final IBinder token) {
+        ensureRunningOnHandlerThread();
+
+        return CollectionUtils.findFirst(mAutomaticOnOffKeepalives,
+                it -> it.mCallback.asBinder().equals(token));
+    }
+
+    /**
+     * Handle keepalive events from lower layer.
+     *
+     * Forward to KeepaliveTracker.
+     */
+    public void handleEventSocketKeepalive(@NonNull NetworkAgentInfo nai, int slot, int reason) {
+        mKeepaliveTracker.handleEventSocketKeepalive(nai, slot, reason);
+    }
+
+    /**
+     * Handle stop all keepalives on the specific network.
+     */
+    public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
+        mKeepaliveTracker.handleStopAllKeepalives(nai, reason);
+        final List<AutomaticOnOffKeepalive> matches =
+                CollectionUtils.filter(mAutomaticOnOffKeepalives, it -> it.mKi.getNai() == nai);
+        for (final AutomaticOnOffKeepalive ki : matches) {
+            cleanupAutoOnOffKeepalive(ki);
+        }
+    }
+
+    /**
+     * Handle start keepalive contained within a message.
+     *
+     * The message is expected to contain a KeepaliveTracker.KeepaliveInfo.
+     */
+    public void handleStartKeepalive(Message message) {
+        final AutomaticOnOffKeepalive autoKi = (AutomaticOnOffKeepalive) message.obj;
+        mKeepaliveTracker.handleStartKeepalive(autoKi.mKi);
+
+        // Add automatic on/off request into list to track its life cycle.
+        try {
+            autoKi.mKi.mCallback.asBinder().linkToDeath(autoKi, 0);
+        } catch (RemoteException e) {
+            // The underlying keepalive performs its own cleanup
+            autoKi.binderDied();
+            return;
+        }
+        mAutomaticOnOffKeepalives.add(autoKi);
+        if (STATE_ALWAYS_ON != autoKi.mAutomaticOnOffState) {
+            startTcpPollingAlarm(autoKi.mAlarmListener);
+        }
+    }
+
+    private void handleResumeKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki) {
+        mKeepaliveTracker.handleStartKeepalive(ki);
+    }
+
+    private void handlePauseKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki) {
+        // TODO : mKT.handleStopKeepalive should take a KeepaliveInfo instead
+        mKeepaliveTracker.handleStopKeepalive(ki.getNai(), ki.getSlot(), SUCCESS_PAUSED);
+    }
+
+    /**
+     * Handle stop keepalives on the specific network with given slot.
+     */
+    public void handleStopKeepalive(@NonNull final AutomaticOnOffKeepalive autoKi, int reason) {
+        // Stop the keepalive unless it was suspended. This includes the case where it's managed
+        // but enabled, and the case where it's always on.
+        if (autoKi.mAutomaticOnOffState != STATE_SUSPENDED) {
+            final KeepaliveTracker.KeepaliveInfo ki = autoKi.mKi;
+            mKeepaliveTracker.handleStopKeepalive(ki.getNai(), ki.getSlot(), reason);
+        } else {
+            mKeepaliveTracker.finalizePausedKeepalive(autoKi.mKi);
+        }
+
+        cleanupAutoOnOffKeepalive(autoKi);
+    }
+
+    private void cleanupAutoOnOffKeepalive(@NonNull final AutomaticOnOffKeepalive autoKi) {
+        ensureRunningOnHandlerThread();
+        autoKi.close();
+        if (null != autoKi.mAlarmListener) mAlarmManager.cancel(autoKi.mAlarmListener);
+
+        // If the KI is not in the array, it's because it was already removed, or it was never
+        // added ; the only ways this can happen is if the keepalive is stopped by the app and the
+        // app dies immediately, or if the app died before the link to death could be registered.
+        if (!mAutomaticOnOffKeepalives.remove(autoKi)) return;
+
+        autoKi.mKi.mCallback.asBinder().unlinkToDeath(autoKi, 0);
+    }
+
+    /**
+     * Called when requesting that keepalives be started on a IPsec NAT-T socket. See
+     * {@link android.net.SocketKeepalive}.
+     *
+     * Forward to KeepaliveTracker.
+     **/
+    public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
+            @Nullable FileDescriptor fd,
+            int intervalSeconds,
+            @NonNull ISocketKeepaliveCallback cb,
+            @NonNull String srcAddrString,
+            int srcPort,
+            @NonNull String dstAddrString,
+            int dstPort, boolean automaticOnOffKeepalives, @Nullable Network underpinnedNetwork) {
+        final KeepaliveTracker.KeepaliveInfo ki = mKeepaliveTracker.makeNattKeepaliveInfo(nai, fd,
+                intervalSeconds, cb, srcAddrString, srcPort, dstAddrString, dstPort);
+        if (null == ki) return;
+        try {
+            final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
+                    automaticOnOffKeepalives, mContext, underpinnedNetwork);
+            mConnectivityServiceHandler.obtainMessage(NetworkAgent.CMD_START_SOCKET_KEEPALIVE,
+                    // TODO : move ConnectivityService#encodeBool to a static lib.
+                    automaticOnOffKeepalives ? 1 : 0, 0, autoKi).sendToTarget();
+        } catch (InvalidSocketException e) {
+            mKeepaliveTracker.notifyErrorCallback(cb, e.error);
+        }
+    }
+
+    /**
+     * Called when requesting that keepalives be started on a IPsec NAT-T socket. See
+     * {@link android.net.SocketKeepalive}.
+     *
+     * Forward to KeepaliveTracker.
+     **/
+    public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
+            @Nullable FileDescriptor fd,
+            int resourceId,
+            int intervalSeconds,
+            @NonNull ISocketKeepaliveCallback cb,
+            @NonNull String srcAddrString,
+            @NonNull String dstAddrString,
+            int dstPort,
+            boolean automaticOnOffKeepalives,
+            @Nullable Network underpinnedNetwork) {
+        final KeepaliveTracker.KeepaliveInfo ki = mKeepaliveTracker.makeNattKeepaliveInfo(nai, fd,
+                resourceId, intervalSeconds, cb, srcAddrString, dstAddrString, dstPort);
+        if (null == ki) return;
+        try {
+            final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
+                    automaticOnOffKeepalives, mContext, underpinnedNetwork);
+            mConnectivityServiceHandler.obtainMessage(NetworkAgent.CMD_START_SOCKET_KEEPALIVE,
+                    // TODO : move ConnectivityService#encodeBool to a static lib.
+                    automaticOnOffKeepalives ? 1 : 0, 0, autoKi).sendToTarget();
+        } catch (InvalidSocketException e) {
+            mKeepaliveTracker.notifyErrorCallback(cb, e.error);
+        }
+    }
+
+    /**
+     * Called by ConnectivityService to start TCP keepalive on a file descriptor.
+     *
+     * In order to offload keepalive for application correctly, sequence number, ack number and
+     * other fields are needed to form the keepalive packet. Thus, this function synchronously
+     * puts the socket into repair mode to get the necessary information. After the socket has been
+     * put into repair mode, the application cannot access the socket until reverted to normal.
+     * See {@link android.net.SocketKeepalive}.
+     *
+     * Forward to KeepaliveTracker.
+     **/
+    public void startTcpKeepalive(@Nullable NetworkAgentInfo nai,
+            @NonNull FileDescriptor fd,
+            int intervalSeconds,
+            @NonNull ISocketKeepaliveCallback cb) {
+        final KeepaliveTracker.KeepaliveInfo ki = mKeepaliveTracker.makeTcpKeepaliveInfo(nai, fd,
+                intervalSeconds, cb);
+        if (null == ki) return;
+        try {
+            final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
+                    false /* autoOnOff, tcp keepalives are never auto on/off */,
+                    mContext, null /* underpinnedNetwork, tcp keepalives do not refer to this */);
+            mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, autoKi)
+                    .sendToTarget();
+        } catch (InvalidSocketException e) {
+            mKeepaliveTracker.notifyErrorCallback(cb, e.error);
+        }
+    }
+
+    /**
+     * Dump AutomaticOnOffKeepaliveTracker state.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        mKeepaliveTracker.dump(pw);
+        // Reading DeviceConfig will check if the calling uid and calling package name are the same.
+        // Clear calling identity to align the calling uid and package so that it won't fail if cts
+        // would like to do the dump()
+        final boolean featureEnabled = BinderUtils.withCleanCallingIdentity(
+                () -> mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+                        true /* defaultEnabled */));
+        pw.println("AutomaticOnOff enabled: " + featureEnabled);
+        pw.increaseIndent();
+        for (AutomaticOnOffKeepalive autoKi : mAutomaticOnOffKeepalives) {
+            pw.println(autoKi.toString());
+        }
+        pw.decreaseIndent();
+    }
+
+    /**
+     * Check all keepalives on the network are still valid.
+     *
+     * Forward to KeepaliveTracker.
+     */
+    public void handleCheckKeepalivesStillValid(NetworkAgentInfo nai) {
+        mKeepaliveTracker.handleCheckKeepalivesStillValid(nai);
+    }
+
+    @VisibleForTesting
+    boolean isAnyTcpSocketConnected(int netId) {
+        FileDescriptor fd = null;
+
+        try {
+            fd = mDependencies.createConnectedNetlinkSocket();
+
+            // Get network mask
+            final MarkMaskParcel parcel = mNetd.getFwmarkForNetwork(netId);
+            final int networkMark = (parcel != null) ? parcel.mark : NetlinkUtils.UNKNOWN_MARK;
+            final int networkMask = (parcel != null) ? parcel.mask : NetlinkUtils.NULL_MASK;
+
+            // Send request for each IP family
+            for (final int family : ADDRESS_FAMILIES) {
+                if (isAnyTcpSocketConnectedForFamily(fd, family, networkMark, networkMask)) {
+                    return true;
+                }
+            }
+        } catch (ErrnoException | SocketException | InterruptedIOException | RemoteException e) {
+            Log.e(TAG, "Fail to get socket info via netlink.", e);
+        } finally {
+            SocketUtils.closeSocketQuietly(fd);
+        }
+
+        return false;
+    }
+
+    private boolean isAnyTcpSocketConnectedForFamily(FileDescriptor fd, int family, int networkMark,
+            int networkMask) throws ErrnoException, InterruptedIOException {
+        ensureRunningOnHandlerThread();
+        // Build SocketDiag messages and cache it.
+        if (mSockDiagMsg.get(family) == null) {
+            mSockDiagMsg.put(family, InetDiagMessage.buildInetDiagReqForAliveTcpSockets(family));
+        }
+        mDependencies.sendRequest(fd, mSockDiagMsg.get(family));
+
+        // Iteration limitation as a protection to avoid possible infinite loops.
+        // DEFAULT_RECV_BUFSIZE could read more than 20 sockets per time. Max iteration
+        // should be enough to go through reasonable TCP sockets in the device.
+        final int maxIteration = 100;
+        int parsingIteration = 0;
+        while (parsingIteration < maxIteration) {
+            final ByteBuffer bytes = mDependencies.recvSockDiagResponse(fd);
+
+            try {
+                while (NetlinkUtils.enoughBytesRemainForValidNlMsg(bytes)) {
+                    final int startPos = bytes.position();
+
+                    final int nlmsgLen = bytes.getInt();
+                    final int nlmsgType = bytes.getShort();
+                    if (isEndOfMessageOrError(nlmsgType)) return false;
+                    // TODO: Parse InetDiagMessage to get uid and dst address information to filter
+                    //  socket via NetlinkMessage.parse.
+
+                    // Skip the header to move to data part.
+                    bytes.position(startPos + SOCKDIAG_MSG_HEADER_SIZE);
+
+                    if (isTargetTcpSocket(bytes, nlmsgLen, networkMark, networkMask)) {
+                        if (Log.isLoggable(TAG, Log.DEBUG)) {
+                            bytes.position(startPos);
+                            final InetDiagMessage diagMsg = (InetDiagMessage) NetlinkMessage.parse(
+                                    bytes, OsConstants.NETLINK_INET_DIAG);
+                            Log.d(TAG, String.format("Found open TCP connection by uid %d to %s"
+                                            + " cookie %d",
+                                    diagMsg.inetDiagMsg.idiag_uid,
+                                    diagMsg.inetDiagMsg.id.remSocketAddress,
+                                    diagMsg.inetDiagMsg.id.cookie));
+                        }
+                        return true;
+                    }
+                }
+            } catch (BufferUnderflowException e) {
+                // The exception happens in random place in either header position or any data
+                // position. Partial bytes from the middle of the byte buffer may not be enough to
+                // clarify, so print out the content before the error to possibly prevent printing
+                // the whole 8K buffer.
+                final int exceptionPos = bytes.position();
+                final String hex = HexDump.dumpHexString(bytes.array(), 0, exceptionPos);
+                Log.e(TAG, "Unexpected socket info parsing: " + hex, e);
+            }
+
+            parsingIteration++;
+        }
+        return false;
+    }
+
+    private boolean isEndOfMessageOrError(int nlmsgType) {
+        return nlmsgType == NLMSG_DONE || nlmsgType != SOCK_DIAG_BY_FAMILY;
+    }
+
+    private boolean isTargetTcpSocket(@NonNull ByteBuffer bytes, int nlmsgLen, int networkMark,
+            int networkMask) {
+        final int mark = readSocketDataAndReturnMark(bytes, nlmsgLen);
+        return (mark & networkMask) == networkMark;
+    }
+
+    private int readSocketDataAndReturnMark(@NonNull ByteBuffer bytes, int nlmsgLen) {
+        final int nextMsgOffset = bytes.position() + nlmsgLen - SOCKDIAG_MSG_HEADER_SIZE;
+        int mark = NetlinkUtils.INIT_MARK_VALUE;
+        // Get socket mark
+        // TODO: Add a parsing method in NetlinkMessage.parse to support this to skip the remaining
+        //  data.
+        while (bytes.position() < nextMsgOffset) {
+            final StructNlAttr nlattr = StructNlAttr.parse(bytes);
+            if (nlattr != null && nlattr.nla_type == NetlinkUtils.INET_DIAG_MARK) {
+                mark = nlattr.getValueAsInteger();
+            }
+        }
+        return mark;
+    }
+
+    private void ensureRunningOnHandlerThread() {
+        if (mConnectivityServiceHandler.getLooper().getThread() != Thread.currentThread()) {
+            throw new IllegalStateException(
+                    "Not running on handler thread: " + Thread.currentThread().getName());
+        }
+    }
+
+    private long getTcpPollingInterval() {
+        final boolean useLowTimer = mTestLowTcpPollingTimerUntilMs > System.currentTimeMillis();
+        return useLowTimer ? LOW_TCP_POLLING_INTERVAL_MS : DEFAULT_TCP_POLLING_INTERVAL_MS;
+    }
+
+    /**
+     * Temporarily use low TCP polling timer for testing.
+     * The value works when the time set is more than {@link System.currentTimeMillis()}.
+     */
+    public void handleSetTestLowTcpPollingTimer(long timeMs) {
+        Log.d(TAG, "handleSetTestLowTcpPollingTimer: " + timeMs);
+        mTestLowTcpPollingTimerUntilMs = timeMs;
+    }
+
+    /**
+     * Dependencies class for testing.
+     */
+    @VisibleForTesting
+    public static class Dependencies {
+        private final Context mContext;
+
+        public Dependencies(final Context context) {
+            mContext = context;
+        }
+
+        /**
+         * Create a netlink socket connected to the kernel.
+         *
+         * @return fd the fileDescriptor of the socket.
+         */
+        public FileDescriptor createConnectedNetlinkSocket()
+                throws ErrnoException, SocketException {
+            final FileDescriptor fd = NetlinkUtils.createNetLinkInetDiagSocket();
+            NetlinkUtils.connectSocketToNetlink(fd);
+            Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO,
+                    StructTimeval.fromMillis(IO_TIMEOUT_MS));
+            return fd;
+        }
+
+        /**
+         * Send composed message request to kernel.
+         *
+         * The given FileDescriptor is expected to be created by
+         * {@link #createConnectedNetlinkSocket} or equivalent way.
+         *
+         * @param fd a netlink socket {@code FileDescriptor} connected to the kernel.
+         * @param msg the byte array representing the request message to write to kernel.
+         */
+        public void sendRequest(@NonNull final FileDescriptor fd,
+                @NonNull final byte[] msg)
+                throws ErrnoException, InterruptedIOException {
+            Os.write(fd, msg, 0 /* byteOffset */, msg.length);
+        }
+
+        /**
+         * Get an INetd connector.
+         */
+        public INetd getNetd() {
+            return INetd.Stub.asInterface(
+                    (IBinder) mContext.getSystemService(Context.NETD_SERVICE));
+        }
+
+        /**
+         * Get an instance of AlarmManager
+         */
+        public AlarmManager getAlarmManager(@NonNull final Context ctx) {
+            return ctx.getSystemService(AlarmManager.class);
+        }
+
+        /**
+         * Receive the response message from kernel via given {@code FileDescriptor}.
+         * The usage should follow the {@code #sendRequest} call with the same
+         * FileDescriptor.
+         *
+         * The overall response may be large but the individual messages should not be
+         * excessively large(8-16kB) because trying to get the kernel to return
+         * everything in one big buffer is inefficient as it forces the kernel to allocate
+         * large chunks of linearly physically contiguous memory. The usage should iterate the
+         * call of this method until the end of the overall message.
+         *
+         * The default receiving buffer size should be small enough that it is always
+         * processed within the {@link NetlinkUtils#IO_TIMEOUT_MS} timeout.
+         */
+        public ByteBuffer recvSockDiagResponse(@NonNull final FileDescriptor fd)
+                throws ErrnoException, InterruptedIOException {
+            return NetlinkUtils.recvMessage(
+                    fd, NetlinkUtils.DEFAULT_RECV_BUFSIZE, NetlinkUtils.IO_TIMEOUT_MS);
+        }
+
+        /**
+         * Construct a new KeepaliveTracker.
+         */
+        public KeepaliveTracker newKeepaliveTracker(@NonNull Context context,
+                @NonNull Handler connectivityserviceHander) {
+            return new KeepaliveTracker(mContext, connectivityserviceHander);
+        }
+
+        /**
+         * Find out if a feature is enabled from DeviceConfig.
+         *
+         * @param name The name of the property to look up.
+         * @param defaultEnabled whether to consider the feature enabled in the absence of
+         *                       the flag. This MUST be a statically-known constant.
+         * @return whether the feature is enabled
+         */
+        public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
+            return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
+                    defaultEnabled);
+        }
+    }
+}
diff --git a/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java b/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
index b06c8aa..4325763 100644
--- a/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
+++ b/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
@@ -38,6 +38,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.HandlerExecutor;
 import com.android.networkstack.apishim.TelephonyManagerShimImpl;
 import com.android.networkstack.apishim.common.TelephonyManagerShim;
 import com.android.networkstack.apishim.common.TelephonyManagerShim.CarrierPrivilegesListenerShim;
@@ -46,7 +47,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
 
 /**
  * Tracks the uid of the carrier privileged app that provides the carrier config.
@@ -105,27 +105,6 @@
     }
 
     /**
-     * An adapter {@link Executor} that posts all executed tasks onto the given
-     * {@link Handler}.
-     *
-     * TODO : migrate to the version in frameworks/libs/net when it's ready
-     *
-     * @hide
-     */
-    public class HandlerExecutor implements Executor {
-        private final Handler mHandler;
-        public HandlerExecutor(@NonNull Handler handler) {
-            mHandler = handler;
-        }
-        @Override
-        public void execute(Runnable command) {
-            if (!mHandler.post(command)) {
-                throw new RejectedExecutionException(mHandler + " is shutting down");
-            }
-        }
-    }
-
-    /**
      * Broadcast receiver for ACTION_MULTI_SIM_CONFIG_CHANGED
      *
      * <p>The broadcast receiver is registered with mHandler
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/FullScore.java b/service/src/com/android/server/connectivity/FullScore.java
index 2303894..87ae0c9 100644
--- a/service/src/com/android/server/connectivity/FullScore.java
+++ b/service/src/com/android/server/connectivity/FullScore.java
@@ -23,7 +23,7 @@
 import static android.net.NetworkScore.KEEP_CONNECTED_NONE;
 import static android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI;
 
-import static com.android.net.module.util.BitUtils.appendStringRepresentationOfBitMaskToStringBuilder;
+import static com.android.net.module.util.BitUtils.describeDifferences;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -338,31 +338,14 @@
 
     /**
      * Returns a short but human-readable string of updates from an older score.
-     * @param old the old capabilities to diff from
+     * @param old the old score to diff from
      * @return a string fit for logging differences, or null if no differences.
-     *         this method cannot return the empty string.
+     *         this method cannot return the empty string. See BitUtils#describeDifferences.
      */
     @Nullable
     public String describeDifferencesFrom(@Nullable final FullScore old) {
         final long oldPolicies = null == old ? 0 : old.mPolicies;
-        final long changed = oldPolicies ^ mPolicies;
-        if (0 == changed) return null;
-        // If the control reaches here, there are changes (additions, removals, or both) so
-        // the code below is guaranteed to add something to the string and can't return "".
-        final long removed = oldPolicies & changed;
-        final long added = mPolicies & changed;
-        final StringBuilder sb = new StringBuilder();
-        if (0 != removed) {
-            sb.append("-");
-            appendStringRepresentationOfBitMaskToStringBuilder(sb, removed,
-                    FullScore::policyNameOf, "-");
-        }
-        if (0 != added) {
-            sb.append("+");
-            appendStringRepresentationOfBitMaskToStringBuilder(sb, added,
-                    FullScore::policyNameOf, "+");
-        }
-        return sb.toString();
+        return describeDifferences(oldPolicies, mPolicies, FullScore::policyNameOf);
     }
 
     // Example output :
diff --git a/service/src/com/android/server/connectivity/KeepaliveTracker.java b/service/src/com/android/server/connectivity/KeepaliveTracker.java
index 3b58823..06294db 100644
--- a/service/src/com/android/server/connectivity/KeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/KeepaliveTracker.java
@@ -18,7 +18,6 @@
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.NattSocketKeepalive.NATT_PORT;
-import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
 import static android.net.SocketKeepalive.BINDER_DIED;
 import static android.net.SocketKeepalive.DATA_RECEIVED;
 import static android.net.SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES;
@@ -33,6 +32,7 @@
 import static android.net.SocketKeepalive.MIN_INTERVAL_SEC;
 import static android.net.SocketKeepalive.NO_KEEPALIVE;
 import static android.net.SocketKeepalive.SUCCESS;
+import static android.net.SocketKeepalive.SUCCESS_PAUSED;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -50,7 +50,6 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.system.ErrnoException;
@@ -59,6 +58,7 @@
 import android.util.Pair;
 
 import com.android.connectivity.resources.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.net.module.util.HexDump;
 import com.android.net.module.util.IpUtils;
@@ -88,7 +88,6 @@
     /** Keeps track of keepalive requests. */
     private final HashMap <NetworkAgentInfo, HashMap<Integer, KeepaliveInfo>> mKeepalives =
             new HashMap<> ();
-    private final Handler mConnectivityServiceHandler;
     @NonNull
     private final TcpKeepaliveController mTcpController;
     @NonNull
@@ -109,9 +108,9 @@
     private final int mAllowedUnprivilegedSlotsForUid;
 
     public KeepaliveTracker(Context context, Handler handler) {
-        mConnectivityServiceHandler = handler;
         mTcpController = new TcpKeepaliveController(handler);
         mContext = context;
+
         mSupportedKeepalives = KeepaliveUtils.getSupportedKeepalives(mContext);
 
         final ConnectivityResources res = new ConnectivityResources(mContext);
@@ -127,15 +126,20 @@
      * All information about this keepalive is known at construction time except the slot number,
      * which is only returned when the hardware has successfully started the keepalive.
      */
-    class KeepaliveInfo implements IBinder.DeathRecipient {
+    @VisibleForTesting
+    public class KeepaliveInfo implements IBinder.DeathRecipient {
+        // TODO : remove this member. Only AutoOnOffKeepalive should have a reference to this.
+        public final ISocketKeepaliveCallback mCallback;
         // Bookkeeping data.
-        private final ISocketKeepaliveCallback mCallback;
         private final int mUid;
         private final int mPid;
         private final boolean mPrivileged;
-        private final NetworkAgentInfo mNai;
+        public final NetworkAgentInfo mNai;
         private final int mType;
-        private final FileDescriptor mFd;
+        public final FileDescriptor mFd;
+        // True if this was resumed from a previously turned off keepalive, otherwise false.
+        // This is necessary to send the correct callbacks.
+        public final boolean mResumed;
 
         public static final int TYPE_NATT = 1;
         public static final int TYPE_TCP = 2;
@@ -162,6 +166,16 @@
                 int interval,
                 int type,
                 @Nullable FileDescriptor fd) throws InvalidSocketException {
+            this(callback, nai, packet, interval, type, fd, false /* resumed */);
+        }
+
+        KeepaliveInfo(@NonNull ISocketKeepaliveCallback callback,
+                @NonNull NetworkAgentInfo nai,
+                @NonNull KeepalivePacketData packet,
+                int interval,
+                int type,
+                @Nullable FileDescriptor fd,
+                boolean resumed) throws InvalidSocketException {
             mCallback = callback;
             mPid = Binder.getCallingPid();
             mUid = Binder.getCallingUid();
@@ -171,6 +185,7 @@
             mPacket = packet;
             mInterval = interval;
             mType = type;
+            mResumed = resumed;
 
             // For SocketKeepalive, a dup of fd is kept in mFd so the source port from which the
             // keepalives are sent cannot be reused by another app even if the fd gets closed by
@@ -234,6 +249,8 @@
 
         /** Called when the application process is killed. */
         public void binderDied() {
+            // TODO b/267106526 : this is not called on the handler thread but stop() happily
+            // assumes it is, which means this is a pretty dangerous race condition.
             stop(BINDER_DIED);
         }
 
@@ -243,6 +260,10 @@
             }
         }
 
+        public int getSlot() {
+            return mSlot;
+        }
+
         private int checkNetworkConnected() {
             if (!mNai.networkInfo.isConnectedOrConnecting()) {
                 return ERROR_INVALID_NETWORK;
@@ -325,6 +346,10 @@
         }
 
         void start(int slot) {
+            // BINDER_DIED can happen if the binder died before the KeepaliveInfo was created and
+            // the constructor set the state to BINDER_DIED. If that's the case, the KI is already
+            // cleaned up.
+            if (BINDER_DIED == mStartedState) return;
             mSlot = slot;
             int error = isValid();
             if (error == SUCCESS) {
@@ -369,7 +394,10 @@
             // To prevent races from re-entrance of stop(), return if the state is already stopping.
             // This might happen if multiple event sources stop keepalive in a short time. Such as
             // network disconnect after user calls stop(), or tear down socket after binder died.
-            if (mStartedState == STOPPING) return;
+            // Note that it's always possible this method is called by the auto keepalive timer
+            // or any other way after the binder died, hence the check for BINDER_DIED. If the
+            // binder has died, then the KI has already been cleaned up.
+            if (mStartedState == STOPPING || mStartedState == BINDER_DIED) return;
 
             // Store the reason of stopping, and report it after the keepalive is fully stopped.
             if (mStopReason != ERROR_STOP_REASON_UNINITIALIZED) {
@@ -380,9 +408,10 @@
                     + ": " + reason);
             switch (mStartedState) {
                 case NOT_STARTED:
-                    // Remove the reference of the keepalive that meet error before starting,
+                    // Remove the reference to this keepalive that had an error before starting,
                     // e.g. invalid parameter.
                     cleanupStoppedKeepalive(mNai, mSlot);
+                    if (BINDER_DIED == reason) mStartedState = BINDER_DIED;
                     break;
                 default:
                     mStartedState = STOPPING;
@@ -415,6 +444,14 @@
         void onFileDescriptorInitiatedStop(final int socketKeepaliveReason) {
             handleStopKeepalive(mNai, mSlot, socketKeepaliveReason);
         }
+
+        /**
+         * Construct a new KeepaliveInfo from existing KeepaliveInfo with a new fd.
+         */
+        public KeepaliveInfo withFd(@NonNull FileDescriptor fd) throws InvalidSocketException {
+            return new KeepaliveInfo(mCallback, mNai, mPacket, mInterval, mType, fd,
+                    true /* resumed */);
+        }
     }
 
     void notifyErrorCallback(ISocketKeepaliveCallback cb, int error) {
@@ -444,8 +481,10 @@
         return slot;
     }
 
-    public void handleStartKeepalive(Message message) {
-        KeepaliveInfo ki = (KeepaliveInfo) message.obj;
+    /**
+     * Handle start keepalives with the message.
+     */
+    public void handleStartKeepalive(KeepaliveInfo ki) {
         NetworkAgentInfo nai = ki.getNai();
         int slot = findFirstFreeSlot(nai);
         mKeepalives.get(nai).put(slot, ki);
@@ -512,6 +551,12 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Discarded onStop callback: " + reason);
             }
+        } else if (reason == SUCCESS_PAUSED) {
+            try {
+                ki.mCallback.onPaused();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Discarded onPaused callback: " + reason);
+            }
         } else if (reason == DATA_RECEIVED) {
             try {
                 ki.mCallback.onDataReceived();
@@ -529,6 +574,25 @@
         ki.unlinkDeathRecipient();
     }
 
+    /**
+     * Finalize a paused keepalive.
+     *
+     * This will simply send the onStopped() callback after checking that this keepalive is
+     * indeed paused.
+     *
+     * @param ki the keepalive to finalize
+     */
+    public void finalizePausedKeepalive(@NonNull final KeepaliveInfo ki) {
+        if (SUCCESS_PAUSED != ki.mStopReason) {
+            throw new IllegalStateException("Keepalive is not paused");
+        }
+        try {
+            ki.mCallback.onStopped();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Discarded onStopped callback while finalizing paused keepalive");
+        }
+    }
+
     public void handleCheckKeepalivesStillValid(NetworkAgentInfo nai) {
         HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
         if (networkKeepalives != null) {
@@ -578,9 +642,14 @@
                 Log.d(TAG, "Started keepalive " + slot + " on " + nai.toShortString());
                 ki.mStartedState = KeepaliveInfo.STARTED;
                 try {
-                    ki.mCallback.onStarted(slot);
+                    if (ki.mResumed) {
+                        ki.mCallback.onResumed();
+                    } else {
+                        ki.mCallback.onStarted();
+                    }
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Discarded onStarted(" + slot + ") callback");
+                    Log.w(TAG, "Discarded " + (ki.mResumed ? "onResumed" : "onStarted")
+                            + " callback for slot " + slot);
                 }
             } else {
                 Log.d(TAG, "Failed to start keepalive " + slot + " on " + nai.toShortString()
@@ -604,7 +673,8 @@
      * Called when requesting that keepalives be started on a IPsec NAT-T socket. See
      * {@link android.net.SocketKeepalive}.
      **/
-    public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
+    @Nullable
+    public KeepaliveInfo makeNattKeepaliveInfo(@Nullable NetworkAgentInfo nai,
             @Nullable FileDescriptor fd,
             int intervalSeconds,
             @NonNull ISocketKeepaliveCallback cb,
@@ -614,7 +684,7 @@
             int dstPort) {
         if (nai == null) {
             notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
-            return;
+            return null;
         }
 
         InetAddress srcAddress, dstAddress;
@@ -623,7 +693,7 @@
             dstAddress = InetAddresses.parseNumericAddress(dstAddrString);
         } catch (IllegalArgumentException e) {
             notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS);
-            return;
+            return null;
         }
 
         KeepalivePacketData packet;
@@ -632,7 +702,7 @@
                     srcAddress, srcPort, dstAddress, NATT_PORT);
         } catch (InvalidPacketException e) {
             notifyErrorCallback(cb, e.getError());
-            return;
+            return null;
         }
         KeepaliveInfo ki = null;
         try {
@@ -641,15 +711,14 @@
         } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) {
             Log.e(TAG, "Fail to construct keepalive", e);
             notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
-            return;
+            return null;
         }
-        Log.d(TAG, "Created keepalive: " + ki.toString());
-        mConnectivityServiceHandler.obtainMessage(
-                NetworkAgent.CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
+        Log.d(TAG, "Created keepalive: " + ki);
+        return ki;
     }
 
     /**
-     * Called by ConnectivityService to start TCP keepalive on a file descriptor.
+     * Make a KeepaliveInfo for a TCP socket.
      *
      * In order to offload keepalive for application correctly, sequence number, ack number and
      * other fields are needed to form the keepalive packet. Thus, this function synchronously
@@ -658,13 +727,14 @@
      *
      * See {@link android.net.SocketKeepalive}.
      **/
-    public void startTcpKeepalive(@Nullable NetworkAgentInfo nai,
+    @Nullable
+    public KeepaliveInfo makeTcpKeepaliveInfo(@Nullable NetworkAgentInfo nai,
             @NonNull FileDescriptor fd,
             int intervalSeconds,
             @NonNull ISocketKeepaliveCallback cb) {
         if (nai == null) {
             notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
-            return;
+            return null;
         }
 
         final TcpKeepalivePacketData packet;
@@ -672,10 +742,10 @@
             packet = TcpKeepaliveController.getTcpKeepalivePacket(fd);
         } catch (InvalidSocketException e) {
             notifyErrorCallback(cb, e.error);
-            return;
+            return null;
         } catch (InvalidPacketException e) {
             notifyErrorCallback(cb, e.getError());
-            return;
+            return null;
         }
         KeepaliveInfo ki = null;
         try {
@@ -684,20 +754,22 @@
         } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) {
             Log.e(TAG, "Fail to construct keepalive e=" + e);
             notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
-            return;
+            return null;
         }
         Log.d(TAG, "Created keepalive: " + ki.toString());
-        mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
+        return ki;
     }
 
-   /**
-    * Called when requesting that keepalives be started on a IPsec NAT-T socket. This function is
-    * identical to {@link #startNattKeepalive}, but also takes a {@code resourceId}, which is the
-    * resource index bound to the {@link UdpEncapsulationSocket} when creating by
-    * {@link com.android.server.IpSecService} to verify whether the given
-    * {@link UdpEncapsulationSocket} is legitimate.
-    **/
-    public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
+    /**
+     * Make a KeepaliveInfo for an IPSec NAT-T socket.
+     *
+     * This function is identical to {@link #makeNattKeepaliveInfo}, but also takes a
+     * {@code resourceId}, which is the resource index bound to the {@link UdpEncapsulationSocket}
+     * when creating by {@link com.android.server.IpSecService} to verify whether the given
+     * {@link UdpEncapsulationSocket} is legitimate.
+     **/
+    @Nullable
+    public KeepaliveInfo makeNattKeepaliveInfo(@Nullable NetworkAgentInfo nai,
             @Nullable FileDescriptor fd,
             int resourceId,
             int intervalSeconds,
@@ -708,6 +780,7 @@
         // Ensure that the socket is created by IpSecService.
         if (!isNattKeepaliveSocketValid(fd, resourceId)) {
             notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
+            return null;
         }
 
         // Get src port to adopt old API.
@@ -717,10 +790,11 @@
             srcPort = ((InetSocketAddress) srcSockAddr).getPort();
         } catch (ErrnoException e) {
             notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
+            return null;
         }
 
         // Forward request to old API.
-        startNattKeepalive(nai, fd, intervalSeconds, cb, srcAddrString, srcPort,
+        return makeNattKeepaliveInfo(nai, fd, intervalSeconds, cb, srcAddrString, srcPort,
                 dstAddrString, dstPort);
     }
 
@@ -739,6 +813,9 @@
         return true;
     }
 
+    /**
+     * Dump KeepaliveTracker state.
+     */
     public void dump(IndentingPrintWriter pw) {
         pw.println("Supported Socket keepalives: " + Arrays.toString(mSupportedKeepalives));
         pw.println("Reserved Privileged keepalives: " + mReservedPrivilegedSlots);
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index ff979d8..c15f042 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -1211,18 +1211,6 @@
         }
     }
 
-    /** Should only be used by unit tests */
-    @VisibleForTesting
-    public synchronized Set<UidRange> getVpnInterfaceUidRanges(String iface) {
-        return mVpnInterfaceUidRanges.get(iface);
-    }
-
-    /** Should only be used by unit tests */
-    @VisibleForTesting
-    synchronized Set<UidRange> getVpnLockdownUidRanges() {
-        return mVpnLockdownUidRanges.getSet();
-    }
-
     private synchronized void onSettingChanged() {
         // Step1. Update uids allowed to use restricted networks and compute the set of uids to
         // update.
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/tests/common/Android.bp b/tests/common/Android.bp
index 5c9cc63..8e47235 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -65,7 +65,7 @@
     defaults: ["jarjar-rules-combine-defaults"],
     srcs: [
         "tethering-jni-jarjar-rules.txt",
-        ":connectivity-jarjar-rules",
+        ":frameworks-net-tests-jarjar-rules",
         ":TetheringTestsJarJarRules",
         ":NetworkStackJarJarRules",
     ],
diff --git a/tests/common/AndroidTest_Coverage.xml b/tests/common/AndroidTest_Coverage.xml
index 48d26b8..c94ec27 100644
--- a/tests/common/AndroidTest_Coverage.xml
+++ b/tests/common/AndroidTest_Coverage.xml
@@ -13,7 +13,7 @@
      limitations under the License.
 -->
 <configuration description="Runs coverage tests for Connectivity">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
       <option name="test-file-name" value="ConnectivityCoverageTests.apk" />
       <option name="install-arg" value="-t" />
     </target_preparer>
diff --git a/tests/common/java/android/net/LinkPropertiesTest.java b/tests/common/java/android/net/LinkPropertiesTest.java
index 5ee375f..09f5d6e 100644
--- a/tests/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/common/java/android/net/LinkPropertiesTest.java
@@ -32,6 +32,7 @@
 
 import android.compat.testing.PlatformCompatChangeRule;
 import android.net.LinkProperties.ProvisioningChange;
+import android.net.connectivity.ConnectivityCompatChanges;
 import android.os.Build;
 import android.system.OsConstants;
 import android.util.ArraySet;
@@ -1261,7 +1262,7 @@
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
     @CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
-    @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+    @EnableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
     public void testHasExcludeRoute() {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
@@ -1274,7 +1275,7 @@
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
     @CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
-    @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+    @EnableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
     public void testRouteAddWithSameKey() throws Exception {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("wlan0");
@@ -1348,14 +1349,14 @@
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
     @CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
-    @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+    @EnableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
     public void testExcludedRoutesEnabledByCompatChange() {
         assertExcludeRoutesVisible();
     }
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
     @CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
-    @DisableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+    @DisableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
     public void testExcludedRoutesDisabledByCompatChange() {
         checkExcludeRoutesNotVisibleAfterS();
     }
diff --git a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
index cdf32a4..c2eacbc 100644
--- a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
+++ b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
@@ -19,22 +19,18 @@
 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
 import android.net.NetworkTemplate.MATCH_ETHERNET
 import android.net.NetworkTemplate.MATCH_MOBILE
-import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
 import android.net.NetworkTemplate.MATCH_PROXY
 import android.net.NetworkTemplate.MATCH_WIFI
-import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
 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
@@ -66,10 +62,8 @@
         }
 
         // Verify hidden match rules cannot construct templates.
-        listOf(MATCH_WIFI_WILDCARD, MATCH_MOBILE_WILDCARD, MATCH_PROXY).forEach {
-            assertFailsWith<IllegalArgumentException> {
-                NetworkTemplate.Builder(it).build()
-            }
+        assertFailsWith<IllegalArgumentException> {
+            NetworkTemplate.Builder(MATCH_PROXY).build()
         }
 
         // Verify template which matches metered cellular and carrier networks with
@@ -77,10 +71,9 @@
         listOf(MATCH_MOBILE, MATCH_CARRIER).forEach { matchRule ->
             NetworkTemplate.Builder(matchRule).setSubscriberIds(setOf(TEST_IMSI1))
                     .setMeteredness(METERED_YES).build().let {
-                        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)
+                        val expectedTemplate = NetworkTemplate(matchRule, arrayOf(TEST_IMSI1),
+                                emptyArray<String>(), METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                                NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
                         assertEquals(expectedTemplate, it)
                     }
         }
@@ -90,10 +83,9 @@
         listOf(MATCH_MOBILE, MATCH_CARRIER).forEach { matchRule ->
             NetworkTemplate.Builder(matchRule).setSubscriberIds(setOf(TEST_IMSI1))
                     .setRoaming(ROAMING_YES).setMeteredness(METERED_YES).build().let {
-                        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)
+                        val expectedTemplate = NetworkTemplate(matchRule, arrayOf(TEST_IMSI1),
+                                emptyArray<String>(), METERED_YES, ROAMING_YES, DEFAULT_NETWORK_ALL,
+                                NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
                         assertEquals(expectedTemplate, it)
                     }
         }
@@ -103,45 +95,49 @@
             NetworkTemplate.Builder(MATCH_CARRIER).build()
         }
 
+        // Verify carrier and mobile template cannot contain one of subscriber Id is null.
+        listOf(MATCH_MOBILE, MATCH_CARRIER).forEach {
+            assertFailsWith<IllegalArgumentException> {
+                NetworkTemplate.Builder(it).setSubscriberIds(setOf(null)).build()
+            }
+        }
+
         // Verify template which matches metered cellular networks,
         // regardless of IMSI. See buildTemplateMobileWildcard.
         NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build().let {
-            val expectedTemplate = NetworkTemplate(MATCH_MOBILE_WILDCARD, null /*subscriberId*/,
-                    emptyArray<String>() /*subscriberIds*/, emptyArray<String>(),
+            val expectedTemplate = NetworkTemplate(MATCH_MOBILE,
+                    emptyArray<String>() /*subscriberIds*/, emptyArray<String>() /*wifiNetworkKey*/,
                     METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                    OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+                    OEM_MANAGED_ALL)
             assertEquals(expectedTemplate, it)
         }
 
         // Verify template which matches metered cellular networks and ratType.
-        // See NetworkTemplate#buildTemplateMobileWithRatType.
         NetworkTemplate.Builder(MATCH_MOBILE).setSubscriberIds(setOf(TEST_IMSI1))
                 .setMeteredness(METERED_YES).setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
                 .build().let {
-                    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)
+                    val expectedTemplate = NetworkTemplate(MATCH_MOBILE, arrayOf(TEST_IMSI1),
+                            emptyArray<String>(), METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                            TelephonyManager.NETWORK_TYPE_UMTS, OEM_MANAGED_ALL)
                     assertEquals(expectedTemplate, it)
                 }
 
         // Verify template which matches all wifi networks,
         // regardless of Wifi Network Key. See buildTemplateWifiWildcard and buildTemplateWifi.
         NetworkTemplate.Builder(MATCH_WIFI).build().let {
-            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)
+            val expectedTemplate = NetworkTemplate(MATCH_WIFI,
+                    emptyArray<String>() /*subscriberIds*/, emptyArray<String>(), METERED_ALL,
+                    ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
             assertEquals(expectedTemplate, it)
         }
 
         // Verify template which matches wifi networks with the given Wifi Network Key.
         // See buildTemplateWifi(wifiNetworkKey).
         NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build().let {
-            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)
+            val expectedTemplate =
+                    NetworkTemplate(MATCH_WIFI, emptyArray<String>() /*subscriberIds*/,
+                    arrayOf(TEST_WIFI_KEY1), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                    NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
             assertEquals(expectedTemplate, it)
         }
 
@@ -149,10 +145,9 @@
         // given Wifi Network Key, and IMSI. See buildTemplateWifi(wifiNetworkKey, subscriberId).
         NetworkTemplate.Builder(MATCH_WIFI).setSubscriberIds(setOf(TEST_IMSI1))
                 .setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build().let {
-                    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)
+                    val expectedTemplate = NetworkTemplate(MATCH_WIFI, arrayOf(TEST_IMSI1),
+                            arrayOf(TEST_WIFI_KEY1), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                            NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
                     assertEquals(expectedTemplate, it)
                 }
 
@@ -160,16 +155,33 @@
         // See buildTemplateEthernet and buildTemplateBluetooth.
         listOf(MATCH_ETHERNET, MATCH_BLUETOOTH).forEach { matchRule ->
             NetworkTemplate.Builder(matchRule).build().let {
-                val expectedTemplate = NetworkTemplate(matchRule, null /*subscriberId*/,
+                val expectedTemplate = NetworkTemplate(matchRule,
                         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)
             }
         }
     }
 
     @Test
+    fun testUnsupportedAppUsageConstructor() {
+        val templateMobile = NetworkTemplate(MATCH_MOBILE, null /* subscriberId */,
+                null /* wifiNetworkKey */)
+        val templateMobileWildcard = NetworkTemplate(6 /* MATCH_MOBILE_WILDCARD */,
+                null /* subscriberId */, null /* wifiNetworkKey */)
+        val templateWifiWildcard = NetworkTemplate(7 /* MATCH_WIFI_WILDCARD */,
+                null /* subscriberId */,
+                null /* wifiNetworkKey */)
+
+        assertEquals(NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build(),
+                templateMobile)
+        assertEquals(NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build(),
+                templateMobileWildcard)
+        assertEquals(NetworkTemplate.Builder(MATCH_WIFI).build(), templateWifiWildcard)
+    }
+
+    @Test
     fun testBuilderWifiNetworkKeys() {
         // Verify template builder which generates same template with the given different
         // sequence keys.
@@ -195,10 +207,10 @@
 
         // Verify template which matches wifi wildcard with the given empty key set.
         NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf<String>()).build().let {
-            val expectedTemplate = NetworkTemplate(MATCH_WIFI_WILDCARD, null /*subscriberId*/,
+            val expectedTemplate = NetworkTemplate(MATCH_WIFI,
                     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/Android.bp b/tests/cts/hostside/Android.bp
index 47ea53e..ff9bd31 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -12,6 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+next_app_data = [ ":CtsHostsideNetworkTestsAppNext" ]
+
+// The above line is put in place to prevent any future automerger merge conflict between aosp,
+// downstream branches. The CtsHostsideNetworkTestsAppNext target will not exist in
+// some downstream branches, but it should exist in aosp and some downstream branches.
+
+
+
+
+
 package {
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
@@ -37,7 +47,6 @@
     data: [
         ":CtsHostsideNetworkTestsApp",
         ":CtsHostsideNetworkTestsApp2",
-        ":CtsHostsideNetworkTestsAppNext",
-    ],
+    ] + next_app_data,
     per_testcase_directory: true,
 }
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 a62ef8a..a5bf000 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
@@ -41,6 +41,7 @@
 import static com.android.networkstack.apishim.ConstantsShim.RECEIVER_EXPORTED;
 import static com.android.testutils.Cleanup.testAndCleanup;
 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS_INT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -94,7 +95,6 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructPollfd;
-import android.telephony.TelephonyManager;
 import android.test.MoreAsserts;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -198,8 +198,8 @@
     private RemoteSocketFactoryClient mRemoteSocketFactoryClient;
     private CtsNetUtils mCtsNetUtils;
     private PackageManager mPackageManager;
-    private TelephonyManager mTelephonyManager;
-
+    private Context mTestContext;
+    private Context mTargetContext;
     Network mNetwork;
     NetworkCallback mCallback;
     final Object mLock = new Object();
@@ -229,21 +229,19 @@
     public void setUp() throws Exception {
         mNetwork = null;
         mCallback = null;
+        mTestContext = getInstrumentation().getContext();
+        mTargetContext = getInstrumentation().getTargetContext();
         storePrivateDnsSetting();
-
         mDevice = UiDevice.getInstance(getInstrumentation());
-        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
-                MyActivity.class);
+        mActivity = launchActivity(mTargetContext.getPackageName(), MyActivity.class);
         mPackageName = mActivity.getPackageName();
         mCM = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWifiManager = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);
         mRemoteSocketFactoryClient = new RemoteSocketFactoryClient(mActivity);
         mRemoteSocketFactoryClient.bind();
         mDevice.waitForIdle();
-        mCtsNetUtils = new CtsNetUtils(getInstrumentation().getContext());
-        mPackageManager = getInstrumentation().getContext().getPackageManager();
-        mTelephonyManager =
-                getInstrumentation().getContext().getSystemService(TelephonyManager.class);
+        mCtsNetUtils = new CtsNetUtils(mTestContext);
+        mPackageManager = mTestContext.getPackageManager();
     }
 
     @After
@@ -742,7 +740,7 @@
     }
 
     private ContentResolver getContentResolver() {
-        return getInstrumentation().getContext().getContentResolver();
+        return mTestContext.getContentResolver();
     }
 
     private boolean isPrivateDnsInStrictMode() {
@@ -791,7 +789,7 @@
     }
 
     private void setAndVerifyPrivateDns(boolean strictMode) throws Exception {
-        final ContentResolver cr = getInstrumentation().getContext().getContentResolver();
+        final ContentResolver cr = mTestContext.getContentResolver();
         String privateDnsHostname;
 
         if (strictMode) {
@@ -929,7 +927,7 @@
         }
 
         final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(
-                getInstrumentation().getTargetContext(), MyVpnService.ACTION_ESTABLISHED);
+                mTargetContext, MyVpnService.ACTION_ESTABLISHED);
         receiver.register();
 
         // Test the behaviour of a variety of types of network callbacks.
@@ -1525,7 +1523,7 @@
         private boolean received;
 
         public ProxyChangeBroadcastReceiver() {
-            super(getInstrumentation().getContext(), Proxy.PROXY_CHANGE_ACTION);
+            super(mTestContext, Proxy.PROXY_CHANGE_ACTION);
             received = false;
         }
 
@@ -1555,12 +1553,11 @@
                 "" /* allowedApps */, "com.android.providers.downloads", null /* proxyInfo */,
                 null /* underlyingNetworks */, false /* isAlwaysMetered */);
 
-        final Context context = getInstrumentation().getContext();
-        final DownloadManager dm = context.getSystemService(DownloadManager.class);
+        final DownloadManager dm = mTestContext.getSystemService(DownloadManager.class);
         final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
         try {
             final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0;
-            context.registerReceiver(receiver,
+            mTestContext.registerReceiver(receiver,
                     new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), flags);
 
             // Enqueue a request and check only one download.
@@ -1578,7 +1575,7 @@
             assertEquals(1, dm.remove(id));
             assertEquals(0, getTotalNumberDownloads(dm, new Query()));
         } finally {
-            context.unregisterReceiver(receiver);
+            mTestContext.unregisterReceiver(receiver);
         }
     }
 
@@ -1615,8 +1612,7 @@
 
         // Create a TUN interface
         final FileDescriptor tunFd = runWithShellPermissionIdentity(() -> {
-            final TestNetworkManager tnm = getInstrumentation().getContext().getSystemService(
-                    TestNetworkManager.class);
+            final TestNetworkManager tnm = mTestContext.getSystemService(TestNetworkManager.class);
             final TestNetworkInterface iface = tnm.createTunInterface(List.of(
                     TEST_IP4_DST_ADDR, TEST_IP6_DST_ADDR));
             return iface.getFileDescriptor().getFileDescriptor();
@@ -1643,7 +1639,8 @@
             // setRequireVpnForUids setup a lockdown rule asynchronously. So it needs to wait for
             // BlockedStatusCallback to be fired before checking the blocking status of incoming
             // packets.
-            remoteUidCallback.expectBlockedStatusCallback(network, BLOCKED_REASON_LOCKDOWN_VPN);
+            remoteUidCallback.expect(BLOCKED_STATUS_INT, network,
+                    cb -> cb.getReason() == BLOCKED_REASON_LOCKDOWN_VPN);
 
             if (SdkLevel.isAtLeastT()) {
                 // On T and above, lockdown rule drop packets not coming from lo regardless of the
@@ -1818,9 +1815,6 @@
             super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
                     BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
         }
-        public void expectBlockedStatusCallback(Network network, int blockedStatus) {
-            super.expectBlockedStatusCallback(blockedStatus, network, NETWORK_CALLBACK_TIMEOUT_MS);
-        }
         public void onBlockedStatusChanged(Network network, int blockedReasons) {
             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
         }
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
index d0567ae..2aa1032 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
@@ -31,6 +31,7 @@
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.util.RunUtil;
 
 import java.io.FileNotFoundException;
 import java.util.Map;
@@ -120,7 +121,7 @@
             i++;
             Log.v(TAG, "Package " + packageName + " not uninstalled yet (" + result
                     + "); sleeping 1s before polling again");
-            Thread.sleep(1000);
+            RunUtil.getDefault().sleep(1000);
         }
         fail("Package '" + packageName + "' not uinstalled after " + max_tries + " seconds");
     }
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index 7a613b3..21c78b7 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -20,6 +20,7 @@
 
 import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.util.RunUtil;
 
 public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestCase {
 
@@ -359,7 +360,7 @@
             }
             Log.v(TAG, "whitelist check for uid " + uid + " doesn't match yet (expected "
                     + expected + ", got " + actual + "); sleeping 1s before polling again");
-            Thread.sleep(1000);
+            RunUtil.getDefault().sleep(1000);
         }
         fail("whitelist check for uid " + uid + " failed: expected "
                 + expected + ", got " + actual);
@@ -384,7 +385,7 @@
             if (result.equals(expectedResult)) return;
             Log.v(TAG, "Command '" + command + "' returned '" + result + " instead of '"
                     + expectedResult + "' on attempt #; sleeping 1s before polling again");
-            Thread.sleep(1000);
+            RunUtil.getDefault().sleep(1000);
         }
         fail("Command '" + command + "' did not return '" + expectedResult + "' after " + maxTries
                 + " attempts");
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index 23cb15c..f9fe5b0 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -114,34 +114,39 @@
     ],
 }
 
-android_test {
-    name: "CtsNetTestCasesMaxTargetSdk31",  // Must match CtsNetTestCasesMaxTargetSdk31 annotation.
+java_defaults {
+    name: "CtsNetTestCasesMaxTargetSdkDefaults",
     defaults: [
         "CtsNetTestCasesDefaults",
         "CtsNetTestCasesApiStableDefaults",
     ],
-    target_sdk_version: "31",
-    package_name: "android.net.cts.maxtargetsdk31",  // CTS package names must be unique.
-    instrumentation_target_package: "android.net.cts.maxtargetsdk31",
     test_suites: [
         "cts",
         "general-tests",
-        "mts-networking",
+        "mts-tethering",
     ],
 }
 
 android_test {
+    name: "CtsNetTestCasesMaxTargetSdk33",  // Must match CtsNetTestCasesMaxTargetSdk33 annotation.
+    defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
+    target_sdk_version: "33",
+    package_name: "android.net.cts.maxtargetsdk33",
+    instrumentation_target_package: "android.net.cts.maxtargetsdk33",
+}
+
+android_test {
+    name: "CtsNetTestCasesMaxTargetSdk31",  // Must match CtsNetTestCasesMaxTargetSdk31 annotation.
+    defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
+    target_sdk_version: "31",
+    package_name: "android.net.cts.maxtargetsdk31",  // CTS package names must be unique.
+    instrumentation_target_package: "android.net.cts.maxtargetsdk31",
+}
+
+android_test {
     name: "CtsNetTestCasesMaxTargetSdk30",  // Must match CtsNetTestCasesMaxTargetSdk30 annotation.
-    defaults: [
-        "CtsNetTestCasesDefaults",
-        "CtsNetTestCasesApiStableDefaults",
-    ],
+    defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
     target_sdk_version: "30",
     package_name: "android.net.cts.maxtargetsdk30",  // CTS package names must be unique.
     instrumentation_target_package: "android.net.cts.maxtargetsdk30",
-    test_suites: [
-        "cts",
-        "general-tests",
-        "mts-networking",
-    ],
 }
diff --git a/tests/cts/net/AndroidManifest.xml b/tests/cts/net/AndroidManifest.xml
index 25490da..999614c 100644
--- a/tests/cts/net/AndroidManifest.xml
+++ b/tests/cts/net/AndroidManifest.xml
@@ -54,8 +54,6 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.net.cts"
                      android:label="CTS tests of android.net">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 
 </manifest>
diff --git a/tests/cts/net/api23Test/AndroidManifest.xml b/tests/cts/net/api23Test/AndroidManifest.xml
index 69ee0dd..44c63f6 100644
--- a/tests/cts/net/api23Test/AndroidManifest.xml
+++ b/tests/cts/net/api23Test/AndroidManifest.xml
@@ -39,7 +39,5 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
          android:targetPackage="android.net.cts.api23test"
          android:label="CTS tests of android.net">
-        <meta-data android:name="listener"
-             android:value="com.android.cts.runner.CtsTestRunListener"/>
     </instrumentation>
 </manifest>
diff --git a/tests/cts/net/native/dns/Android.bp b/tests/cts/net/native/dns/Android.bp
index 434e529..49b9337 100644
--- a/tests/cts/net/native/dns/Android.bp
+++ b/tests/cts/net/native/dns/Android.bp
@@ -24,6 +24,10 @@
         "liblog",
         "libutils",
     ],
+    static_libs: [
+        "libbase",
+        "libnetdutils",
+    ],
     // To be compatible with Q devices, the min_sdk_version must be 29.
     min_sdk_version: "29",
 }
diff --git a/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp b/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp
index e501475..68bd227 100644
--- a/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp
+++ b/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp
@@ -28,6 +28,7 @@
 
 #include <android/multinetwork.h>
 #include <gtest/gtest.h>
+#include <netdutils/NetNativeTestBase.h>
 
 namespace {
 constexpr int MAXPACKET = 8 * 1024;
@@ -101,7 +102,9 @@
 
 } // namespace
 
-TEST (NativeDnsAsyncTest, Async_Query) {
+class NativeDnsAsyncTest : public NetNativeTestBase {};
+
+TEST_F(NativeDnsAsyncTest, Async_Query) {
     // V4
     int fd1 = android_res_nquery(
             NETWORK_UNSPECIFIED, "www.google.com", ns_c_in, ns_t_a, 0);
@@ -123,7 +126,7 @@
     expectAnswersValid(fd1, AF_INET6, ns_r_noerror);
 }
 
-TEST (NativeDnsAsyncTest, Async_Send) {
+TEST_F(NativeDnsAsyncTest, Async_Send) {
     // V4
     uint8_t buf1[MAXPACKET] = {};
     int len1 = res_mkquery(ns_o_query, "www.googleapis.com",
@@ -162,7 +165,7 @@
     expectAnswersValid(fd1, AF_INET6, ns_r_noerror);
 }
 
-TEST (NativeDnsAsyncTest, Async_NXDOMAIN) {
+TEST_F(NativeDnsAsyncTest, Async_NXDOMAIN) {
     uint8_t buf[MAXPACKET] = {};
     int len = res_mkquery(ns_o_query, "test1-nx.metric.gstatic.com",
             ns_c_in, ns_t_a, nullptr, 0, nullptr, buf, sizeof(buf));
@@ -191,7 +194,7 @@
     expectAnswersValid(fd1, AF_INET6, ns_r_nxdomain);
 }
 
-TEST (NativeDnsAsyncTest, Async_Cancel) {
+TEST_F(NativeDnsAsyncTest, Async_Cancel) {
     int fd = android_res_nquery(
             NETWORK_UNSPECIFIED, "www.google.com", ns_c_in, ns_t_a, 0);
     errno = 0;
@@ -202,7 +205,7 @@
     // otherwise it will hit fdsan double-close fd.
 }
 
-TEST (NativeDnsAsyncTest, Async_Query_MALFORMED) {
+TEST_F(NativeDnsAsyncTest, Async_Query_MALFORMED) {
     // Empty string to create BLOB and query, we will get empty result and rcode = 0
     // on DNSTLS.
     int fd = android_res_nquery(
@@ -221,7 +224,7 @@
     EXPECT_EQ(-EMSGSIZE, fd);
 }
 
-TEST (NativeDnsAsyncTest, Async_Send_MALFORMED) {
+TEST_F(NativeDnsAsyncTest, Async_Send_MALFORMED) {
     uint8_t buf[10] = {};
     // empty BLOB
     int fd = android_res_nsend(NETWORK_UNSPECIFIED, buf, 10, 0);
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 0e04a80..7985dc4 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -96,6 +96,7 @@
 import static com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL;
 import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
 import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
+import static com.android.networkstack.apishim.ConstantsShim.RECEIVER_EXPORTED;
 import static com.android.testutils.Cleanup.testAndCleanup;
 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
 import static com.android.testutils.MiscAsserts.assertThrows;
@@ -1131,18 +1132,16 @@
 
         final ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
                 mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED);
-        mContext.registerReceiver(receiver, filter);
+        final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0;
+        mContext.registerReceiver(receiver, filter, flags);
 
         // Create a broadcast PendingIntent for NETWORK_CALLBACK_ACTION.
         final Intent intent = new Intent(NETWORK_CALLBACK_ACTION)
                 .setPackage(mContext.getPackageName());
         // While ConnectivityService would put extra info such as network or request id before
         // broadcasting the inner intent. The MUTABLE flag needs to be added accordingly.
-        // TODO: replace with PendingIntent.FLAG_MUTABLE when this code compiles against S+ or
-        //  shims.
-        final int pendingIntentFlagMutable = 1 << 25;
         final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0 /*requestCode*/,
-                intent, PendingIntent.FLAG_CANCEL_CURRENT | pendingIntentFlagMutable);
+                intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
 
         // We will register for a WIFI network being available or lost.
         mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
@@ -1182,14 +1181,13 @@
         // Avoid receiving broadcasts from other runs by appending a timestamp
         final String broadcastAction = NETWORK_CALLBACK_ACTION + System.currentTimeMillis();
         try {
-            // TODO: replace with PendingIntent.FLAG_MUTABLE when this code compiles against S+
             // Intent is mutable to receive EXTRA_NETWORK_REQUEST from ConnectivityService
-            final int pendingIntentFlagMutable = 1 << 25;
             final String extraBoolKey = "extra_bool";
             firstIntent = PendingIntent.getBroadcast(mContext,
                     0 /* requestCode */,
-                    new Intent(broadcastAction).putExtra(extraBoolKey, false),
-                    PendingIntent.FLAG_UPDATE_CURRENT | pendingIntentFlagMutable);
+                    new Intent(broadcastAction).putExtra(extraBoolKey, false)
+                            .setPackage(mContext.getPackageName()),
+                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
 
             if (useListen) {
                 mCm.registerNetworkCallback(firstRequest, firstIntent);
@@ -1201,8 +1199,9 @@
             // intent will be updated with the new extras
             secondIntent = PendingIntent.getBroadcast(mContext,
                     0 /* requestCode */,
-                    new Intent(broadcastAction).putExtra(extraBoolKey, true),
-                    PendingIntent.FLAG_UPDATE_CURRENT | pendingIntentFlagMutable);
+                    new Intent(broadcastAction).putExtra(extraBoolKey, true)
+                            .setPackage(mContext.getPackageName()),
+                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
 
             // Because secondIntent.intentFilterEquals the first, the request should be replaced
             if (useListen) {
@@ -1225,7 +1224,8 @@
                     networkFuture.complete(intent.getParcelableExtra(EXTRA_NETWORK));
                 }
             };
-            mContext.registerReceiver(receiver, filter);
+            final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0;
+            mContext.registerReceiver(receiver, filter, flags);
 
             final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
             try {
@@ -2385,13 +2385,14 @@
         }
         public void eventuallyExpectBlockedStatusCallback(Network network, int blockedStatus) {
             super.eventuallyExpect(CallbackEntry.BLOCKED_STATUS_INT, NETWORK_CALLBACK_TIMEOUT_MS,
-                    (it) -> it.getNetwork().equals(network) && it.getBlocked() == blockedStatus);
+                    (it) -> it.getNetwork().equals(network) && it.getReason() == blockedStatus);
         }
         public void onBlockedStatusChanged(Network network, int blockedReasons) {
+            Log.v(TAG, "onBlockedStatusChanged " + network + " " + blockedReasons);
             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);
         }
     }
@@ -2408,7 +2409,11 @@
         }
     }
 
-    private void doTestBlockedStatusCallback() throws Exception {
+    @Test
+    public void testBlockedStatusCallback() throws Exception {
+        // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
+        // shims, and @IgnoreUpTo does not check that.
+        assumeTrue(TestUtils.shouldTestSApis());
         // The test will need a stable active network that is persistent during the test.
         // Try to connect to a wifi network and wait for it becomes the default network before
         // starting the test to prevent from sudden active network change caused by previous
@@ -2426,7 +2431,8 @@
         final Handler handler = new Handler(Looper.getMainLooper());
 
         registerDefaultNetworkCallback(myUidCallback, handler);
-        registerDefaultNetworkCallbackForUid(otherUid, otherUidCallback, handler);
+        runWithShellPermissionIdentity(() -> registerDefaultNetworkCallbackForUid(
+                otherUid, otherUidCallback, handler), NETWORK_SETTINGS);
 
         final Network defaultNetwork = mCm.getActiveNetwork();
         final List<DetailedBlockedStatusCallback> allCallbacks =
@@ -2438,23 +2444,27 @@
         final Range<Integer> myUidRange = new Range<>(myUid, myUid);
         final Range<Integer> otherUidRange = new Range<>(otherUid, otherUid);
 
-        setRequireVpnForUids(true, List.of(myUidRange));
+        runWithShellPermissionIdentity(() -> setRequireVpnForUids(
+                true, List.of(myUidRange)), NETWORK_SETTINGS);
         myUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork,
                 BLOCKED_REASON_LOCKDOWN_VPN);
         otherUidCallback.assertNoBlockedStatusCallback();
 
-        setRequireVpnForUids(true, List.of(myUidRange, otherUidRange));
+        runWithShellPermissionIdentity(() -> setRequireVpnForUids(
+                true, List.of(myUidRange, otherUidRange)), NETWORK_SETTINGS);
         myUidCallback.assertNoBlockedStatusCallback();
         otherUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork,
                 BLOCKED_REASON_LOCKDOWN_VPN);
 
         // setRequireVpnForUids does no deduplication or refcounting. Removing myUidRange does not
         // unblock myUid because it was added to the blocked ranges twice.
-        setRequireVpnForUids(false, List.of(myUidRange));
+        runWithShellPermissionIdentity(() ->
+                setRequireVpnForUids(false, List.of(myUidRange)), NETWORK_SETTINGS);
         myUidCallback.assertNoBlockedStatusCallback();
         otherUidCallback.assertNoBlockedStatusCallback();
 
-        setRequireVpnForUids(false, List.of(myUidRange, otherUidRange));
+        runWithShellPermissionIdentity(() -> setRequireVpnForUids(
+                false, List.of(myUidRange, otherUidRange)), NETWORK_SETTINGS);
         myUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE);
         otherUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE);
 
@@ -2463,14 +2473,6 @@
     }
 
     @Test
-    public void testBlockedStatusCallback() {
-        // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
-        // shims, and @IgnoreUpTo does not check that.
-        assumeTrue(TestUtils.shouldTestSApis());
-        runWithShellPermissionIdentity(() -> doTestBlockedStatusCallback(), NETWORK_SETTINGS);
-    }
-
-    @Test
     public void testSetVpnDefaultForUids() {
         assumeTrue(TestUtils.shouldTestUApis());
         final String session = UUID.randomUUID().toString();
@@ -2979,7 +2981,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();
@@ -3151,7 +3153,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));
     }
@@ -3372,7 +3374,7 @@
     }
 
     private void checkFirewallBlocking(final DatagramSocket srcSock, final DatagramSocket dstSock,
-            final boolean expectBlock) throws Exception {
+            final boolean expectBlock, final int chain) throws Exception {
         final Random random = new Random();
         final byte[] sendData = new byte[100];
         random.nextBytes(sendData);
@@ -3385,11 +3387,17 @@
             if (expectBlock) {
                 return;
             }
-            fail("Expect not to be blocked by firewall but sending packet was blocked");
+            fail("Expect not to be blocked by firewall but sending packet was blocked:"
+                    + " chain=" + chain
+                    + " chainEnabled=" + mCm.getFirewallChainEnabled(chain)
+                    + " uidFirewallRule=" + mCm.getUidFirewallRule(chain, Process.myUid()));
         }
 
         if (expectBlock) {
-            fail("Expect to be blocked by firewall but sending packet was not blocked");
+            fail("Expect to be blocked by firewall but sending packet was not blocked:"
+                    + " chain=" + chain
+                    + " chainEnabled=" + mCm.getFirewallChainEnabled(chain)
+                    + " uidFirewallRule=" + mCm.getUidFirewallRule(chain, Process.myUid()));
         }
 
         dstSock.receive(pkt);
@@ -3409,34 +3417,40 @@
         runWithShellPermissionIdentity(() -> {
             // Firewall chain status will be restored after the test.
             final boolean wasChainEnabled = mCm.getFirewallChainEnabled(chain);
+            final int previousUidFirewallRule = mCm.getUidFirewallRule(chain, myUid);
             final DatagramSocket srcSock = new DatagramSocket();
             final DatagramSocket dstSock = new DatagramSocket();
             testAndCleanup(() -> {
                 if (wasChainEnabled) {
                     mCm.setFirewallChainEnabled(chain, false /* enable */);
                 }
+                if (previousUidFirewallRule == ruleToAddMatch) {
+                    mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
+                }
                 dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
 
                 // Chain disabled, UID not on chain.
-                checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+                checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain);
 
                 // Chain enabled, UID not on chain.
                 mCm.setFirewallChainEnabled(chain, true /* enable */);
                 assertTrue(mCm.getFirewallChainEnabled(chain));
-                checkFirewallBlocking(srcSock, dstSock, isAllowList ? EXPECT_BLOCK : EXPECT_PASS);
+                checkFirewallBlocking(
+                        srcSock, dstSock, isAllowList ? EXPECT_BLOCK : EXPECT_PASS, chain);
 
                 // Chain enabled, UID on chain.
                 mCm.setUidFirewallRule(chain, myUid, ruleToAddMatch);
-                checkFirewallBlocking(srcSock, dstSock, isAllowList ?  EXPECT_PASS : EXPECT_BLOCK);
+                checkFirewallBlocking(
+                        srcSock, dstSock, isAllowList ?  EXPECT_PASS : EXPECT_BLOCK, chain);
 
                 // Chain disabled, UID on chain.
                 mCm.setFirewallChainEnabled(chain, false /* enable */);
                 assertFalse(mCm.getFirewallChainEnabled(chain));
-                checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+                checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain);
 
                 // Chain disabled, UID not on chain.
                 mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
-                checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+                checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain);
             }, /* cleanup */ () -> {
                     srcSock.close();
                     dstSock.close();
@@ -3444,8 +3458,9 @@
                     // Restore the global chain status
                     mCm.setFirewallChainEnabled(chain, wasChainEnabled);
                 }, /* cleanup */ () -> {
+                    // Restore the uid firewall rule status
                     try {
-                        mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
+                        mCm.setUidFirewallRule(chain, myUid, previousUidFirewallRule);
                     } catch (IllegalStateException ignored) {
                         // Removing match causes an exception when the rule entry for the uid does
                         // not exist. But this is fine and can be ignored.
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/Ikev2VpnTest.java b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
index ac50740..6ba0fda 100644
--- a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
+++ b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
@@ -529,11 +529,10 @@
             assertFalse(profileState.isLockdownEnabled());
         }
 
-        cb.expectCapabilitiesThat(vpnNetwork, TIMEOUT_MS,
-                caps -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasCapability(NET_CAPABILITY_INTERNET)
-                && !caps.hasCapability(NET_CAPABILITY_VALIDATED)
-                && Process.myUid() == caps.getOwnerUid());
+        cb.expectCaps(vpnNetwork, TIMEOUT_MS, c -> c.hasTransport(TRANSPORT_VPN)
+                && c.hasCapability(NET_CAPABILITY_INTERNET)
+                && !c.hasCapability(NET_CAPABILITY_VALIDATED)
+                && Process.myUid() == c.getOwnerUid());
         cb.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, vpnNetwork);
         cb.expect(CallbackEntry.BLOCKED_STATUS, vpnNetwork);
 
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
index 8234ec1..4fa0080 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
@@ -16,6 +16,7 @@
 
 package android.net.cts;
 
+import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.net.IpSecAlgorithm.AUTH_AES_CMAC;
 import static android.net.IpSecAlgorithm.AUTH_AES_XCBC;
 import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM;
@@ -52,7 +53,9 @@
 
 import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel;
 import static com.android.compatibility.common.util.PropertyUtil.getVendorApiLevel;
+import static com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast;
 import static com.android.testutils.MiscAsserts.assertThrows;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -62,6 +65,8 @@
 
 import android.net.IpSecAlgorithm;
 import android.net.IpSecManager;
+import android.net.IpSecManager.SecurityParameterIndex;
+import android.net.IpSecManager.UdpEncapsulationSocket;
 import android.net.IpSecTransform;
 import android.net.TrafficStats;
 import android.os.Build;
@@ -73,6 +78,7 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.modules.utils.build.SdkLevel;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 
@@ -120,7 +126,7 @@
     @Test
     public void testAllocSpi() throws Exception {
         for (InetAddress addr : GOOGLE_DNS_LIST) {
-            IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
+            SecurityParameterIndex randomSpi, droidSpi;
             randomSpi = mISM.allocateSecurityParameterIndex(addr);
             assertTrue(
                     "Failed to receive a valid SPI",
@@ -258,6 +264,24 @@
         accepted.close();
     }
 
+    private IpSecTransform buildTransportModeTransform(
+            SecurityParameterIndex spi, InetAddress localAddr,
+            UdpEncapsulationSocket encapSocket)
+            throws Exception {
+        final IpSecTransform.Builder builder =
+                new IpSecTransform.Builder(InstrumentationRegistry.getContext())
+                        .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
+                        .setAuthentication(
+                                new IpSecAlgorithm(
+                                        IpSecAlgorithm.AUTH_HMAC_SHA256,
+                                        AUTH_KEY,
+                                        AUTH_KEY.length * 8));
+        if (encapSocket != null) {
+            builder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
+        }
+        return builder.buildTransportModeTransform(localAddr, spi);
+    }
+
     /*
      * Alloc outbound SPI
      * Alloc inbound SPI
@@ -268,21 +292,8 @@
      * release transform
      * send data (expect exception)
      */
-    @Test
-    public void testCreateTransform() throws Exception {
-        InetAddress localAddr = InetAddress.getByName(IPV4_LOOPBACK);
-        IpSecManager.SecurityParameterIndex spi =
-                mISM.allocateSecurityParameterIndex(localAddr);
-
-        IpSecTransform transform =
-                new IpSecTransform.Builder(InstrumentationRegistry.getContext())
-                        .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
-                        .setAuthentication(
-                                new IpSecAlgorithm(
-                                        IpSecAlgorithm.AUTH_HMAC_SHA256,
-                                        AUTH_KEY,
-                                        AUTH_KEY.length * 8))
-                        .buildTransportModeTransform(localAddr, spi);
+    private void doTestCreateTransform(String loopbackAddrString, boolean encap) throws Exception {
+        InetAddress localAddr = InetAddress.getByName(loopbackAddrString);
 
         final boolean [][] applyInApplyOut = {
                 {false, false}, {false, true}, {true, false}, {true,true}};
@@ -291,50 +302,93 @@
 
         byte[] in = new byte[data.length];
         DatagramPacket inPacket = new DatagramPacket(in, in.length);
-        DatagramSocket localSocket;
         int localPort;
 
         for(boolean[] io : applyInApplyOut) {
             boolean applyIn = io[0];
             boolean applyOut = io[1];
-            // Bind localSocket to a random available port.
-            localSocket = new DatagramSocket(0);
-            localPort = localSocket.getLocalPort();
-            localSocket.setSoTimeout(200);
-            outPacket.setPort(localPort);
-            if (applyIn) {
-                mISM.applyTransportModeTransform(
-                        localSocket, IpSecManager.DIRECTION_IN, transform);
-            }
-            if (applyOut) {
-                mISM.applyTransportModeTransform(
-                        localSocket, IpSecManager.DIRECTION_OUT, transform);
-            }
-            if (applyIn == applyOut) {
-                localSocket.send(outPacket);
-                localSocket.receive(inPacket);
-                assertTrue("Encapsulated data did not match.",
-                        Arrays.equals(outPacket.getData(), inPacket.getData()));
-                mISM.removeTransportModeTransforms(localSocket);
-                localSocket.close();
-            } else {
-                try {
+            try (
+                SecurityParameterIndex spi = mISM.allocateSecurityParameterIndex(localAddr);
+                UdpEncapsulationSocket encapSocket = encap
+                        ? getPrivilegedUdpEncapSocket(/*ipv6=*/ localAddr instanceof Inet6Address)
+                        : null;
+                IpSecTransform transform = buildTransportModeTransform(spi, localAddr,
+                        encapSocket);
+                // Bind localSocket to a random available port.
+                DatagramSocket localSocket = new DatagramSocket(0);
+            ) {
+                localPort = localSocket.getLocalPort();
+                localSocket.setSoTimeout(200);
+                outPacket.setPort(localPort);
+                if (applyIn) {
+                    mISM.applyTransportModeTransform(
+                            localSocket, IpSecManager.DIRECTION_IN, transform);
+                }
+                if (applyOut) {
+                    mISM.applyTransportModeTransform(
+                            localSocket, IpSecManager.DIRECTION_OUT, transform);
+                }
+                if (applyIn == applyOut) {
                     localSocket.send(outPacket);
                     localSocket.receive(inPacket);
-                } catch (IOException e) {
-                    continue;
-                } finally {
+                    assertTrue("Encrypted data did not match.",
+                            Arrays.equals(outPacket.getData(), inPacket.getData()));
                     mISM.removeTransportModeTransforms(localSocket);
-                    localSocket.close();
+                } else {
+                    try {
+                        localSocket.send(outPacket);
+                        localSocket.receive(inPacket);
+                    } catch (IOException e) {
+                        continue;
+                    } finally {
+                        mISM.removeTransportModeTransforms(localSocket);
+                    }
+                    // FIXME: This check is disabled because sockets currently receive data
+                    // if there is a valid SA for decryption, even when the input policy is
+                    // not applied to a socket.
+                    //  fail("Data IO should fail on asymmetrical transforms! + Input="
+                    //          + applyIn + " Output=" + applyOut);
                 }
-                // FIXME: This check is disabled because sockets currently receive data
-                // if there is a valid SA for decryption, even when the input policy is
-                // not applied to a socket.
-                //  fail("Data IO should fail on asymmetrical transforms! + Input="
-                //          + applyIn + " Output=" + applyOut);
             }
         }
-        transform.close();
+    }
+
+    private UdpEncapsulationSocket getPrivilegedUdpEncapSocket(boolean ipv6) throws Exception {
+        return runAsShell(NETWORK_SETTINGS, () -> {
+            if (ipv6) {
+                return mISM.openUdpEncapsulationSocket(65536);
+            } else {
+                // Can't pass 0 to IpSecManager#openUdpEncapsulationSocket(int).
+                return mISM.openUdpEncapsulationSocket();
+            }
+        });
+    }
+
+    private void assumeExperimentalIpv6UdpEncapSupported() throws Exception {
+        assumeTrue("Not supported before U", SdkLevel.isAtLeastU());
+        assumeTrue("Not supported by kernel", isKernelVersionAtLeast("5.15.31")
+                || (isKernelVersionAtLeast("5.10.108") && !isKernelVersionAtLeast("5.15.0")));
+    }
+
+    @Test
+    public void testCreateTransformIpv4() throws Exception {
+        doTestCreateTransform(IPV4_LOOPBACK, false);
+    }
+
+    @Test
+    public void testCreateTransformIpv6() throws Exception {
+        doTestCreateTransform(IPV6_LOOPBACK, false);
+    }
+
+    @Test
+    public void testCreateTransformIpv4Encap() throws Exception {
+        doTestCreateTransform(IPV4_LOOPBACK, true);
+    }
+
+    @Test
+    public void testCreateTransformIpv6Encap() throws Exception {
+        assumeExperimentalIpv6UdpEncapSupported();
+        doTestCreateTransform(IPV6_LOOPBACK, true);
     }
 
     /** Snapshot of TrafficStats as of initStatsChecker call for later comparisons */
@@ -503,8 +557,8 @@
         StatsChecker.initStatsChecker();
         InetAddress local = InetAddress.getByName(localAddress);
 
-        try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
-                IpSecManager.SecurityParameterIndex spi =
+        try (UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
+                SecurityParameterIndex spi =
                         mISM.allocateSecurityParameterIndex(local)) {
 
             IpSecTransform.Builder transformBuilder =
@@ -656,7 +710,7 @@
     public void testIkeOverUdpEncapSocket() throws Exception {
         // IPv6 not supported for UDP-encap-ESP
         InetAddress local = InetAddress.getByName(IPV4_LOOPBACK);
-        try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+        try (UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
             NativeUdpSocket wrappedEncapSocket =
                     new NativeUdpSocket(encapSocket.getFileDescriptor());
             checkIkePacket(wrappedEncapSocket, local);
@@ -665,7 +719,7 @@
             IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
             IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96);
 
-            try (IpSecManager.SecurityParameterIndex spi =
+            try (SecurityParameterIndex spi =
                             mISM.allocateSecurityParameterIndex(local);
                     IpSecTransform transform =
                             new IpSecTransform.Builder(InstrumentationRegistry.getContext())
@@ -1498,7 +1552,7 @@
 
     @Test
     public void testOpenUdpEncapSocketSpecificPort() throws Exception {
-        IpSecManager.UdpEncapsulationSocket encapSocket = null;
+        UdpEncapsulationSocket encapSocket = null;
         int port = -1;
         for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
             try {
@@ -1527,7 +1581,7 @@
 
     @Test
     public void testOpenUdpEncapSocketRandomPort() throws Exception {
-        try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+        try (UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
             assertTrue("Returned invalid port", encapSocket.getPort() != 0);
         }
     }
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
index a9a3380..5fc3068 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
@@ -32,10 +32,13 @@
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
 
+import static com.android.compatibility.common.util.PropertyUtil.getVsrApiLevel;
+
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
@@ -80,6 +83,11 @@
 
     private static final String TAG = IpSecManagerTunnelTest.class.getSimpleName();
 
+    // 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.
+    private static final String FEATURE_IPSEC_TUNNEL_MIGRATION =
+            "android.software.ipsec_tunnel_migration";
+
     private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1");
     private static final InetAddress REMOTE_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.2");
     private static final InetAddress LOCAL_OUTER_6 =
@@ -994,6 +1002,41 @@
         checkTunnelInput(innerFamily, outerFamily, useEncap, transportInTunnelMode);
     }
 
+    /** Checks if FEATURE_IPSEC_TUNNEL_MIGRATION is enabled on the device */
+    private static boolean hasIpsecTunnelMigrateFeature() {
+        return sContext.getPackageManager().hasSystemFeature(FEATURE_IPSEC_TUNNEL_MIGRATION);
+    }
+
+    @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    @Test
+    public void testHasIpSecTunnelMigrateFeature() throws Exception {
+        // FEATURE_IPSEC_TUNNEL_MIGRATION is required when VSR API is U/U+
+        if (getVsrApiLevel() > Build.VERSION_CODES.TIRAMISU) {
+            assertTrue(hasIpsecTunnelMigrateFeature());
+        }
+    }
+
+    @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    @Test
+    public void testMigrateTunnelModeTransform() throws Exception {
+        assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
+        assumeTrue(hasIpsecTunnelMigrateFeature());
+
+        IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(sContext);
+        transformBuilder.setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY));
+        transformBuilder.setAuthentication(
+                new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4));
+        int spi = getRandomSpi(LOCAL_OUTER_4, REMOTE_OUTER_4);
+
+        try (IpSecManager.SecurityParameterIndex outSpi =
+                        mISM.allocateSecurityParameterIndex(REMOTE_OUTER_4, spi);
+                IpSecTransform outTunnelTransform =
+                        transformBuilder.buildTunnelModeTransform(LOCAL_INNER_4, outSpi)) {
+            mISM.startTunnelModeTransformMigration(
+                    outTunnelTransform, LOCAL_OUTER_4_NEW, REMOTE_OUTER_4_NEW);
+        }
+    }
+
     // Transport-in-Tunnel mode tests
     @Test
     public void testTransportInTunnelModeV4InV4() throws Exception {
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 6df71c8..f578ff3 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -391,9 +391,7 @@
             val nc = NetworkCapabilities(agent.nc)
             nc.addCapability(NET_CAPABILITY_NOT_METERED)
             agent.sendNetworkCapabilities(nc)
-            callback.expectCapabilitiesThat(agent.network) {
-                it.hasCapability(NET_CAPABILITY_NOT_METERED)
-            }
+            callback.expectCaps(agent.network) { it.hasCapability(NET_CAPABILITY_NOT_METERED) }
             val networkInfo = mCM.getNetworkInfo(agent.network)
             assertEquals(subtypeUMTS, networkInfo.getSubtype())
             assertEquals(subtypeNameUMTS, networkInfo.getSubtypeName())
@@ -434,27 +432,28 @@
             (agent, callback) ->
             // Send signal strength and check that the callbacks are called appropriately.
             val nc = NetworkCapabilities(agent.nc)
+            val net = agent.network!!
             nc.setSignalStrength(20)
             agent.sendNetworkCapabilities(nc)
             callbacks.forEach { it.assertNoCallback(NO_CALLBACK_TIMEOUT) }
 
             nc.setSignalStrength(40)
             agent.sendNetworkCapabilities(nc)
-            callbacks[0].expectAvailableCallbacks(agent.network!!)
+            callbacks[0].expectAvailableCallbacks(net)
             callbacks[1].assertNoCallback(NO_CALLBACK_TIMEOUT)
             callbacks[2].assertNoCallback(NO_CALLBACK_TIMEOUT)
 
             nc.setSignalStrength(80)
             agent.sendNetworkCapabilities(nc)
-            callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 80 }
-            callbacks[1].expectAvailableCallbacks(agent.network!!)
-            callbacks[2].expectAvailableCallbacks(agent.network!!)
+            callbacks[0].expectCaps(net) { it.signalStrength == 80 }
+            callbacks[1].expectAvailableCallbacks(net)
+            callbacks[2].expectAvailableCallbacks(net)
 
             nc.setSignalStrength(55)
             agent.sendNetworkCapabilities(nc)
-            callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 }
-            callbacks[1].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 }
-            callbacks[2].expect<Lost>(agent.network!!)
+            callbacks[0].expectCaps(net) { it.signalStrength == 55 }
+            callbacks[1].expectCaps(net) { it.signalStrength == 55 }
+            callbacks[2].expect<Lost>(net)
         }
         callbacks.forEach {
             mCM.unregisterNetworkCallback(it)
@@ -507,15 +506,11 @@
         val lp = LinkProperties(agent.lp)
         lp.setInterfaceName(ifaceName)
         agent.sendLinkProperties(lp)
-        callback.expectLinkPropertiesThat(agent.network!!) {
-            it.getInterfaceName() == ifaceName
-        }
+        callback.expect<LinkPropertiesChanged>(agent.network!!) { it.lp.interfaceName == ifaceName }
         val nc = NetworkCapabilities(agent.nc)
         nc.addCapability(NET_CAPABILITY_NOT_METERED)
         agent.sendNetworkCapabilities(nc)
-        callback.expectCapabilitiesThat(agent.network!!) {
-            it.hasCapability(NET_CAPABILITY_NOT_METERED)
-        }
+        callback.expectCaps(agent.network!!) { it.hasCapability(NET_CAPABILITY_NOT_METERED) }
     }
 
     private fun ncWithAllowedUids(vararg uids: Int) = NetworkCapabilities.Builder()
@@ -533,12 +528,12 @@
 
         // Make sure the UIDs have been ignored.
         callback.expect<Available>(agent.network!!)
-        callback.expectCapabilitiesThat(agent.network!!) {
+        callback.expectCaps(agent.network!!) {
             it.allowedUids.isEmpty() && !it.hasCapability(NET_CAPABILITY_VALIDATED)
         }
         callback.expect<LinkPropertiesChanged>(agent.network!!)
         callback.expect<BlockedStatus>(agent.network!!)
-        callback.expectCapabilitiesThat(agent.network!!) {
+        callback.expectCaps(agent.network!!) {
             it.allowedUids.isEmpty() && it.hasCapability(NET_CAPABILITY_VALIDATED)
         }
         callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
@@ -582,8 +577,8 @@
         // tearDown() will unregister the requests and agents
     }
 
-    private fun hasAllTransports(nc: NetworkCapabilities?, transports: IntArray) =
-            nc != null && transports.all { nc.hasTransport(it) }
+    private fun NetworkCapabilities?.hasAllTransports(transports: IntArray) =
+            this != null && transports.all { hasTransport(it) }
 
     @Test
     @IgnoreUpTo(Build.VERSION_CODES.R)
@@ -625,25 +620,25 @@
         assertEquals(mySessionId, (vpnNc.transportInfo as VpnTransportInfo).sessionId)
 
         val testAndVpn = intArrayOf(TRANSPORT_TEST, TRANSPORT_VPN)
-        assertTrue(hasAllTransports(vpnNc, testAndVpn))
+        assertTrue(vpnNc.hasAllTransports(testAndVpn))
         assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_VPN))
-        assertTrue(hasAllTransports(vpnNc, defaultNetworkTransports),
+        assertTrue(vpnNc.hasAllTransports(defaultNetworkTransports),
                 "VPN transports ${Arrays.toString(vpnNc.transportTypes)}" +
                         " lacking transports from ${Arrays.toString(defaultNetworkTransports)}")
 
         // Check that when no underlying networks are announced the underlying transport disappears.
         agent.setUnderlyingNetworks(listOf<Network>())
-        callback.expectCapabilitiesThat(agent.network!!) {
-            it.transportTypes.size == 2 && hasAllTransports(it, testAndVpn)
+        callback.expectCaps(agent.network!!) {
+            it.transportTypes.size == 2 && it.hasAllTransports(testAndVpn)
         }
 
         // Put the underlying network back and check that the underlying transport reappears.
         val expectedTransports = (defaultNetworkTransports.toSet() + TRANSPORT_TEST + TRANSPORT_VPN)
                 .toIntArray()
         agent.setUnderlyingNetworks(null)
-        callback.expectCapabilitiesThat(agent.network!!) {
+        callback.expectCaps(agent.network!!) {
             it.transportTypes.size == expectedTransports.size &&
-                    hasAllTransports(it, expectedTransports)
+                    it.hasAllTransports(expectedTransports)
         }
 
         // Check that some underlying capabilities are propagated.
@@ -757,7 +752,7 @@
         val nc1 = NetworkCapabilities(agent.nc)
                 .addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
         agent.sendNetworkCapabilities(nc1)
-        callback.expectCapabilitiesThat(agent.network!!) {
+        callback.expectCaps(agent.network!!) {
             it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
         }
 
@@ -765,7 +760,7 @@
         val nc2 = NetworkCapabilities(agent.nc)
                 .removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
         agent.sendNetworkCapabilities(nc2)
-        callback.expectCapabilitiesThat(agent.network!!) {
+        callback.expectCaps(agent.network!!) {
             !it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
         }
 
@@ -917,12 +912,10 @@
         val history = ArrayTrackRecord<CallbackEntry>().newReadHead()
 
         sealed class CallbackEntry {
-            data class OnQosSessionAvailable(val sess: QosSession, val attr: QosSessionAttributes)
-                : CallbackEntry()
-            data class OnQosSessionLost(val sess: QosSession)
-                : CallbackEntry()
-            data class OnError(val ex: QosCallbackException)
-                : CallbackEntry()
+            data class OnQosSessionAvailable(val sess: QosSession, val attr: QosSessionAttributes) :
+                CallbackEntry()
+            data class OnQosSessionLost(val sess: QosSession) : CallbackEntry()
+            data class OnError(val ex: QosCallbackException) : CallbackEntry()
         }
 
         override fun onQosSessionAvailable(sess: QosSession, attr: QosSessionAttributes) {
@@ -1330,14 +1323,10 @@
 
         val (wifiAgent, wifiNetwork) = connectNetwork(TRANSPORT_WIFI)
         testCallback.expectAvailableCallbacks(wifiNetwork, validated = true)
-        testCallback.expectCapabilitiesThat(wifiNetwork) {
-            it.hasCapability(NET_CAPABILITY_VALIDATED)
-        }
+        testCallback.expectCaps(wifiNetwork) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
         matchAllCallback.expectAvailableCallbacks(wifiNetwork, validated = false)
         matchAllCallback.expect<Losing>(cellNetwork)
-        matchAllCallback.expectCapabilitiesThat(wifiNetwork) {
-            it.hasCapability(NET_CAPABILITY_VALIDATED)
-        }
+        matchAllCallback.expectCaps(wifiNetwork) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
 
         wifiAgent.unregisterAfterReplacement(5_000 /* timeoutMillis */)
         wifiAgent.expectCallback<OnNetworkDestroyed>()
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 2b5c305..de5e46f 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -20,6 +20,8 @@
 import android.net.ConnectivityManager
 import android.net.ConnectivityManager.NetworkCallback
 import android.net.LinkProperties
+import android.net.LocalSocket
+import android.net.LocalSocketAddress
 import android.net.Network
 import android.net.NetworkAgentConfig
 import android.net.NetworkCapabilities
@@ -30,6 +32,7 @@
 import android.net.TestNetworkInterface
 import android.net.TestNetworkManager
 import android.net.TestNetworkSpecifier
+import android.net.connectivity.ConnectivityCompatChanges
 import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.DiscoveryStarted
 import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.DiscoveryStopped
 import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.ServiceFound
@@ -40,8 +43,15 @@
 import android.net.cts.NsdManagerTest.NsdRegistrationRecord.RegistrationEvent.ServiceRegistered
 import android.net.cts.NsdManagerTest.NsdRegistrationRecord.RegistrationEvent.ServiceUnregistered
 import android.net.cts.NsdManagerTest.NsdRegistrationRecord.RegistrationEvent.UnregistrationFailed
+import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.ResolutionStopped
 import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.ResolveFailed
 import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.ServiceResolved
+import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.StopResolutionFailed
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.RegisterCallbackFailed
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.ServiceUpdated
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.ServiceUpdatedLost
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.UnregisterCallbackSucceeded
+import android.net.cts.util.CtsNetUtils
 import android.net.nsd.NsdManager
 import android.net.nsd.NsdManager.DiscoveryListener
 import android.net.nsd.NsdManager.RegistrationListener
@@ -55,17 +65,34 @@
 import android.util.Log
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.PollingCheck
+import com.android.compatibility.common.util.PropertyUtil
 import com.android.net.module.util.ArrayTrackRecord
 import com.android.net.module.util.TrackRecord
 import com.android.networkstack.apishim.NsdShimImpl
+import com.android.networkstack.apishim.common.NsdShim
 import com.android.testutils.ConnectivityModuleTest
 import com.android.testutils.DevSdkIgnoreRule
 import com.android.testutils.TestableNetworkAgent
 import com.android.testutils.TestableNetworkCallback
 import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk30
+import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk33
 import com.android.testutils.runAsShell
 import com.android.testutils.tryTest
 import com.android.testutils.waitForIdle
+import java.io.File
+import java.io.IOException
+import java.net.ServerSocket
+import java.nio.charset.StandardCharsets
+import java.util.Random
+import java.util.concurrent.Executor
+import kotlin.math.min
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+import kotlin.test.fail
 import org.junit.After
 import org.junit.Assert.assertArrayEquals
 import org.junit.Assert.assertFalse
@@ -75,17 +102,6 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import java.io.File
-import java.net.ServerSocket
-import java.nio.charset.StandardCharsets
-import java.util.Random
-import java.util.concurrent.Executor
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertNotNull
-import kotlin.test.assertNull
-import kotlin.test.assertTrue
-import kotlin.test.fail
 
 private const val TAG = "NsdManagerTest"
 private const val TIMEOUT_MS = 2000L
@@ -113,6 +129,7 @@
     private val serviceName = "NsdTest%09d".format(Random().nextInt(1_000_000_000))
     private val serviceType = "_nmt%09d._tcp".format(Random().nextInt(1_000_000_000))
     private val handlerThread = HandlerThread(NsdManagerTest::class.java.simpleName)
+    private val ctsNetUtils by lazy{ CtsNetUtils(context) }
 
     private lateinit var testNetwork1: TestTapNetwork
     private lateinit var testNetwork2: TestTapNetwork
@@ -155,7 +172,8 @@
 
         inline fun <reified V : NsdEvent> expectCallback(timeoutMs: Long = TIMEOUT_MS): V {
             val nextEvent = nextEvents.poll(timeoutMs)
-            assertNotNull(nextEvent, "No callback received after $timeoutMs ms")
+            assertNotNull(nextEvent, "No callback received after $timeoutMs ms, expected " +
+                    "${V::class.java.simpleName}")
             assertTrue(nextEvent is V, "Expected ${V::class.java.simpleName} but got " +
                     nextEvent.javaClass.simpleName)
             return nextEvent
@@ -182,10 +200,10 @@
                 val errorCode: Int
             ) : RegistrationEvent()
 
-            data class ServiceRegistered(override val serviceInfo: NsdServiceInfo)
-                : RegistrationEvent()
-            data class ServiceUnregistered(override val serviceInfo: NsdServiceInfo)
-                : RegistrationEvent()
+            data class ServiceRegistered(override val serviceInfo: NsdServiceInfo) :
+                    RegistrationEvent()
+            data class ServiceUnregistered(override val serviceInfo: NsdServiceInfo) :
+                    RegistrationEvent()
         }
 
         override fun onRegistrationFailed(si: NsdServiceInfo, err: Int) {
@@ -208,11 +226,11 @@
     private class NsdDiscoveryRecord(expectedThreadId: Int? = null) :
             DiscoveryListener, NsdRecord<NsdDiscoveryRecord.DiscoveryEvent>(expectedThreadId) {
         sealed class DiscoveryEvent : NsdEvent {
-            data class StartDiscoveryFailed(val serviceType: String, val errorCode: Int)
-                : DiscoveryEvent()
+            data class StartDiscoveryFailed(val serviceType: String, val errorCode: Int) :
+                    DiscoveryEvent()
 
-            data class StopDiscoveryFailed(val serviceType: String, val errorCode: Int)
-                : DiscoveryEvent()
+            data class StopDiscoveryFailed(val serviceType: String, val errorCode: Int) :
+                    DiscoveryEvent()
 
             data class DiscoveryStarted(val serviceType: String) : DiscoveryEvent()
             data class DiscoveryStopped(val serviceType: String) : DiscoveryEvent()
@@ -259,10 +277,13 @@
     private class NsdResolveRecord : ResolveListener,
             NsdRecord<NsdResolveRecord.ResolveEvent>() {
         sealed class ResolveEvent : NsdEvent {
-            data class ResolveFailed(val serviceInfo: NsdServiceInfo, val errorCode: Int)
-                : ResolveEvent()
+            data class ResolveFailed(val serviceInfo: NsdServiceInfo, val errorCode: Int) :
+                    ResolveEvent()
 
             data class ServiceResolved(val serviceInfo: NsdServiceInfo) : ResolveEvent()
+            data class ResolutionStopped(val serviceInfo: NsdServiceInfo) : ResolveEvent()
+            data class StopResolutionFailed(val serviceInfo: NsdServiceInfo, val errorCode: Int) :
+                    ResolveEvent()
         }
 
         override fun onResolveFailed(si: NsdServiceInfo, err: Int) {
@@ -272,6 +293,40 @@
         override fun onServiceResolved(si: NsdServiceInfo) {
             add(ServiceResolved(si))
         }
+
+        override fun onResolutionStopped(si: NsdServiceInfo) {
+            add(ResolutionStopped(si))
+        }
+
+        override fun onStopResolutionFailed(si: NsdServiceInfo, err: Int) {
+            add(StopResolutionFailed(si, err))
+        }
+    }
+
+    private class NsdServiceInfoCallbackRecord : NsdShim.ServiceInfoCallbackShim,
+            NsdRecord<NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent>() {
+        sealed class ServiceInfoCallbackEvent : NsdEvent {
+            data class RegisterCallbackFailed(val errorCode: Int) : ServiceInfoCallbackEvent()
+            data class ServiceUpdated(val serviceInfo: NsdServiceInfo) : ServiceInfoCallbackEvent()
+            object ServiceUpdatedLost : ServiceInfoCallbackEvent()
+            object UnregisterCallbackSucceeded : ServiceInfoCallbackEvent()
+        }
+
+        override fun onServiceInfoCallbackRegistrationFailed(err: Int) {
+            add(RegisterCallbackFailed(err))
+        }
+
+        override fun onServiceUpdated(si: NsdServiceInfo) {
+            add(ServiceUpdated(si))
+        }
+
+        override fun onServiceLost() {
+            add(ServiceUpdatedLost)
+        }
+
+        override fun onServiceInfoCallbackUnregistered() {
+            add(UnregisterCallbackSucceeded)
+        }
     }
 
     @Before
@@ -715,6 +770,69 @@
         }
     }
 
+    private fun checkConnectSocketToMdnsd(shouldFail: Boolean) {
+        val discoveryRecord = NsdDiscoveryRecord()
+        val localSocket = LocalSocket()
+        tryTest {
+            // Discover any service from NsdManager to enforce NsdService to start the mdnsd.
+            nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryRecord)
+            discoveryRecord.expectCallback<DiscoveryStarted>()
+
+            // Checks the /dev/socket/mdnsd is created.
+            val socket = File("/dev/socket/mdnsd")
+            val doesSocketExist = PollingCheck.waitFor(
+                TIMEOUT_MS,
+                {
+                    socket.exists()
+                },
+                { doesSocketExist ->
+                    doesSocketExist
+                },
+            )
+
+            // If the socket is not created, then no need to check the access.
+            if (doesSocketExist) {
+                // Create a LocalSocket and try to connect to mdnsd.
+                assertFalse("LocalSocket is connected.", localSocket.isConnected)
+                val address = LocalSocketAddress("mdnsd", LocalSocketAddress.Namespace.RESERVED)
+                if (shouldFail) {
+                    assertFailsWith<IOException>("Expect fail but socket connected") {
+                        localSocket.connect(address)
+                    }
+                } else {
+                    localSocket.connect(address)
+                    assertTrue("LocalSocket is not connected.", localSocket.isConnected)
+                }
+            }
+        } cleanup {
+            localSocket.close()
+            nsdManager.stopServiceDiscovery(discoveryRecord)
+            discoveryRecord.expectCallback<DiscoveryStopped>()
+        }
+    }
+
+    /**
+     * Starting from Android U, the access to the /dev/socket/mdnsd is blocked by the
+     * sepolicy(b/265364111).
+     */
+    @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun testCannotConnectSocketToMdnsd() {
+        val targetSdkVersion = context.packageManager
+                .getTargetSdkVersion(context.applicationInfo.packageName)
+        assumeTrue(targetSdkVersion > Build.VERSION_CODES.TIRAMISU)
+        val firstApiLevel = min(PropertyUtil.getFirstApiLevel(), PropertyUtil.getVendorApiLevel())
+        // The sepolicy is implemented in the vendor image, so the access may not be blocked if
+        // the vendor image is not update to date.
+        assumeTrue(firstApiLevel > Build.VERSION_CODES.TIRAMISU)
+        checkConnectSocketToMdnsd(shouldFail = true)
+    }
+
+    @Test @CtsNetTestCasesMaxTargetSdk33("mdnsd socket is accessible up to target SDK 33")
+    fun testCanConnectSocketToMdnsd() {
+        checkConnectSocketToMdnsd(shouldFail = false)
+    }
+
     @Test @CtsNetTestCasesMaxTargetSdk30("Socket is started with the service up to target SDK 30")
     fun testManagerCreatesLegacySocket() {
         nsdManager // Ensure the lazy-init member is initialized, so NsdManager is created
@@ -736,7 +854,85 @@
         // when the compat change is disabled.
         // Note that before T the compat constant had a different int value.
         assertFalse(CompatChanges.isChangeEnabled(
-                NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER))
+                ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER))
+    }
+
+    @Test
+    fun testStopServiceResolution() {
+        // This test requires shims supporting U+ APIs (NsdManager.stopServiceResolution)
+        assumeTrue(TestUtils.shouldTestUApis())
+
+        val si = NsdServiceInfo()
+        si.serviceType = this@NsdManagerTest.serviceType
+        si.serviceName = this@NsdManagerTest.serviceName
+        si.port = 12345 // Test won't try to connect so port does not matter
+
+        val resolveRecord = NsdResolveRecord()
+        // Try to resolve an unknown service then stop it immediately.
+        // Expected ResolutionStopped callback.
+        nsdShim.resolveService(nsdManager, si, { it.run() }, resolveRecord)
+        nsdShim.stopServiceResolution(nsdManager, resolveRecord)
+        val stoppedCb = resolveRecord.expectCallback<ResolutionStopped>()
+        assertEquals(si.serviceName, stoppedCb.serviceInfo.serviceName)
+        assertEquals(si.serviceType, stoppedCb.serviceInfo.serviceType)
+    }
+
+    @Test
+    fun testRegisterServiceInfoCallback() {
+        // This test requires shims supporting U+ APIs (NsdManager.subscribeService)
+        assumeTrue(TestUtils.shouldTestUApis())
+
+        // Ensure Wi-Fi network connected and get addresses
+        val wifiNetwork = ctsNetUtils.ensureWifiConnected()
+        val lp = cm.getLinkProperties(wifiNetwork)
+        assertNotNull(lp)
+        val addresses = lp.addresses
+        assertFalse(addresses.isEmpty())
+
+        val si = NsdServiceInfo().apply {
+            serviceType = this@NsdManagerTest.serviceType
+            serviceName = this@NsdManagerTest.serviceName
+            network = wifiNetwork
+            port = 12345 // Test won't try to connect so port does not matter
+        }
+
+        // Register service on Wi-Fi network
+        val registrationRecord = NsdRegistrationRecord()
+        registerService(registrationRecord, si)
+
+        val discoveryRecord = NsdDiscoveryRecord()
+        val cbRecord = NsdServiceInfoCallbackRecord()
+        tryTest {
+            // Discover service on Wi-Fi network.
+            nsdShim.discoverServices(nsdManager, serviceType, NsdManager.PROTOCOL_DNS_SD,
+                    wifiNetwork, Executor { it.run() }, discoveryRecord)
+            val foundInfo = discoveryRecord.waitForServiceDiscovered(
+                    serviceName, wifiNetwork)
+
+            // Subscribe to service and check the addresses are the same as Wi-Fi addresses
+            nsdShim.registerServiceInfoCallback(nsdManager, foundInfo, { it.run() }, cbRecord)
+            for (i in addresses.indices) {
+                val subscribeCb = cbRecord.expectCallback<ServiceUpdated>()
+                assertEquals(foundInfo.serviceName, subscribeCb.serviceInfo.serviceName)
+                val hostAddresses = subscribeCb.serviceInfo.hostAddresses
+                assertEquals(i + 1, hostAddresses.size)
+                for (hostAddress in hostAddresses) {
+                    assertTrue(addresses.contains(hostAddress))
+                }
+            }
+        } cleanupStep {
+            nsdManager.unregisterService(registrationRecord)
+            registrationRecord.expectCallback<ServiceUnregistered>()
+            discoveryRecord.expectCallback<ServiceLost>()
+            cbRecord.expectCallback<ServiceUpdatedLost>()
+        } cleanupStep {
+            // Cancel subscription and check stop callback received.
+            nsdShim.unregisterServiceInfoCallback(nsdManager, cbRecord)
+            cbRecord.expectCallback<UnregisterCallbackSucceeded>()
+        } cleanup {
+            nsdManager.stopServiceDiscovery(discoveryRecord)
+            discoveryRecord.expectCallback<DiscoveryStopped>()
+        }
     }
 
     /**
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/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java b/tests/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java
index 11eb466..25534b8 100644
--- a/tests/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java
@@ -42,8 +42,9 @@
 public class IkeSessionTestUtils {
     private static final String TEST_SERVER_ADDR_V4 = "192.0.2.2";
     private static final String TEST_SERVER_ADDR_V6 = "2001:db8::2";
-    private static final String TEST_IDENTITY = "client.cts.android.com";
+    public static final String TEST_IDENTITY = "client.cts.android.com";
     private static final byte[] TEST_PSK = "ikeAndroidPsk".getBytes();
+    public static final int TEST_KEEPALIVE_TIMEOUT_UNSET = -1;
     public static final IkeSessionParams IKE_PARAMS_V4 = getTestIkeSessionParams(false);
     public static final IkeSessionParams IKE_PARAMS_V6 = getTestIkeSessionParams(true);
 
@@ -63,17 +64,26 @@
 
     public static IkeSessionParams getTestIkeSessionParams(boolean testIpv6,
             IkeIdentification identification) {
+        return getTestIkeSessionParams(testIpv6, identification, TEST_KEEPALIVE_TIMEOUT_UNSET);
+    }
+
+    public static IkeSessionParams getTestIkeSessionParams(boolean testIpv6,
+            IkeIdentification identification, int keepaliveTimer) {
         final String testServer = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4;
         final InetAddress addr = InetAddresses.parseNumericAddress(testServer);
         final IkeSessionParams.Builder ikeOptionsBuilder =
                 new IkeSessionParams.Builder()
                         .setServerHostname(testServer)
-                        .setLocalIdentification(new IkeFqdnIdentification(TEST_IDENTITY))
+                        .setLocalIdentification(identification)
                         .setRemoteIdentification(testIpv6
                                 ? new IkeIpv6AddrIdentification((Inet6Address) addr)
                                 : new IkeIpv4AddrIdentification((Inet4Address) addr))
                         .setAuthPsk(TEST_PSK)
+
                         .addSaProposal(getIkeSaProposals());
+        if (keepaliveTimer != TEST_KEEPALIVE_TIMEOUT_UNSET) {
+            ikeOptionsBuilder.setNattKeepAliveDelaySeconds(keepaliveTimer);
+        }
 
         return ikeOptionsBuilder.build();
     }
diff --git a/tests/cts/netpermission/internetpermission/AndroidManifest.xml b/tests/cts/netpermission/internetpermission/AndroidManifest.xml
index 45ef5bd..ae7de3f 100644
--- a/tests/cts/netpermission/internetpermission/AndroidManifest.xml
+++ b/tests/cts/netpermission/internetpermission/AndroidManifest.xml
@@ -43,8 +43,6 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
          android:targetPackage="android.networkpermission.internetpermission.cts"
          android:label="CTS tests for INTERNET permissions">
-        <meta-data android:name="listener"
-             android:value="com.android.cts.runner.CtsTestRunListener"/>
     </instrumentation>
 
 </manifest>
diff --git a/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml b/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml
index 6babe8f..8a7e3f7 100644
--- a/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml
+++ b/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml
@@ -51,8 +51,6 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
          android:targetPackage="android.networkpermission.updatestatspermission.cts"
          android:label="CTS tests for UPDATE_DEVICE_STATS permissions">
-        <meta-data android:name="listener"
-             android:value="com.android.cts.runner.CtsTestRunListener"/>
     </instrumentation>
 
 </manifest>
diff --git a/tests/cts/tethering/AndroidManifest.xml b/tests/cts/tethering/AndroidManifest.xml
index 911dbf2..bad722b 100644
--- a/tests/cts/tethering/AndroidManifest.xml
+++ b/tests/cts/tethering/AndroidManifest.xml
@@ -27,8 +27,6 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.tethering.cts"
                      android:label="CTS tests of android.tethering">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 
 </manifest>
diff --git a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 26b058d..3c1340d 100644
--- a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -37,7 +37,6 @@
 import android.net.TestNetworkStackClient
 import android.net.Uri
 import android.net.metrics.IpConnectivityLog
-import com.android.server.connectivity.MultinetworkPolicyTracker
 import android.os.ConditionVariable
 import android.os.IBinder
 import android.os.SystemConfigManager
@@ -52,7 +51,9 @@
 import com.android.server.NetworkAgentWrapper
 import com.android.server.TestNetIdManager
 import com.android.server.connectivity.MockableSystemProperties
+import com.android.server.connectivity.MultinetworkPolicyTracker
 import com.android.server.connectivity.ProxyTracker
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
 import com.android.testutils.TestableNetworkCallback
 import org.junit.After
 import org.junit.Before
@@ -73,8 +74,6 @@
 import org.mockito.MockitoAnnotations
 import org.mockito.Spy
 import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertNotNull
 import kotlin.test.assertTrue
 import kotlin.test.fail
 
@@ -289,15 +288,16 @@
 
         testCb.expectAvailableCallbacks(na.network, validated = false, tmt = TEST_TIMEOUT_MS)
 
-        val capportData = testCb.expectLinkPropertiesThat(na, TEST_TIMEOUT_MS) {
-            it.captivePortalData != null
+        val capportData = testCb.expect<LinkPropertiesChanged>(na, TEST_TIMEOUT_MS) {
+            it.lp.captivePortalData != null
         }.lp.captivePortalData
-        assertNotNull(capportData)
         assertTrue(capportData.isCaptive)
         assertEquals(Uri.parse("https://login.capport.android.com"), capportData.userPortalUrl)
         assertEquals(Uri.parse("https://venueinfo.capport.android.com"), capportData.venueInfoUrl)
 
-        val nc = testCb.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, na, TEST_TIMEOUT_MS)
-        assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED))
+        testCb.expectCaps(na, TEST_TIMEOUT_MS) {
+            it.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) &&
+                    !it.hasCapability(NET_CAPABILITY_VALIDATED)
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 209430a..36b3356 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -69,12 +69,11 @@
         "java/com/android/server/VpnManagerServiceTest.java",
         "java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java",
         "java/com/android/server/connectivity/IpConnectivityMetricsTest.java",
+        "java/com/android/server/connectivity/MetricsTestUtil.java",
         "java/com/android/server/connectivity/MultipathPolicyTrackerTest.java",
         "java/com/android/server/connectivity/NetdEventListenerServiceTest.java",
         "java/com/android/server/connectivity/VpnTest.java",
         "java/com/android/server/net/ipmemorystore/*.java",
-        "java/com/android/server/connectivity/mdns/**/*.java",
-        "java/com/android/server/connectivity/mdns/**/*.kt",
     ]
 }
 
@@ -116,6 +115,7 @@
         "service-connectivity-pre-jarjar",
         "service-connectivity-tiramisu-pre-jarjar",
         "services.core-vpn",
+        "testables",
         "cts-net-utils"
     ],
     libs: [
@@ -137,6 +137,37 @@
     visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
 }
 
+genrule {
+    name: "frameworks-net-tests-jarjar-rules",
+    defaults: ["jarjar-rules-combine-defaults"],
+    srcs: [
+        ":frameworks-net-tests-lib-jarjar-gen",
+        // This is necessary because the tests use framework-connectivity-internal-test-defaults,
+        // which require the user to use connectivity jarjar rules.
+        ":connectivity-jarjar-rules",
+    ],
+    out: ["frameworks-net-tests-jarjar-rules.txt"],
+    visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
+}
+
+java_genrule {
+    name: "frameworks-net-tests-lib-jarjar-gen",
+    tool_files: [
+        ":FrameworksNetTestsLib{.jar}",
+        "jarjar-excludes.txt",
+    ],
+    tools: [
+        "jarjar-rules-generator",
+    ],
+    out: ["frameworks-net-tests-lib-jarjar-rules.txt"],
+    cmd: "$(location jarjar-rules-generator) " +
+        "$(location :FrameworksNetTestsLib{.jar}) " +
+        "--prefix android.net.connectivity " +
+        "--excludes $(location jarjar-excludes.txt) " +
+        "--output $(out)",
+    visibility: ["//visibility:private"],
+}
+
 android_test {
     name: "FrameworksNetTests",
     enabled: enable_frameworks_net_tests,
@@ -144,12 +175,11 @@
         "FrameworksNetTestsDefaults",
         "FrameworksNetTests-jni-defaults",
     ],
-    jarjar_rules: ":connectivity-jarjar-rules",
+    jarjar_rules: ":frameworks-net-tests-jarjar-rules",
     test_suites: ["device-tests"],
     static_libs: [
         "services.core",
         "services.net",
-        "service-mdns",
     ],
     jni_libs: [
         "libandroid_net_connectivity_com_android_net_module_util_jni",
diff --git a/tests/unit/AndroidManifest.xml b/tests/unit/AndroidManifest.xml
index 5bac2dd..5d4bdf7 100644
--- a/tests/unit/AndroidManifest.xml
+++ b/tests/unit/AndroidManifest.xml
@@ -63,7 +63,7 @@
         <uses-library android:name="android.test.runner" />
         <uses-library android:name="android.net.ipsec.ike" />
         <activity
-            android:name="com.android.server.connectivity.NetworkNotificationManagerTest$TestDialogActivity"/>
+            android:name="android.net.connectivity.com.android.server.connectivity.NetworkNotificationManagerTest$TestDialogActivity"/>
     </application>
 
     <instrumentation
diff --git a/tests/unit/jarjar-excludes.txt b/tests/unit/jarjar-excludes.txt
new file mode 100644
index 0000000..d2022bf
--- /dev/null
+++ b/tests/unit/jarjar-excludes.txt
@@ -0,0 +1,27 @@
+# Exclude some test prefixes, otherwise the classes reference below can't find
+# them after jarjared.
+android\.compat\..+
+androidx\.test\..+
+com\.android\.frameworks\.tests\..+
+com\.android\.testutils\..+
+com\.android\.dx\.mockito\..+
+com\.android\.internal\.compat\..+
+com\.android\.internal\.org\.bouncycastle\..+
+kotlin\.test\..+
+kotlin\.reflect\..+
+org\.junit\..+
+org\.mockito\..+
+
+# Auto-jarjar-gen can't handle kotlin object expression, exclude the tests which use
+# object expressions.
+#
+# For example: Illegal class access:
+# 'android.net.connectivity.com.android.net.module.util.TrackRecordTest' attempting to access
+# 'com.android.networkstack.tethering.util.TRTInterpreter' (declaration of
+# 'android.net.connectivity.com.android.net.module.util.TrackRecordTest' ...
+#
+# In coverage test, TRTInterpreter don't be jarjar'ed to
+# android.net.connectivity* by frameworks-net-tests-jarjar-rules instead it is
+# jarjar'ed by follow up TetheringTestsJarJarRules.
+# TODO(b/269259216): remove this after fixing Auto-jarjar-gen.
+com\.android\.net\.module\.util\.TrackRecord.*
diff --git a/tests/unit/java/android/net/Ikev2VpnProfileTest.java b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
index 3b68120..e12e961 100644
--- a/tests/unit/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
@@ -492,6 +492,29 @@
     }
 
     @Test
+    public void testAutomaticNattAndIpVersionConversionIsLossless() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+        builder.setAutomaticNattKeepaliveTimerEnabled(true);
+        builder.setAutomaticIpVersionSelectionEnabled(true);
+
+        builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+        final Ikev2VpnProfile ikeProfile = builder.build();
+
+        assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+    }
+
+    @Test
+    public void testAutomaticNattAndIpVersionDefaults() throws Exception {
+        final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+        builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+        final Ikev2VpnProfile ikeProfile = builder.build();
+
+        assertEquals(false, ikeProfile.isAutomaticNattKeepaliveTimerEnabled());
+        assertEquals(false, ikeProfile.isAutomaticIpVersionSelectionEnabled());
+    }
+
+    @Test
     public void testEquals() throws Exception {
         // Verify building without IkeTunnelConnectionParams
         final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
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..edbcea9 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -34,10 +34,8 @@
 import android.net.NetworkStats.ROAMING_ALL
 import android.net.NetworkTemplate.MATCH_CARRIER
 import android.net.NetworkTemplate.MATCH_MOBILE
-import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
 import android.net.NetworkTemplate.MATCH_TEST
 import android.net.NetworkTemplate.MATCH_WIFI
-import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
 import android.net.NetworkTemplate.NETWORK_TYPE_ALL
 import android.net.NetworkTemplate.OEM_MANAGED_ALL
 import android.net.NetworkTemplate.OEM_MANAGED_NO
@@ -49,7 +47,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
@@ -232,7 +229,6 @@
         val templateMobileWildcard = buildTemplateMobileWildcard()
         val templateMobileNullImsiWithRatType = NetworkTemplate.Builder(MATCH_MOBILE)
                 .setRatType(TelephonyManager.NETWORK_TYPE_UMTS).build()
-
         val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1)
         val identMobile1 = buildNetworkIdentity(mockContext, mobileImsi1,
                 false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
@@ -447,20 +443,48 @@
     }
 
     @Test
+    fun testEquals() {
+        val templateImsi1 = NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES)
+                .setSubscriberIds(setOf(TEST_IMSI1)).setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
+                .build()
+        val dupTemplateImsi1 = NetworkTemplate(MATCH_MOBILE, arrayOf(TEST_IMSI1),
+                emptyArray<String>(), METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                TelephonyManager.NETWORK_TYPE_UMTS, OEM_MANAGED_ALL)
+        val templateImsi2 = NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES)
+                .setSubscriberIds(setOf(TEST_IMSI2)).setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
+                .build()
+
+        assertEquals(templateImsi1, dupTemplateImsi1)
+        assertEquals(dupTemplateImsi1, templateImsi1)
+        assertNotEquals(templateImsi1, templateImsi2)
+
+        val templateWifiKey1 = NetworkTemplate.Builder(MATCH_WIFI)
+                .setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build()
+        val dupTemplateWifiKey1 = NetworkTemplate(MATCH_WIFI, emptyArray<String>(),
+                arrayOf(TEST_WIFI_KEY1), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
+        val templateWifiKey2 = NetworkTemplate.Builder(MATCH_WIFI)
+                .setWifiNetworkKeys(setOf(TEST_WIFI_KEY2)).build()
+
+        assertEquals(templateWifiKey1, dupTemplateWifiKey1)
+        assertEquals(dupTemplateWifiKey1, templateWifiKey1)
+        assertNotEquals(templateWifiKey1, templateWifiKey2)
+    }
+
+    @Test
     fun testParcelUnparcel() {
-        val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, emptyArray<String>(),
+        val templateMobile = NetworkTemplate(MATCH_MOBILE, arrayOf(TEST_IMSI1),
                 emptyArray<String>(), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
-                TelephonyManager.NETWORK_TYPE_LTE, OEM_MANAGED_ALL,
-                SUBSCRIBER_ID_MATCH_RULE_EXACT)
-        val templateWifi = NetworkTemplate(MATCH_WIFI, null, emptyArray<String>(),
+                TelephonyManager.NETWORK_TYPE_LTE, OEM_MANAGED_ALL)
+        val templateWifi = NetworkTemplate(MATCH_WIFI, 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, 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, 8)
+        assertParcelSane(templateWifi, 8)
+        assertParcelSane(templateOem, 8)
     }
 
     // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with
@@ -493,13 +517,14 @@
      * @param matchType A match rule from {@code NetworkTemplate.MATCH_*} corresponding to the
      *         networkType.
      * @param subscriberId To be populated with {@code TEST_IMSI*} only if networkType is
-     *         {@code TYPE_MOBILE}. May be left as null when matchType is
-     *         {@link NetworkTemplate.MATCH_MOBILE_WILDCARD}.
-     * @param templateWifiKey Top be populated with {@code TEST_WIFI_KEY*} only if networkType is
-     *         {@code TYPE_WIFI}. May be left as null when matchType is
-     *         {@link NetworkTemplate.MATCH_WIFI_WILDCARD}.
-     * @param identWifiKey If networkType is {@code TYPE_WIFI}, this value must *NOT* be null. Provide
-     *         one of {@code TEST_WIFI_KEY*}.
+     *         {@code TYPE_MOBILE}. Note that {@code MATCH_MOBILE} with an empty subscriberId list
+     *         will match any subscriber ID.
+     * @param templateWifiKey To be populated with {@code TEST_WIFI_KEY*} only if networkType is
+     *         {@code TYPE_WIFI}. Note that {@code MATCH_WIFI} with both an empty subscriberId list
+     *         and an empty wifiNetworkKey list will match any subscriber ID and/or any wifi network
+     *         key.
+     * @param identWifiKey If networkType is {@code TYPE_WIFI}, this value must *NOT* be null.
+     *         Provide one of {@code TEST_WIFI_KEY*}.
      */
     private fun matchOemManagedIdent(
         networkType: Int,
@@ -509,17 +534,17 @@
         identWifiKey: String? = null
     ) {
         val oemManagedStates = arrayOf(OEM_NONE, OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE)
-        val matchSubscriberIds = arrayOf(subscriberId)
-        val matchWifiNetworkKeys = arrayOf(templateWifiKey)
+        val matchSubscriberIds =
+                if (subscriberId == null) emptyArray<String>() else arrayOf(subscriberId)
+        val matchWifiNetworkKeys =
+                if (templateWifiKey == null) emptyArray<String>() else arrayOf(templateWifiKey)
 
-        val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
+        val templateOemYes = NetworkTemplate(matchType, matchSubscriberIds,
                 matchWifiNetworkKeys, METERED_ALL, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_YES,
-                SUBSCRIBER_ID_MATCH_RULE_EXACT)
-        val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
+                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_YES)
+        val templateOemAll = NetworkTemplate(matchType, 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,
@@ -528,10 +553,9 @@
 
             // Create a template with each OEM managed type and match it against the NetworkIdentity
             for (templateOemManagedState in oemManagedStates) {
-                val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds,
+                val template = NetworkTemplate(matchType, 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 {
@@ -552,11 +576,10 @@
     @Test
     fun testOemManagedMatchesIdent() {
         matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE, subscriberId = TEST_IMSI1)
-        matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE_WILDCARD)
+        matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE)
         matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, templateWifiKey = TEST_WIFI_KEY1,
                 identWifiKey = TEST_WIFI_KEY1)
-        matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI_WILDCARD,
-                identWifiKey = TEST_WIFI_KEY1)
+        matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, identWifiKey = TEST_WIFI_KEY1)
     }
 
     @Test
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index 8a4932b..da65b62 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -32,6 +32,7 @@
 
 import android.compat.testing.PlatformCompatChangeRule;
 import android.content.Context;
+import android.net.connectivity.ConnectivityCompatChanges;
 import android.os.Build;
 
 import androidx.test.filters.SmallTest;
@@ -81,70 +82,70 @@
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testResolveServiceS() throws Exception {
         verify(mServiceConn, never()).startDaemon();
         doTestResolveService();
     }
 
     @Test
-    @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testResolveServicePreS() throws Exception {
         verify(mServiceConn).startDaemon();
         doTestResolveService();
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testDiscoverServiceS() throws Exception {
         verify(mServiceConn, never()).startDaemon();
         doTestDiscoverService();
     }
 
     @Test
-    @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testDiscoverServicePreS() throws Exception {
         verify(mServiceConn).startDaemon();
         doTestDiscoverService();
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testParallelResolveServiceS() throws Exception {
         verify(mServiceConn, never()).startDaemon();
         doTestParallelResolveService();
     }
 
     @Test
-    @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testParallelResolveServicePreS() throws Exception {
         verify(mServiceConn).startDaemon();
         doTestParallelResolveService();
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testInvalidCallsS() throws Exception {
         verify(mServiceConn, never()).startDaemon();
         doTestInvalidCalls();
     }
 
     @Test
-    @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testInvalidCallsPreS() throws Exception {
         verify(mServiceConn).startDaemon();
         doTestInvalidCalls();
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testRegisterServiceS() throws Exception {
         verify(mServiceConn, never()).startDaemon();
         doTestRegisterService();
     }
 
     @Test
-    @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testRegisterServicePreS() throws Exception {
         verify(mServiceConn).startDaemon();
         doTestRegisterService();
diff --git a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
index 64355ed..9ce0693 100644
--- a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
+++ b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.net.InetAddresses;
 import android.net.Network;
 import android.os.Build;
 import android.os.Bundle;
@@ -38,6 +39,7 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 
 @RunWith(DevSdkIgnoreRunner.class)
@@ -45,6 +47,8 @@
 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
 public class NsdServiceInfoTest {
 
+    private static final InetAddress IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1");
+    private static final InetAddress IPV6_ADDRESS = InetAddresses.parseNumericAddress("2001:db8::");
     public final static InetAddress LOCALHOST;
     static {
         // Because test.
@@ -124,6 +128,7 @@
         fullInfo.setServiceType("_kitten._tcp");
         fullInfo.setPort(4242);
         fullInfo.setHost(LOCALHOST);
+        fullInfo.setHostAddresses(List.of(IPV4_ADDRESS));
         fullInfo.setNetwork(new Network(123));
         fullInfo.setInterfaceIndex(456);
         checkParcelable(fullInfo);
@@ -139,6 +144,7 @@
         attributedInfo.setServiceType("_kitten._tcp");
         attributedInfo.setPort(4242);
         attributedInfo.setHost(LOCALHOST);
+        fullInfo.setHostAddresses(List.of(IPV6_ADDRESS, IPV4_ADDRESS));
         attributedInfo.setAttribute("color", "pink");
         attributedInfo.setAttribute("sound", (new String("にゃあ")).getBytes("UTF-8"));
         attributedInfo.setAttribute("adorable", (String) null);
diff --git a/tests/unit/java/com/android/internal/net/VpnProfileTest.java b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
index 0a6d2f2..b2dff2e 100644
--- a/tests/unit/java/com/android/internal/net/VpnProfileTest.java
+++ b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
@@ -20,6 +20,7 @@
 import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS_V4;
 
 import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
 import static com.android.testutils.ParcelUtils.assertParcelSane;
 
 import static org.junit.Assert.assertEquals;
@@ -55,6 +56,9 @@
     private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
     private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25;
     private static final int ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION = 26;
+    private static final int ENCODED_INDEX_IKE_TUN_CONN_PARAMS = 27;
+    private static final int ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED = 28;
+    private static final int ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED = 29;
 
     @Test
     public void testDefaults() throws Exception {
@@ -85,12 +89,15 @@
         assertFalse(p.isRestrictedToTestNetworks);
         assertFalse(p.excludeLocalRoutes);
         assertFalse(p.requiresInternetValidation);
+        assertFalse(p.automaticNattKeepaliveTimerEnabled);
+        assertFalse(p.automaticIpVersionSelectionEnabled);
     }
 
     private VpnProfile getSampleIkev2Profile(String key) {
         final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
                 false /* excludesLocalRoutes */, true /* requiresPlatformValidation */,
-                null /* ikeTunConnParams */);
+                null /* ikeTunConnParams */, true /* mAutomaticNattKeepaliveTimerEnabled */,
+                true /* automaticIpVersionSelectionEnabled */);
 
         p.name = "foo";
         p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
@@ -128,7 +135,9 @@
     private VpnProfile getSampleIkev2ProfileWithIkeTunConnParams(String key) {
         final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
                 false /* excludesLocalRoutes */, true /* requiresPlatformValidation */,
-                new IkeTunnelConnectionParams(IKE_PARAMS_V4, CHILD_PARAMS));
+                new IkeTunnelConnectionParams(IKE_PARAMS_V4, CHILD_PARAMS),
+                true /* mAutomaticNattKeepaliveTimerEnabled */,
+                true /* automaticIpVersionSelectionEnabled */);
 
         p.name = "foo";
         p.server = "bar";
@@ -166,7 +175,11 @@
 
     @Test
     public void testParcelUnparcel() {
-        if (isAtLeastT()) {
+        if (isAtLeastU()) {
+            // automaticNattKeepaliveTimerEnabled, automaticIpVersionSelectionEnabled added in U.
+            assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 28);
+            assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 28);
+        } else if (isAtLeastT()) {
             // excludeLocalRoutes, requiresPlatformValidation were added in T.
             assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 26);
             assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 26);
@@ -221,16 +234,28 @@
                         ENCODED_INDEX_AUTH_PARAMS_INLINE,
                         ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
                         ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
-                        ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+                        ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION,
+                        ENCODED_INDEX_IKE_TUN_CONN_PARAMS,
+                        ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED,
+                        ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED
+                        /* missingIndices */);
 
         assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
     }
 
+    private String getEncodedDecodedIkev2ProfileWithtooFewValues() {
+        return getEncodedDecodedIkev2ProfileMissingValues(
+                ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
+                ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+                ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION,
+                ENCODED_INDEX_IKE_TUN_CONN_PARAMS,
+                ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED,
+                ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED /* missingIndices */);
+    }
+
     @Test
     public void testEncodeDecodeMissingIsRestrictedToTestNetworks() {
-        final String tooFewValues =
-                getEncodedDecodedIkev2ProfileMissingValues(
-                        ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */);
+        final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
 
         // Verify decoding without isRestrictedToTestNetworks defaults to false
         final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
@@ -239,10 +264,7 @@
 
     @Test
     public void testEncodeDecodeMissingExcludeLocalRoutes() {
-        final String tooFewValues =
-                getEncodedDecodedIkev2ProfileMissingValues(
-                        ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
-                        ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+        final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
 
         // Verify decoding without excludeLocalRoutes defaults to false
         final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
@@ -251,9 +273,7 @@
 
     @Test
     public void testEncodeDecodeMissingRequiresValidation() {
-        final String tooFewValues =
-                getEncodedDecodedIkev2ProfileMissingValues(
-                        ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+        final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
 
         // Verify decoding without requiresValidation defaults to false
         final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
@@ -261,6 +281,24 @@
     }
 
     @Test
+    public void testEncodeDecodeMissingAutomaticNattKeepaliveTimerEnabled() {
+        final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+        // Verify decoding without automaticNattKeepaliveTimerEnabled defaults to false
+        final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+        assertFalse(decoded.automaticNattKeepaliveTimerEnabled);
+    }
+
+    @Test
+    public void testEncodeDecodeMissingAutomaticIpVersionSelectionEnabled() {
+        final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+        // Verify decoding without automaticIpVersionSelectionEnabled defaults to false
+        final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+        assertFalse(decoded.automaticIpVersionSelectionEnabled);
+    }
+
+    @Test
     public void testEncodeDecodeLoginsNotSaved() {
         final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
         profile.saveLogin = false;
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
index 0e17cd7..d189848 100644
--- a/tests/unit/java/com/android/server/BpfNetMapsTest.java
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -690,6 +690,80 @@
                 mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_ALLOW));
     }
 
+    private void doTestGetUidRule(final List<Integer> enableChains) throws Exception {
+        mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(0, getMatch(enableChains)));
+
+        for (final int chain: FIREWALL_CHAINS) {
+            final String testCase = "EnabledChains: " + enableChains + " CheckedChain: " + chain;
+            if (enableChains.contains(chain)) {
+                final int expectedRule = mBpfNetMaps.isFirewallAllowList(chain)
+                        ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY;
+                assertEquals(testCase, expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID));
+            } else {
+                final int expectedRule = mBpfNetMaps.isFirewallAllowList(chain)
+                        ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW;
+                assertEquals(testCase, expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID));
+            }
+        }
+    }
+
+    private void doTestGetUidRule(final int enableChain) throws Exception {
+        doTestGetUidRule(List.of(enableChain));
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+    public void testGetUidRule() throws Exception {
+        doTestGetUidRule(FIREWALL_CHAIN_DOZABLE);
+        doTestGetUidRule(FIREWALL_CHAIN_STANDBY);
+        doTestGetUidRule(FIREWALL_CHAIN_POWERSAVE);
+        doTestGetUidRule(FIREWALL_CHAIN_RESTRICTED);
+        doTestGetUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY);
+        doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_1);
+        doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_2);
+        doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_3);
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+    public void testGetUidRuleMultipleChainEnabled() throws Exception {
+        doTestGetUidRule(List.of(
+                FIREWALL_CHAIN_DOZABLE,
+                FIREWALL_CHAIN_STANDBY));
+        doTestGetUidRule(List.of(
+                FIREWALL_CHAIN_DOZABLE,
+                FIREWALL_CHAIN_STANDBY,
+                FIREWALL_CHAIN_POWERSAVE,
+                FIREWALL_CHAIN_RESTRICTED));
+        doTestGetUidRule(FIREWALL_CHAINS);
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+    public void testGetUidRuleNoEntry() throws Exception {
+        mUidOwnerMap.clear();
+        for (final int chain: FIREWALL_CHAINS) {
+            final int expectedRule = mBpfNetMaps.isFirewallAllowList(chain)
+                    ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW;
+            assertEquals(expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID));
+        }
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+    public void testGetUidRuleInvalidChain() {
+        final Class<ServiceSpecificException> expected = ServiceSpecificException.class;
+        assertThrows(expected, () -> mBpfNetMaps.getUidRule(-1 /* childChain */, TEST_UID));
+        assertThrows(expected, () -> mBpfNetMaps.getUidRule(1000 /* childChain */, TEST_UID));
+    }
+
+    @Test
+    @IgnoreAfter(Build.VERSION_CODES.S_V2)
+    public void testGetUidRuleBeforeT() {
+        assertThrows(UnsupportedOperationException.class,
+                () -> mBpfNetMaps.getUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID));
+    }
+
     @Test
     @IgnoreUpTo(Build.VERSION_CODES.S_V2)
     public void testReplaceUidChain() throws Exception {
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 3d6ee09..5b98237 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -27,6 +27,7 @@
 import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
 import static android.Manifest.permission.NETWORK_FACTORY;
 import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.NETWORK_SETUP_WIZARD;
 import static android.Manifest.permission.NETWORK_STACK;
 import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -64,6 +65,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;
@@ -137,6 +139,7 @@
 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
+import static android.net.Proxy.PROXY_CHANGE_ACTION;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED;
 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED;
@@ -150,6 +153,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;
@@ -167,6 +171,16 @@
 import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
 import static com.android.testutils.MiscAsserts.assertSameElements;
 import static com.android.testutils.MiscAsserts.assertThrows;
+import static com.android.testutils.RecorderCallback.CallbackEntry.AVAILABLE;
+import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS;
+import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS_INT;
+import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED;
+import static com.android.testutils.RecorderCallback.CallbackEntry.LOSING;
+import static com.android.testutils.RecorderCallback.CallbackEntry.LOST;
+import static com.android.testutils.RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED;
+import static com.android.testutils.RecorderCallback.CallbackEntry.RESUMED;
+import static com.android.testutils.RecorderCallback.CallbackEntry.SUSPENDED;
+import static com.android.testutils.RecorderCallback.CallbackEntry.UNAVAILABLE;
 import static com.android.testutils.TestPermissionUtil.runAsShell;
 
 import static org.junit.Assert.assertEquals;
@@ -209,6 +223,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,9 +374,12 @@
 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;
+import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
 import com.android.server.connectivity.ClatCoordinator;
 import com.android.server.connectivity.ConnectivityFlags;
@@ -523,11 +541,12 @@
     private MockContext mServiceContext;
     private HandlerThread mCsHandlerThread;
     private ConnectivityServiceDependencies mDeps;
+    private AutomaticOnOffKeepaliveTrackerDependencies mAutoOnOffKeepaliveDependencies;
     private ConnectivityService mService;
     private WrappedConnectivityManager mCm;
-    private TestNetworkAgentWrapper mWiFiNetworkAgent;
-    private TestNetworkAgentWrapper mCellNetworkAgent;
-    private TestNetworkAgentWrapper mEthernetNetworkAgent;
+    private TestNetworkAgentWrapper mWiFiAgent;
+    private TestNetworkAgentWrapper mCellAgent;
+    private TestNetworkAgentWrapper mEthernetAgent;
     private MockVpn mMockVpn;
     private Context mContext;
     private NetworkPolicyCallback mPolicyCallback;
@@ -573,6 +592,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 +840,26 @@
             // 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)));
+                    verify(mBroadcastOptionsShim).setDeferUntilActive(eq(true));
+                } 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.
@@ -850,9 +890,9 @@
 
     private void waitForIdle() {
         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
-        waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
-        waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
-        waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
+        waitForIdle(mCellAgent, TIMEOUT_MS);
+        waitForIdle(mWiFiAgent, TIMEOUT_MS);
+        waitForIdle(mEthernetAgent, TIMEOUT_MS);
         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
         HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
     }
@@ -875,15 +915,15 @@
 
         // Bring up a network that we can use to send messages to ConnectivityService.
         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
         b.expectBroadcast();
-        Network n = mWiFiNetworkAgent.getNetwork();
+        Network n = mWiFiAgent.getNetwork();
         assertNotNull(n);
 
         // Tests that calling waitForIdle waits for messages to be processed.
         for (int i = 0; i < attempts; i++) {
-            mWiFiNetworkAgent.setSignalStrength(i);
+            mWiFiAgent.setSignalStrength(i);
             waitForIdle();
             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
         }
@@ -895,16 +935,16 @@
     public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
         // Bring up a network that we can use to send messages to ConnectivityService.
         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
         b.expectBroadcast();
-        Network n = mWiFiNetworkAgent.getNetwork();
+        Network n = mWiFiAgent.getNetwork();
         assertNotNull(n);
 
         // Ensure that not calling waitForIdle causes a race condition.
         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
         for (int i = 0; i < attempts; i++) {
-            mWiFiNetworkAgent.setSignalStrength(i);
+            mWiFiAgent.setSignalStrength(i);
             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
                 // We hit a race condition, as expected. Pass the test.
                 return;
@@ -1058,15 +1098,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 +1129,7 @@
                     .clearCapabilities()
                     .build();
             if (validated) {
-                setNetworkValid(isStrictMode);
+                setNetworkValid(privateDnsProbeSent);
             }
             final NetworkCallback callback = new NetworkCallback() {
                 public void onCapabilitiesChanged(Network network,
@@ -1099,14 +1154,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 +1170,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 +1187,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 +1204,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 +1226,7 @@
             setProbesStatus(probesCompleted, probesSucceeded);
         }
 
-        void setNetworkPartialValid(boolean isStrictMode) {
+        void setNetworkPartialValid(boolean privateDnsProbeSent) {
             setNetworkPartial();
             mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
             mNmValidationRedirectUrl = null;
@@ -1178,7 +1235,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 +1530,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 +1549,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 +1565,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 {
@@ -1784,7 +1842,8 @@
         doReturn(mResources).when(mockResContext).getResources();
         ConnectivityResources.setResourcesContextForTest(mockResContext);
         mDeps = new ConnectivityServiceDependencies(mockResContext);
-
+        mAutoOnOffKeepaliveDependencies =
+                new AutomaticOnOffKeepaliveTrackerDependencies(mServiceContext);
         mService = new ConnectivityService(mServiceContext,
                 mMockDnsResolver,
                 mock(IpConnectivityLog.class),
@@ -1885,6 +1944,12 @@
         }
 
         @Override
+        public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(final Context c,
+                final Handler h) {
+            return new AutomaticOnOffKeepaliveTracker(c, h, mAutoOnOffKeepaliveDependencies);
+        }
+
+        @Override
         public ConnectivityResources getResources(final Context ctx) {
             return mConnRes;
         }
@@ -2034,6 +2099,26 @@
             assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
             mActiveRateLimit.put(iface, -1L);
         }
+
+        @Override
+        public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
+            reset(mBroadcastOptionsShim);
+            return mBroadcastOptionsShim;
+        }
+    }
+
+    private class AutomaticOnOffKeepaliveTrackerDependencies
+            extends AutomaticOnOffKeepaliveTracker.Dependencies {
+        AutomaticOnOffKeepaliveTrackerDependencies(Context context) {
+            super(context);
+        }
+
+        @Override
+        public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
+            // Tests for enabling the feature are verified in AutomaticOnOffKeepaliveTrackerTest.
+            // Assuming enabled here to focus on ConnectivityService tests.
+            return true;
+        }
     }
 
     private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
@@ -2067,17 +2152,17 @@
         unregisterDefaultNetworkCallbacks();
         maybeTearDownEnterpriseNetwork();
         setAlwaysOnNetworks(false);
-        if (mCellNetworkAgent != null) {
-            mCellNetworkAgent.disconnect();
-            mCellNetworkAgent = null;
+        if (mCellAgent != null) {
+            mCellAgent.disconnect();
+            mCellAgent = null;
         }
-        if (mWiFiNetworkAgent != null) {
-            mWiFiNetworkAgent.disconnect();
-            mWiFiNetworkAgent = null;
+        if (mWiFiAgent != null) {
+            mWiFiAgent.disconnect();
+            mWiFiAgent = null;
         }
-        if (mEthernetNetworkAgent != null) {
-            mEthernetNetworkAgent.disconnect();
-            mEthernetNetworkAgent = null;
+        if (mEthernetAgent != null) {
+            mEthernetAgent.disconnect();
+            mEthernetAgent = null;
         }
 
         if (mQosCallbackMockHelper != null) {
@@ -2140,13 +2225,13 @@
         }
         switch (transport) {
             case TRANSPORT_WIFI:
-                assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+                assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
                 break;
             case TRANSPORT_CELLULAR:
-                assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+                assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
                 break;
             case TRANSPORT_ETHERNET:
-                assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+                assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
                 break;
             default:
                 break;
@@ -2214,22 +2299,15 @@
         }
     }
 
-    /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
-    private ExpectedBroadcast registerConnectivityBroadcast(final int count) {
-        return registerConnectivityBroadcastThat(count, intent -> true);
-    }
-
-    private ExpectedBroadcast registerConnectivityBroadcastThat(final int count,
+    private ExpectedBroadcast registerBroadcastReceiverThat(final String action, final int count,
             @NonNull final Predicate<Intent> filter) {
-        final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
+        final IntentFilter intentFilter = new IntentFilter(action);
         // AtomicReference allows receiver to access expected even though it is constructed later.
         final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
         final BroadcastReceiver receiver = new BroadcastReceiver() {
             private int mRemaining = count;
             public void onReceive(Context context, Intent intent) {
-                final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
-                final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
-                Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni);
+                logIntent(intent);
                 if (!filter.test(intent)) return;
                 if (--mRemaining == 0) {
                     expectedRef.get().complete(intent);
@@ -2242,39 +2320,49 @@
         return expected;
     }
 
+    private void logIntent(Intent intent) {
+        final String action = intent.getAction();
+        if (CONNECTIVITY_ACTION.equals(action)) {
+            final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
+            final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
+            Log.d(TAG, "Received " + action + ", type=" + type + " ni=" + ni);
+        } else if (PROXY_CHANGE_ACTION.equals(action)) {
+            final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
+                    Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
+            Log.d(TAG, "Received " + action + ", proxy = " + proxy);
+        } else {
+            throw new IllegalArgumentException("Unsupported logging " + action);
+        }
+    }
+
+    /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
+    private ExpectedBroadcast expectConnectivityAction(final int count) {
+        return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, count, intent -> true);
+    }
+
+    private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
+        return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, 1, intent -> {
+            final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
+            final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
+            return type == actualType
+                    && state == ni.getDetailedState()
+                    && extraInfoInBroadcastHasExpectedNullness(ni);
+        });
+    }
+
+    /** Expects that PROXY_CHANGE_ACTION broadcast is received. */
+    private ExpectedBroadcast expectProxyChangeAction() {
+        return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> true);
+    }
+
     private ExpectedBroadcast expectProxyChangeAction(ProxyInfo proxy) {
-        return registerPacProxyBroadcastThat(intent -> {
+        return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> {
             final ProxyInfo actualProxy = (ProxyInfo) intent.getExtra(Proxy.EXTRA_PROXY_INFO,
                     ProxyInfo.buildPacProxy(Uri.EMPTY));
             return proxy.equals(actualProxy);
         });
     }
 
-    private ExpectedBroadcast registerPacProxyBroadcast() {
-        return registerPacProxyBroadcastThat(intent -> true);
-    }
-
-    private ExpectedBroadcast registerPacProxyBroadcastThat(
-            @NonNull final Predicate<Intent> filter) {
-        final IntentFilter intentFilter = new IntentFilter(Proxy.PROXY_CHANGE_ACTION);
-        // AtomicReference allows receiver to access expected even though it is constructed later.
-        final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            public void onReceive(Context context, Intent intent) {
-                final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
-                            Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
-                Log.d(TAG, "Receive PROXY_CHANGE_ACTION, proxy = " + proxy);
-                if (filter.test(intent)) {
-                    expectedRef.get().complete(intent);
-                }
-            }
-        };
-        final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
-        expectedRef.set(expected);
-        mServiceContext.registerReceiver(receiver, intentFilter);
-        return expected;
-    }
-
     private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) {
         final DetailedState state = ni.getDetailedState();
         if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false;
@@ -2290,16 +2378,6 @@
         return true;
     }
 
-    private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
-        return registerConnectivityBroadcastThat(1, intent -> {
-            final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
-            final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
-            return type == actualType
-                    && state == ni.getDetailedState()
-                    && extraInfoInBroadcastHasExpectedNullness(ni);
-        });
-    }
-
     @Test
     public void testNetworkTypes() {
         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
@@ -2320,10 +2398,10 @@
     @Test
     public void testNetworkFeature() throws Exception {
         // Connect the cell agent and wait for the connected broadcast.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.addCapability(NET_CAPABILITY_SUPL);
         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
-        mCellNetworkAgent.connect(true);
+        mCellAgent.connect(true);
         b.expectBroadcast();
 
         // Build legacy request for SUPL.
@@ -2334,56 +2412,56 @@
                 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
 
         // File request, withdraw it and make sure no broadcast is sent
-        b = registerConnectivityBroadcast(1);
+        b = expectConnectivityAction(1);
         final TestNetworkCallback callback = new TestNetworkCallback();
         mCm.requestNetwork(legacyRequest, callback);
-        callback.expect(CallbackEntry.AVAILABLE, mCellNetworkAgent);
+        callback.expect(AVAILABLE, mCellAgent);
         mCm.unregisterNetworkCallback(callback);
         b.expectNoBroadcast(800);  // 800ms long enough to at least flake if this is sent
 
         // Disconnect the network and expect mobile disconnected broadcast.
         b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         b.expectBroadcast();
     }
 
     @Test
     public void testLingering() throws Exception {
         verifyNoNetwork();
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         assertNull(mCm.getActiveNetworkInfo());
         assertNull(mCm.getActiveNetwork());
         // Test bringing up validated cellular.
         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
-        mCellNetworkAgent.connect(true);
+        mCellAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         assertLength(2, mCm.getAllNetworks());
-        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
-                mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
-        assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
-                mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
+        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
+                || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
+        assertTrue(mCm.getAllNetworks()[0].equals(mWiFiAgent.getNetwork())
+                || mCm.getAllNetworks()[1].equals(mWiFiAgent.getNetwork()));
         // Test bringing up validated WiFi.
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.connect(true);
+        b = expectConnectivityAction(2);
+        mWiFiAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         assertLength(2, mCm.getAllNetworks());
-        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
-                mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
-        assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
-                mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
+        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
+                || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
+        assertTrue(mCm.getAllNetworks()[0].equals(mCellAgent.getNetwork())
+                || mCm.getAllNetworks()[1].equals(mCellAgent.getNetwork()));
         // Test cellular linger timeout.
-        mCellNetworkAgent.expectDisconnected();
+        mCellAgent.expectDisconnected();
         waitForIdle();
         assertLength(1, mCm.getAllNetworks());
         verifyActiveNetwork(TRANSPORT_WIFI);
         assertLength(1, mCm.getAllNetworks());
         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
         // Test WiFi disconnect.
-        b = registerConnectivityBroadcast(1);
-        mWiFiNetworkAgent.disconnect();
+        b = expectConnectivityAction(1);
+        mWiFiAgent.disconnect();
         b.expectBroadcast();
         verifyNoNetwork();
     }
@@ -2400,43 +2478,43 @@
 
         // 1. Create a network that is not requested by anyone, and does not satisfy any of the
         // default requests. Verify that the network will be inactive instead of torn down.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connectWithoutInternet();
-        listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connectWithoutInternet();
+        listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         listenCallback.assertNoCallback();
 
         // Verify that the network will be torn down after nascent expiry. A small period of time
         // is added in case of flakiness.
         final int nascentTimeoutMs =
                 mService.mNascentDelayMs + mService.mNascentDelayMs / 4;
-        listenCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent, nascentTimeoutMs);
+        listenCallback.expect(LOST, mWiFiAgent, nascentTimeoutMs);
 
         // 2. Create a network that is satisfied by a request comes later.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connectWithoutInternet();
-        listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connectWithoutInternet();
+        listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI).build();
         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
         mCm.requestNetwork(wifiRequest, wifiCallback);
-        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         // Verify that the network will be kept since the request is still satisfied. And is able
         // to get disconnected as usual if the request is released after the nascent timer expires.
         listenCallback.assertNoCallback(nascentTimeoutMs);
         mCm.unregisterNetworkCallback(wifiCallback);
-        listenCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        listenCallback.expect(LOST, mWiFiAgent);
 
         // 3. Create a network that is satisfied by a request comes later.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connectWithoutInternet();
-        listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connectWithoutInternet();
+        listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         mCm.requestNetwork(wifiRequest, wifiCallback);
-        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         // Verify that the network will still be torn down after the request gets removed.
         mCm.unregisterNetworkCallback(wifiCallback);
-        listenCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        listenCallback.expect(LOST, mWiFiAgent);
 
         // There is no need to ensure that LOSING is never sent in the common case that the
         // network immediately satisfies a request that was already present, because it is already
@@ -2469,20 +2547,20 @@
                 .addCapability(NET_CAPABILITY_FOREGROUND).build(), fgMobileListenCallback);
 
         // Connect wifi, which satisfies default request.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
 
         // Connect a cellular network, verify that satisfies only the background callback.
         setAlwaysOnNetworks(true);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         fgMobileListenCallback.assertNoCallback();
-        assertFalse(isForegroundNetwork(mCellNetworkAgent));
+        assertFalse(isForegroundNetwork(mCellAgent));
 
-        mCellNetworkAgent.disconnect();
-        bgMobileListenCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        bgMobileListenCallback.expect(LOST, mCellAgent);
         fgMobileListenCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(wifiListenCallback);
@@ -2547,34 +2625,34 @@
             final boolean cellRadioTimesharingCapable) throws Exception {
         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
         // Test bringing up unvalidated WiFi
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        ExpectedBroadcast b = expectConnectivityAction(1);
+        mWiFiAgent.connect(false);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test bringing up unvalidated cellular
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(false);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(false);
         waitForIdle();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test cellular disconnect.
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         waitForIdle();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test bringing up validated cellular
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        b = registerConnectivityBroadcast(2);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        b = expectConnectivityAction(2);
+        mCellAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Test cellular disconnect.
-        b = registerConnectivityBroadcast(2);
-        mCellNetworkAgent.disconnect();
+        b = expectConnectivityAction(2);
+        mCellAgent.disconnect();
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test WiFi disconnect.
-        b = registerConnectivityBroadcast(1);
-        mWiFiNetworkAgent.disconnect();
+        b = expectConnectivityAction(1);
+        mWiFiAgent.disconnect();
         b.expectBroadcast();
         verifyNoNetwork();
     }
@@ -2595,25 +2673,25 @@
             final boolean cellRadioTimesharingCapable) throws Exception {
         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
         // Test bringing up unvalidated cellular.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
-        mCellNetworkAgent.connect(false);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        ExpectedBroadcast b = expectConnectivityAction(1);
+        mCellAgent.connect(false);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Test bringing up unvalidated WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        b = expectConnectivityAction(2);
+        mWiFiAgent.connect(false);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test WiFi disconnect.
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.disconnect();
+        b = expectConnectivityAction(2);
+        mWiFiAgent.disconnect();
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Test cellular disconnect.
-        b = registerConnectivityBroadcast(1);
-        mCellNetworkAgent.disconnect();
+        b = expectConnectivityAction(1);
+        mCellAgent.disconnect();
         b.expectBroadcast();
         verifyNoNetwork();
     }
@@ -2634,28 +2712,28 @@
             final boolean cellRadioTimesharingCapable) throws Exception {
         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
         // Test bringing up unvalidated WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        ExpectedBroadcast b = expectConnectivityAction(1);
+        mWiFiAgent.connect(false);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
-        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+        assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         // Test bringing up validated cellular.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        b = registerConnectivityBroadcast(2);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        b = expectConnectivityAction(2);
+        mCellAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
-        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+        assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         // Test cellular disconnect.
-        b = registerConnectivityBroadcast(2);
-        mCellNetworkAgent.disconnect();
+        b = expectConnectivityAction(2);
+        mCellAgent.disconnect();
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Unlingering a network should not cause it to be marked as validated.
-        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+        assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
     }
 
@@ -2712,7 +2790,7 @@
         if (expectLingering) {
             generalCb.expectLosing(net1);
         }
-        generalCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, net2);
+        generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
 
         // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
@@ -2727,7 +2805,7 @@
             net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
         }
         net1.disconnect();
-        generalCb.expect(CallbackEntry.LOST, net1);
+        generalCb.expect(LOST, net1);
 
         // Remove primary from net 2
         net2.setScore(new NetworkScore.Builder().build());
@@ -2757,13 +2835,14 @@
             // 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);
         }
         net2.disconnect();
-        generalCb.expect(CallbackEntry.LOST, net2);
+        generalCb.expect(LOST, net2);
         defaultCb.assertNoCallback();
 
         net3.disconnect();
@@ -2788,25 +2867,25 @@
             final boolean cellRadioTimesharingCapable) throws Exception {
         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
         // Test bringing up validated cellular.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        ExpectedBroadcast b = expectConnectivityAction(1);
+        mCellAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Test bringing up validated WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        b = expectConnectivityAction(2);
+        mWiFiAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test WiFi getting really weak.
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.adjustScore(-11);
+        b = expectConnectivityAction(2);
+        mWiFiAgent.adjustScore(-11);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Test WiFi restoring signal strength.
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.adjustScore(11);
+        b = expectConnectivityAction(2);
+        mWiFiAgent.adjustScore(11);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
     }
@@ -2828,29 +2907,29 @@
         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
         // Expect it to be torn down immediately because it satisfies no requests.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connectWithoutInternet();
-        mWiFiNetworkAgent.expectDisconnected();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connectWithoutInternet();
+        mWiFiAgent.expectDisconnected();
         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
         // Expect it to be torn down immediately because it satisfies no requests.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mCellNetworkAgent.connectWithoutInternet();
-        mCellNetworkAgent.expectDisconnected();
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mCellAgent.connectWithoutInternet();
+        mCellAgent.expectDisconnected();
         // Test bringing up validated WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test bringing up unvalidated cellular.
         // Expect it to be torn down because it could never be the highest scoring network
         // satisfying the default request even if it validated.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(false);
-        mCellNetworkAgent.expectDisconnected();
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(false);
+        mCellAgent.expectDisconnected();
         verifyActiveNetwork(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.disconnect();
-        mWiFiNetworkAgent.expectDisconnected();
+        mWiFiAgent.disconnect();
+        mWiFiAgent.expectDisconnected();
     }
 
     // TODO : migrate to @Parameterized
@@ -2869,37 +2948,37 @@
             final boolean cellRadioTimesharingCapable) throws Exception {
         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
         // Test bringing up validated cellular.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        ExpectedBroadcast b = expectConnectivityAction(1);
+        mCellAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Test bringing up validated WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        b = expectConnectivityAction(2);
+        mWiFiAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Reevaluate WiFi (it'll instantly fail DNS).
-        b = registerConnectivityBroadcast(2);
-        assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+        b = expectConnectivityAction(2);
+        assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
-        mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
+        mCm.reportBadNetwork(mWiFiAgent.getNetwork());
         // Should quickly fall back to Cellular.
         b.expectBroadcast();
-        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+        assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Reevaluate cellular (it'll instantly fail DNS).
-        b = registerConnectivityBroadcast(2);
-        assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
+        b = expectConnectivityAction(2);
+        assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
-        mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
+        mCm.reportBadNetwork(mCellAgent.getNetwork());
         // Should quickly fall back to WiFi.
         b.expectBroadcast();
-        assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
+        assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
-        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+        assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         verifyActiveNetwork(TRANSPORT_WIFI);
     }
@@ -2920,25 +2999,25 @@
             final boolean cellRadioTimesharingCapable) throws Exception {
         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
         // Test bringing up unvalidated WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        ExpectedBroadcast b = expectConnectivityAction(1);
+        mWiFiAgent.connect(false);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test bringing up validated cellular.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        b = registerConnectivityBroadcast(2);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        b = expectConnectivityAction(2);
+        mCellAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Reevaluate cellular (it'll instantly fail DNS).
-        b = registerConnectivityBroadcast(2);
-        assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
+        b = expectConnectivityAction(2);
+        assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
-        mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
+        mCm.reportBadNetwork(mCellAgent.getNetwork());
         // Should quickly fall back to WiFi.
         b.expectBroadcast();
-        assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
+        assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         verifyActiveNetwork(TRANSPORT_WIFI);
     }
@@ -2957,18 +3036,16 @@
      */
     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) {
-            final CallbackEntry.Losing losing = expect(CallbackEntry.LOSING, n, timeoutMs);
+            final CallbackEntry.Losing losing = expect(LOSING, n, timeoutMs);
             final int maxMsToLive = losing.getMaxMsToLive();
             if (maxMsToLive < 0 || maxMsToLive > mService.mLingerDelayMs) {
                 // maxMsToLive is the value that was received in the onLosing callback. That must
@@ -2990,27 +3067,32 @@
 
     // 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
         }
     }
 
     static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) {
         for (TestNetworkCallback c : callbacks) {
-            c.expect(CallbackEntry.LOST, network);
+            c.expect(LOST, network);
         }
     }
 
     static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network,
             NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
         for (TestNetworkCallback c : callbacks) {
-            c.expect(CallbackEntry.AVAILABLE, network);
-            c.expectCapabilitiesThat(network, (nc) ->
-                    !nc.hasCapability(NET_CAPABILITY_VALIDATED)
-                            && Objects.equals(specifier, nc.getNetworkSpecifier()));
-            c.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, network);
-            c.expect(CallbackEntry.BLOCKED_STATUS, network);
+            c.expect(AVAILABLE, network);
+            c.expectCaps(network, cb -> !cb.hasCapability(NET_CAPABILITY_VALIDATED)
+                    && Objects.equals(specifier, cb.getNetworkSpecifier()));
+            c.expect(LINK_PROPERTIES_CHANGED, network);
+            c.expect(BLOCKED_STATUS, network);
         }
     }
 
@@ -3020,12 +3102,12 @@
         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI).build();
         mCm.requestNetwork(wifiRequest, cb);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         // Updating the score triggers a rematch.
-        mWiFiNetworkAgent.setScore(new NetworkScore.Builder().build());
+        mWiFiAgent.setScore(new NetworkScore.Builder().build());
         cb.assertNoCallback();
-        mWiFiNetworkAgent.connect(false);
-        cb.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent.connect(false);
+        cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         cb.assertNoCallback();
         mCm.unregisterNetworkCallback(cb);
     }
@@ -3036,13 +3118,13 @@
         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI).build();
         mCm.registerNetworkCallback(wifiRequest, cb);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        final NetworkCapabilities nc = mWiFiNetworkAgent.getNetworkCapabilities();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        final NetworkCapabilities nc = mWiFiAgent.getNetworkCapabilities();
         nc.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
-        mWiFiNetworkAgent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
+        mWiFiAgent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
         cb.assertNoCallback();
-        mWiFiNetworkAgent.connect(false);
-        cb.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent.connect(false);
+        cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         final CallbackEntry found = CollectionUtils.findLast(cb.getHistory(),
                 it -> it instanceof CallbackEntry.CapabilitiesChanged);
         assertTrue(((CallbackEntry.CapabilitiesChanged) found).getCaps()
@@ -3067,77 +3149,81 @@
         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
 
         // Test unvalidated networks
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(false);
-        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        ExpectedBroadcast b = expectConnectivityAction(1);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(false);
+        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         b.expectBroadcast();
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
         // This should not trigger spurious onAvailable() callbacks, b/21762680.
-        mCellNetworkAgent.adjustScore(-1);
+        mCellAgent.adjustScore(-1);
         waitForIdle();
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
 
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        b = expectConnectivityAction(2);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         b.expectBroadcast();
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
-        b = registerConnectivityBroadcast(2);
-        mWiFiNetworkAgent.disconnect();
-        genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        b = expectConnectivityAction(2);
+        mWiFiAgent.disconnect();
+        genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
+        wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
         cellNetworkCallback.assertNoCallback();
         b.expectBroadcast();
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
-        b = registerConnectivityBroadcast(1);
-        mCellNetworkAgent.disconnect();
-        genericNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        b = expectConnectivityAction(1);
+        mCellAgent.disconnect();
+        genericNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
+        cellNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
         b.expectBroadcast();
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
         // Test validated networks
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
         // This should not trigger spurious onAvailable() callbacks, b/21762680.
-        mCellNetworkAgent.adjustScore(-1);
+        mCellAgent.adjustScore(-1);
         waitForIdle();
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        genericNetworkCallback.expectLosing(mCellNetworkAgent);
-        genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        cellNetworkCallback.expectLosing(mCellNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        genericNetworkCallback.expectLosing(mCellAgent);
+        genericNetworkCallback.expectCaps(mWiFiAgent,
+                c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        cellNetworkCallback.expectLosing(mCellAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
+        // Cell will disconnect after the lingering period. Before that elapses check that
+        // there have been no callbacks.
+        assertNoCallbacks(0 /* timeoutMs */,
+                genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
+
+        mWiFiAgent.disconnect();
+        genericNetworkCallback.expect(LOST, mWiFiAgent);
+        wifiNetworkCallback.expect(LOST, mWiFiAgent);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
-        mWiFiNetworkAgent.disconnect();
-        genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
-
-        mCellNetworkAgent.disconnect();
-        genericNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        genericNetworkCallback.expect(LOST, mCellAgent);
+        cellNetworkCallback.expect(LOST, mCellAgent);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
     }
 
@@ -3149,10 +3235,10 @@
         mCm.registerNetworkCallback(wifiRequest, callback);
         mCm.registerDefaultNetworkCallback(defaultCallback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         final LinkProperties newLp = new LinkProperties();
         final Uri capportUrl = Uri.parse("https://capport.example.com/api");
@@ -3161,20 +3247,20 @@
 
         final Uri expectedCapportUrl = sanitized ? null : capportUrl;
         newLp.setCaptivePortalApiUrl(capportUrl);
-        mWiFiNetworkAgent.sendLinkProperties(newLp);
-        callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
-                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
-        defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
-                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
+        mWiFiAgent.sendLinkProperties(newLp);
+        callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+                Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
+        defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+                Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
 
         final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
-        mWiFiNetworkAgent.notifyCapportApiDataChanged(capportData);
-        callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
-                Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
-        defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
-                Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
+        mWiFiAgent.notifyCapportApiDataChanged(capportData);
+        callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+                Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
+        defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+                Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
 
-        final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
+        final LinkProperties lp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
         assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
         assertEquals(expectedCapportData, lp.getCaptivePortalData());
     }
@@ -3209,19 +3295,18 @@
         final int originalOwnerUid = Process.myUid();
         ncTemplate.setOwnerUid(originalOwnerUid);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
-                ncTemplate);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
+        mWiFiAgent.connect(false);
         waitForIdle();
 
-        // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes
+        // Send ConnectivityService an update to the mWiFiAgent's capabilities that changes
         // the owner UID and an unrelated capability.
-        NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities();
+        NetworkCapabilities agentCapabilities = mWiFiAgent.getNetworkCapabilities();
         assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
         agentCapabilities.setOwnerUid(42);
         assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
         agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
-        mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
+        mWiFiAgent.setNetworkCapabilities(agentCapabilities, true);
         waitForIdle();
 
         // Owner UIDs are not visible without location permission.
@@ -3229,7 +3314,7 @@
                 Manifest.permission.ACCESS_FINE_LOCATION);
 
         // Check that the capability change has been applied but the owner UID is not modified.
-        NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
+        NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
         assertEquals(originalOwnerUid, nc.getOwnerUid());
         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
     }
@@ -3251,56 +3336,56 @@
         TestNetworkCallback defaultCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultCallback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
 
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
 
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent.connect(true);
         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
         // We then get LOSING when wifi validates and cell is outscored.
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectLosing(mCellNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        callback.expectLosing(mCellAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
-        mEthernetNetworkAgent.connect(true);
-        callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
+        mEthernetAgent.connect(true);
+        callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectLosing(mWiFiNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
-        assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        callback.expectLosing(mWiFiAgent);
+        callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
+        assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
-        mEthernetNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
-        defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+        mEthernetAgent.disconnect();
+        callback.expect(LOST, mEthernetAgent);
+        defaultCallback.expect(LOST, mEthernetAgent);
+        defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         for (int i = 0; i < 4; i++) {
             TestNetworkAgentWrapper oldNetwork, newNetwork;
             if (i % 2 == 0) {
-                mWiFiNetworkAgent.adjustScore(-15);
-                oldNetwork = mWiFiNetworkAgent;
-                newNetwork = mCellNetworkAgent;
+                mWiFiAgent.adjustScore(-15);
+                oldNetwork = mWiFiAgent;
+                newNetwork = mCellAgent;
             } else {
-                mWiFiNetworkAgent.adjustScore(15);
-                oldNetwork = mCellNetworkAgent;
-                newNetwork = mWiFiNetworkAgent;
+                mWiFiAgent.adjustScore(15);
+                oldNetwork = mCellAgent;
+                newNetwork = mWiFiAgent;
 
             }
             callback.expectLosing(oldNetwork);
@@ -3309,28 +3394,28 @@
             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
         }
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
         // if the network is still up.
-        mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
         // We expect a notification about the capabilities change, and nothing else.
-        defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
+        defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
         defaultCallback.assertNoCallback();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        callback.expect(LOST, mWiFiAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Wifi no longer satisfies our listen, which is for an unmetered network.
         // But because its score is 55, it's still up (and the default network).
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Disconnect our test networks.
-        mWiFiNetworkAgent.disconnect();
-        defaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mWiFiAgent.disconnect();
+        defaultCallback.expect(LOST, mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
-        mCellNetworkAgent.disconnect();
-        defaultCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        defaultCallback.expect(LOST, mCellAgent);
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
 
@@ -3344,64 +3429,64 @@
 
         mCm.registerNetworkCallback(request, callback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(false);   // Score: 10
-        callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(false);   // Score: 10
+        callback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Bring up wifi with a score of 20.
         // Cell stays up because it would satisfy the default request if it validated.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);   // Score: 20
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);   // Score: 20
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        defaultCallback.expect(LOST, mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
         // it's arguably correct to linger it, since it was the default network before it validated.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectLosing(mCellNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        callback.expectLosing(mCellAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        mCellNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        defaultCallback.expect(LOST, mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        mCellAgent.disconnect();
+        callback.expect(LOST, mCellAgent);
+        defaultCallback.expect(LOST, mCellAgent);
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
 
         // If a network is lingering, and we add and remove a request from it, resume lingering.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         // TODO: Investigate sending validated before losing.
-        callback.expectLosing(mCellNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        callback.expectLosing(mCellAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         NetworkRequest cellRequest = new NetworkRequest.Builder()
@@ -3411,14 +3496,14 @@
         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
         // lingering?
         mCm.unregisterNetworkCallback(noopCallback);
-        callback.expectLosing(mCellNetworkAgent);
+        callback.expectLosing(mCellAgent);
 
         // Similar to the above: lingering can start even after the lingered request is removed.
         // Disconnect wifi and switch to cell.
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        defaultCallback.expect(LOST, mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Cell is now the default network. Pin it with a cell-specific request.
@@ -3426,44 +3511,44 @@
         mCm.requestNetwork(cellRequest, noopCallback);
 
         // Now connect wifi, and expect it to become the default network.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
         // The default request is lingering on cell, but nothing happens to cell, and we send no
         // callbacks for it, because it's kept up by cellRequest.
         callback.assertNoCallback();
         // Now unregister cellRequest and expect cell to start lingering.
         mCm.unregisterNetworkCallback(noopCallback);
-        callback.expectLosing(mCellNetworkAgent);
+        callback.expectLosing(mCellAgent);
 
         // 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);
+        callback.expect(LOST, mCellAgent, lingerTimeoutMs);
 
         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
-        trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
-        mEthernetNetworkAgent.connect(true);
-        callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
-        callback.expectLosing(mWiFiNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
-        trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
+        trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetAgent.connect(true);
+        callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
+        callback.expectLosing(mWiFiAgent);
+        callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Let linger run its course.
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
+        callback.expect(LOST, mWiFiAgent, lingerTimeoutMs);
 
         // Clean up.
-        mEthernetNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
-        trackDefaultCallback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
+        mEthernetAgent.disconnect();
+        callback.expect(LOST, mEthernetAgent);
+        defaultCallback.expect(LOST, mEthernetAgent);
+        trackDefaultCallback.expect(LOST, mEthernetAgent);
 
         mCm.unregisterNetworkCallback(callback);
         mCm.unregisterNetworkCallback(defaultCallback);
@@ -3499,19 +3584,19 @@
         TestNetworkCallback defaultCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultCallback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
 
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
         // Wifi comes up and cell lingers.
-        mWiFiNetworkAgent.connect(true);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectLosing(mCellNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mWiFiAgent.connect(true);
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expectLosing(mCellAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
 
         // File a request for cellular, then release it.
         NetworkRequest cellRequest = new NetworkRequest.Builder()
@@ -3519,13 +3604,13 @@
         NetworkCallback noopCallback = new NetworkCallback();
         mCm.requestNetwork(cellRequest, noopCallback);
         mCm.unregisterNetworkCallback(noopCallback);
-        callback.expectLosing(mCellNetworkAgent);
+        callback.expectLosing(mCellAgent);
 
         // Let linger run its course.
         callback.assertNoCallback();
         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
-        callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
-                lingerTimeoutMs);
+        callback.expectCaps(mCellAgent, lingerTimeoutMs,
+                c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
 
         // Clean up.
         mCm.unregisterNetworkCallback(defaultCallback);
@@ -3580,7 +3665,7 @@
 
     private void expectDisconnectAndClearNotifications(TestNetworkCallback callback,
             TestNetworkAgentWrapper agent, NotificationType type) {
-        callback.expect(CallbackEntry.LOST, agent);
+        callback.expect(LOST, agent);
         expectClearNotification(agent, type);
     }
 
@@ -3651,7 +3736,7 @@
         final NetworkAgentWrapper.Callbacks callbacks = new NetworkAgentWrapper.Callbacks(
                 onNetworkCreated, onNetworkUnwanted, onNetworkDisconnected);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
 
         // Connect a network, and file a request for it after it has come up, to ensure the nascent
         // timer is cleared and the test does not have to wait for it. Filing the request after the
@@ -3659,13 +3744,13 @@
         // nascent timer if the first request satisfied by the network was filed before the network
         // connected.
         // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
-        mWiFiNetworkAgent.connectWithoutInternet();
+        mWiFiAgent.connectWithoutInternet();
         waitForIdle();
         mCm.requestNetwork(request, callback);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         // Set teardown delay and make sure CS has processed it.
-        mWiFiNetworkAgent.getNetworkAgent().setTeardownDelayMillis(300);
+        mWiFiAgent.getNetworkAgent().setTeardownDelayMillis(300);
         waitForIdle();
 
         // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
@@ -3673,7 +3758,7 @@
         // down the network and started the teardown timer, and short enough that the lambda is
         // scheduled to run before the teardown timer.
         final Handler h = new Handler(mCsHandlerThread.getLooper());
-        h.postDelayed(() -> duringTeardown.accept(mWiFiNetworkAgent.getNetwork()), 150);
+        h.postDelayed(() -> duringTeardown.accept(mWiFiAgent.getNetwork()), 150);
 
         // Disconnect the network and check that events happened in the right order.
         mCm.unregisterNetworkCallback(callback);
@@ -3694,106 +3779,104 @@
         mCm.registerNetworkCallback(request, callback);
 
         // Bring up validated cell.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
         // Bring up unvalidated wifi with explicitlySelected=true.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(true, false);
-        mWiFiNetworkAgent.connect(false);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.explicitlySelected(true, false);
+        mWiFiAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         // Cell remains the default.
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Expect a high-priority NO_INTERNET notification.
-        expectUnvalidationCheckWillNotify(mWiFiNetworkAgent, NotificationType.NO_INTERNET);
+        expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
 
         // Lower WiFi's score to lower than cell, and check that it doesn't disconnect because
         // it's explicitly selected.
-        mWiFiNetworkAgent.adjustScore(-40);
-        mWiFiNetworkAgent.adjustScore(40);
+        mWiFiAgent.adjustScore(-40);
+        mWiFiAgent.adjustScore(40);
         callback.assertNoCallback();
 
         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
         // wifi even though it's unvalidated.
-        mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
-        callback.expectLosing(mCellNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), true, false);
+        callback.expectLosing(mCellAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
-        mWiFiNetworkAgent.disconnect();
-        expectDisconnectAndClearNotifications(callback, mWiFiNetworkAgent,
-                NotificationType.NO_INTERNET);
+        mWiFiAgent.disconnect();
+        expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(true, false);
-        mWiFiNetworkAgent.connect(false);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.explicitlySelected(true, false);
+        mWiFiAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         // Expect a high-priority NO_INTERNET notification.
-        expectUnvalidationCheckWillNotify(mWiFiNetworkAgent, NotificationType.NO_INTERNET);
+        expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
 
         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
         // network to disconnect.
-        mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
-        expectDisconnectAndClearNotifications(callback, mWiFiNetworkAgent,
-                NotificationType.NO_INTERNET);
+        mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), false, false);
+        expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
         reset(mNotificationManager);
 
         // Reconnect, again with explicitlySelected=true, but this time validate.
         // Expect no notifications.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(true, false);
-        mWiFiNetworkAgent.connect(true);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectLosing(mCellNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.explicitlySelected(true, false);
+        mWiFiAgent.connect(true);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expectLosing(mCellAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
+        expectUnvalidationCheckWillNotNotify(mWiFiAgent);
 
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
-        mEthernetNetworkAgent.connect(true);
-        callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
-        callback.expectLosing(mWiFiNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
-        assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetAgent.connect(true);
+        callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
+        callback.expectLosing(mWiFiAgent);
+        callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
         callback.assertNoCallback();
 
         // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
         // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
         // wifi immediately.
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(true, true);
-        mWiFiNetworkAgent.connect(false);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectLosing(mEthernetNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        mEthernetNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
-        expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.explicitlySelected(true, true);
+        mWiFiAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expectLosing(mEthernetAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
+        mEthernetAgent.disconnect();
+        callback.expect(LOST, mEthernetAgent);
+        expectUnvalidationCheckWillNotNotify(mWiFiAgent);
 
         // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
         // Check that the network is not scored specially and that the device prefers cell data.
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(false, true);
-        mWiFiNetworkAgent.connect(false);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.explicitlySelected(false, true);
+        mWiFiAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
+        expectUnvalidationCheckWillNotNotify(mWiFiAgent);
 
         // Clean up.
-        mWiFiNetworkAgent.disconnect();
-        mCellNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
+        mCellAgent.disconnect();
 
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        callback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        callback.expect(LOST, mWiFiAgent);
+        callback.expect(LOST, mCellAgent);
     }
 
     private void doTestFirstEvaluation(
@@ -3807,36 +3890,36 @@
         TestNetworkCallback callback = new TestNetworkCallback();
         mCm.registerNetworkCallback(request, callback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        doConnect.accept(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        doConnect.accept(mWiFiAgent);
         // Expect the available callbacks, but don't require specific values for their arguments
         // since this method doesn't know how the network was connected.
-        callback.expect(CallbackEntry.AVAILABLE, mWiFiNetworkAgent);
-        callback.expect(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
-        callback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiNetworkAgent);
-        callback.expect(CallbackEntry.BLOCKED_STATUS, mWiFiNetworkAgent);
+        callback.expect(AVAILABLE, mWiFiAgent);
+        callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
+        callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent);
+        callback.expect(BLOCKED_STATUS, mWiFiAgent);
         if (waitForSecondCaps) {
             // This is necessary because of b/245893397, the same bug that happens where we use
             // expectAvailableDoubleValidatedCallbacks.
-            callback.expect(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
+            callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
         }
         final NetworkAgentInfo nai =
-                mService.getNetworkAgentInfoForNetwork(mWiFiNetworkAgent.getNetwork());
+                mService.getNetworkAgentInfoForNetwork(mWiFiAgent.getNetwork());
         final long firstEvaluation = nai.getFirstEvaluationConcludedTime();
         if (evaluatedByValidation) {
             assertNotEquals(0L, firstEvaluation);
         } else {
             assertEquals(0L, firstEvaluation);
         }
-        mService.scheduleEvaluationTimeout(mWiFiNetworkAgent.getNetwork(), 0L /* timeout */);
+        mService.scheduleEvaluationTimeout(mWiFiAgent.getNetwork(), 0L /* timeout */);
         waitForIdle();
         if (evaluatedByValidation) {
             assertEquals(firstEvaluation, nai.getFirstEvaluationConcludedTime());
         } else {
             assertNotEquals(0L, nai.getFirstEvaluationConcludedTime());
         }
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
 
         mCm.unregisterNetworkCallback(callback);
     }
@@ -4005,9 +4088,9 @@
 
     @Test
     public void testRegisterIgnoringScore() throws Exception {
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build());
-        mWiFiNetworkAgent.connect(true /* validated */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build());
+        mWiFiAgent.connect(true /* validated */);
 
         // Make sure the factory sees the default network
         final NetworkCapabilities filter = new NetworkCapabilities();
@@ -4030,13 +4113,13 @@
         testFactoryAll.expectRequestAdd();
 
         // The legacy int will be ignored anyway, set the only other knob to true
-        mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(110)
+        mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(110)
                 .setTransportPrimary(true).build());
 
         expectNoRequestChanged(testFactory); // still not seeing the request
         expectNoRequestChanged(testFactoryAll); // still seeing the request
 
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
     }
 
     @Test
@@ -4124,18 +4207,18 @@
     @Test
     public void testMMSonWiFi() throws Exception {
         // Test bringing up cellular without MMS NetworkRequest gets reaped
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
-        mCellNetworkAgent.connectWithoutInternet();
-        mCellNetworkAgent.expectDisconnected();
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.addCapability(NET_CAPABILITY_MMS);
+        mCellAgent.connectWithoutInternet();
+        mCellAgent.expectDisconnected();
         waitForIdle();
         assertEmpty(mCm.getAllNetworks());
         verifyNoNetwork();
 
         // Test bringing up validated WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
 
@@ -4146,24 +4229,24 @@
         mCm.requestNetwork(builder.build(), networkCallback);
 
         // Test bringing up unvalidated cellular with MMS
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
-        mCellNetworkAgent.connectWithoutInternet();
-        networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.addCapability(NET_CAPABILITY_MMS);
+        mCellAgent.connectWithoutInternet();
+        networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
         verifyActiveNetwork(TRANSPORT_WIFI);
 
         // Test releasing NetworkRequest disconnects cellular with MMS
         mCm.unregisterNetworkCallback(networkCallback);
-        mCellNetworkAgent.expectDisconnected();
+        mCellAgent.expectDisconnected();
         verifyActiveNetwork(TRANSPORT_WIFI);
     }
 
     @Test
     public void testMMSonCell() throws Exception {
         // Test bringing up cellular without MMS
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
-        mCellNetworkAgent.connect(false);
+        mCellAgent.connect(false);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_CELLULAR);
 
@@ -4197,142 +4280,139 @@
         mCm.registerNetworkCallback(request, callback);
 
         // Bring up validated mobile data.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
         // Bring up wifi with partial connectivity.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connectWithPartialConnectivity();
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connectWithPartialConnectivity();
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
 
         // Mobile data should be the default network.
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         callback.assertNoCallback();
 
         // Expect a PARTIAL_CONNECTIVITY notification. The notification appears as soon as partial
         // connectivity is detected, and is low priority because the network was not explicitly
         // selected by the user. This happens if we reconnect to a network where the user previously
         // accepted partial connectivity without checking "always".
-        expectNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY);
+        expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
 
         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
         // probe.
-        mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
+        mWiFiAgent.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 */,
+        mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
                 false /* always */);
         // If user accepts partial connectivity network,
         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
         waitForIdle();
-        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+        verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
 
         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
         // validated.
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        callback.expectLosing(mCellNetworkAgent);
-        NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
-                mWiFiNetworkAgent);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+        callback.expectLosing(mCellAgent);
+        NetworkCapabilities nc =
+                callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Once the network validates, the notification disappears.
-        expectClearNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY);
+        expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
 
         // Disconnect and reconnect wifi with partial connectivity again.
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connectWithPartialConnectivity();
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connectWithPartialConnectivity();
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
 
         // Mobile data should be the default network.
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         waitForIdle();
 
         // Expect a low-priority PARTIAL_CONNECTIVITY notification as soon as partial connectivity
         // is detected.
-        expectNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY);
+        expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
 
         // If the user chooses no, disconnect wifi immediately.
-        mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false /* accept */,
+        mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), false /* accept */,
                 false /* always */);
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        expectClearNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY);
+        callback.expect(LOST, mWiFiAgent);
+        expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
         reset(mNotificationManager);
 
         // If the user accepted partial connectivity before, and the device connects to that network
         // again, but now the network has full connectivity, then the network shouldn't contain
         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         // acceptUnvalidated is also used as setting for accepting partial networks.
-        mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
-                true /* acceptUnvalidated */);
-        mWiFiNetworkAgent.connect(true);
-        expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
+        mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
+        mWiFiAgent.connect(true);
+        expectUnvalidationCheckWillNotNotify(mWiFiAgent);
 
         // If user accepted partial connectivity network before,
         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
         // ConnectivityService#updateNetworkInfo().
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        callback.expectLosing(mCellNetworkAgent);
-        nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+        callback.expectLosing(mCellAgent);
+        nc = callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
 
         // Wifi should be the default network.
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
 
         // The user accepted partial connectivity and selected "don't ask again". Now the user
         // reconnects to the partial connectivity network. Switch to wifi as soon as partial
         // connectivity is detected.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
-                true /* acceptUnvalidated */);
-        mWiFiNetworkAgent.connectWithPartialConnectivity();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
+        mWiFiAgent.connectWithPartialConnectivity();
         // If user accepted partial connectivity network before,
         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
         // ConnectivityService#updateNetworkInfo().
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        callback.expectLosing(mCellNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
-        expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+        callback.expectLosing(mCellAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
+        expectUnvalidationCheckWillNotNotify(mWiFiAgent);
 
-        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
+        mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
 
         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
         // validated.
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
 
         // If the user accepted partial connectivity, and the device auto-reconnects to the partial
         // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
-                true /* acceptUnvalidated */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.explicitlySelected(false /* explicitlySelected */, true /* acceptUnvalidated */);
 
         // 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 */);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        callback.expectLosing(mCellNetworkAgent);
-        callback.expectCapabilitiesWith(
-                NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.connectWithPartialValidConnectivity(false /* privateDnsProbeSent */);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+        callback.expectLosing(mCellAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
+                && c.hasCapability(NET_CAPABILITY_VALIDATED));
+        expectUnvalidationCheckWillNotNotify(mWiFiAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
         verifyNoMoreInteractions(mNotificationManager);
     }
 
@@ -4351,42 +4431,40 @@
 
         // Bring up a network with a captive portal.
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String redirectUrl = "http://android.com/path";
-        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
-        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
+        mWiFiAgent.connectWithCaptivePortal(redirectUrl, false /* privateDnsProbeSent */);
+        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.waitForRedirectUrl(), redirectUrl);
 
         // This is necessary because of b/245893397, the same bug that happens where we use
         // expectAvailableDoubleValidatedCallbacks.
         // TODO : fix b/245893397 and remove this.
-        wifiCallback.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, mWiFiNetworkAgent);
+        wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
 
         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
-        mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
-        verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
-                .launchCaptivePortalApp();
+        mCm.startCaptivePortalApp(mWiFiAgent.getNetwork());
+        verify(mWiFiAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1)).launchCaptivePortalApp();
 
         // Report that the captive portal is dismissed with partial connectivity, and check that
         // callbacks are fired with PARTIAL and without CAPTIVE_PORTAL.
-        mWiFiNetworkAgent.setNetworkPartial();
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
+        mWiFiAgent.setNetworkPartial();
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
         waitForIdle();
-        wifiCallback.expectCapabilitiesThat(
-                mWiFiNetworkAgent, nc ->
-                nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
-                && !nc.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+        wifiCallback.expectCaps(mWiFiAgent,
+                c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
+                        && !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
 
         // Report partial connectivity is accepted.
-        mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
-        mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
+        mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
+        mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
                 false /* always */);
         waitForIdle();
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        wifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
-                mWiFiNetworkAgent);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+        wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+        validatedCallback.expectCaps(mWiFiAgent,
+                c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
 
         mCm.unregisterNetworkCallback(wifiCallback);
         mCm.unregisterNetworkCallback(validatedCallback);
@@ -4406,39 +4484,39 @@
 
         // Bring up a network with a captive portal.
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String firstRedirectUrl = "http://example.com/firstPath";
-        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
-        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
+        mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
+        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.waitForRedirectUrl(), firstRedirectUrl);
 
         // Take down network.
         // Expect onLost callback.
-        mWiFiNetworkAgent.disconnect();
-        captivePortalCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        captivePortalCallback.expect(LOST, mWiFiAgent);
 
         // Bring up a network with a captive portal.
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String secondRedirectUrl = "http://example.com/secondPath";
-        mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
-        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
+        mWiFiAgent.connectWithCaptivePortal(secondRedirectUrl, false /* privateDnsProbeSent */);
+        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.waitForRedirectUrl(), secondRedirectUrl);
 
         // Make captive portal disappear then revalidate.
         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
-        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        captivePortalCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+        captivePortalCallback.expect(LOST, mWiFiAgent);
 
         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
-        validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
 
         // Break network connectivity.
         // Expect NET_CAPABILITY_VALIDATED onLost callback.
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
-        validatedCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
+        validatedCallback.expect(LOST, mWiFiAgent);
     }
 
     private Intent startCaptivePortalApp(TestNetworkAgentWrapper networkAgent) throws Exception {
@@ -4475,36 +4553,35 @@
         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
 
         // Bring up wifi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        Network wifiNetwork = mWiFiAgent.getNetwork();
 
         // Check that calling startCaptivePortalApp does nothing.
         final int fastTimeoutMs = 100;
         mCm.startCaptivePortalApp(wifiNetwork);
         waitForIdle();
-        verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
+        verify(mWiFiAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
 
         // Turn into a captive portal.
-        mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
+        mWiFiAgent.setNetworkPortal("http://example.com", false /* privateDnsProbeSent */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
-        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        validatedCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        validatedCallback.expect(LOST, mWiFiAgent);
         // This is necessary because of b/245893397, the same bug that happens where we use
         // expectAvailableDoubleValidatedCallbacks.
         // TODO : fix b/245893397 and remove this.
-        captivePortalCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                mWiFiNetworkAgent);
+        captivePortalCallback.expectCaps(mWiFiAgent);
 
-        startCaptivePortalApp(mWiFiNetworkAgent);
+        startCaptivePortalApp(mWiFiAgent);
 
         // Report that the captive portal is dismissed, and check that callbacks are fired
-        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
-        mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
-        validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        captivePortalCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
+        mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+        validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+        captivePortalCallback.expect(LOST, mWiFiAgent);
 
         mCm.unregisterNetworkCallback(validatedCallback);
         mCm.unregisterNetworkCallback(captivePortalCallback);
@@ -4517,11 +4594,11 @@
                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false);
-        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false);
+        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
-        final Intent signInIntent = startCaptivePortalApp(mWiFiNetworkAgent);
+        final Intent signInIntent = startCaptivePortalApp(mWiFiAgent);
         final CaptivePortal captivePortal = signInIntent
                 .getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
 
@@ -4529,14 +4606,14 @@
         waitForIdle();
 
         // Since network will disconnect, ensure no notification of response to NetworkMonitor
-        verify(mWiFiNetworkAgent.mNetworkMonitor, never())
+        verify(mWiFiAgent.mNetworkMonitor, never())
                 .notifyCaptivePortalAppFinished(CaptivePortal.APP_RETURN_UNWANTED);
 
         // Report that the network is disconnected
-        mWiFiNetworkAgent.expectDisconnected();
-        mWiFiNetworkAgent.expectPreventReconnectReceived();
-        verify(mWiFiNetworkAgent.mNetworkMonitor).notifyNetworkDisconnected();
-        captivePortalCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.expectDisconnected();
+        mWiFiAgent.expectPreventReconnectReceived();
+        verify(mWiFiAgent.mNetworkMonitor).notifyNetworkDisconnected();
+        captivePortalCallback.expect(LOST, mWiFiAgent);
 
         mCm.unregisterNetworkCallback(captivePortalCallback);
     }
@@ -4556,12 +4633,12 @@
         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
         // Bring up a network with a captive portal.
         // Expect it to fail to connect and not result in any callbacks.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        String firstRedirectUrl = "http://example.com/firstPath";
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        final String firstRedirectUrl = "http://example.com/firstPath";
 
-        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
-        mWiFiNetworkAgent.expectDisconnected();
-        mWiFiNetworkAgent.expectPreventReconnectReceived();
+        mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
+        mWiFiAgent.expectDisconnected();
+        mWiFiAgent.expectPreventReconnectReceived();
 
         assertNoCallbacks(captivePortalCallback, validatedCallback);
     }
@@ -4575,28 +4652,30 @@
                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         final String redirectUrl = "http://example.com/firstPath";
 
-        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
-        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent.connectWithCaptivePortal(redirectUrl,
+                false /* privateDnsProbeSent */);
+        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         final CaptivePortalData testData = new CaptivePortalData.Builder()
                 .setUserPortalUrl(Uri.parse(redirectUrl))
                 .setBytesRemaining(12345L)
                 .build();
 
-        mWiFiNetworkAgent.notifyCapportApiDataChanged(testData);
+        mWiFiAgent.notifyCapportApiDataChanged(testData);
 
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> testData.equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> testData.equals(cb.getLp().getCaptivePortalData()));
 
         final LinkProperties newLps = new LinkProperties();
         newLps.setMtu(1234);
-        mWiFiNetworkAgent.sendLinkProperties(newLps);
+        mWiFiAgent.sendLinkProperties(newLps);
         // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> testData.equals(cb.getLp().getCaptivePortalData())
+                        && cb.getLp().getMtu() == 1234);
     }
 
     private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
@@ -4609,10 +4688,11 @@
                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
 
-        mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false /* isStrictMode */);
-        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL,
+                false /* privateDnsProbeSent */);
+        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         return captivePortalCallback;
     }
 
@@ -4687,53 +4767,54 @@
         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
 
         // Baseline capport data
-        mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
+        mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
 
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
 
         // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm
         // that API data gets precedence on the bytes remaining.
         final LinkProperties linkProperties = new LinkProperties();
         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
-        mWiFiNetworkAgent.sendLinkProperties(linkProperties);
+        mWiFiAgent.sendLinkProperties(linkProperties);
 
         // Make sure that the capport data is merged
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mExpectedMergedPasspointData
-                        .equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
+                        cb.getLp().getCaptivePortalData()));
 
         // Now send this information from non-Passpoint source, confirm that Capport data takes
         // precedence
         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
-        mWiFiNetworkAgent.sendLinkProperties(linkProperties);
+        mWiFiAgent.sendLinkProperties(linkProperties);
 
         // Make sure that the capport data is merged
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mExpectedMergedOtherData
-                        .equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
+                        cb.getLp().getCaptivePortalData()));
 
         // Create a new LP with no Network agent capport data
         final LinkProperties newLps = new LinkProperties();
         newLps.setMtu(1234);
-        mWiFiNetworkAgent.sendLinkProperties(newLps);
+        mWiFiAgent.sendLinkProperties(newLps);
         // CaptivePortalData is not lost and has the original values when LPs are received from the
         // NetworkAgent
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())
-                        && lp.getMtu() == 1234);
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData())
+                        && cb.getLp().getMtu() == 1234);
 
         // Now send capport data only from the Network agent
-        mWiFiNetworkAgent.notifyCapportApiDataChanged(null);
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> lp.getCaptivePortalData() == null);
+        mWiFiAgent.notifyCapportApiDataChanged(null);
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> cb.getLp().getCaptivePortalData() == null);
 
         newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
-        mWiFiNetworkAgent.sendLinkProperties(newLps);
+        mWiFiAgent.sendLinkProperties(newLps);
 
         // Make sure that only the network agent capport data is available
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mNaPasspointData.equals(
+                        cb.getLp().getCaptivePortalData()));
     }
 
     @Test
@@ -4745,28 +4826,29 @@
         // on the bytes remaining.
         final LinkProperties linkProperties = new LinkProperties();
         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
-        mWiFiNetworkAgent.sendLinkProperties(linkProperties);
+        mWiFiAgent.sendLinkProperties(linkProperties);
 
         // Make sure that the data is saved correctly
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mNaPasspointData.equals(
+                        cb.getLp().getCaptivePortalData()));
 
         // Expected merged data: Network agent data is preferred, and values that are not used by
         // it are merged from capport data
-        mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
+        mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
 
         // Make sure that the Capport data is merged correctly
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mExpectedMergedPasspointData.equals(
-                        lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
+                        cb.getLp().getCaptivePortalData()));
 
         // Now set the naData to null
         linkProperties.setCaptivePortalData(null);
-        mWiFiNetworkAgent.sendLinkProperties(linkProperties);
+        mWiFiAgent.sendLinkProperties(linkProperties);
 
         // Make sure that the Capport data is retained correctly
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
     }
 
     @Test
@@ -4779,20 +4861,20 @@
         // on the bytes remaining.
         final LinkProperties linkProperties = new LinkProperties();
         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
-        mWiFiNetworkAgent.sendLinkProperties(linkProperties);
+        mWiFiAgent.sendLinkProperties(linkProperties);
 
         // Make sure that the data is saved correctly
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mNaOtherData.equals(lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mNaOtherData.equals(cb.getLp().getCaptivePortalData()));
 
         // Expected merged data: Network agent data is preferred, and values that are not used by
         // it are merged from capport data
-        mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
+        mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
 
         // Make sure that the Capport data is merged correctly
-        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
-                lp -> captivePortalTestData.mExpectedMergedOtherData.equals(
-                        lp.getCaptivePortalData()));
+        captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+                cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
+                        cb.getLp().getCaptivePortalData()));
     }
 
     private NetworkRequest.Builder newWifiRequestBuilder() {
@@ -4912,51 +4994,50 @@
         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
                 cEmpty1, cEmpty2, cEmpty3, cEmpty4);
         assertNoCallbacks(cFoo, cBar);
 
-        mWiFiNetworkAgent.disconnect();
-        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
+        mWiFiAgent.disconnect();
+        expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
-        mWiFiNetworkAgent.connect(false);
-        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsFoo,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.setNetworkSpecifier(nsFoo);
+        mWiFiAgent.connect(false);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsFoo,
                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
         cBar.assertNoCallback();
         assertEquals(nsFoo,
-                mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
+                mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
 
-        mWiFiNetworkAgent.disconnect();
-        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
+        mWiFiAgent.disconnect();
+        expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
-        mWiFiNetworkAgent.connect(false);
-        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsBar,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.setNetworkSpecifier(nsBar);
+        mWiFiAgent.connect(false);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsBar,
                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
         cFoo.assertNoCallback();
         assertEquals(nsBar,
-                mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
+                mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
 
-        mWiFiNetworkAgent.disconnect();
-        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
+        mWiFiAgent.disconnect();
+        expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
         cFoo.assertNoCallback();
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
-        mWiFiNetworkAgent.connect(false);
-        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
+        mWiFiAgent.connect(false);
+        expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
-        assertNull(
-                mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
+        assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
 
-        mWiFiNetworkAgent.disconnect();
-        expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
+        mWiFiAgent.disconnect();
+        expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
     }
 
     /**
@@ -5035,8 +5116,8 @@
 
     @Test
     public void testNetworkRequestUidSpoofSecurityException() throws Exception {
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
         NetworkRequest networkRequest = newWifiRequestBuilder().build();
         TestNetworkCallback networkCallback = new TestNetworkCallback();
         doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
@@ -5091,35 +5172,35 @@
         cellNetworkCallback.assertNoCallback();
 
         // Bring up cell and expect CALLBACK_AVAILABLE.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Bring up wifi and expect CALLBACK_AVAILABLE.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
         cellNetworkCallback.assertNoCallback();
-        defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Bring down cell. Expect no default network callback, since it wasn't the default.
-        mCellNetworkAgent.disconnect();
-        cellNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        cellNetworkCallback.expect(LOST, mCellAgent);
         defaultNetworkCallback.assertNoCallback();
         systemDefaultCallback.assertNoCallback();
         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         // Bring up cell. Expect no default network callback, since it won't be the default.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         defaultNetworkCallback.assertNoCallback();
         systemDefaultCallback.assertNoCallback();
         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -5127,16 +5208,16 @@
 
         // Bring down wifi. Expect the default network callback to notified of LOST wifi
         // followed by AVAILABLE cell.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         cellNetworkCallback.assertNoCallback();
-        defaultNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        systemDefaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        systemDefaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        mCellNetworkAgent.disconnect();
-        cellNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        defaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        systemDefaultCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        defaultNetworkCallback.expect(LOST, mWiFiAgent);
+        defaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
+        systemDefaultCallback.expect(LOST, mWiFiAgent);
+        systemDefaultCallback.expectAvailableCallbacksValidated(mCellAgent);
+        mCellAgent.disconnect();
+        cellNetworkCallback.expect(LOST, mCellAgent);
+        defaultNetworkCallback.expect(LOST, mCellAgent);
+        systemDefaultCallback.expect(LOST, mCellAgent);
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
 
@@ -5148,7 +5229,7 @@
         assertEquals(null, systemDefaultCallback.getLastAvailableNetwork());
 
         mMockVpn.disconnect();
-        defaultNetworkCallback.expect(CallbackEntry.LOST, mMockVpn);
+        defaultNetworkCallback.expect(LOST, mMockVpn);
         systemDefaultCallback.assertNoCallback();
         waitForIdle();
         assertEquals(null, mCm.getActiveNetwork());
@@ -5163,29 +5244,28 @@
         mCm.requestNetwork(cellRequest, cellNetworkCallback);
 
         // Bring up the mobile network.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
         // We should get onAvailable(), onCapabilitiesChanged(), and
         // onLinkPropertiesChanged() in rapid succession. Additionally, we
         // should get onCapabilitiesChanged() when the mobile network validates.
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         cellNetworkCallback.assertNoCallback();
 
         // Update LinkProperties.
         final LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("foonet_data0");
-        mCellNetworkAgent.sendLinkProperties(lp);
+        mCellAgent.sendLinkProperties(lp);
         // We should get onLinkPropertiesChanged().
-        cellNetworkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                mCellNetworkAgent);
+        cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
 
         // Suspend the network.
-        mCellNetworkAgent.suspend();
-        cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
-                mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.SUSPENDED, mCellNetworkAgent);
+        mCellAgent.suspend();
+        cellNetworkCallback.expectCaps(mCellAgent,
+                c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        cellNetworkCallback.expect(SUSPENDED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
 
@@ -5194,21 +5274,21 @@
         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
         // as well as onNetworkSuspended() in rapid succession.
-        dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
+        dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellAgent, true);
         dfltNetworkCallback.assertNoCallback();
         mCm.unregisterNetworkCallback(dfltNetworkCallback);
 
-        mCellNetworkAgent.resume();
-        cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
-                mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.RESUMED, mCellNetworkAgent);
+        mCellAgent.resume();
+        cellNetworkCallback.expectCaps(mCellAgent,
+                c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        cellNetworkCallback.expect(RESUMED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
 
         dfltNetworkCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
         // This time onNetworkSuspended should not be called.
-        dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        dfltNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
         dfltNetworkCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(dfltNetworkCallback);
@@ -5217,8 +5297,8 @@
 
     @Test
     public void testRegisterPrivilegedDefaultCallbacksRequirePermissions() throws Exception {
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(false /* validated */);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(false /* validated */);
         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
 
         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
@@ -5233,16 +5313,23 @@
         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
         mCm.registerSystemDefaultNetworkCallback(callback, handler);
         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
-        callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mCellAgent);
         mCm.unregisterNetworkCallback(callback);
 
         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
         mCm.registerSystemDefaultNetworkCallback(callback, handler);
-        callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mCellAgent);
         mCm.unregisterNetworkCallback(callback);
 
+        mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
+        mServiceContext.setPermission(NETWORK_SETUP_WIZARD, PERMISSION_GRANTED);
+        mCm.registerSystemDefaultNetworkCallback(callback, handler);
+        callback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        mCm.unregisterNetworkCallback(callback);
+
+        mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
         mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler);
-        callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mCellAgent);
         mCm.unregisterNetworkCallback(callback);
     }
 
@@ -5273,15 +5360,15 @@
         mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback);
 
         // Both callbacks see a network with no specifier that applies to their UID.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false /* validated */);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        otherUidCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        includeOtherUidsCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        otherUidCallback.expect(LOST, mWiFiAgent);
+        includeOtherUidsCallback.expect(LOST, mWiFiAgent);
 
         // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID.
         final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
@@ -5292,7 +5379,7 @@
         otherUidCallback.assertNoCallback();
 
         mMockVpn.disconnect();
-        includeOtherUidsCallback.expect(CallbackEntry.LOST, mMockVpn);
+        includeOtherUidsCallback.expect(LOST, mMockVpn);
         callback.assertNoCallback();
         otherUidCallback.assertNoCallback();
     }
@@ -5357,10 +5444,10 @@
         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
                 .addTransportType(TRANSPORT_WIFI)
                 .setNetworkSpecifier(specifier);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
-        mWiFiNetworkAgent.connect(false /* validated */);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
+        mWiFiAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         includeOtherUidsCallback.assertNoCallback();
     }
 
@@ -5415,63 +5502,63 @@
         mCm.registerNetworkCallback(request, callback);
         mCm.registerNetworkCallback(fgRequest, fgCallback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        assertTrue(isForegroundNetwork(mCellNetworkAgent));
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        fgCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        assertTrue(isForegroundNetwork(mCellAgent));
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
 
         // When wifi connects, cell lingers.
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectLosing(mCellNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        fgCallback.expectLosing(mCellNetworkAgent);
-        fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        assertTrue(isForegroundNetwork(mCellNetworkAgent));
-        assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expectLosing(mCellAgent);
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        fgCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        fgCallback.expectLosing(mCellAgent);
+        fgCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        assertTrue(isForegroundNetwork(mCellAgent));
+        assertTrue(isForegroundNetwork(mWiFiAgent));
 
         // When lingering is complete, cell is still there but is now in the background.
         waitForIdle();
         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
-        fgCallback.expect(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
+        fgCallback.expect(LOST, mCellAgent, timeoutMs);
         // Expect a network capabilities update sans FOREGROUND.
-        callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
-        assertFalse(isForegroundNetwork(mCellNetworkAgent));
-        assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+        callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
+        assertFalse(isForegroundNetwork(mCellAgent));
+        assertTrue(isForegroundNetwork(mWiFiAgent));
 
         // File a cell request and check that cell comes into the foreground.
         final NetworkRequest cellRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_CELLULAR).build();
         final TestNetworkCallback cellCallback = new TestNetworkCallback();
         mCm.requestNetwork(cellRequest, cellCallback);
-        cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        cellCallback.expectAvailableCallbacksValidated(mCellAgent);
+        fgCallback.expectAvailableCallbacksValidated(mCellAgent);
         // Expect a network capabilities update with FOREGROUND, because the most recent
         // request causes its state to change.
-        cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
-        callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
-        assertTrue(isForegroundNetwork(mCellNetworkAgent));
-        assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+        cellCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
+        callback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
+        assertTrue(isForegroundNetwork(mCellAgent));
+        assertTrue(isForegroundNetwork(mWiFiAgent));
 
         // Release the request. The network immediately goes into the background, since it was not
         // lingering.
         mCm.unregisterNetworkCallback(cellCallback);
-        fgCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        fgCallback.expect(LOST, mCellAgent);
         // Expect a network capabilities update sans FOREGROUND.
-        callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
-        assertFalse(isForegroundNetwork(mCellNetworkAgent));
-        assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+        callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
+        assertFalse(isForegroundNetwork(mCellAgent));
+        assertTrue(isForegroundNetwork(mWiFiAgent));
 
         // Disconnect wifi and check that cell is foreground again.
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        fgCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        assertTrue(isForegroundNetwork(mCellNetworkAgent));
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        fgCallback.expect(LOST, mWiFiAgent);
+        fgCallback.expectAvailableCallbacksValidated(mCellAgent);
+        assertTrue(isForegroundNetwork(mCellAgent));
 
         mCm.unregisterNetworkCallback(callback);
         mCm.unregisterNetworkCallback(fgCallback);
@@ -5512,11 +5599,11 @@
             }
         });
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         // Don't request that the network validate, because otherwise connect() will block until
         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
         // and we won't actually measure anything.
-        mCellNetworkAgent.connect(false);
+        mCellAgent.connect(false);
 
         long onAvailableDispatchingDuration = durationOf(() -> {
             await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
@@ -5529,9 +5616,9 @@
                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
 
         // Give wifi a high enough score that we'll linger cell when wifi comes up.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.adjustScore(40);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.adjustScore(40);
+        mWiFiAgent.connect(false);
 
         long onLostDispatchingDuration = durationOf(() -> {
             await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
@@ -5577,9 +5664,9 @@
             assertTrue(testFactory.getMyStartRequested());
 
             // Bring up wifi. The factory stops looking for a network.
-            mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+            mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
             // Score 60 - 40 penalty for not validated yet, then 60 when it validates
-            mWiFiNetworkAgent.connect(true);
+            mWiFiAgent.connect(true);
             // The network connects with a low score, so the offer can still beat it and
             // nothing happens. Then the network validates, and the offer with its filter score
             // of 40 can no longer beat it and the request is removed.
@@ -5598,9 +5685,9 @@
 
             // Bring up cell data and check that the factory stops looking.
             assertLength(1, mCm.getAllNetworks());
-            mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-            mCellNetworkAgent.connect(false);
-            cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent, false, false, false,
+            mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+            mCellAgent.connect(false);
+            cellNetworkCallback.expectAvailableCallbacks(mCellAgent, false, false, false,
                     TEST_CALLBACK_TIMEOUT_MS);
             // When cell connects, it will satisfy the "mobile always on request" right away
             // by virtue of being the only network that can satisfy the request. However, its
@@ -5610,11 +5697,12 @@
             // Next, cell validates. This gives it a score of 50 and the test factory can't
             // hope to beat that according to its filters. It will see the message that its
             // offer is now unnecessary.
-            mCellNetworkAgent.setNetworkValid(true);
+            mCellAgent.setNetworkValid(true);
             // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
             // validated – see testPartialConnectivity.
-            mCm.reportNetworkConnectivity(mCellNetworkAgent.getNetwork(), true);
-            cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
+            mCm.reportNetworkConnectivity(mCellAgent.getNetwork(), true);
+            cellNetworkCallback.expectCaps(mCellAgent,
+                    c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
             testFactory.expectRequestRemove();
             testFactory.assertRequestCountEquals(0);
             // Accordingly, the factory shouldn't be started.
@@ -5627,8 +5715,8 @@
 
             // Cell disconnects. There is still the "mobile data always on" request outstanding,
             // and the test factory should see it now that it isn't hopelessly outscored.
-            mCellNetworkAgent.disconnect();
-            cellNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+            mCellAgent.disconnect();
+            cellNetworkCallback.expect(LOST, mCellAgent);
             // Wait for the network to be removed from internal structures before
             // calling synchronous getter
             waitForIdle();
@@ -5639,9 +5727,9 @@
             // Reconnect cell validated, see the request disappear again. Then withdraw the
             // mobile always on request. This will tear down cell, and there shouldn't be a
             // blip where the test factory briefly sees the request or anything.
-            mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-            mCellNetworkAgent.connect(true);
-            cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+            mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+            mCellAgent.connect(true);
+            cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
             waitForIdle();
             assertLength(2, mCm.getAllNetworks());
             testFactory.expectRequestRemove();
@@ -5651,7 +5739,7 @@
             testFactory.assertRequestCountEquals(0);
             assertFalse(testFactory.getMyStartRequested());
             // ...  and cell data to be torn down immediately since it is no longer nascent.
-            cellNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+            cellNetworkCallback.expect(LOST, mCellAgent);
             waitForIdle();
             assertLength(1, mCm.getAllNetworks());
             testFactory.terminate();
@@ -5796,39 +5884,40 @@
         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
 
         // Cell connects and validates.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
                 new LinkProperties(), null /* ncTemplate */, cellProvider);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         cellCallback.assertNoCallback();
         wifiCallback.assertNoCallback();
 
         // Bring up wifi. At first it's invalidated, so cell is still needed.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
-        mWiFiNetworkAgent.connect(false);
-        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent.connect(false);
+        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         cellCallback.assertNoCallback();
         wifiCallback.assertNoCallback();
 
         // Wifi validates. Cell is no longer needed, because it's outscored.
-        mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
+        mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
         // Have CS reconsider the network (see testPartialConnectivity)
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+        wifiNetworkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         cellCallback.expectOnNetworkUnneeded(defaultCaps);
         wifiCallback.assertNoCallback();
 
         // Wifi is no longer validated. Cell is needed again.
-        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
-        wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
+        wifiNetworkCallback.expectCaps(mWiFiAgent,
+                c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
         cellCallback.expectOnNetworkNeeded(defaultCaps);
         wifiCallback.assertNoCallback();
 
         // Disconnect wifi and pretend the carrier restricts moving away from bad wifi.
-        mWiFiNetworkAgent.disconnect();
-        wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        wifiNetworkCallback.expect(LOST, mWiFiAgent);
         // This has getAvoidBadWifi return false. This test doesn't change the value of the
         // associated setting.
         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
@@ -5836,23 +5925,25 @@
         waitForIdle();
 
         // Connect wifi again, cell is needed until wifi validates.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
-        mWiFiNetworkAgent.connect(false);
-        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent.connect(false);
+        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         cellCallback.assertNoCallback();
         wifiCallback.assertNoCallback();
-        mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-        wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+        wifiNetworkCallback.expectCaps(mWiFiAgent,
+                c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         cellCallback.expectOnNetworkUnneeded(defaultCaps);
         wifiCallback.assertNoCallback();
 
         // Wifi loses validation. Because the device doesn't avoid bad wifis, cell is
         // not needed.
-        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
-        wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
+        wifiNetworkCallback.expectCaps(mWiFiAgent,
+                c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
         cellCallback.assertNoCallback();
         wifiCallback.assertNoCallback();
     }
@@ -5870,23 +5961,23 @@
                 .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.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         if (preferBadWifi) {
-            expectUnvalidationCheckWillNotify(mWiFiNetworkAgent, NotificationType.LOST_INTERNET);
-            mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+            expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.LOST_INTERNET);
+            mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         } else {
-            expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
+            expectUnvalidationCheckWillNotNotify(mWiFiAgent);
             mDefaultNetworkCallback.assertNoCallback();
         }
     }
@@ -5931,25 +6022,25 @@
         mPolicyTracker.reevaluate();
 
         // Bring up validated cell.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        Network cellNetwork = mCellNetworkAgent.getNetwork();
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        Network cellNetwork = mCellAgent.getNetwork();
 
         // Bring up validated wifi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        Network wifiNetwork = mWiFiAgent.getNetwork();
 
         // Fail validation on wifi.
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
+        mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
-        defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        validatedWifiCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        expectNotification(mWiFiNetworkAgent, NotificationType.LOST_INTERNET);
+        defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
+        validatedWifiCallback.expect(LOST, mWiFiAgent);
+        expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
 
         // Because avoid bad wifi is off, we don't switch to cellular.
         defaultCallback.assertNoCallback();
@@ -5963,24 +6054,24 @@
         // that we switch back to cell.
         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
         mPolicyTracker.reevaluate();
-        defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
-        expectClearNotification(mWiFiNetworkAgent, NotificationType.LOST_INTERNET);
+        expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
 
         // Switch back to a restrictive carrier.
         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
         mPolicyTracker.reevaluate();
-        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
         // A notification was already shown for this very network.
-        expectNoNotification(mWiFiNetworkAgent);
+        expectNoNotification(mWiFiAgent);
 
         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
         // In principle this is a little bit unrealistic because the switch to a less restrictive
         // carrier above should have remove the notification but this doesn't matter for the
         // purposes of this test.
         mCm.setAvoidUnvalidated(wifiNetwork);
-        defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
@@ -5988,54 +6079,54 @@
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
 
         // Disconnect and reconnect wifi to clear the one-time switch above.
-        mWiFiNetworkAgent.disconnect();
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-        wifiNetwork = mWiFiNetworkAgent.getNetwork();
+        mWiFiAgent.disconnect();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+        wifiNetwork = mWiFiAgent.getNetwork();
 
         // Fail validation on wifi and expect the dialog to appear.
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
+        mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
-        defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        validatedWifiCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        expectNotification(mWiFiNetworkAgent, NotificationType.LOST_INTERNET);
+        defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
+        validatedWifiCallback.expect(LOST, mWiFiAgent);
+        expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
 
         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
         mPolicyTracker.reevaluate();
 
         // We now switch to cell.
-        defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
-        expectClearNotification(mWiFiNetworkAgent, NotificationType.LOST_INTERNET);
+        expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
 
         // Simulate the user turning the cellular fallback setting off and then on.
         // We switch to wifi and then to cell.
         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
         mPolicyTracker.reevaluate();
-        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
         // Notification is cleared again because CS doesn't particularly remember that it has
         // cleared it before, and if it hasn't cleared it before then it should do so now.
-        expectClearNotification(mWiFiNetworkAgent, NotificationType.LOST_INTERNET);
+        expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
         mPolicyTracker.reevaluate();
-        defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
 
         // If cell goes down, we switch to wifi.
-        mCellNetworkAgent.disconnect();
-        defaultCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mCellAgent.disconnect();
+        defaultCallback.expect(LOST, mCellAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         validatedWifiCallback.assertNoCallback();
         // Notification is cleared yet again because the device switched to wifi.
-        expectClearNotification(mWiFiNetworkAgent, NotificationType.LOST_INTERNET);
+        expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
 
         mCm.unregisterNetworkCallback(cellNetworkCallback);
         mCm.unregisterNetworkCallback(validatedWifiCallback);
@@ -6072,9 +6163,9 @@
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
                 TEST_CALLBACK_TIMEOUT_MS);
 
         // pass timeout and validate that UNAVAILABLE is not called
@@ -6092,12 +6183,12 @@
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
                 TEST_CALLBACK_TIMEOUT_MS);
-        mWiFiNetworkAgent.disconnect();
-        networkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        networkCallback.expect(LOST, mWiFiAgent);
 
         // Validate that UNAVAILABLE is not called
         networkCallback.assertNoCallback();
@@ -6117,11 +6208,11 @@
         mCm.requestNetwork(nr, networkCallback, timeoutMs);
 
         // pass timeout and validate that UNAVAILABLE is called
-        networkCallback.expect(CallbackEntry.UNAVAILABLE);
+        networkCallback.expect(UNAVAILABLE);
 
         // create a network satisfying request - validate that request not triggered
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
         networkCallback.assertNoCallback();
     }
 
@@ -6143,8 +6234,8 @@
         networkCallback.assertNoCallback();
 
         // create a network satisfying request - validate that request not triggered
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
         networkCallback.assertNoCallback();
     }
 
@@ -6201,7 +6292,7 @@
                 // onUnavailable!
                 testFactory.triggerUnfulfillable(newRequest);
 
-                networkCallback.expect(CallbackEntry.UNAVAILABLE);
+                networkCallback.expect(UNAVAILABLE);
 
                 // Declaring a request unfulfillable releases it automatically.
                 testFactory.expectRequestRemove();
@@ -6382,18 +6473,18 @@
 
     private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
         // Ensure the network is disconnected before anything else occurs
-        if (mWiFiNetworkAgent != null) {
-            assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
+        if (mWiFiAgent != null) {
+            assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()));
         }
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent.connect(true);
         b.expectBroadcast();
         verifyActiveNetwork(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
+        mWiFiAgent.sendLinkProperties(lp);
         waitForIdle();
-        return mWiFiNetworkAgent.getNetwork();
+        return mWiFiAgent.getNetwork();
     }
 
     @Test
@@ -6450,10 +6541,10 @@
         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
 
         // Check that a started keepalive can be stopped.
-        mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
+        mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
         callback.expectStarted();
-        mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
+        mWiFiAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
         ka.stop();
         callback.expectStopped();
 
@@ -6463,15 +6554,15 @@
         callback.expectStarted();
         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
-        mWiFiNetworkAgent.sendLinkProperties(bogusLp);
+        mWiFiAgent.sendLinkProperties(bogusLp);
         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
+        mWiFiAgent.sendLinkProperties(lp);
 
         // Check that a started keepalive is stopped correctly when the network disconnects.
         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
         callback.expectStarted();
-        mWiFiNetworkAgent.disconnect();
-        mWiFiNetworkAgent.expectDisconnected();
+        mWiFiAgent.disconnect();
+        mWiFiAgent.expectDisconnected();
         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
 
         // ... and that stopping it after that has no adverse effects.
@@ -6482,15 +6573,15 @@
 
         // Reconnect.
         myNet = connectKeepaliveNetwork(lp);
-        mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
+        mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
 
         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
-        mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
+        mWiFiAgent.setExpectedKeepaliveSlot(1);
         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
         callback.expectStarted();
 
         // The second one gets slot 2.
-        mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
+        mWiFiAgent.setExpectedKeepaliveSlot(2);
         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
         PacketKeepalive ka2 = mCm.startNattKeepalive(
                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
@@ -6500,7 +6591,7 @@
         ka.stop();
         callback.expectStopped();
 
-        mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
+        mWiFiAgent.setExpectedKeepaliveSlot(1);
         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
         PacketKeepalive ka3 = mCm.startNattKeepalive(
                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
@@ -6602,12 +6693,12 @@
         }
 
         // Check that a started keepalive can be stopped.
-        mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
+        mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
         try (SocketKeepalive ka = mCm.createSocketKeepalive(
                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
             ka.start(validKaInterval);
             callback.expectStarted();
-            mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
+            mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
             ka.stop();
             callback.expectStopped();
 
@@ -6636,9 +6727,9 @@
             callback.expectStarted();
             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
-            mWiFiNetworkAgent.sendLinkProperties(bogusLp);
+            mWiFiAgent.sendLinkProperties(bogusLp);
             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
-            mWiFiNetworkAgent.sendLinkProperties(lp);
+            mWiFiAgent.sendLinkProperties(lp);
         }
 
         // Check that a started keepalive is stopped correctly when the network disconnects.
@@ -6646,21 +6737,20 @@
                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
             ka.start(validKaInterval);
             callback.expectStarted();
-            mWiFiNetworkAgent.disconnect();
-            mWiFiNetworkAgent.expectDisconnected();
+            mWiFiAgent.disconnect();
+            mWiFiAgent.expectDisconnected();
             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
 
             // ... and that stopping it after that has no adverse effects.
             waitForIdle();
-            final Network myNetAlias = myNet;
-            assertNull(mCm.getNetworkCapabilities(myNetAlias));
+            assertNull(mCm.getNetworkCapabilities(myNet));
             ka.stop();
             callback.assertNoCallback();
         }
 
         // Reconnect.
         myNet = connectKeepaliveNetwork(lp);
-        mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
+        mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
 
         // Check that a stop followed by network disconnects does not result in crash.
         try (SocketKeepalive ka = mCm.createSocketKeepalive(
@@ -6669,7 +6759,7 @@
             callback.expectStarted();
             // Delay the response of keepalive events in networkAgent long enough to make sure
             // the follow-up network disconnection will be processed first.
-            mWiFiNetworkAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
+            mWiFiAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
             ka.stop();
             // Call stop() twice shouldn't result in crash, b/182586681.
             ka.stop();
@@ -6679,8 +6769,8 @@
             waitForIdleSerialExecutor(executor, TIMEOUT_MS);
             waitForIdle();
 
-            mWiFiNetworkAgent.disconnect();
-            mWiFiNetworkAgent.expectDisconnected();
+            mWiFiAgent.disconnect();
+            mWiFiAgent.expectDisconnected();
             callback.expectStopped();
             callback.assertNoCallback();
         }
@@ -6688,20 +6778,18 @@
         // Reconnect.
         waitForIdle();
         myNet = connectKeepaliveNetwork(lp);
-        mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
+        mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
 
         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
-        mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
-        int srcPort2 = 0;
+        mWiFiAgent.setExpectedKeepaliveSlot(1);
         try (SocketKeepalive ka = mCm.createSocketKeepalive(
                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
             ka.start(validKaInterval);
             callback.expectStarted();
 
             // The second one gets slot 2.
-            mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
+            mWiFiAgent.setExpectedKeepaliveSlot(2);
             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
-            srcPort2 = testSocket2.getPort();
             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
@@ -6724,9 +6812,9 @@
         // assertFalse(isUdpPortInUse(srcPort));
         // assertFalse(isUdpPortInUse(srcPort2));
 
-        mWiFiNetworkAgent.disconnect();
-        mWiFiNetworkAgent.expectDisconnected();
-        mWiFiNetworkAgent = null;
+        mWiFiAgent.disconnect();
+        mWiFiAgent.expectDisconnected();
+        mWiFiAgent = null;
     }
 
     @Test
@@ -6800,9 +6888,9 @@
         testSocketV4.close();
         testSocketV6.close();
 
-        mWiFiNetworkAgent.disconnect();
-        mWiFiNetworkAgent.expectDisconnected();
-        mWiFiNetworkAgent = null;
+        mWiFiAgent.disconnect();
+        mWiFiAgent.expectDisconnected();
+        mWiFiAgent = null;
     }
 
     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
@@ -6817,8 +6905,8 @@
         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
         Network myNet = connectKeepaliveNetwork(lp);
-        mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
-        mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
+        mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
+        mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
 
         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
 
@@ -6853,9 +6941,9 @@
         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
         // assertFalse(isUdpPortInUse(srcPort));
 
-        mWiFiNetworkAgent.disconnect();
-        mWiFiNetworkAgent.expectDisconnected();
-        mWiFiNetworkAgent = null;
+        mWiFiAgent.disconnect();
+        mWiFiAgent.expectDisconnected();
+        mWiFiAgent = null;
     }
 
     private static boolean isUdpPortInUse(int port) {
@@ -6893,18 +6981,18 @@
     }
 
     private void assertPinnedToWifiWithCellDefault() {
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
     }
 
     private void assertPinnedToWifiWithWifiDefault() {
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
     }
 
     private void assertNotPinnedToWifi() {
         assertNull(mCm.getBoundNetworkForProcess());
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
     }
 
     @Test
@@ -6917,23 +7005,23 @@
         TestNetworkPinner.pin(mServiceContext, wifiRequest);
         assertNull(mCm.getBoundNetworkForProcess());
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
 
         // When wi-fi connects, expect to be pinned.
         assertTrue(TestNetworkPinner.awaitPin(100));
         assertPinnedToWifiWithCellDefault();
 
         // Disconnect and expect the pin to drop.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         assertTrue(TestNetworkPinner.awaitUnpin(100));
         assertNotPinnedToWifi();
 
         // Reconnecting does not cause the pin to come back.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
         assertFalse(TestNetworkPinner.awaitPin(100));
         assertNotPinnedToWifi();
 
@@ -6947,22 +7035,22 @@
         assertNotPinnedToWifi();
 
         // Disconnect cell and wifi.
-        ExpectedBroadcast b = registerConnectivityBroadcast(3);  // cell down, wifi up, wifi down.
-        mCellNetworkAgent.disconnect();
-        mWiFiNetworkAgent.disconnect();
+        ExpectedBroadcast b = expectConnectivityAction(3);  // cell down, wifi up, wifi down.
+        mCellAgent.disconnect();
+        mWiFiAgent.disconnect();
         b.expectBroadcast();
 
         // Pinning takes effect even if the pinned network is the default when the pin is set...
         TestNetworkPinner.pin(mServiceContext, wifiRequest);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
         assertTrue(TestNetworkPinner.awaitPin(100));
         assertPinnedToWifiWithWifiDefault();
 
         // ... and is maintained even when that network is no longer the default.
-        b = registerConnectivityBroadcast(1);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mCellNetworkAgent.connect(true);
+        b = expectConnectivityAction(1);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mCellAgent.connect(true);
         b.expectBroadcast();
         assertPinnedToWifiWithCellDefault();
     }
@@ -7137,7 +7225,7 @@
 
     @Test
     public void testNetworkInfoOfTypeNone() throws Exception {
-        ExpectedBroadcast b = registerConnectivityBroadcast(1);
+        ExpectedBroadcast b = expectConnectivityAction(1);
 
         verifyNoNetwork();
         TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
@@ -7155,7 +7243,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());
@@ -7166,7 +7254,7 @@
 
         // Disconnect wifi aware network.
         wifiAware.disconnect();
-        callback.expect(CallbackEntry.LOST, TIMEOUT_MS);
+        callback.expect(LOST, TIMEOUT_MS);
         mCm.unregisterNetworkCallback(callback);
 
         verifyNoNetwork();
@@ -7213,13 +7301,12 @@
         // ConnectivityService.
         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
         networkAgent.connect(true);
-        networkCallback.expect(CallbackEntry.AVAILABLE, networkAgent);
-        networkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
+        networkCallback.expect(AVAILABLE, networkAgent);
+        networkCallback.expect(NETWORK_CAPS_UPDATED, networkAgent);
         CallbackEntry.LinkPropertiesChanged cbi =
-                networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                networkAgent);
-        networkCallback.expect(CallbackEntry.BLOCKED_STATUS, networkAgent);
-        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
+                networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
+        networkCallback.expect(BLOCKED_STATUS, networkAgent);
+        networkCallback.expectCaps(networkAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         networkCallback.assertNoCallback();
         checkDirectlyConnectedRoutes(cbi.getLp(), asList(myIpv4Address),
                 asList(myIpv4DefaultRoute));
@@ -7233,7 +7320,7 @@
         newLp.addLinkAddress(myIpv6Address1);
         newLp.addLinkAddress(myIpv6Address2);
         networkAgent.sendLinkProperties(newLp);
-        cbi = networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
+        cbi = networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
         networkCallback.assertNoCallback();
         checkDirectlyConnectedRoutes(cbi.getLp(),
                 asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
@@ -7294,15 +7381,15 @@
     }
 
     private List<Network> onlyCell() {
-        return List.of(mCellNetworkAgent.getNetwork());
+        return List.of(mCellAgent.getNetwork());
     }
 
     private List<Network> onlyWifi() {
-        return List.of(mWiFiNetworkAgent.getNetwork());
+        return List.of(mWiFiAgent.getNetwork());
     }
 
     private List<Network> cellAndWifi() {
-        return List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork());
+        return List.of(mCellAgent.getNetwork(), mWiFiAgent.getNetwork());
     }
 
     @Test
@@ -7312,11 +7399,11 @@
         LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
 
         // Simple connection with initial LP should have updated ifaces.
-        mCellNetworkAgent.connect(false);
+        mCellAgent.connect(false);
         waitForIdle();
         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
         reset(mStatsManager);
@@ -7326,13 +7413,13 @@
         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
                 MOBILE_IFNAME));
         cellLp.setDnsServers(List.of(InetAddress.getAllByName("8.8.8.8")));
-        mCellNetworkAgent.sendLinkProperties(cellLp);
+        mCellAgent.sendLinkProperties(cellLp);
         verifyNoMoreInteractions(mStatsManager);
         reset(mStatsManager);
 
         // Default network switch should update ifaces.
-        mWiFiNetworkAgent.connect(false);
-        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+        mWiFiAgent.connect(false);
+        mWiFiAgent.sendLinkProperties(wifiLp);
         waitForIdle();
         assertEquals(wifiLp, mService.getActiveLinkProperties());
         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
@@ -7344,52 +7431,52 @@
         // notifyNetworkStatus is called again, traffic on that interface will be accounted to the
         // disconnected network. This is likely a bug in ConnectivityService; it should probably
         // call notifyNetworkStatus again without the disconnected network.
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         waitForIdle();
         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
         verifyNoMoreInteractions(mStatsManager);
         reset(mStatsManager);
 
         // Connecting a network updates ifaces even if the network doesn't become default.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(false);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(false);
         waitForIdle();
         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
         reset(mStatsManager);
 
         // Disconnect should update ifaces.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         waitForIdle();
         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
         reset(mStatsManager);
 
         // Metered change should update ifaces
-        mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         waitForIdle();
         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
         reset(mStatsManager);
 
-        mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        mCellAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         waitForIdle();
         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
         reset(mStatsManager);
 
         // Temp metered change shouldn't update ifaces
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+        mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
         waitForIdle();
         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
         reset(mStatsManager);
 
         // Congested change shouldn't update ifaces
-        mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
+        mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
         waitForIdle();
         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
         reset(mStatsManager);
 
         // Roaming change should update ifaces
-        mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
+        mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
         waitForIdle();
         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
         reset(mStatsManager);
@@ -7401,25 +7488,22 @@
         mMockVpn.establishForMyUid(lp);
         assertUidRangesUpdatedForMyUid(true);
 
-        final List<Network> cellAndVpn =
-                List.of(mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork());
+        final List<Network> cellAndVpn = List.of(mCellAgent.getNetwork(), mMockVpn.getNetwork());
 
         // A VPN with default (null) underlying networks sets the underlying network's interfaces...
         expectNotifyNetworkStatus(cellAndVpn, cellAndVpn, MOBILE_IFNAME, Process.myUid(),
                 VPN_IFNAME, List.of(MOBILE_IFNAME));
 
         // ...and updates them as the default network switches.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        mWiFiAgent.sendLinkProperties(wifiLp);
         final Network[] onlyNull = new Network[]{null};
-        final List<Network> wifiAndVpn =
-                List.of(mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork());
-        final List<Network> cellWifiAndVpn =
-                List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork(),
-                        mMockVpn.getNetwork());
+        final List<Network> wifiAndVpn = List.of(mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
+        final List<Network> cellWifiAndVpn = List.of(mCellAgent.getNetwork(),
+                mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
         final Network[] cellNullAndWifi =
-                new Network[]{mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
+                new Network[] { mCellAgent.getNetwork(), null, mWiFiAgent.getNetwork() };
 
         waitForIdle();
         assertEquals(wifiLp, mService.getActiveLinkProperties());
@@ -7459,9 +7543,9 @@
         // could result in incorrect data usage measurements if the interface used by the
         // disconnected network is reused by a system component that does not register an agent for
         // it (e.g., tethering).
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         waitForIdle();
-        assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork()));
+        assertNull(mService.getLinkProperties(mCellAgent.getNetwork()));
         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
                 VPN_IFNAME, List.of(MOBILE_IFNAME, WIFI_IFNAME));
 
@@ -7477,16 +7561,16 @@
         // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
         // called again, it does. For example, connect Ethernet, but with a low score, such that it
         // does not become the default network.
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
-        mEthernetNetworkAgent.setScore(
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetAgent.setScore(
                 new NetworkScore.Builder().setLegacyInt(30).setExiting(true).build());
-        mEthernetNetworkAgent.connect(false);
+        mEthernetAgent.connect(false);
         waitForIdle();
         verify(mStatsManager).notifyNetworkStatus(any(List.class),
                 any(List.class), any() /* anyString() doesn't match null */,
                 argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1
                         && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0))));
-        mEthernetNetworkAgent.disconnect();
+        mEthernetAgent.disconnect();
         waitForIdle();
         reset(mStatsManager);
 
@@ -7526,18 +7610,17 @@
         final int[] adminUids = new int[] {Process.myUid() + 1};
         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
         ncTemplate.setAdministratorUids(adminUids);
-        mCellNetworkAgent =
+        mCellAgent =
                 new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), ncTemplate);
-        mCellNetworkAgent.connect(false /* validated */);
+        mCellAgent.connect(false /* validated */);
 
         // Verify case where caller has permission
         mServiceContext.setPermission(
                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
         TestNetworkCallback callback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(callback);
-        callback.expect(CallbackEntry.AVAILABLE, mCellNetworkAgent);
-        callback.expectCapabilitiesThat(
-                mCellNetworkAgent, nc -> Arrays.equals(adminUids, nc.getAdministratorUids()));
+        callback.expect(AVAILABLE, mCellAgent);
+        callback.expectCaps(mCellAgent, c -> Arrays.equals(adminUids, c.getAdministratorUids()));
         mCm.unregisterNetworkCallback(callback);
 
         // Verify case where caller does NOT have permission
@@ -7546,9 +7629,8 @@
         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
         callback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(callback);
-        callback.expect(CallbackEntry.AVAILABLE, mCellNetworkAgent);
-        callback.expectCapabilitiesThat(
-                mCellNetworkAgent, nc -> nc.getAdministratorUids().length == 0);
+        callback.expect(AVAILABLE, mCellAgent);
+        callback.expectCaps(mCellAgent, c -> c.getAdministratorUids().length == 0);
     }
 
     @Test
@@ -7565,10 +7647,10 @@
         // Connect a VCN-managed wifi network.
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.connect(true /* validated */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.connect(true /* validated */);
 
         final List<Network> none = List.of();
         expectNotifyNetworkStatus(onlyWifi(), none, null);  // Wifi is not the default network
@@ -7583,7 +7665,7 @@
         final LinkProperties lp = new LinkProperties();
         lp.setInterfaceName(vcnIface);
         final TestNetworkAgentWrapper vcn = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
-        vcn.setUnderlyingNetworks(List.of(mWiFiNetworkAgent.getNetwork()));
+        vcn.setUnderlyingNetworks(List.of(mWiFiAgent.getNetwork()));
         vcn.connect(false /* validated */);
 
         final TestNetworkCallback callback = new TestNetworkCallback();
@@ -7596,12 +7678,12 @@
         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
         final List<Network> onlyVcn = List.of(vcn.getNetwork());
-        final List<Network> vcnAndWifi = List.of(vcn.getNetwork(), mWiFiNetworkAgent.getNetwork());
+        final List<Network> vcnAndWifi = List.of(vcn.getNetwork(), mWiFiAgent.getNetwork());
         expectNotifyNetworkStatus(vcnAndWifi, onlyVcn, vcnIface, ownerUid, vcnIface,
                 List.of(WIFI_IFNAME));
 
         // Add NOT_METERED to the underlying network, check that it is not propagated.
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
         callback.assertNoCallback();
         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
@@ -7609,11 +7691,11 @@
         // Switch underlying networks.
         final LinkProperties cellLp = new LinkProperties();
         cellLp.setInterfaceName(MOBILE_IFNAME);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
-        mCellNetworkAgent.connect(false /* validated */);
-        vcn.setUnderlyingNetworks(List.of(mCellNetworkAgent.getNetwork()));
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+        mCellAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
+        mCellAgent.connect(false /* validated */);
+        vcn.setUnderlyingNetworks(List.of(mCellAgent.getNetwork()));
 
         // The underlying capability changes do not propagate to the virtual network, but
         // NetworkStatsService is informed of the new underlying interface.
@@ -7622,7 +7704,7 @@
         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         final List<Network> vcnWifiAndCell = List.of(vcn.getNetwork(),
-                mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork());
+                mWiFiAgent.getNetwork(), mCellAgent.getNetwork());
         expectNotifyNetworkStatus(vcnWifiAndCell, onlyVcn, vcnIface, ownerUid, vcnIface,
                 List.of(MOBILE_IFNAME));
     }
@@ -7631,7 +7713,7 @@
     public void testBasicDnsConfigurationPushed() throws Exception {
         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         waitForIdle();
         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
         verifyNoMoreInteractions(mMockDnsResolver);
@@ -7647,18 +7729,17 @@
         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
                 MOBILE_IFNAME));
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        mCellNetworkAgent.connect(false);
+        mCellAgent.sendLinkProperties(cellLp);
+        mCellAgent.connect(false);
         waitForIdle();
 
-        verify(mMockDnsResolver, times(1)).createNetworkCache(
-                eq(mCellNetworkAgent.getNetwork().netId));
+        verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
         // CS tells dnsresolver about the empty DNS config for this network.
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
         reset(mMockDnsResolver);
 
         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
-        mCellNetworkAgent.sendLinkProperties(cellLp);
+        mCellAgent.sendLinkProperties(cellLp);
         waitForIdle();
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
                 mResolverParamsParcelCaptor.capture());
@@ -7670,7 +7751,7 @@
         reset(mMockDnsResolver);
 
         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
-        mCellNetworkAgent.sendLinkProperties(cellLp);
+        mCellAgent.sendLinkProperties(cellLp);
         waitForIdle();
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
                 mResolverParamsParcelCaptor.capture());
@@ -7688,7 +7769,7 @@
         final String TLS_SERVER6 = "2001:db8:53::53";
         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
-        mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
+        mCellAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
 
         waitForIdle();
@@ -7709,11 +7790,10 @@
         final TestNetworkCallback callback = new TestNetworkCallback();
         mCm.registerNetworkCallback(request, callback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        verify(mMockDnsResolver, times(1)).createNetworkCache(
-                eq(mWiFiNetworkAgent.getNetwork().netId));
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mWiFiAgent.getNetwork().netId));
         verify(mMockDnsResolver, times(2)).setResolverConfiguration(
                 mResolverParamsParcelCaptor.capture());
         final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
@@ -7729,31 +7809,31 @@
         TestNetworkCallback callback = new TestNetworkCallback();
         mCm.registerNetworkCallback(request, callback);
         // Bring up wifi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         // Private DNS resolution failed, checking if the notification will be shown or not.
-        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
-        mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+        mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
+        mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
         // If network validation failed, NetworkMonitor will re-evaluate the network.
         // ConnectivityService should filter the redundant notification. This part is trying to
         // simulate that situation and check if ConnectivityService could filter that case.
-        mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+        mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
                 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.mNetworkMonitor.forceReevaluation(Process.myUid());
+        mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
+        mWiFiAgent.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.mNetworkMonitor.forceReevaluation(Process.myUid());
+        mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
+        mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
@@ -7769,7 +7849,7 @@
                 .addTransportType(TRANSPORT_CELLULAR).build();
         mCm.requestNetwork(cellRequest, cellNetworkCallback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         waitForIdle();
         // CS tells netd about the empty DNS config for this network.
         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
@@ -7789,11 +7869,10 @@
         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
 
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        mCellNetworkAgent.connect(false);
+        mCellAgent.sendLinkProperties(cellLp);
+        mCellAgent.connect(false);
         waitForIdle();
-        verify(mMockDnsResolver, times(1)).createNetworkCache(
-                eq(mCellNetworkAgent.getNetwork().netId));
+        verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
                 mResolverParamsParcelCaptor.capture());
         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
@@ -7805,12 +7884,11 @@
         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
                 asList("2001:db8::1", "192.0.2.1")));
         reset(mMockDnsResolver);
-        cellNetworkCallback.expect(CallbackEntry.AVAILABLE, mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                mCellNetworkAgent);
+        cellNetworkCallback.expect(AVAILABLE, mCellAgent);
+        cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expect(
-                CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
+                LINK_PROPERTIES_CHANGED, mCellAgent);
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -7841,8 +7919,7 @@
         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
         // Can't test dns configuration for strict mode without properly mocking
         // out the DNS lookups, but can test that LinkProperties is updated.
-        cbi = cellNetworkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                mCellNetworkAgent);
+        cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertTrue(cbi.getLp().isPrivateDnsActive());
         assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
@@ -7868,18 +7945,17 @@
                 .addTransportType(TRANSPORT_CELLULAR).build();
         mCm.requestNetwork(cellRequest, cellNetworkCallback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         waitForIdle();
         LinkProperties lp = new LinkProperties();
-        mCellNetworkAgent.sendLinkProperties(lp);
-        mCellNetworkAgent.connect(false);
+        mCellAgent.sendLinkProperties(lp);
+        mCellAgent.connect(false);
         waitForIdle();
-        cellNetworkCallback.expect(CallbackEntry.AVAILABLE, mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                mCellNetworkAgent);
+        cellNetworkCallback.expect(AVAILABLE, mCellAgent);
+        cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expect(
-                CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        cellNetworkCallback.expect(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
+                LINK_PROPERTIES_CHANGED, mCellAgent);
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -7889,16 +7965,15 @@
         // Send a validation event for a server that is not part of the current
         // resolver config. The validation event should be ignored.
         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
-                makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, "",
+                makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId, "",
                         "145.100.185.18", VALIDATION_RESULT_SUCCESS));
         cellNetworkCallback.assertNoCallback();
 
         // Add a dns server to the LinkProperties.
         LinkProperties lp2 = new LinkProperties(lp);
         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
-        mCellNetworkAgent.sendLinkProperties(lp2);
-        cbi = cellNetworkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(lp2);
+        cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -7908,13 +7983,13 @@
         // Send a validation event containing a hostname that is not part of
         // the current resolver config. The validation event should be ignored.
         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
-                makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
+                makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
                         "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS));
         cellNetworkCallback.assertNoCallback();
 
         // Send a validation event where validation failed.
         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
-                makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
+                makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
                         "145.100.185.16", "", VALIDATION_RESULT_FAILURE));
         cellNetworkCallback.assertNoCallback();
 
@@ -7922,10 +7997,9 @@
         // the current resolver config. A LinkProperties callback with updated
         // private dns fields should be sent.
         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
-                makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
+                makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
                         "145.100.185.16", "", VALIDATION_RESULT_SUCCESS));
-        cbi = cellNetworkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                mCellNetworkAgent);
+        cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertTrue(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -7935,9 +8009,8 @@
         // the network agent sends unrelated changes.
         LinkProperties lp3 = new LinkProperties(lp2);
         lp3.setMtu(1300);
-        mCellNetworkAgent.sendLinkProperties(lp3);
-        cbi = cellNetworkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(lp3);
+        cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertTrue(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -7948,9 +8021,8 @@
         // fields in LinkProperties.
         LinkProperties lp4 = new LinkProperties(lp3);
         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
-        mCellNetworkAgent.sendLinkProperties(lp4);
-        cbi = cellNetworkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(lp4);
+        cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         cellNetworkCallback.assertNoCallback();
         assertFalse(cbi.getLp().isPrivateDnsActive());
         assertNull(cbi.getLp().getPrivateDnsServerName());
@@ -7985,10 +8057,10 @@
 
     @Test
     public void testApplyUnderlyingCapabilities() throws Exception {
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mCellNetworkAgent.connect(false /* validated */);
-        mWiFiNetworkAgent.connect(false /* validated */);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mCellAgent.connect(false /* validated */);
+        mWiFiAgent.connect(false /* validated */);
 
         final NetworkCapabilities cellNc = new NetworkCapabilities()
                 .addTransportType(TRANSPORT_CELLULAR)
@@ -8005,12 +8077,12 @@
                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
                 .setLinkUpstreamBandwidthKbps(20);
-        mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
-        mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
+        mCellAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
+        mWiFiAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
         waitForIdle();
 
-        final Network mobile = mCellNetworkAgent.getNetwork();
-        final Network wifi = mWiFiNetworkAgent.getNetwork();
+        final Network mobile = mCellAgent.getNetwork();
+        final Network wifi = mWiFiAgent.getNetwork();
 
         final NetworkCapabilities initialCaps = new NetworkCapabilities();
         initialCaps.addTransportType(TRANSPORT_VPN);
@@ -8141,9 +8213,7 @@
             mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
             // onCapabilitiesChanged() should be called because
             // NetworkCapabilities#mUnderlyingNetworks is updated.
-            CallbackEntry ce = callback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                    mMockVpn);
-            final NetworkCapabilities vpnNc1 = ((CallbackEntry.CapabilitiesChanged) ce).getCaps();
+            final NetworkCapabilities vpnNc1 = callback.expectCaps(mMockVpn);
             // Since the wifi network hasn't brought up,
             // ConnectivityService#applyUnderlyingCapabilities cannot find it. Update
             // NetworkCapabilities#mUnderlyingNetworks to an empty array, and it will be updated to
@@ -8165,9 +8235,9 @@
 
             // Make that underlying network connect, and expect to see its capabilities immediately
             // reflected in the VPN's capabilities.
-            mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-            assertEquals(wifiNetwork, mWiFiNetworkAgent.getNetwork());
-            mWiFiNetworkAgent.connect(false);
+            mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+            assertEquals(wifiNetwork, mWiFiAgent.getNetwork());
+            mWiFiAgent.connect(false);
             // TODO: the callback for the VPN happens before any callbacks are called for the wifi
             // network that has just connected. There appear to be two issues here:
             // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities()
@@ -8178,23 +8248,22 @@
             // 2. When a network connects, updateNetworkInfo propagates underlying network
             //    capabilities before rematching networks.
             // Given that this scenario can't really happen, this is probably fine for now.
-            ce = callback.expect(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
-            final NetworkCapabilities vpnNc2 = ((CallbackEntry.CapabilitiesChanged) ce).getCaps();
+            final NetworkCapabilities vpnNc2 = callback.expectCaps(mMockVpn);
             // The wifi network is brought up, NetworkCapabilities#mUnderlyingNetworks is updated to
             // it.
             underlyingNetwork.add(wifiNetwork);
             assertEquals(underlyingNetwork, vpnNc2.getUnderlyingNetworks());
-            callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+            callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
                     .hasTransport(TRANSPORT_VPN));
             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
                     .hasTransport(TRANSPORT_WIFI));
 
             // Disconnect the network, and expect to see the VPN capabilities change accordingly.
-            mWiFiNetworkAgent.disconnect();
-            callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-            callback.expectCapabilitiesThat(mMockVpn, (nc) ->
-                    nc.getTransportTypes().length == 1 && nc.hasTransport(TRANSPORT_VPN));
+            mWiFiAgent.disconnect();
+            callback.expect(LOST, mWiFiAgent);
+            callback.expectCaps(mMockVpn, c -> c.getTransportTypes().length == 1
+                            && c.hasTransport(TRANSPORT_VPN));
 
             mMockVpn.disconnect();
             mCm.unregisterNetworkCallback(callback);
@@ -8214,15 +8283,14 @@
 
         // Connect a VPN.
         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
 
         // Connect cellular data.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(false /* validated */);
-        callback.expectCapabilitiesThat(mMockVpn,
-                nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        && nc.hasTransport(TRANSPORT_CELLULAR));
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(false /* validated */);
+        callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                && c.hasTransport(TRANSPORT_CELLULAR));
         callback.assertNoCallback();
 
         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8234,11 +8302,10 @@
         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
 
         // Suspend the cellular network and expect the VPN to be suspended.
-        mCellNetworkAgent.suspend();
-        callback.expectCapabilitiesThat(mMockVpn,
-                nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        && nc.hasTransport(TRANSPORT_CELLULAR));
-        callback.expect(CallbackEntry.SUSPENDED, mMockVpn);
+        mCellAgent.suspend();
+        callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                && c.hasTransport(TRANSPORT_CELLULAR));
+        callback.expect(SUSPENDED, mMockVpn);
         callback.assertNoCallback();
 
         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8251,12 +8318,11 @@
         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
 
         // Switch to another network. The VPN should no longer be suspended.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false /* validated */);
-        callback.expectCapabilitiesThat(mMockVpn,
-                nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        && nc.hasTransport(TRANSPORT_WIFI));
-        callback.expect(CallbackEntry.RESUMED, mMockVpn);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false /* validated */);
+        callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                && c.hasTransport(TRANSPORT_WIFI));
+        callback.expect(RESUMED, mMockVpn);
         callback.assertNoCallback();
 
         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8268,16 +8334,14 @@
         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
 
         // Unsuspend cellular and then switch back to it. The VPN remains not suspended.
-        mCellNetworkAgent.resume();
+        mCellAgent.resume();
         callback.assertNoCallback();
-        mWiFiNetworkAgent.disconnect();
-        callback.expectCapabilitiesThat(mMockVpn,
-                nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        && nc.hasTransport(TRANSPORT_CELLULAR));
+        mWiFiAgent.disconnect();
+        callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                && c.hasTransport(TRANSPORT_CELLULAR));
         // Spurious double callback?
-        callback.expectCapabilitiesThat(mMockVpn,
-                nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        && nc.hasTransport(TRANSPORT_CELLULAR));
+        callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                && c.hasTransport(TRANSPORT_CELLULAR));
         callback.assertNoCallback();
 
         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8289,11 +8353,10 @@
         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
 
         // Suspend cellular and expect no connectivity.
-        mCellNetworkAgent.suspend();
-        callback.expectCapabilitiesThat(mMockVpn,
-                nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        && nc.hasTransport(TRANSPORT_CELLULAR));
-        callback.expect(CallbackEntry.SUSPENDED, mMockVpn);
+        mCellAgent.suspend();
+        callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                && c.hasTransport(TRANSPORT_CELLULAR));
+        callback.expect(SUSPENDED, mMockVpn);
         callback.assertNoCallback();
 
         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8305,11 +8368,10 @@
         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
 
         // Resume cellular and expect that connectivity comes back.
-        mCellNetworkAgent.resume();
-        callback.expectCapabilitiesThat(mMockVpn,
-                nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        && nc.hasTransport(TRANSPORT_CELLULAR));
-        callback.expect(CallbackEntry.RESUMED, mMockVpn);
+        mCellAgent.resume();
+        callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                && c.hasTransport(TRANSPORT_CELLULAR));
+        callback.expect(RESUMED, mMockVpn);
         callback.assertNoCallback();
 
         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8348,14 +8410,14 @@
                 new Handler(ConnectivityThread.getInstanceLooper()));
         defaultCallback.assertNoCallback();
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false);
 
-        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         vpnNetworkCallback.assertNoCallback();
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -8370,7 +8432,7 @@
                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
                         .isVpnValidationRequired(),
                 mMockVpn.getAgent().getNetworkCapabilities()));
-        mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
+        mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
 
         mMockVpn.connect(false);
 
@@ -8381,16 +8443,15 @@
         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
         systemDefaultCallback.assertNoCallback();
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
-        assertEquals(mWiFiNetworkAgent.getNetwork(),
-                systemDefaultCallback.getLastAvailableNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), systemDefaultCallback.getLastAvailableNetwork());
 
         ranges.clear();
         mMockVpn.setUids(ranges);
 
-        genericNetworkCallback.expect(CallbackEntry.LOST, mMockVpn);
+        genericNetworkCallback.expect(LOST, mMockVpn);
         genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
-        vpnNetworkCallback.expect(CallbackEntry.LOST, mMockVpn);
+        vpnNetworkCallback.expect(LOST, mMockVpn);
 
         // TODO : The default network callback should actually get a LOST call here (also see the
         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
@@ -8398,7 +8459,7 @@
         // can't currently update their UIDs without disconnecting, so this does not matter too
         // much, but that is the reason the test here has to check for an update to the
         // capabilities instead of the expected LOST then AVAILABLE.
-        defaultCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
+        defaultCallback.expectCaps(mMockVpn);
         systemDefaultCallback.assertNoCallback();
 
         ranges.add(new UidRange(uid, uid));
@@ -8410,25 +8471,25 @@
         vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
         // happen outside of the test, ConnectivityService does not rematch callbacks.
-        defaultCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
+        defaultCallback.expectCaps(mMockVpn);
         systemDefaultCallback.assertNoCallback();
 
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
 
-        genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        genericNotVpnNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        genericNetworkCallback.expect(LOST, mWiFiAgent);
+        genericNotVpnNetworkCallback.expect(LOST, mWiFiAgent);
+        wifiNetworkCallback.expect(LOST, mWiFiAgent);
         vpnNetworkCallback.assertNoCallback();
         defaultCallback.assertNoCallback();
-        systemDefaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        systemDefaultCallback.expect(LOST, mWiFiAgent);
 
         mMockVpn.disconnect();
 
-        genericNetworkCallback.expect(CallbackEntry.LOST, mMockVpn);
+        genericNetworkCallback.expect(LOST, mMockVpn);
         genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
-        vpnNetworkCallback.expect(CallbackEntry.LOST, mMockVpn);
-        defaultCallback.expect(CallbackEntry.LOST, mMockVpn);
+        vpnNetworkCallback.expect(LOST, mMockVpn);
+        defaultCallback.expect(LOST, mMockVpn);
         systemDefaultCallback.assertNoCallback();
         assertEquals(null, mCm.getActiveNetwork());
 
@@ -8446,14 +8507,14 @@
         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultCallback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
 
-        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         defaultCallback.assertNoCallback();
@@ -8472,22 +8533,22 @@
         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultCallback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
 
-        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
         mMockVpn.disconnect();
-        defaultCallback.expect(CallbackEntry.LOST, mMockVpn);
-        defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+        defaultCallback.expect(LOST, mMockVpn);
+        defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
 
         mCm.unregisterNetworkCallback(defaultCallback);
     }
@@ -8498,14 +8559,14 @@
         mCm.registerDefaultNetworkCallback(callback);
 
         // Bring up Ethernet.
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
-        mEthernetNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
         callback.assertNoCallback();
 
         // 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,16 +8588,16 @@
                 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.
-        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mMockVpn);
+        callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         callback.assertNoCallback();
 
         mMockVpn.disconnect();
-        callback.expect(CallbackEntry.LOST, mMockVpn);
-        callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
+        callback.expect(LOST, mMockVpn);
+        callback.expectAvailableCallbacksValidated(mEthernetAgent);
     }
 
     @Test
@@ -8553,18 +8614,18 @@
 
         // Connect cell. It will become the default network, and in the absence of setting
         // underlying networks explicitly it will become the sole underlying network for the vpn.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        mCellAgent.connect(true);
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
                 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn.getNetwork(), TIMEOUT_MS,
-                nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
+        vpnNetworkCallback.expectCaps(mMockVpn.getNetwork(), TIMEOUT_MS,
+                c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
 
         final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
         assertTrue(nc.hasTransport(TRANSPORT_VPN));
@@ -8602,7 +8663,7 @@
         vpnNetworkCallback.assertNoCallback();
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
@@ -8620,130 +8681,136 @@
         assertDefaultNetworkCapabilities(userId /* no networks */);
 
         // Connect cell and use it as an underlying network.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        mCellAgent.connect(true);
+
+        mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
+
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mCellAgent);
+
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        mWiFiAgent.connect(true);
 
         mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork() });
+                new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
-
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
-        mWiFiNetworkAgent.connect(true);
-
-        mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
-
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
 
         // Don't disconnect, but note the VPN is not using wifi any more.
-        mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork() });
+        mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
         // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
         // network (wifi) as well as the underlying networks (cell).
-        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
+        assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
 
         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        vpnNetworkCallback.expect(CallbackEntry.SUSPENDED, mMockVpn);
+        mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
 
         // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        vpnNetworkCallback.expect(CallbackEntry.RESUMED, mMockVpn);
+        mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        vpnNetworkCallback.expect(RESUMED, mMockVpn);
 
         // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
-        mMockVpn.setUnderlyingNetworks(
-                new Network[] { mWiFiNetworkAgent.getNetwork() });
+        mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && !c.hasTransport(TRANSPORT_CELLULAR)
+                        && c.hasTransport(TRANSPORT_WIFI)
+                        && c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mWiFiAgent);
 
         // Use both again.
         mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
+                new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
 
         // Cell is suspended again. As WiFi is not, this should not cause a callback.
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
         vpnNetworkCallback.assertNoCallback();
 
         // Stop using WiFi. The VPN is suspended again.
-        mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork() });
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        vpnNetworkCallback.expect(CallbackEntry.SUSPENDED, mMockVpn);
-        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
+        mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
+        assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
 
         // Use both again.
         mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
+                new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
-                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-        vpnNetworkCallback.expect(CallbackEntry.RESUMED, mMockVpn);
-        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+                        && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        vpnNetworkCallback.expect(RESUMED, mMockVpn);
+        assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
 
         // Disconnect cell. Receive update without even removing the dead network from the
         // underlying networks – it's dead anyway. Not metered any more.
-        mCellNetworkAgent.disconnect();
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
-        assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
+        mCellAgent.disconnect();
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && !c.hasTransport(TRANSPORT_CELLULAR)
+                        && c.hasTransport(TRANSPORT_WIFI)
+                        && c.hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertDefaultNetworkCapabilities(userId, mWiFiAgent);
 
         // Disconnect wifi too. No underlying networks means this is now metered.
-        mWiFiNetworkAgent.disconnect();
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        mWiFiAgent.disconnect();
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && !c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
         // When a network disconnects, the callbacks are fired before all state is updated, so for a
         // short time, synchronous calls will behave as if the network is still connected. Wait for
         // things to settle.
@@ -8767,7 +8834,7 @@
         vpnNetworkCallback.assertNoCallback();
 
         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
-                false /* isStrictMode */);
+                false /* privateDnsProbeSent */);
         assertUidRangesUpdatedForMyUid(true);
 
         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
@@ -8781,35 +8848,38 @@
         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
 
         // Connect to Cell; Cell is the default network.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
 
         // Connect to WiFi; WiFi is the new default.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.connect(true);
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && !c.hasTransport(TRANSPORT_CELLULAR)
+                        && c.hasTransport(TRANSPORT_WIFI)
+                        && c.hasCapability(NET_CAPABILITY_NOT_METERED));
 
         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
         // the capabilities.
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
 
         // Disconnect wifi too. Now we have no default network.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
 
-        vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
-                (caps) -> caps.hasTransport(TRANSPORT_VPN)
-                && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        vpnNetworkCallback.expectCaps(mMockVpn,
+                c -> c.hasTransport(TRANSPORT_VPN)
+                        && !c.hasTransport(TRANSPORT_CELLULAR)
+                        && !c.hasTransport(TRANSPORT_WIFI)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
 
         mMockVpn.disconnect();
     }
@@ -8825,6 +8895,14 @@
         final TestNetworkCallback callback = new TestNetworkCallback();
         mCm.registerNetworkCallback(request, callback);
 
+        // File a VPN request to prevent VPN network being lingered.
+        final NetworkRequest vpnRequest = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_VPN)
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
+                .build();
+        final TestNetworkCallback vpnCallback = new TestNetworkCallback();
+        mCm.requestNetwork(vpnRequest, vpnCallback);
+
         // Bring up a VPN
         mMockVpn.establishForMyUid();
         assertUidRangesUpdatedForMyUid(true);
@@ -8838,14 +8916,12 @@
         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
 
         // Set an underlying network and expect to see the VPN transports change.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expectCapabilitiesThat(mMockVpn, (caps)
-                -> caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_WIFI));
-        callback.expectCapabilitiesThat(mWiFiNetworkAgent, (caps)
-                -> caps.hasCapability(NET_CAPABILITY_VALIDATED));
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expectCaps(mMockVpn, c -> c.hasTransport(TRANSPORT_VPN)
+                        && c.hasTransport(TRANSPORT_WIFI));
+        callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
 
         doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
                 .getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
@@ -8856,35 +8932,38 @@
         // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
         // restricted user.
         final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
-        final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop);
-        final Range<Integer> singleUidRange = new Range<Integer>(uid, uid);
-        callback.expectCapabilitiesThat(mMockVpn, (caps)
-                -> caps.getUids().size() == 2
-                && caps.getUids().contains(singleUidRange)
-                && caps.getUids().contains(restrictUidRange)
-                && caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_WIFI));
+        final Range<Integer> restrictUidRange = new Range<>(rRange.start, rRange.stop);
+        final Range<Integer> singleUidRange = new Range<>(uid, uid);
+        callback.expectCaps(mMockVpn, c ->
+                c.getUids().size() == 2
+                && c.getUids().contains(singleUidRange)
+                && c.getUids().contains(restrictUidRange)
+                && c.hasTransport(TRANSPORT_VPN)
+                && c.hasTransport(TRANSPORT_WIFI));
 
         // Change the VPN's capabilities somehow (specifically, disconnect wifi).
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        callback.expectCapabilitiesThat(mMockVpn, (caps)
-                -> caps.getUids().size() == 2
-                && caps.getUids().contains(singleUidRange)
-                && caps.getUids().contains(restrictUidRange)
-                && caps.hasTransport(TRANSPORT_VPN)
-                && !caps.hasTransport(TRANSPORT_WIFI));
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        callback.expectCaps(mMockVpn, c ->
+                c.getUids().size() == 2
+                && c.getUids().contains(singleUidRange)
+                && c.getUids().contains(restrictUidRange)
+                && c.hasTransport(TRANSPORT_VPN)
+                && !c.hasTransport(TRANSPORT_WIFI));
 
         // User removed and expect to lose the UID range for the restricted user.
         mMockVpn.onUserRemoved(RESTRICTED_USER);
 
         // Expect that the VPN gains the UID range for the restricted user, and that the capability
         // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
-        callback.expectCapabilitiesThat(mMockVpn, (caps)
-                -> caps.getUids().size() == 1
-                && caps.getUids().contains(singleUidRange)
-                && caps.hasTransport(TRANSPORT_VPN)
-                && !caps.hasTransport(TRANSPORT_WIFI));
+        callback.expectCaps(mMockVpn, c ->
+                c.getUids().size() == 1
+                && c.getUids().contains(singleUidRange)
+                && c.hasTransport(TRANSPORT_VPN)
+                && !c.hasTransport(TRANSPORT_WIFI));
+
+        mCm.unregisterNetworkCallback(callback);
+        mCm.unregisterNetworkCallback(vpnCallback);
     }
 
     @Test
@@ -8907,8 +8986,8 @@
         final int uid = Process.myUid();
 
         // Connect wifi and check that UIDs in the main and restricted profiles have network access.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true /* validated */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true /* validated */);
         final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */);
         assertNotNull(mCm.getActiveNetworkForUid(uid));
         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
@@ -8957,9 +9036,9 @@
     public void testIsActiveNetworkMeteredOverWifi() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.connect(true);
         waitForIdle();
 
         assertFalse(mCm.isActiveNetworkMetered());
@@ -8969,9 +9048,9 @@
     public void testIsActiveNetworkMeteredOverCell() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        mCellAgent.connect(true);
         waitForIdle();
 
         assertTrue(mCm.isActiveNetworkMetered());
@@ -8981,9 +9060,9 @@
     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        mCellAgent.connect(true);
         waitForIdle();
         assertTrue(mCm.isActiveNetworkMetered());
 
@@ -8998,9 +9077,9 @@
         assertTrue(mCm.isActiveNetworkMetered());
 
         // Connect WiFi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.connect(true);
         waitForIdle();
         // VPN should still be the active network.
         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
@@ -9009,13 +9088,13 @@
         assertFalse(mCm.isActiveNetworkMetered());
 
         // Disconnecting Cell should not affect VPN's meteredness.
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         waitForIdle();
 
         assertFalse(mCm.isActiveNetworkMetered());
 
         // Disconnect WiFi; Now there is no platform default network.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         waitForIdle();
 
         // VPN without any underlying networks is treated as metered.
@@ -9028,15 +9107,15 @@
     public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        mCellAgent.connect(true);
         waitForIdle();
         assertTrue(mCm.isActiveNetworkMetered());
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.connect(true);
         waitForIdle();
         assertFalse(mCm.isActiveNetworkMetered());
 
@@ -9047,16 +9126,14 @@
         // Ensure VPN is now the active network.
         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
         // VPN is using Cell
-        mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork() });
+        mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
         waitForIdle();
 
         // Expect VPN to be metered.
         assertTrue(mCm.isActiveNetworkMetered());
 
         // VPN is now using WiFi
-        mMockVpn.setUnderlyingNetworks(
-                new Network[] { mWiFiNetworkAgent.getNetwork() });
+        mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
         waitForIdle();
 
         // Expect VPN to be unmetered
@@ -9064,7 +9141,7 @@
 
         // VPN is using Cell | WiFi.
         mMockVpn.setUnderlyingNetworks(
-                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
+                new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
         waitForIdle();
 
         // Expect VPN to be metered.
@@ -9072,7 +9149,7 @@
 
         // VPN is using WiFi | Cell.
         mMockVpn.setUnderlyingNetworks(
-                new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
+                new Network[] { mWiFiAgent.getNetwork(), mCellAgent.getNetwork() });
         waitForIdle();
 
         // Order should not matter and VPN should still be metered.
@@ -9092,9 +9169,9 @@
     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.connect(true);
         waitForIdle();
         assertFalse(mCm.isActiveNetworkMetered());
 
@@ -9114,8 +9191,7 @@
 
 
         // VPN explicitly declares WiFi as its underlying network.
-        mMockVpn.setUnderlyingNetworks(
-                new Network[] { mWiFiNetworkAgent.getNetwork() });
+        mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
         waitForIdle();
 
         // Doesn't really matter whether VPN declares its underlying networks explicitly.
@@ -9123,7 +9199,7 @@
 
         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
         // anyways suppose to be metered.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         waitForIdle();
 
         assertTrue(mCm.isActiveNetworkMetered());
@@ -9135,11 +9211,6 @@
         public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) {
             super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS);
         }
-        public void expectBlockedStatusCallback(HasNetwork n, int blockedStatus) {
-            // This doesn't work:
-            // super.expectBlockedStatusCallback(blockedStatus, n.getNetwork());
-            super.expectBlockedStatusCallback(blockedStatus, n.getNetwork(), TIMEOUT_MS);
-        }
         public void onBlockedStatusChanged(Network network, int blockedReasons) {
             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
         }
@@ -9157,80 +9228,83 @@
 
         mockUidNetworkingBlocked();
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        detailedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent,
-                BLOCKED_REASON_NONE);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        detailedCallback.expectAvailableThenValidatedCallbacks(mCellAgent, BLOCKED_REASON_NONE);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mCellNetworkAgent);
+        assertExtraInfoFromCmPresent(mCellAgent);
 
         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
-        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
-                BLOCKED_REASON_BATTERY_SAVER);
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_REASON_BATTERY_SAVER);
         assertNull(mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
-        assertExtraInfoFromCmBlocked(mCellNetworkAgent);
+        assertExtraInfoFromCmBlocked(mCellAgent);
 
         // If blocked state does not change but blocked reason does, the boolean callback is called.
         // TODO: investigate de-duplicating.
         setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED);
-        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
-                BLOCKED_METERED_REASON_USER_RESTRICTED);
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_METERED_REASON_USER_RESTRICTED);
 
         setBlockedReasonChanged(BLOCKED_REASON_NONE);
-        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_REASON_NONE);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mCellNetworkAgent);
+        assertExtraInfoFromCmPresent(mCellAgent);
 
         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
-        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
-                BLOCKED_METERED_REASON_DATA_SAVER);
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
         assertNull(mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
-        assertExtraInfoFromCmBlocked(mCellNetworkAgent);
+        assertExtraInfoFromCmBlocked(mCellAgent);
 
         // Restrict the network based on UID rule and NOT_METERED capability change.
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
-        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
-        detailedCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        cellNetworkCallback.expectCaps(mCellAgent,
+                c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+        detailedCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_REASON_NONE);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mCellNetworkAgent);
+        assertExtraInfoFromCmPresent(mCellAgent);
 
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
-        cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
-                mCellNetworkAgent);
-        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
-        detailedCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
-                mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
-                BLOCKED_METERED_REASON_DATA_SAVER);
+        mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        cellNetworkCallback.expectCaps(mCellAgent,
+                c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+        detailedCallback.expectCaps(mCellAgent,
+                c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
         assertNull(mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
-        assertExtraInfoFromCmBlocked(mCellNetworkAgent);
+        assertExtraInfoFromCmBlocked(mCellAgent);
 
         setBlockedReasonChanged(BLOCKED_REASON_NONE);
-        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_REASON_NONE);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mCellNetworkAgent);
+        assertExtraInfoFromCmPresent(mCellAgent);
 
         setBlockedReasonChanged(BLOCKED_REASON_NONE);
         cellNetworkCallback.assertNoCallback();
@@ -9238,30 +9312,31 @@
 
         // Restrict background data. Networking is not blocked because the network is unmetered.
         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
-        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
-                BLOCKED_METERED_REASON_DATA_SAVER);
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
         assertNull(mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
-        assertExtraInfoFromCmBlocked(mCellNetworkAgent);
+        assertExtraInfoFromCmBlocked(mCellAgent);
         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
         cellNetworkCallback.assertNoCallback();
 
         setBlockedReasonChanged(BLOCKED_REASON_NONE);
-        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
-        detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
+        cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+        detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+                cb -> cb.getReason() == BLOCKED_REASON_NONE);
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mCellNetworkAgent);
+        assertExtraInfoFromCmPresent(mCellAgent);
 
         setBlockedReasonChanged(BLOCKED_REASON_NONE);
         cellNetworkCallback.assertNoCallback();
         detailedCallback.assertNoCallback();
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mCellNetworkAgent);
+        assertExtraInfoFromCmPresent(mCellAgent);
 
         mCm.unregisterNetworkCallback(cellNetworkCallback);
     }
@@ -9278,34 +9353,34 @@
         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
         defaultCallback.assertNoCallback();
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
-        defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
+        defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
 
         // Allow to use the network after switching to NOT_METERED network.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.connect(true);
-        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.connect(true);
+        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
 
         // Switch to METERED network. Restrict the use of the network.
-        mWiFiNetworkAgent.disconnect();
-        defaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
+        mWiFiAgent.disconnect();
+        defaultCallback.expect(LOST, mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellAgent);
 
         // Network becomes NOT_METERED.
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
-        defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
+        mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
+        defaultCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
 
         // Verify there's no Networkcallbacks invoked after data saver on/off.
         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
         setBlockedReasonChanged(BLOCKED_REASON_NONE);
         defaultCallback.assertNoCallback();
 
-        mCellNetworkAgent.disconnect();
-        defaultCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        defaultCallback.expect(LOST, mCellAgent);
         defaultCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(defaultCallback);
@@ -9369,7 +9444,7 @@
 
         // Expect exactly one blocked callback for each agent.
         for (int i = 0; i < agents.length; i++) {
-            final CallbackEntry e = callback.expect(CallbackEntry.BLOCKED_STATUS, TIMEOUT_MS,
+            final CallbackEntry e = callback.expect(BLOCKED_STATUS, TIMEOUT_MS,
                     c -> c.getBlocked() == blocked);
             final Network network = e.getNetwork();
             assertTrue("Received unexpected blocked callback for network " + network,
@@ -9422,14 +9497,14 @@
         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
 
         // Connect a network when lockdown is active, expect to see it blocked.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(false /* validated */);
-        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
-        vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
+        vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
         assertNull(mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
         // Mobile is BLOCKED even though it's not actually connected.
@@ -9438,14 +9513,14 @@
 
         // Disable lockdown, expect to see the network unblocked.
         mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
-        callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
-        defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
+        callback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
+        defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcels);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -9467,22 +9542,22 @@
         final UidRangeParcel[] uidRangeParcelsAlsoExcludingUs = uidRangeParcelsExcludingUids(
                 excludedUids.toArray(new Integer[0]));
         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcelsAlsoExcludingUs);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
 
         // Connect a new network, expect it to be unblocked.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(false /* validated */);
-        callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidated(mCellAgent);
         defaultCallback.assertNoCallback();
-        vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
@@ -9497,12 +9572,12 @@
         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
         waitForIdle();
         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
-        defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
-        assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
+        defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
+        assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
         assertNull(mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
@@ -9510,13 +9585,13 @@
 
         // Disable lockdown. Everything is unblocked.
         mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
-        defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
-        assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent);
+        defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
+        assertBlockedCallbackInAnyOrder(callback, false, mWiFiAgent, mCellAgent);
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -9530,8 +9605,8 @@
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -9543,20 +9618,20 @@
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
 
         // Enable lockdown and connect a VPN. The VPN is not blocked.
         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
-        defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
-        assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
+        defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
+        assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
         assertNull(mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
@@ -9569,15 +9644,15 @@
         vpnUidDefaultCallback.assertNoCallback();  // VPN does not apply to VPN_UID
         vpnDefaultCallbackAsUid.assertNoCallback();
         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
 
         mMockVpn.disconnect();
-        defaultCallback.expect(CallbackEntry.LOST, mMockVpn);
-        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+        defaultCallback.expect(LOST, mMockVpn);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
@@ -9596,8 +9671,8 @@
         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
 
         // Connect Wi-Fi.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true /* validated */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true /* validated */);
 
         // Connect a VPN that excludes its UID from its UID ranges.
         final LinkProperties lp = new LinkProperties();
@@ -9606,7 +9681,7 @@
         final Set<UidRange> ranges = new ArraySet<>();
         ranges.add(new UidRange(0, myUid - 1));
         ranges.add(new UidRange(myUid + 1, UserHandle.PER_USER_RANGE - 1));
-        mMockVpn.setUnderlyingNetworks(new Network[]{mWiFiNetworkAgent.getNetwork()});
+        mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
         mMockVpn.establish(lp, myUid, ranges);
 
         // Wait for validation before registering callbacks.
@@ -9628,8 +9703,8 @@
         perUidCb.expectAvailableCallbacksValidated(mMockVpn);
         // getActiveNetwork is not affected by this bug.
         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetworkForUid(myUid + 1));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(myUid));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(myUid));
 
         doAsUid(otherUid, () -> mCm.unregisterNetworkCallback(otherUidCb));
         mCm.unregisterNetworkCallback(defaultCb);
@@ -9712,11 +9787,11 @@
         cellLp.setInterfaceName("rmnet0");
         cellLp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, "rmnet0"));
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(false /* validated */);
-        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
-        systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
+        systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
         waitForIdle();
         assertNull(mMockVpn.getAgent());
 
@@ -9725,37 +9800,36 @@
         // TODO: consider fixing this.
         cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25"));
         cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        callback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        systemDefaultCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED,
-                mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(cellLp);
+        callback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
+        defaultCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
+        systemDefaultCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         waitForIdle();
         assertNull(mMockVpn.getAgent());
 
         // Disconnect, then try again with a network that supports IPv4 at connection time.
         // Expect lockdown VPN to come up.
         ExpectedBroadcast b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
-        mCellNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        defaultCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        systemDefaultCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        callback.expect(LOST, mCellAgent);
+        defaultCallback.expect(LOST, mCellAgent);
+        systemDefaultCallback.expect(LOST, mCellAgent);
         b1.expectBroadcast();
 
         // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
         // with the state of the VPN network. So expect a CONNECTING broadcast.
         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(false /* validated */);
-        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
-        systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
+        systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
         b1.expectBroadcast();
         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
-        assertExtraInfoFromCmBlocked(mCellNetworkAgent);
+        assertExtraInfoFromCmBlocked(mCellAgent);
 
         // TODO: it would be nice if we could simply rely on the production code here, and have
         // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with
@@ -9773,7 +9847,7 @@
         mMockVpn.expectStartLegacyVpnRunner();
         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
         ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
-        establishLegacyLockdownVpn(mCellNetworkAgent.getNetwork());
+        establishLegacyLockdownVpn(mCellAgent.getNetwork());
         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
         systemDefaultCallback.assertNoCallback();
@@ -9784,7 +9858,7 @@
         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mCellNetworkAgent);
+        assertExtraInfoFromCmPresent(mCellAgent);
         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
         assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
         assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
@@ -9799,13 +9873,13 @@
         final NetworkCapabilities wifiNc = new NetworkCapabilities();
         wifiNc.addTransportType(TRANSPORT_WIFI);
         wifiNc.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
 
         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
         // Wifi is CONNECTING because the VPN isn't up yet.
         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
         ExpectedBroadcast b3 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
-        mWiFiNetworkAgent.connect(false /* validated */);
+        mWiFiAgent.connect(false /* validated */);
         b1.expectBroadcast();
         b2.expectBroadcast();
         b3.expectBroadcast();
@@ -9816,23 +9890,23 @@
         // connected, so the network is not considered blocked by the lockdown UID ranges? But the
         // fact that a VPN is connected should only result in the VPN itself being unblocked, not
         // any other network. Bug in isUidBlockedByVpn?
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        callback.expect(CallbackEntry.LOST, mMockVpn);
-        defaultCallback.expect(CallbackEntry.LOST, mMockVpn);
-        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
-        systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        callback.expect(LOST, mMockVpn);
+        defaultCallback.expect(LOST, mMockVpn);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
+        systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         // While the VPN is reconnecting on the new network, everything is blocked.
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
-        assertExtraInfoFromCmBlocked(mWiFiNetworkAgent);
+        assertExtraInfoFromCmBlocked(mWiFiAgent);
 
         // The VPN comes up again on wifi.
         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
-        establishLegacyLockdownVpn(mWiFiNetworkAgent.getNetwork());
+        establishLegacyLockdownVpn(mWiFiAgent.getNetwork());
         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
         systemDefaultCallback.assertNoCallback();
@@ -9842,7 +9916,7 @@
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mWiFiNetworkAgent);
+        assertExtraInfoFromCmPresent(mWiFiAgent);
         vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
         assertTrue(vpnNc.hasTransport(TRANSPORT_WIFI));
@@ -9850,8 +9924,8 @@
         assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
 
         // Disconnect cell. Nothing much happens since it's not the default network.
-        mCellNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        callback.expect(LOST, mCellAgent);
         defaultCallback.assertNoCallback();
         systemDefaultCallback.assertNoCallback();
 
@@ -9859,17 +9933,17 @@
         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
-        assertExtraInfoFromCmPresent(mWiFiNetworkAgent);
+        assertExtraInfoFromCmPresent(mWiFiAgent);
 
         b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
         b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        systemDefaultCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
+        systemDefaultCallback.expect(LOST, mWiFiAgent);
         b1.expectBroadcast();
-        callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI));
+        callback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
         mMockVpn.expectStopVpnRunnerPrivileged();
-        callback.expect(CallbackEntry.LOST, mMockVpn);
+        callback.expect(LOST, mMockVpn);
         b2.expectBroadcast();
 
         VMSHandlerThread.quitSafely();
@@ -10016,32 +10090,32 @@
                     callbackWithoutCap);
 
             // Setup networks with testing capability and verify the default network changes.
-            mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-            mCellNetworkAgent.addCapability(testCap);
-            mCellNetworkAgent.connect(true);
-            callbackWithCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-            callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-            verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
+            mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+            mCellAgent.addCapability(testCap);
+            mCellAgent.connect(true);
+            callbackWithCap.expectAvailableThenValidatedCallbacks(mCellAgent);
+            callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellAgent);
+            verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
             reset(mMockNetd);
 
-            mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-            mWiFiNetworkAgent.addCapability(testCap);
-            mWiFiNetworkAgent.connect(true);
-            callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-            callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
-            verify(mMockNetd).networkSetDefault(eq(mWiFiNetworkAgent.getNetwork().netId));
+            mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+            mWiFiAgent.addCapability(testCap);
+            mWiFiAgent.connect(true);
+            callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+            callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
+            verify(mMockNetd).networkSetDefault(eq(mWiFiAgent.getNetwork().netId));
             reset(mMockNetd);
 
             // Remove the testing capability on wifi, verify the callback and default network
             // changes back to cellular.
-            mWiFiNetworkAgent.removeCapability(testCap);
-            callbackWithCap.expectAvailableCallbacksValidated(mCellNetworkAgent);
-            callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiNetworkAgent);
-            verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
+            mWiFiAgent.removeCapability(testCap);
+            callbackWithCap.expectAvailableCallbacksValidated(mCellAgent);
+            callbackWithoutCap.expectCaps(mWiFiAgent, c -> !c.hasCapability(testCap));
+            verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
             reset(mMockNetd);
 
-            mCellNetworkAgent.removeCapability(testCap);
-            callbackWithCap.expect(CallbackEntry.LOST, mCellNetworkAgent);
+            mCellAgent.removeCapability(testCap);
+            callbackWithCap.expect(LOST, mCellAgent);
             callbackWithoutCap.assertNoCallback();
             verify(mMockNetd).networkClearDefault();
 
@@ -10054,8 +10128,8 @@
     public final void testBatteryStatsNetworkType() throws Exception {
         final LinkProperties cellLp = new LinkProperties();
         cellLp.setInterfaceName("cell0");
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(true);
         waitForIdle();
         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
                 mDeps.mReportedInterfaceHistory.newReadHead();
@@ -10065,24 +10139,24 @@
 
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName("wifi0");
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connect(true);
         waitForIdle();
         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
                 wifiLp.getInterfaceName(),
                 new int[] { TRANSPORT_WIFI })));
 
-        mCellNetworkAgent.disconnect();
-        mWiFiNetworkAgent.disconnect();
+        mCellAgent.disconnect();
+        mWiFiAgent.disconnect();
 
         cellLp.setInterfaceName("wifi0");
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(true);
         waitForIdle();
         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
                 cellLp.getInterfaceName(),
                 new int[] { TRANSPORT_CELLULAR })));
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
     }
 
     /**
@@ -10203,12 +10277,12 @@
         cellLp.addLinkAddress(myIpv6);
         cellLp.addRoute(ipv6Default);
         cellLp.addRoute(ipv6Subnet);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
         reset(mClatCoordinator);
 
         // Connect with ipv6 link properties. Expect prefix discovery to be started.
-        mCellNetworkAgent.connect(true);
-        int cellNetId = mCellNetworkAgent.getNetwork().netId;
+        mCellAgent.connect(true);
+        int cellNetId = mCellAgent.getNetwork().netId;
         waitForIdle();
 
         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
@@ -10222,7 +10296,7 @@
                 cellLp.getInterfaceName(),
                 new int[] { TRANSPORT_CELLULAR })));
 
-        networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
 
         // Switching default network updates TCP buffer sizes.
@@ -10230,8 +10304,8 @@
         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
         // the NAT64 prefix was removed because one was never discovered.
         cellLp.addLinkAddress(myIpv4);
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(cellLp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         assertRoutesAdded(cellNetId, ipv4Subnet);
         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
@@ -10253,37 +10327,37 @@
 
         // Remove IPv4 address. Expect prefix discovery to be started again.
         cellLp.removeLinkAddress(myIpv4);
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(cellLp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
         assertRoutesRemoved(cellNetId, ipv4Subnet);
 
         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
-        Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
-        assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
+        Nat464Xlat clat = getNat464Xlat(mCellAgent);
+        assertNull(mCm.getLinkProperties(mCellAgent.getNetwork()).getNat64Prefix());
         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
         LinkProperties lpBeforeClat = networkCallback.expect(
-                CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
+                LINK_PROPERTIES_CHANGED, mCellAgent).getLp();
         assertEquals(0, lpBeforeClat.getStackedLinks().size());
         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
 
         // Clat iface comes up. Expect stacked link to be added.
         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
+        List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellAgent.getNetwork())
                 .getStackedLinks();
         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
         assertRoutesAdded(cellNetId, stackedDefault);
         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
         // Change trivial linkproperties and see if stacked link is preserved.
         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(cellLp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
 
         List<LinkProperties> stackedLpsAfterChange =
-                mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
+                mCm.getLinkProperties(mCellAgent.getNetwork()).getStackedLinks();
         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
 
@@ -10306,19 +10380,19 @@
         // Expect clatd to be stopped and started with the new prefix.
         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
                 cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96));
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getStackedLinks().size() == 0);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getStackedLinks().size() == 0);
         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
         assertRoutesRemoved(cellNetId, stackedDefault);
         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
 
         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId,
                 kOtherNat64Prefix.toString());
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getNat64Prefix().equals(kOtherNat64Prefix));
         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getStackedLinks().size() == 1);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getStackedLinks().size() == 1);
         assertRoutesAdded(cellNetId, stackedDefault);
         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
         reset(mMockNetd);
@@ -10328,15 +10402,15 @@
         // linkproperties are cleaned up.
         cellLp.addLinkAddress(myIpv4);
         cellLp.addRoute(ipv4Subnet);
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(cellLp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         assertRoutesAdded(cellNetId, ipv4Subnet);
         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
 
         // As soon as stop is called, the linkproperties lose the stacked interface.
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
-        LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
+        LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellAgent.getNetwork());
         LinkProperties expected = new LinkProperties(cellLp);
         expected.setNat64Prefix(kOtherNat64Prefix);
         assertEquals(expected, actualLpAfterIpv4);
@@ -10359,49 +10433,56 @@
         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
                 cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96));
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getNat64Prefix() == null);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getNat64Prefix() == null);
 
         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
         cellLp.removeLinkAddress(myIpv4);
         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(cellLp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         assertRoutesRemoved(cellNetId, ipv4Subnet);  // Directly-connected routes auto-added.
         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
                 cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
 
         // Clat iface comes up. Expect stacked link to be added.
         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getStackedLinks().size() == 1
+                        && cb.getLp().getNat64Prefix() != null);
         assertRoutesAdded(cellNetId, stackedDefault);
         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
 
         // NAT64 prefix is removed. Expect that clat is stopped.
         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
                 cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96));
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getStackedLinks().size() == 0
+                        && cb.getLp().getNat64Prefix() == null);
         assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
 
         // Stop has no effect because clat is already stopped.
         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getStackedLinks().size() == 0);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getStackedLinks().size() == 0);
         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
         verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME);
         // Clean up.
-        mCellNetworkAgent.disconnect();
-        networkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        networkCallback.expect(LOST, mCellAgent);
         networkCallback.assertNoCallback();
         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_CELLULAR)));
         verify(mMockNetd).networkDestroy(cellNetId);
+        if (SdkLevel.isAtLeastU()) {
+            verify(mMockNetd).setNetworkAllowlist(any());
+        } else {
+            verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
         verifyNoMoreInteractions(mMockNetd);
         verifyNoMoreInteractions(mClatCoordinator);
         reset(mMockNetd);
@@ -10413,21 +10494,21 @@
         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
         cellLp.setNat64Prefix(kNat64Prefix);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(false /* validated */);
-        networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        cellNetId = mCellNetworkAgent.getNetwork().netId;
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(false /* validated */);
+        networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        cellNetId = mCellAgent.getNetwork().netId;
         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
                 INetd.PERMISSION_NONE));
         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
 
         // Clatd is started and clat iface comes up. Expect stacked link to be added.
         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
-        clat = getNat464Xlat(mCellNetworkAgent);
+        clat = getNat464Xlat(mCellAgent);
         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true /* up */);
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                (lp) -> lp.getStackedLinks().size() == 1
-                        && lp.getNat64Prefix().equals(kNat64Prefix));
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                cb -> cb.getLp().getStackedLinks().size() == 1
+                        && cb.getLp().getNat64Prefix().equals(kNat64Prefix));
         verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
         // assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again.
         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault);
@@ -10435,22 +10516,28 @@
         reset(mClatCoordinator);
 
         // Disconnect the network. clat is stopped and the network is destroyed.
-        mCellNetworkAgent.disconnect();
-        networkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        networkCallback.expect(LOST, mCellAgent);
         networkCallback.assertNoCallback();
         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
         verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_CELLULAR)));
         verify(mMockNetd).networkDestroy(cellNetId);
+        if (SdkLevel.isAtLeastU()) {
+            verify(mMockNetd).setNetworkAllowlist(any());
+        } else {
+            verify(mMockNetd, never()).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));
+        callback.expect(LINK_PROPERTIES_CHANGED, agent,
+                x -> Objects.equals(x.getLp().getNat64Prefix(), prefix));
     }
 
     @Test
@@ -10480,11 +10567,11 @@
         // prefix discovery is never started.
         LinkProperties lp = new LinkProperties(baseLp);
         lp.setNat64Prefix(pref64FromRa);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
-        mWiFiNetworkAgent.connect(false);
-        final Network network = mWiFiNetworkAgent.getNetwork();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
+        mWiFiAgent.connect(false);
+        final Network network = mWiFiAgent.getNetwork();
         int netId = network.getNetId();
-        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
@@ -10493,8 +10580,8 @@
 
         // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
         lp.setNat64Prefix(null);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
+        mWiFiAgent.sendLinkProperties(lp);
+        expectNat64PrefixChange(callback, mWiFiAgent, null);
         verifyClatdStop(inOrder, iface);
         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
@@ -10502,8 +10589,8 @@
         // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
         // clatd is started with the prefix from the RA.
         lp.setNat64Prefix(pref64FromRa);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
+        mWiFiAgent.sendLinkProperties(lp);
+        expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
@@ -10511,21 +10598,21 @@
         // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
         // discovery has succeeded.
         lp.setNat64Prefix(null);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
+        mWiFiAgent.sendLinkProperties(lp);
+        expectNat64PrefixChange(callback, mWiFiAgent, null);
         verifyClatdStop(inOrder, iface);
         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
 
         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
+        expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
 
         // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
         // discovery is not stopped, and there are no callbacks.
         lp.setNat64Prefix(pref64FromDns);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
+        mWiFiAgent.sendLinkProperties(lp);
         callback.assertNoCallback();
         verifyNeverClatdStop(inOrder, iface);
         verifyNeverClatdStart(inOrder, iface);
@@ -10535,7 +10622,7 @@
 
         // If the RA is later withdrawn, nothing happens again.
         lp.setNat64Prefix(null);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
+        mWiFiAgent.sendLinkProperties(lp);
         callback.assertNoCallback();
         verifyNeverClatdStop(inOrder, iface);
         verifyNeverClatdStart(inOrder, iface);
@@ -10545,8 +10632,8 @@
 
         // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
         lp.setNat64Prefix(pref64FromRa);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
+        mWiFiAgent.sendLinkProperties(lp);
+        expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
         verifyClatdStop(inOrder, iface);
         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
 
@@ -10560,8 +10647,8 @@
 
         // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
         lp.setNat64Prefix(newPref64FromRa);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, newPref64FromRa);
+        mWiFiAgent.sendLinkProperties(lp);
+        expectNat64PrefixChange(callback, mWiFiAgent, newPref64FromRa);
         verifyClatdStop(inOrder, iface);
         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
         verifyClatdStart(inOrder, iface, netId, newPref64FromRa.toString());
@@ -10571,7 +10658,7 @@
 
         // If the RA prefix changes to the same value, nothing happens.
         lp.setNat64Prefix(newPref64FromRa);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
+        mWiFiAgent.sendLinkProperties(lp);
         callback.assertNoCallback();
         assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
         verifyNeverClatdStop(inOrder, iface);
@@ -10585,19 +10672,19 @@
         // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
         // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
         lp.setNat64Prefix(null);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
+        mWiFiAgent.sendLinkProperties(lp);
+        expectNat64PrefixChange(callback, mWiFiAgent, null);
         verifyClatdStop(inOrder, iface);
         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
-        expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
+        expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
 
         lp.setNat64Prefix(pref64FromDns);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
+        mWiFiAgent.sendLinkProperties(lp);
         callback.assertNoCallback();
         verifyNeverClatdStop(inOrder, iface);
         verifyNeverClatdStart(inOrder, iface);
@@ -10609,8 +10696,8 @@
         // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
         // clat has been stopped, or the test will be flaky.
         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
-        mWiFiNetworkAgent.disconnect();
-        callback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        callback.expect(LOST, mWiFiAgent);
         b.expectBroadcast();
 
         verifyClatdStop(inOrder, iface);
@@ -10637,17 +10724,17 @@
         cellLp.setInterfaceName(MOBILE_IFNAME);
         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME));
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
 
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        final int cellNetId = mCellNetworkAgent.getNetwork().netId;
+        mCellAgent.sendLinkProperties(cellLp);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        final int cellNetId = mCellAgent.getNetwork().netId;
         waitForIdle();
 
         verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId);
-        Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
+        Nat464Xlat clat = getNat464Xlat(mCellAgent);
         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
 
         // This cannot happen because prefix discovery cannot succeed if it is never started.
@@ -10667,25 +10754,25 @@
                 .build();
         mCm.registerNetworkCallback(networkRequest, networkCallback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         final LinkProperties cellLp = new LinkProperties();
         cellLp.setInterfaceName(MOBILE_IFNAME);
-        mCellNetworkAgent.sendLinkProperties(cellLp);
-        mCellNetworkAgent.connect(true);
-        networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(cellLp);
+        mCellAgent.connect(true);
+        networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_CELLULAR)));
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+        mWiFiAgent.sendLinkProperties(wifiLp);
 
         // Network switch
-        mWiFiNetworkAgent.connect(true);
-        networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        networkCallback.expectLosing(mCellNetworkAgent);
-        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mWiFiAgent.connect(true);
+        networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        networkCallback.expectLosing(mCellAgent);
+        networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_WIFI)));
         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
@@ -10693,8 +10780,8 @@
 
         // Disconnect wifi and switch back to cell
         reset(mMockNetd);
-        mWiFiNetworkAgent.disconnect();
-        networkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
+        mWiFiAgent.disconnect();
+        networkCallback.expect(LOST, mWiFiAgent);
         assertNoCallbacks(networkCallback);
         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_WIFI)));
@@ -10703,13 +10790,13 @@
 
         // reconnect wifi
         reset(mMockNetd);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
-        mWiFiNetworkAgent.connect(true);
-        networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        networkCallback.expectLosing(mCellNetworkAgent);
-        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mWiFiAgent.sendLinkProperties(wifiLp);
+        mWiFiAgent.connect(true);
+        networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        networkCallback.expectLosing(mCellAgent);
+        networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_WIFI)));
         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
@@ -10717,21 +10804,20 @@
 
         // Disconnect cell
         reset(mMockNetd);
-        mCellNetworkAgent.disconnect();
-        networkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        networkCallback.expect(LOST, mCellAgent);
         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
         // sent as network being switched. Ensure rule removal for cell will not be triggered
         // unexpectedly before network being removed.
         waitForIdle();
         verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_CELLULAR)));
-        verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
-        verify(mMockDnsResolver, times(1))
-                .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
+        verify(mMockNetd, times(1)).networkDestroy(eq(mCellAgent.getNetwork().netId));
+        verify(mMockDnsResolver, times(1)).destroyNetworkCache(eq(mCellAgent.getNetwork().netId));
 
         // Disconnect wifi
         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         b.expectBroadcast();
         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
                 eq(Integer.toString(TRANSPORT_WIFI)));
@@ -10758,21 +10844,21 @@
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
         mCm.registerNetworkCallback(networkRequest, networkCallback);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         reset(mMockNetd);
         // Switching default network updates TCP buffer sizes.
-        mCellNetworkAgent.connect(false);
-        networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        mCellAgent.connect(false);
+        networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
         // Change link Properties should have updated tcp buffer size.
         LinkProperties lp = new LinkProperties();
         lp.setTcpBufferSizes(testTcpBufferSizes);
-        mCellNetworkAgent.sendLinkProperties(lp);
-        networkCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        mCellAgent.sendLinkProperties(lp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
         verifyTcpBufferSizeChange(testTcpBufferSizes);
         // Clean up.
-        mCellNetworkAgent.disconnect();
-        networkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        networkCallback.expect(LOST, mCellAgent);
         networkCallback.assertNoCallback();
         mCm.unregisterNetworkCallback(networkCallback);
     }
@@ -10780,8 +10866,8 @@
     @Test
     public void testGetGlobalProxyForNetwork() throws Exception {
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        final Network wifiNetwork = mWiFiAgent.getNetwork();
         mProxyTracker.setGlobalProxy(testProxyInfo);
         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
     }
@@ -10789,15 +10875,15 @@
     @Test
     public void testGetProxyForActiveNetwork() throws Exception {
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
         waitForIdle();
         assertNull(mService.getProxyForNetwork(null));
 
         final LinkProperties testLinkProperties = new LinkProperties();
         testLinkProperties.setHttpProxy(testProxyInfo);
 
-        mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
+        mWiFiAgent.sendLinkProperties(testLinkProperties);
         waitForIdle();
 
         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
@@ -10808,8 +10894,8 @@
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
 
         // Set up a WiFi network with no proxy
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
         waitForIdle();
         assertNull(mService.getProxyForNetwork(null));
 
@@ -10822,7 +10908,7 @@
         // Test that the VPN network returns a proxy, and the WiFi does not.
         assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
-        assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
+        assertNull(mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
 
         // Test that the VPN network returns no proxy when it is set to null.
         testLinkProperties.setHttpProxy(null);
@@ -10833,7 +10919,7 @@
 
         // Set WiFi proxy and check that the vpn proxy is still null.
         testLinkProperties.setHttpProxy(testProxyInfo);
-        mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
+        mWiFiAgent.sendLinkProperties(testLinkProperties);
         waitForIdle();
         assertNull(mService.getProxyForNetwork(null));
 
@@ -10841,8 +10927,8 @@
         // correct proxy setting.
         mMockVpn.disconnect();
         waitForIdle();
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
-        assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
     }
 
@@ -10863,7 +10949,6 @@
         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
-        assertTrue(mService.mPermissionMonitor.getVpnInterfaceUidRanges("tun0").equals(vpnRange));
 
         mMockVpn.disconnect();
         waitForIdle();
@@ -10871,7 +10956,6 @@
         // Disconnected VPN should have interface rules removed
         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
-        assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges("tun0"));
     }
 
     private void checkInterfaceFilteringRuleWithNullInterface(final LinkProperties lp,
@@ -10896,8 +10980,6 @@
                 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
                 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
             }
-            assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
-                    vpnRange);
 
             mMockVpn.disconnect();
             waitForIdle();
@@ -10909,7 +10991,6 @@
             } else {
                 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
             }
-            assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
         } else {
             // Before T, rules are not configured for null interface.
             verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
@@ -11021,15 +11102,15 @@
 
     @Test
     public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
 
         LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
         wifiLp.setWakeOnLanSupported(false);
 
         // Default network switch should update ifaces.
-        mWiFiNetworkAgent.connect(false);
-        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+        mWiFiAgent.connect(false);
+        mWiFiAgent.sendLinkProperties(wifiLp);
         waitForIdle();
 
         // ConnectivityService should have changed the WakeOnLanSupported to true
@@ -11421,20 +11502,19 @@
                 .addTransportType(TRANSPORT_WIFI).build();
         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
                 ncTemplate);
-        mWiFiNetworkAgent.connect(false);
+        mWiFiAgent.connect(false);
 
-        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
         // Send network capabilities update with TransportInfo to trigger capabilities changed
         // callback.
-        mWiFiNetworkAgent.setNetworkCapabilities(
-                ncTemplate.setTransportInfo(actualTransportInfo), true);
+        mWiFiAgent.setNetworkCapabilities(ncTemplate.setTransportInfo(actualTransportInfo), true);
 
-        wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent,
-                nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid())
-                        && Objects.equals(expectedTransportInfo, nc.getTransportInfo()));
+        wifiNetworkCallback.expectCaps(mWiFiAgent,
+                c -> Objects.equals(expectedOwnerUid, c.getOwnerUid())
+                        && Objects.equals(expectedTransportInfo, c.getTransportInfo()));
     }
 
     @Test
@@ -11461,32 +11541,31 @@
                 .addTransportType(TRANSPORT_WIFI)
                 .setTransportInfo(new TestTransportInfo());
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
-                ncTemplate);
-        mWiFiNetworkAgent.connect(true /* validated; waits for callback */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
+        mWiFiAgent.connect(true /* validated; waits for callback */);
 
         // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission
-        assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
+        assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
         withPermission(NETWORK_SETTINGS, () -> {
-            assertFalse(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
+            assertFalse(getTestTransportInfo(mWiFiAgent).settingsRedacted);
         });
-        assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
+        assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
 
         // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission
-        assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
+        assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
         withPermission(LOCAL_MAC_ADDRESS, () -> {
-            assertFalse(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
+            assertFalse(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
         });
-        assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
+        assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
 
         // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive
         // information.
-        assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
+        assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
                 Manifest.permission.ACCESS_FINE_LOCATION);
-        assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
+        assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
         denyAllLocationPrivilegedPermissions();
-        assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
+        assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
     }
 
     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
@@ -11911,9 +11990,9 @@
         mCm.registerDefaultNetworkCallback(callback);
         final LinkProperties linkProperties = new LinkProperties();
         linkProperties.setInterfaceName(INTERFACE_NAME);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
         callback.assertNoCallback();
 
         final NetworkRequest request = new NetworkRequest.Builder().build();
@@ -11950,10 +12029,10 @@
         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
                 .addTransportType(TRANSPORT_CELLULAR)
                 .setTransportInfo(new TestTransportInfo());
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
                 ncTemplate);
-        mCellNetworkAgent.connect(true);
-        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellAgent);
         callback.assertNoCallback();
 
         // Make sure a report is sent and that the caps are suitably redacted.
@@ -11979,7 +12058,7 @@
 
         // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
         // cellular network agent
-        mCellNetworkAgent.notifyDataStallSuspected();
+        mCellAgent.notifyDataStallSuspected();
 
         // Verify onDataStallSuspected fired
         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)).onDataStallSuspected(
@@ -11990,7 +12069,7 @@
     public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
         setUpConnectivityDiagnosticsCallback();
 
-        final Network n = mCellNetworkAgent.getNetwork();
+        final Network n = mCellAgent.getNetwork();
         final boolean hasConnectivity = true;
         mService.reportNetworkConnectivity(n, hasConnectivity);
 
@@ -12023,7 +12102,7 @@
 
         // report known Connectivity from a different uid. Verify that network is not re-validated
         // and this callback is not notified.
-        final Network n = mCellNetworkAgent.getNetwork();
+        final Network n = mCellAgent.getNetwork();
         final boolean hasConnectivity = true;
         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, hasConnectivity));
 
@@ -12075,11 +12154,11 @@
         final NetworkRequest request = new NetworkRequest.Builder().build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
         mCm.registerNetworkCallback(request, networkCallback);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         reset(mMockNetd);
-        mCellNetworkAgent.connect(false);
-        networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        final int netId = mCellNetworkAgent.getNetwork().netId;
+        mCellAgent.connect(false);
+        networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
+        final int netId = mCellAgent.getNetwork().netId;
 
         final String iface = "rmnet_data0";
         final InetAddress gateway = InetAddress.getByName("fe80::5678");
@@ -12096,8 +12175,9 @@
         lp.addRoute(direct);
         lp.addRoute(rio1);
         lp.addRoute(defaultRoute);
-        mCellNetworkAgent.sendLinkProperties(lp);
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
+        mCellAgent.sendLinkProperties(lp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                x -> x.getLp().getRoutes().size() == 3);
 
         assertRoutesAdded(netId, direct, rio1, defaultRoute);
         reset(mMockNetd);
@@ -12111,9 +12191,9 @@
         assertFalse(lp.getRoutes().contains(defaultRoute));
         assertTrue(lp.getRoutes().contains(defaultWithMtu));
 
-        mCellNetworkAgent.sendLinkProperties(lp);
-        networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
-                x -> x.getRoutes().contains(rio2));
+        mCellAgent.sendLinkProperties(lp);
+        networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+                x -> x.getLp().getRoutes().contains(rio2));
 
         assertRoutesRemoved(netId, rio1);
         assertRoutesAdded(netId, rio2);
@@ -12225,12 +12305,12 @@
     @Test
     public void testVpnUidRangesUpdate() throws Exception {
         // Set up a WiFi network without proxy.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
         assertNull(mService.getProxyForNetwork(null));
         assertNull(mCm.getDefaultProxy());
 
-        final ExpectedBroadcast b1 = registerPacProxyBroadcast();
+        final ExpectedBroadcast b1 = expectProxyChangeAction();
         final LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
@@ -12243,7 +12323,7 @@
         b1.expectNoBroadcast(500);
 
         // Update to new range which is old range minus APP1, i.e. only APP2
-        final ExpectedBroadcast b2 = registerPacProxyBroadcast();
+        final ExpectedBroadcast b2 = expectProxyChangeAction();
         final Set<UidRange> newRanges = new HashSet<>(asList(
                 new UidRange(vpnRange.start, APP1_UID - 1),
                 new UidRange(APP1_UID + 1, vpnRange.stop)));
@@ -12257,20 +12337,20 @@
         b2.expectNoBroadcast(500);
 
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
-        final ExpectedBroadcast b3 = registerPacProxyBroadcast();
+        final ExpectedBroadcast b3 = expectProxyChangeAction();
         lp.setHttpProxy(testProxyInfo);
         mMockVpn.sendLinkProperties(lp);
         waitForIdle();
         // Proxy is set, so send a proxy broadcast.
         b3.expectBroadcast();
 
-        final ExpectedBroadcast b4 = registerPacProxyBroadcast();
+        final ExpectedBroadcast b4 = expectProxyChangeAction();
         mMockVpn.setUids(vpnRanges);
         waitForIdle();
         // Uid has changed and proxy is already set, so send a proxy broadcast.
         b4.expectBroadcast();
 
-        final ExpectedBroadcast b5 = registerPacProxyBroadcast();
+        final ExpectedBroadcast b5 = expectProxyChangeAction();
         // Proxy is removed, send a proxy broadcast.
         lp.setHttpProxy(null);
         mMockVpn.sendLinkProperties(lp);
@@ -12278,11 +12358,11 @@
         b5.expectBroadcast();
 
         // Proxy is added in WiFi(default network), setDefaultProxy will be called.
-        final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
+        final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
         assertNotNull(wifiLp);
         final ExpectedBroadcast b6 = expectProxyChangeAction(testProxyInfo);
         wifiLp.setHttpProxy(testProxyInfo);
-        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+        mWiFiAgent.sendLinkProperties(wifiLp);
         waitForIdle();
         b6.expectBroadcast();
     }
@@ -12290,8 +12370,8 @@
     @Test
     public void testProxyBroadcastWillBeSentWhenVpnHasProxyAndConnects() throws Exception {
         // Set up a WiFi network without proxy.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
         assertNull(mService.getProxyForNetwork(null));
         assertNull(mCm.getDefaultProxy());
 
@@ -12303,7 +12383,7 @@
         lp.setHttpProxy(testProxyInfo);
         final UidRange vpnRange = PRIMARY_UIDRANGE;
         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
-        final ExpectedBroadcast b1 = registerPacProxyBroadcast();
+        final ExpectedBroadcast b1 = expectProxyChangeAction();
         mMockVpn.setOwnerAndAdminUid(VPN_UID);
         mMockVpn.registerAgent(false, vpnRanges, lp);
         // In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
@@ -12311,8 +12391,9 @@
         // proxy broadcast will get null.
         b1.expectNoBroadcast(500);
 
-        final ExpectedBroadcast b2 = registerPacProxyBroadcast();
-        mMockVpn.connect(true /* validated */, true /* hasInternet */, false /* isStrictMode */);
+        final ExpectedBroadcast b2 = expectProxyChangeAction();
+        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
@@ -12324,31 +12405,31 @@
     public void testProxyBroadcastWillBeSentWhenTheProxyOfNonDefaultNetworkHasChanged()
             throws Exception {
         // Set up a CELLULAR network without proxy.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
         assertNull(mService.getProxyForNetwork(null));
         assertNull(mCm.getDefaultProxy());
         // CELLULAR network should be the default network.
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Set up a WiFi network without proxy.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
         assertNull(mService.getProxyForNetwork(null));
         assertNull(mCm.getDefaultProxy());
         // WiFi network should be the default network.
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
         // CELLULAR network is not the default network.
-        assertNotEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertNotEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
 
         // CELLULAR network is not the system default network, but it might be a per-app default
         // network. The proxy broadcast should be sent once its proxy has changed.
         final LinkProperties cellularLp = new LinkProperties();
         cellularLp.setInterfaceName(MOBILE_IFNAME);
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
-        final ExpectedBroadcast b = registerPacProxyBroadcast();
+        final ExpectedBroadcast b = expectProxyChangeAction();
         cellularLp.setHttpProxy(testProxyInfo);
-        mCellNetworkAgent.sendLinkProperties(cellularLp);
+        mCellAgent.sendLinkProperties(cellularLp);
         b.expectBroadcast();
     }
 
@@ -12377,66 +12458,64 @@
                 .build();
         mCm.registerNetworkCallback(allNetworksRequest, allNetworksCb);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true /* validated */);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true /* validated */);
 
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true /* validated */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true /* validated */);
 
-        mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
         // While the default callback doesn't see the network before it's validated, the listen
         // sees the network come up and validate later
-        allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
-        allNetworksCb.expectLosing(mCellNetworkAgent);
-        allNetworksCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
-        allNetworksCb.expect(CallbackEntry.LOST, mCellNetworkAgent,
-                TEST_LINGER_DELAY_MS * 2);
+        allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
+        allNetworksCb.expectLosing(mCellAgent);
+        allNetworksCb.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+        allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
 
         // The cell network has disconnected (see LOST above) because it was outscored and
         // had no requests (see setAlwaysOnNetworks(false) above)
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         final NetworkScore score = new NetworkScore.Builder().setLegacyInt(30).build();
-        mCellNetworkAgent.setScore(score);
-        mCellNetworkAgent.connect(false /* validated */);
+        mCellAgent.setScore(score);
+        mCellAgent.connect(false /* validated */);
 
         // The cell network gets torn down right away.
-        allNetworksCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
-        allNetworksCb.expect(CallbackEntry.LOST, mCellNetworkAgent,
-                TEST_NASCENT_DELAY_MS * 2);
+        allNetworksCb.expectAvailableCallbacksUnvalidated(mCellAgent);
+        allNetworksCb.expect(LOST, mCellAgent, TEST_NASCENT_DELAY_MS * 2);
         allNetworksCb.assertNoCallback();
 
         // Now create a cell network with KEEP_CONNECTED_FOR_HANDOVER and make sure it's
         // not disconnected immediately when outscored.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
         final NetworkScore scoreKeepup = new NetworkScore.Builder().setLegacyInt(30)
                 .setKeepConnectedReason(KEEP_CONNECTED_FOR_HANDOVER).build();
-        mCellNetworkAgent.setScore(scoreKeepup);
-        mCellNetworkAgent.connect(true /* validated */);
+        mCellAgent.setScore(scoreKeepup);
+        mCellAgent.connect(true /* validated */);
 
-        allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
         mDefaultNetworkCallback.assertNoCallback();
 
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
 
-        allNetworksCb.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        mDefaultNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        allNetworksCb.expect(LOST, mWiFiAgent);
+        mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
+        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
 
         // Reconnect a WiFi network and make sure the cell network is still not torn down.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true /* validated */);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true /* validated */);
 
-        allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
 
         // Now remove the reason to keep connected and make sure the network lingers and is
         // torn down.
-        mCellNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build());
-        allNetworksCb.expectLosing(mCellNetworkAgent, TEST_NASCENT_DELAY_MS * 2);
-        allNetworksCb.expect(CallbackEntry.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS * 2);
+        mCellAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build());
+        allNetworksCb.expectLosing(mCellAgent, TEST_NASCENT_DELAY_MS * 2);
+        allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
         mDefaultNetworkCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(allNetworksCb);
@@ -12454,21 +12533,21 @@
             mFilter = mock(QosFilter.class);
 
             // Ensure the network is disconnected before anything else occurs
-            assertNull(mCellNetworkAgent);
+            assertNull(mCellAgent);
 
-            mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-            mCellNetworkAgent.connect(true);
+            mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+            mCellAgent.connect(true);
 
             verifyActiveNetwork(TRANSPORT_CELLULAR);
             waitForIdle();
-            final Network network = mCellNetworkAgent.getNetwork();
+            final Network network = mCellAgent.getNetwork();
 
             final Pair<IQosCallback, IBinder> pair = createQosCallback();
             mCallback = pair.first;
 
             doReturn(network).when(mFilter).getNetwork();
             doReturn(QosCallbackException.EX_TYPE_FILTER_NONE).when(mFilter).validate();
-            mAgentWrapper = mCellNetworkAgent;
+            mAgentWrapper = mCellAgent;
         }
 
         void registerQosCallback(@NonNull final QosFilter filter,
@@ -13058,12 +13137,12 @@
             // Corresponds to a metered cellular network. Will be used for the default network.
             case TRANSPORT_CELLULAR:
                 if (!connectAgent) {
-                    mCellNetworkAgent.disconnect();
+                    mCellAgent.disconnect();
                     break;
                 }
-                mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-                mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
-                mCellNetworkAgent.connect(true);
+                mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+                mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+                mCellAgent.connect(true);
                 break;
             // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE.
             case TRANSPORT_ETHERNET:
@@ -13076,12 +13155,12 @@
             // Corresponds to unmetered Wi-Fi.
             case TRANSPORT_WIFI:
                 if (!connectAgent) {
-                    mWiFiNetworkAgent.disconnect();
+                    mWiFiAgent.disconnect();
                     break;
                 }
-                mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-                mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-                mWiFiNetworkAgent.connect(true);
+                mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+                mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+                mWiFiAgent.connect(true);
                 break;
             default:
                 throw new AssertionError("Unsupported transport type passed in.");
@@ -13091,15 +13170,15 @@
     }
 
     private void startOemManagedNetwork(final boolean isOemPaid) throws Exception {
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
-        mEthernetNetworkAgent.addCapability(
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetAgent.addCapability(
                 isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE);
-        mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
-        mEthernetNetworkAgent.connect(true);
+        mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        mEthernetAgent.connect(true);
     }
 
     private void stopOemManagedNetwork() {
-        mEthernetNetworkAgent.disconnect();
+        mEthernetAgent.disconnect();
         waitForIdle();
     }
 
@@ -13332,7 +13411,7 @@
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
                 null,
-                mEthernetNetworkAgent.getNetwork());
+                mEthernetAgent.getNetwork());
 
         // Verify that the active network is correct
         verifyActiveNetwork(TRANSPORT_ETHERNET);
@@ -13353,16 +13432,16 @@
         assertTrue(mCm.isActiveNetworkMetered());
 
         // Connect to an unmetered restricted network that will only be available to the OEM pref.
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
-        mEthernetNetworkAgent.addCapability(NET_CAPABILITY_OEM_PAID);
-        mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
-        mEthernetNetworkAgent.connect(true);
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+        mEthernetAgent.addCapability(NET_CAPABILITY_OEM_PAID);
+        mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        mEthernetAgent.connect(true);
         waitForIdle();
 
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
                 null,
-                mEthernetNetworkAgent.getNetwork());
+                mEthernetAgent.getNetwork());
 
         assertFalse(mCm.isActiveNetworkMetered());
         // default NCs will be unregistered in tearDown
@@ -13393,19 +13472,18 @@
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
                 null,
-                mEthernetNetworkAgent.getNetwork());
+                mEthernetAgent.getNetwork());
 
         // At this point with a restricted network used, the available callback should trigger.
-        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
-        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
+        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
         otherUidDefaultCallback.assertNoCallback();
 
         // Now bring down the default network which should trigger a LOST callback.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
 
         // At this point, with no network is available, the lost callback should trigger
-        defaultNetworkCallback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
+        defaultNetworkCallback.expect(LOST, mEthernetAgent);
         otherUidDefaultCallback.assertNoCallback();
 
         // Confirm we can unregister without issues.
@@ -13438,12 +13516,11 @@
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
                 null,
-                mEthernetNetworkAgent.getNetwork());
+                mEthernetAgent.getNetwork());
 
         // At this point with a restricted network used, the available callback should trigger
-        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
-        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
+        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
         otherUidDefaultCallback.assertNoCallback();
 
         // Now bring down the default network which should trigger a LOST callback.
@@ -13451,7 +13528,7 @@
         otherUidDefaultCallback.assertNoCallback();
 
         // At this point, with no network is available, the lost callback should trigger
-        defaultNetworkCallback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
+        defaultNetworkCallback.expect(LOST, mEthernetAgent);
         otherUidDefaultCallback.assertNoCallback();
 
         // Confirm we can unregister without issues.
@@ -13484,27 +13561,26 @@
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
                 null,
-                mEthernetNetworkAgent.getNetwork());
+                mEthernetAgent.getNetwork());
 
         // As this callback does not have access to the OEM_PAID network, it will not fire.
         defaultNetworkCallback.assertNoCallback();
         assertDefaultNetworkCapabilities(userId /* no networks */);
 
         // The other UID does have access, and gets a callback.
-        otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+        otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
 
         // Bring up unrestricted cellular. This should now satisfy the default network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // At this point with an unrestricted network used, the available callback should trigger
         // The other UID is unaffected and remains on the paid network.
-        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
-                mCellNetworkAgent.getNetwork());
-        assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
+        defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCellAgent.getNetwork());
+        assertDefaultNetworkCapabilities(userId, mCellAgent);
         otherUidDefaultCallback.assertNoCallback();
 
         // Now bring down the per-app network.
@@ -13513,13 +13589,13 @@
         // Since the callback didn't use the per-app network, only the other UID gets a callback.
         // Because the preference specifies no fallback, it does not switch to cellular.
         defaultNetworkCallback.assertNoCallback();
-        otherUidDefaultCallback.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
+        otherUidDefaultCallback.expect(LOST, mEthernetAgent);
 
         // Now bring down the default network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
 
         // As this callback was tracking the default, this should now trigger.
-        defaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        defaultNetworkCallback.expect(LOST, mCellAgent);
         otherUidDefaultCallback.assertNoCallback();
 
         // Confirm we can unregister without issues.
@@ -13672,22 +13748,22 @@
         // Bring up metered cellular. This will satisfy the fallback network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 OEM_PREF_ANY_NET_ID, 0 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mEthernetAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
-                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mWiFiAgent.getNetwork().netId, 1 /* times */,
+                mEthernetAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered.
@@ -13701,15 +13777,15 @@
         // Disconnecting unmetered should put PANS on lowest priority fallback request.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
-                mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
+                mWiFiAgent.getNetwork().netId, 0 /* times */,
                 true /* shouldDestroyNetwork */);
 
         // Disconnecting the fallback network should result in no connectivity.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
                 OEM_PREF_ANY_NET_ID, 0 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 0 /* times */,
+                mCellAgent.getNetwork().netId, 0 /* times */,
                 true /* shouldDestroyNetwork */);
     }
 
@@ -13747,22 +13823,22 @@
         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mEthernetAgent.getNetwork().netId, 1 /* times */,
                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
-                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mWiFiAgent.getNetwork().netId, 1 /* times */,
+                mEthernetAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Disconnecting unmetered should put PANS on OEM_PAID.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
-                mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
+                mEthernetAgent.getNetwork().netId, 1 /* times */,
+                mWiFiAgent.getNetwork().netId, 0 /* times */,
                 true /* shouldDestroyNetwork */);
 
         // Disconnecting OEM_PAID should result in no connectivity.
@@ -13770,7 +13846,7 @@
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
-                mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
+                mEthernetAgent.getNetwork().netId, 0 /* times */,
                 true /* shouldDestroyNetwork */);
     }
 
@@ -13814,7 +13890,7 @@
         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mEthernetAgent.getNetwork().netId, 1 /* times */,
                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
@@ -13822,7 +13898,7 @@
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
-                mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
+                mEthernetAgent.getNetwork().netId, 0 /* times */,
                 true /* shouldDestroyNetwork */);
     }
 
@@ -13866,7 +13942,7 @@
         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
         startOemManagedNetwork(false);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
+                mEthernetAgent.getNetwork().netId, 1 /* times */,
                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
@@ -13874,7 +13950,7 @@
         stopOemManagedNetwork();
         verifySetOemNetworkPreferenceForPreference(uidRanges,
                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
-                mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
+                mEthernetAgent.getNetwork().netId, 0 /* times */,
                 true /* shouldDestroyNetwork */);
     }
 
@@ -13907,7 +13983,7 @@
         // Test that we correctly add the expected values for multiple users.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 OEM_PREF_ANY_NET_ID, 0 /* times */,
                 false /* shouldDestroyNetwork */);
 
@@ -13915,7 +13991,7 @@
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
         verifySetOemNetworkPreferenceForPreference(uidRanges,
                 OEM_PREF_ANY_NET_ID, 0 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 0 /* times */,
+                mCellAgent.getNetwork().netId, 0 /* times */,
                 true /* shouldDestroyNetwork */);
     }
 
@@ -13950,7 +14026,7 @@
         // Test that we correctly add the expected values for multiple users.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 OEM_PREF_ANY_NET_ID, 0 /* times */,
                 false /* shouldDestroyNetwork */);
 
@@ -13963,8 +14039,8 @@
 
         // Test that we correctly add values for all users and remove for the single user.
         verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Send a broadcast indicating a user was removed.
@@ -13975,8 +14051,8 @@
 
         // Test that we correctly add values for the single user and remove for the all users.
         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
     }
 
@@ -14006,7 +14082,7 @@
         // Test that we correctly add the expected values for installed packages.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 OEM_PREF_ANY_NET_ID, 0 /* times */,
                 false /* shouldDestroyNetwork */);
 
@@ -14022,8 +14098,8 @@
 
         // Test the single package is removed and the combined packages are added.
         verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Set the system to no longer recognize the package to be installed
@@ -14036,8 +14112,8 @@
 
         // Test the combined packages are removed and the single package is added.
         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
 
         // Set the system to change the installed package's uid
@@ -14053,8 +14129,8 @@
 
         // Test the original uid is removed and is replaced with the new uid.
         verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
-                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
+                mCellAgent.getNetwork().netId, 1 /* times */,
                 false /* shouldDestroyNetwork */);
     }
 
@@ -14079,32 +14155,32 @@
         // Bring up metered cellular. This will satisfy the fallback network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mCellNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mCellAgent.getNetwork());
 
         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mWiFiNetworkAgent.getNetwork(),
-                mWiFiNetworkAgent.getNetwork());
+                mWiFiAgent.getNetwork(),
+                mWiFiAgent.getNetwork());
 
         // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
                 null,
-                mEthernetNetworkAgent.getNetwork());
+                mEthernetAgent.getNetwork());
 
         // Disconnecting OEM_PAID will put both on null as it is the last network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
@@ -14152,8 +14228,8 @@
         oemPaidFactory.register();
         oemPaidFactory.expectRequestAdd(); // Because nobody satisfies the request
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
         // A network connected that satisfies the default internet request. For the OEM_PAID
         // preference, this is not as good as an OEM_PAID network, so even if the score of
@@ -14188,7 +14264,7 @@
         expectNoRequestChanged(internetFactory);
         internetFactory.assertRequestCountEquals(0);
 
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         // The network satisfying the default internet request has disconnected, so the
         // internetFactory sees the default request again. However there is a network with OEM_PAID
         // connected, so the 2nd OEM_PAID req is already satisfied, so the oemPaidFactory doesn't
@@ -14199,8 +14275,8 @@
         internetFactory.assertRequestCountEquals(1);
 
         // Cell connects again, still with score 50. Back to the previous state.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
         expectNoRequestChanged(oemPaidFactory);
         oemPaidFactory.assertRequestCountEquals(1);
         internetFactory.expectRequestRemove();
@@ -14212,18 +14288,18 @@
                 wifiCallback);
 
         // Now WiFi connects and it's unmetered, but it's weaker than cell.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
-        mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true)
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true)
                 .build()); // Not the best Internet network, but unmetered
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent.connect(true);
 
         // The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so
         // the oemPaidFactory can't beat wifi no matter how high its score.
         oemPaidFactory.expectRequestRemove();
         expectNoRequestChanged(internetFactory);
 
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         // Now that the best internet network (cell, with its 50 score compared to 30 for WiFi
         // at this point), the default internet request is satisfied by a network worse than
         // the internetFactory announced, so it gets the request. However, there is still an
@@ -14254,32 +14330,32 @@
         // Bring up metered cellular. This will satisfy the fallback network but not the pref.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
+                mCellAgent.getNetwork(),
                 mService.mNoServiceNetwork.network());
 
         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mWiFiNetworkAgent.getNetwork(),
-                mWiFiNetworkAgent.getNetwork());
+                mWiFiAgent.getNetwork(),
+                mWiFiAgent.getNetwork());
 
         // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
                 null,
-                mEthernetNetworkAgent.getNetwork());
+                mEthernetAgent.getNetwork());
 
         // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
@@ -14312,32 +14388,32 @@
         // Bring up metered cellular. This will satisfy the fallback network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
+                mCellAgent.getNetwork(),
                 mService.mNoServiceNetwork.network());
 
         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mWiFiNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mWiFiAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID.
         // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
+                mCellAgent.getNetwork(),
                 mService.mNoServiceNetwork.network());
 
         // Disconnecting cellular will put the fallback on null and the pref on disconnected.
@@ -14371,32 +14447,32 @@
         // Bring up metered cellular. This will satisfy the fallback network.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
+                mCellAgent.getNetwork(),
                 mService.mNoServiceNetwork.network());
 
         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
         startOemManagedNetwork(false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mWiFiNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mWiFiAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
-                mEthernetNetworkAgent.getNetwork());
+                mCellAgent.getNetwork(),
+                mEthernetAgent.getNetwork());
 
         // Disconnecting OEM_PRIVATE will keep the fallback on cellular.
         // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network.
         stopOemManagedNetwork();
         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
-                mCellNetworkAgent.getNetwork(),
+                mCellAgent.getNetwork(),
                 mService.mNoServiceNetwork.network());
 
         // Disconnecting cellular will put the fallback on null and pref on disconnected.
@@ -14417,14 +14493,14 @@
 
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
 
-        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
-        mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
-                nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
-        mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
-                nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+        mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+        mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
+                c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+        mDefaultNetworkCallback.expectCaps(mCellAgent,
+                c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
 
         // default callbacks will be unregistered in tearDown
     }
@@ -14478,29 +14554,29 @@
         final TestNetworkCallback cellCb = new TestNetworkCallback();
         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
                 cellCb);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
-        mCellNetworkAgent.connect(true);
-        cellCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
+        mCellAgent.connect(true);
+        cellCb.expectAvailableCallbacksUnvalidated(mCellAgent);
         List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshots();
         assertLength(1, snapshots);
 
         // Compose the expected cellular snapshot for verification.
         final NetworkCapabilities cellNc =
-                mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork());
+                mCm.getNetworkCapabilities(mCellAgent.getNetwork());
         final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot(
-                mCellNetworkAgent.getNetwork(), cellNc, cellLp,
+                mCellAgent.getNetwork(), cellNc, cellLp,
                 null, ConnectivityManager.TYPE_MOBILE);
         assertEquals(cellSnapshot, snapshots.get(0));
 
         // Connect wifi and verify the snapshots.
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
         waitForIdle();
         // Compose the expected wifi snapshot for verification.
         final NetworkCapabilities wifiNc =
-                mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
+                mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
         final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot(
-                mWiFiNetworkAgent.getNetwork(), wifiNc, new LinkProperties(), null,
+                mWiFiAgent.getNetwork(), wifiNc, new LinkProperties(), null,
                 ConnectivityManager.TYPE_WIFI);
 
         snapshots = mCm.getAllNetworkStateSnapshots();
@@ -14508,33 +14584,33 @@
         assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
 
         // Set cellular as suspended, verify the snapshots will contain suspended networks.
-        mCellNetworkAgent.suspend();
+        mCellAgent.suspend();
         waitForIdle();
         final NetworkCapabilities cellSuspendedNc =
-                mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork());
+                mCm.getNetworkCapabilities(mCellAgent.getNetwork());
         assertFalse(cellSuspendedNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
         final NetworkStateSnapshot cellSuspendedSnapshot = new NetworkStateSnapshot(
-                mCellNetworkAgent.getNetwork(), cellSuspendedNc, cellLp,
+                mCellAgent.getNetwork(), cellSuspendedNc, cellLp,
                 null, ConnectivityManager.TYPE_MOBILE);
         snapshots = mCm.getAllNetworkStateSnapshots();
         assertLength(2, snapshots);
         assertContainsAll(snapshots, cellSuspendedSnapshot, wifiSnapshot);
 
         // Disconnect wifi, verify the snapshots contain only cellular.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         waitForIdle();
         snapshots = mCm.getAllNetworkStateSnapshots();
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
         assertLength(1, snapshots);
         assertEquals(cellSuspendedSnapshot, snapshots.get(0));
 
-        mCellNetworkAgent.resume();
+        mCellAgent.resume();
         waitForIdle();
         snapshots = mCm.getAllNetworkStateSnapshots();
         assertLength(1, snapshots);
         assertEquals(cellSnapshot, snapshots.get(0));
 
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         waitForIdle();
         verifyNoNetwork();
         mCm.unregisterNetworkCallback(cellCb);
@@ -14605,35 +14681,35 @@
                 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
                 bestMatchingCb, mCsHandlerThread.getThreadHandler());
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellAgent);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
 
         // Change something on cellular to trigger capabilities changed, since the callback
         // only cares about the best network, verify it received nothing from cellular.
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+        mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
         bestMatchingCb.assertNoCallback();
 
         // Make cellular the best network again, verify the callback now tracks cellular.
-        mWiFiNetworkAgent.adjustScore(-50);
-        bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mWiFiAgent.adjustScore(-50);
+        bestMatchingCb.expectAvailableCallbacksValidated(mCellAgent);
 
         // Make cellular temporary non-trusted, which will not satisfying the request.
         // Verify the callback switch from/to the other network accordingly.
-        mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
-        bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED);
-        bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent.removeCapability(NET_CAPABILITY_TRUSTED);
+        bestMatchingCb.expectAvailableCallbacksValidated(mWiFiAgent);
+        mCellAgent.addCapability(NET_CAPABILITY_TRUSTED);
+        bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellAgent);
 
         // Verify the callback doesn't care about wifi disconnect.
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         bestMatchingCb.assertNoCallback();
-        mCellNetworkAgent.disconnect();
-        bestMatchingCb.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        bestMatchingCb.expect(LOST, mCellAgent);
     }
 
     private UidRangeParcel[] uidRangeFor(final UserHandle handle) {
@@ -14730,18 +14806,17 @@
             TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
         final InOrder inOrder = inOrder(mMockNetd);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
-        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        profileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        profileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         if (disAllowProfileDefaultNetworkCallback != null) {
-            disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(
-                    mCellNetworkAgent);
+            disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         }
         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
-                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+                mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
 
         final TestNetworkAgentWrapper workAgent =
                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
@@ -14768,7 +14843,7 @@
             // system default is not handled specially, the rules are always active as long as
             // a preference is set.
             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                    mCellNetworkAgent.getNetwork().netId,
+                    mCellAgent.getNetwork().netId,
                     uidRangeFor(testHandle, profileNetworkPreference),
                     PREFERENCE_ORDER_PROFILE));
         }
@@ -14778,7 +14853,7 @@
         if (allowFallback && !connectWorkProfileAgentAhead) {
             assertNoCallbacks(profileDefaultNetworkCallback);
         } else if (!connectWorkProfileAgentAhead) {
-            profileDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+            profileDefaultNetworkCallback.expect(LOST, mCellAgent);
             if (disAllowProfileDefaultNetworkCallback != null) {
                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
             }
@@ -14803,29 +14878,28 @@
 
         if (allowFallback && !connectWorkProfileAgentAhead) {
             inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
-                    mCellNetworkAgent.getNetwork().netId,
+                    mCellAgent.getNetwork().netId,
                     uidRangeFor(testHandle, profileNetworkPreference),
                     PREFERENCE_ORDER_PROFILE));
         }
 
         // Make sure changes to the work agent send callbacks to the app in the work profile, but
         // not to the other apps.
-        workAgent.setNetworkValid(true /* isStrictMode */);
+        workAgent.setNetworkValid(true /* privateDnsProbeSent */);
         workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
-        profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent,
-                nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)
-                        && nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
-                        && nc.hasEnterpriseId(
-                                profileNetworkPreference.getPreferenceEnterpriseId())
-                        && nc.getEnterpriseIds().length == 1);
+        profileDefaultNetworkCallback.expectCaps(workAgent,
+                c -> c.hasCapability(NET_CAPABILITY_VALIDATED)
+                        && c.hasCapability(NET_CAPABILITY_ENTERPRISE)
+                        && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
+                        && c.getEnterpriseIds().length == 1);
         if (disAllowProfileDefaultNetworkCallback != null) {
             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
         }
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
 
         workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
-        profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc ->
-                nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+        profileDefaultNetworkCallback.expectCaps(workAgent,
+                c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
         if (disAllowProfileDefaultNetworkCallback != null) {
             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
         }
@@ -14833,49 +14907,47 @@
 
         // Conversely, change a capability on the system-wide default network and make sure
         // that only the apps outside of the work profile receive the callbacks.
-        mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
-        mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
-                nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
-        mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
-                nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+        mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+        mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
+                c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+        mDefaultNetworkCallback.expectCaps(mCellAgent,
+                c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
         if (disAllowProfileDefaultNetworkCallback != null) {
-            disAllowProfileDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
-                    nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+            disAllowProfileDefaultNetworkCallback.expectCaps(mCellAgent,
+                    c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
         }
         profileDefaultNetworkCallback.assertNoCallback();
 
         // Disconnect and reconnect the system-wide default network and make sure that the
         // apps on this network see the appropriate callbacks, and the app on the work profile
         // doesn't because it continues to use the enterprise network.
-        mCellNetworkAgent.disconnect();
-        mSystemDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        mDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
+        mDefaultNetworkCallback.expect(LOST, mCellAgent);
         if (disAllowProfileDefaultNetworkCallback != null) {
-            disAllowProfileDefaultNetworkCallback.expect(
-                    CallbackEntry.LOST, mCellNetworkAgent);
+            disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
         }
         profileDefaultNetworkCallback.assertNoCallback();
-        inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
+        inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         if (disAllowProfileDefaultNetworkCallback != null) {
-            disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(
-                    mCellNetworkAgent);
+            disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
         }
         profileDefaultNetworkCallback.assertNoCallback();
         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
-                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+                mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
 
         // When the agent disconnects, test that the app on the work profile falls back to the
         // default network.
         workAgent.disconnect();
-        profileDefaultNetworkCallback.expect(CallbackEntry.LOST, workAgent);
+        profileDefaultNetworkCallback.expect(LOST, workAgent);
         if (allowFallback) {
-            profileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+            profileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
             if (disAllowProfileDefaultNetworkCallback != null) {
                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
             }
@@ -14883,27 +14955,26 @@
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
         if (allowFallback) {
             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                    mCellNetworkAgent.getNetwork().netId,
+                    mCellAgent.getNetwork().netId,
                     uidRangeFor(testHandle, profileNetworkPreference),
                     PREFERENCE_ORDER_PROFILE));
         }
         inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
 
-        mCellNetworkAgent.disconnect();
-        mSystemDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        mDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
+        mDefaultNetworkCallback.expect(LOST, mCellAgent);
         if (disAllowProfileDefaultNetworkCallback != null) {
-            disAllowProfileDefaultNetworkCallback.expect(
-                    CallbackEntry.LOST, mCellNetworkAgent);
+            disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
         }
         if (allowFallback) {
-            profileDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
+            profileDefaultNetworkCallback.expect(LOST, mCellAgent);
         }
 
         // Waiting for the handler to be idle before checking for networkDestroy is necessary
         // here because ConnectivityService calls onLost before the network is fully torn down.
         waitForIdle();
-        inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
+        inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
 
         // If the control comes here, callbacks seem to behave correctly in the presence of
         // a default network when the enterprise network goes up and down. Now, make sure they
@@ -14923,14 +14994,13 @@
                 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)
-                        && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
-                        && nc.hasEnterpriseId(
-                        profileNetworkPreference.getPreferenceEnterpriseId())
-                        && nc.getEnterpriseIds().length == 1);
+        profileDefaultNetworkCallback.expectCaps(workAgent2,
+                c -> c.hasCapability(NET_CAPABILITY_ENTERPRISE)
+                        && !c.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+                        && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
+                        && c.getEnterpriseIds().length == 1);
         if (disAllowProfileDefaultNetworkCallback != null) {
             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
         }
@@ -14940,7 +15010,7 @@
         // When the agent disconnects, test that the app on the work profile fall back to the
         // default network.
         workAgent2.disconnect();
-        profileDefaultNetworkCallback.expect(CallbackEntry.LOST, workAgent2);
+        profileDefaultNetworkCallback.expect(LOST, workAgent2);
         if (disAllowProfileDefaultNetworkCallback != null) {
             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
         }
@@ -15286,23 +15356,23 @@
         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
 
         // Connect both a regular cell agent and an enterprise network first.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
         workAgent1.connect(true);
         workAgent2.connect(true);
 
-        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
-        appCb1.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        appCb2.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        appCb3.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
+        appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
+        appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
 
         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
-                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+                mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
@@ -15369,8 +15439,8 @@
 
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
         appCb3.expectAvailableCallbacksValidated(workAgent1);
-        appCb2.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        appCb1.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb2.expectAvailableCallbacksValidated(mCellAgent);
+        appCb1.expectAvailableCallbacksValidated(mCellAgent);
 
         // Set the preferences for testHandle to default.
         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
@@ -15387,9 +15457,9 @@
                 PREFERENCE_ORDER_PROFILE));
 
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb2);
-        appCb3.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb3.expectAvailableCallbacksValidated(mCellAgent);
         workAgent2.disconnect();
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
 
         mCm.unregisterNetworkCallback(appCb1);
         mCm.unregisterNetworkCallback(appCb2);
@@ -15434,8 +15504,8 @@
         registerDefaultNetworkCallbackAsUid(appCb5, testWorkProfileAppUid5);
 
         // Connect both a regular cell agent and an enterprise network first.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
@@ -15449,16 +15519,16 @@
         workAgent4.connect(true);
         workAgent5.connect(true);
 
-        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        appCb1.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        appCb2.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        appCb3.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        appCb4.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        appCb5.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
+        appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
+        appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
+        appCb4.expectAvailableThenValidatedCallbacks(mCellAgent);
+        appCb5.expectAvailableThenValidatedCallbacks(mCellAgent);
 
         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
-                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+                mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
@@ -15550,36 +15620,36 @@
         workAgent4.disconnect();
         workAgent5.disconnect();
 
-        appCb1.expect(CallbackEntry.LOST, workAgent1);
-        appCb2.expect(CallbackEntry.LOST, workAgent2);
-        appCb3.expect(CallbackEntry.LOST, workAgent3);
-        appCb4.expect(CallbackEntry.LOST, workAgent4);
-        appCb5.expect(CallbackEntry.LOST, workAgent5);
+        appCb1.expect(LOST, workAgent1);
+        appCb2.expect(LOST, workAgent2);
+        appCb3.expect(LOST, workAgent3);
+        appCb4.expect(LOST, workAgent4);
+        appCb5.expect(LOST, workAgent5);
 
-        appCb1.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb1.expectAvailableCallbacksValidated(mCellAgent);
         appCb2.assertNoCallback();
-        appCb3.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb3.expectAvailableCallbacksValidated(mCellAgent);
         appCb4.assertNoCallback();
-        appCb5.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb5.expectAvailableCallbacksValidated(mCellAgent);
 
         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId,
+                mCellAgent.getNetwork().netId,
                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
                 PREFERENCE_ORDER_PROFILE));
         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId,
+                mCellAgent.getNetwork().netId,
                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
                 PREFERENCE_ORDER_PROFILE));
         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId,
+                mCellAgent.getNetwork().netId,
                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
                 PREFERENCE_ORDER_PROFILE));
         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId,
+                mCellAgent.getNetwork().netId,
                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
                 PREFERENCE_ORDER_PROFILE));
         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId,
+                mCellAgent.getNetwork().netId,
                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
                 PREFERENCE_ORDER_PROFILE));
 
@@ -15597,9 +15667,9 @@
         listener.expectOnComplete();
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb3,
                 appCb5);
-        appCb2.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        appCb4.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        mCellNetworkAgent.disconnect();
+        appCb2.expectAvailableCallbacksValidated(mCellAgent);
+        appCb4.expectAvailableCallbacksValidated(mCellAgent);
+        mCellAgent.disconnect();
 
         mCm.unregisterNetworkCallback(appCb1);
         mCm.unregisterNetworkCallback(appCb2);
@@ -15619,8 +15689,8 @@
         final UserHandle testHandle = setupEnterpriseNetwork();
 
         // Connect both a regular cell agent and an enterprise network first.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
         workAgent.connect(true);
@@ -15630,27 +15700,27 @@
                 r -> r.run(), listener);
         listener.expectOnComplete();
         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
-                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+                mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
 
         registerDefaultNetworkCallbacks();
 
-        mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
+        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
 
         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
                 r -> r.run(), listener);
         listener.expectOnComplete();
 
-        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
 
         workAgent.disconnect();
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
 
         // Callbacks will be unregistered by tearDown()
     }
@@ -15672,18 +15742,18 @@
         registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4);
 
         // Connect both a regular cell agent and an enterprise network first.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
         workAgent.connect(true);
 
-        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        app4Cb.expectAvailableThenValidatedCallbacks(mCellAgent);
         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
-                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+                mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
 
@@ -15714,12 +15784,12 @@
         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
 
-        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
                 app4Cb);
 
         workAgent.disconnect();
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
 
         mCm.unregisterNetworkCallback(app4Cb);
         // Other callbacks will be unregistered by tearDown()
@@ -15730,17 +15800,17 @@
         final InOrder inOrder = inOrder(mMockNetd);
         final UserHandle testHandle = setupEnterpriseNetwork();
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
 
         final TestOnCompleteListener listener = new TestOnCompleteListener();
         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
                 r -> r.run(), listener);
         listener.expectOnComplete();
         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
-                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+                mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
+                mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
                 PREFERENCE_ORDER_PROFILE));
 
         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
@@ -15748,10 +15818,256 @@
         processBroadcast(removedIntent);
 
         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
-                mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
+                mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
                 PREFERENCE_ORDER_PROFILE));
     }
 
+    @Test
+    public void testProfileNetworkPreferenceBlocking_addUser() throws Exception {
+        final InOrder inOrder = inOrder(mMockNetd);
+        doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
+
+        // Only one network
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+
+        // Verify uid ranges 0~99999 are allowed
+        final ArraySet<UidRange> allowedRanges = new ArraySet<>();
+        allowedRanges.add(PRIMARY_UIDRANGE);
+        final NativeUidRangeConfig config1User = new NativeUidRangeConfig(
+                mCellAgent.getNetwork().netId,
+                toUidRangeStableParcels(allowedRanges),
+                0 /* subPriority */);
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config1User});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE))
+                .when(mUserManager).getUserHandles(anyBoolean());
+        final Intent addedIntent = new Intent(ACTION_USER_ADDED);
+        addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(SECONDARY_USER));
+        processBroadcast(addedIntent);
+
+        // Make sure the allow list has been updated.
+        allowedRanges.add(UidRange.createForUser(SECONDARY_USER_HANDLE));
+        final NativeUidRangeConfig config2Users = new NativeUidRangeConfig(
+                mCellAgent.getNetwork().netId,
+                toUidRangeStableParcels(allowedRanges),
+                0 /* subPriority */);
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config2Users});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+    }
+
+    @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.
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.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(
+                mCellAgent.getNetwork().netId,
+                allowAllUidRangesParcel,
+                0 /* subPriority */);
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(
+                    new NativeUidRangeConfig[]{cellAllAllowedConfig});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        // 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);
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+            assertContainsAll(List.of(configsCaptor.getValue()),
+                    List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        // 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(
+                mCellAgent.getNetwork().netId,
+                excludeAppRangesParcel,
+                0 /* subPriority */);
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+            assertContainsAll(List.of(configsCaptor.getValue()),
+                    List.of(cellExcludeAppConfig, enterpriseAllAllowedConfig));
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        // 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();
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+            assertContainsAll(List.of(configsCaptor.getValue()),
+                    List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        // Verify issuing with cellular set only when a network with enterprise capability
+        // disconnects.
+        enterpriseAgent.disconnect();
+        waitForIdle();
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(
+                    new NativeUidRangeConfig[]{cellAllAllowedConfig});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+    }
+
+    @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();
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        // Start with 1 default network, which should be restricted since the blocking
+        // preference is already set.
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.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(
+                mCellAgent.getNetwork().netId,
+                excludeAppRangesParcel,
+                0 /* subPriority */);
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(
+                    new NativeUidRangeConfig[]{cellExcludeAppConfig});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        // 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);
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+            assertContainsAll(List.of(configsCaptor.getValue()),
+                    List.of(enterpriseAllAllowedConfig, cellExcludeAppConfig));
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        // Verify issuing with cellular set only when enterprise network disconnects.
+        enterpriseAgent.disconnect();
+        waitForIdle();
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(
+                    new NativeUidRangeConfig[]{cellExcludeAppConfig});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+
+        mCellAgent.disconnect();
+        waitForIdle();
+        if (SdkLevel.isAtLeastU()) {
+            inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+        } else {
+            inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+        }
+    }
+
     /**
      * Make sure wrong preferences for per-profile default networking are rejected.
      */
@@ -15762,7 +16078,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,
@@ -15918,7 +16234,7 @@
         nc.setAllowedUids(uids);
         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
         if (SdkLevel.isAtLeastT()) {
-            cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
+            cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
         } else {
             cb.assertNoCallback();
         }
@@ -15935,7 +16251,7 @@
         nc.setAllowedUids(uids);
         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
         if (SdkLevel.isAtLeastT()) {
-            cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
+            cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids200Parcel);
         } else {
             cb.assertNoCallback();
@@ -15946,7 +16262,7 @@
         nc.setAllowedUids(uids);
         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
         if (SdkLevel.isAtLeastT()) {
-            cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
+            cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
         } else {
             cb.assertNoCallback();
         }
@@ -15963,7 +16279,7 @@
         nc.setAllowedUids(uids);
         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
         if (SdkLevel.isAtLeastT()) {
-            cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().isEmpty());
+            cb.expectCaps(agent, c -> c.getAllowedUids().isEmpty());
             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids600Parcel);
         } else {
             cb.assertNoCallback();
@@ -15997,7 +16313,7 @@
                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
 
-        mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET,
+        mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET,
                 new LinkProperties(), ncb.build());
 
         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
@@ -16009,22 +16325,21 @@
                 .addTransportType(TRANSPORT_ETHERNET)
                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
                 .build(), cb);
-        mEthernetNetworkAgent.connect(true);
-        cb.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+        mEthernetAgent.connect(true);
+        cb.expectAvailableThenValidatedCallbacks(mEthernetAgent);
 
         // Cell gets to set the service UID as access UID
         ncb.setAllowedUids(serviceUidSet);
-        mEthernetNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
+        mEthernetAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
         if (SdkLevel.isAtLeastT() && hasAutomotiveFeature) {
-            cb.expectCapabilitiesThat(mEthernetNetworkAgent,
-                    caps -> caps.getAllowedUids().equals(serviceUidSet));
+            cb.expectCaps(mEthernetAgent, c -> c.getAllowedUids().equals(serviceUidSet));
         } else {
             // S and no automotive feature must ignore access UIDs.
             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
         }
 
-        mEthernetNetworkAgent.disconnect();
-        cb.expect(CallbackEntry.LOST, mEthernetNetworkAgent);
+        mEthernetAgent.disconnect();
+        cb.expect(LOST, mEthernetAgent);
         mCm.unregisterNetworkCallback(cb);
     }
 
@@ -16047,7 +16362,7 @@
                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
                 .setNetworkSpecifier(new TelephonyNetworkSpecifier(1 /* subid */));
 
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
                 new LinkProperties(), ncb.build());
 
         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
@@ -16065,13 +16380,12 @@
                 .addTransportType(TRANSPORT_CELLULAR)
                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
                 .build(), cb);
-        mCellNetworkAgent.connect(true);
-        cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent.connect(true);
+        cb.expectAvailableThenValidatedCallbacks(mCellAgent);
         ncb.setAllowedUids(serviceUidSet);
-        mCellNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
+        mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
         if (SdkLevel.isAtLeastT()) {
-            cb.expectCapabilitiesThat(mCellNetworkAgent,
-                    caps -> caps.getAllowedUids().equals(serviceUidSet));
+            cb.expectCaps(mCellAgent, c -> c.getAllowedUids().equals(serviceUidSet));
         } else {
             // S must ignore access UIDs.
             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
@@ -16079,10 +16393,9 @@
 
         // ...but not to some other UID. Rejection sets UIDs to the empty set
         ncb.setAllowedUids(nonServiceUidSet);
-        mCellNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
+        mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
         if (SdkLevel.isAtLeastT()) {
-            cb.expectCapabilitiesThat(mCellNetworkAgent,
-                    caps -> caps.getAllowedUids().isEmpty());
+            cb.expectCaps(mCellAgent, c -> c.getAllowedUids().isEmpty());
         } else {
             // S must ignore access UIDs.
             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
@@ -16090,11 +16403,11 @@
 
         // ...and also not to multiple UIDs even including the service UID
         ncb.setAllowedUids(serviceUidSetPlus);
-        mCellNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
+        mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
 
-        mCellNetworkAgent.disconnect();
-        cb.expect(CallbackEntry.LOST, mCellNetworkAgent);
+        mCellAgent.disconnect();
+        cb.expect(LOST, mCellAgent);
         mCm.unregisterNetworkCallback(cb);
 
         // Must be unset before touching the transports, because remove and add transport types
@@ -16108,12 +16421,11 @@
                 .addTransportType(TRANSPORT_WIFI)
                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
                 .build(), cb);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
-                new LinkProperties(), ncb.build());
-        mWiFiNetworkAgent.connect(true);
-        cb.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncb.build());
+        mWiFiAgent.connect(true);
+        cb.expectAvailableThenValidatedCallbacks(mWiFiAgent);
         ncb.setAllowedUids(serviceUidSet);
-        mWiFiNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
+        mWiFiAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
         mCm.unregisterNetworkCallback(cb);
     }
@@ -16184,7 +16496,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]);
                 }
             });
@@ -16300,12 +16612,12 @@
     public void testMobileDataPreferredUidsChanged() throws Exception {
         final InOrder inorder = inOrder(mMockNetd);
         registerDefaultNetworkCallbacks();
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
 
-        final int cellNetId = mCellNetworkAgent.getNetwork().netId;
+        final int cellNetId = mCellAgent.getNetwork().netId;
         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
                 cellNetId, INetd.PERMISSION_NONE));
 
@@ -16358,13 +16670,13 @@
         cellNetworkCallback.assertNoCallback();
 
         registerDefaultNetworkCallbacks();
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
-        final int wifiNetId = mWiFiNetworkAgent.getNetwork().netId;
+        final int wifiNetId = mWiFiAgent.getNetwork().netId;
         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
                 wifiNetId, INetd.PERMISSION_NONE));
 
@@ -16385,14 +16697,14 @@
 
         // Cellular network connected. mTestPackageDefaultNetworkCallback should receive
         // callback with cellular network and net id and uid ranges should be updated to netd.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         mDefaultNetworkCallback.assertNoCallback();
-        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
-        final int cellNetId = mCellNetworkAgent.getNetwork().netId;
+        final int cellNetId = mCellAgent.getNetwork().netId;
         final NativeUidRangeConfig cellConfig = new NativeUidRangeConfig(cellNetId, uidRanges,
                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
@@ -16402,26 +16714,26 @@
 
         // Cellular network disconnected. mTestPackageDefaultNetworkCallback should receive
         // callback with wifi network from fallback request.
-        mCellNetworkAgent.disconnect();
+        mCellAgent.disconnect();
         mDefaultNetworkCallback.assertNoCallback();
-        cellNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        mTestPackageDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        cellNetworkCallback.expect(LOST, mCellAgent);
+        mTestPackageDefaultNetworkCallback.expect(LOST, mCellAgent);
+        mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
         inorder.verify(mMockNetd).networkDestroy(cellNetId);
 
         // Cellular network comes back. mTestPackageDefaultNetworkCallback should receive
         // callback with cellular network.
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         mDefaultNetworkCallback.assertNoCallback();
-        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
-        final int cellNetId2 = mCellNetworkAgent.getNetwork().netId;
+        final int cellNetId2 = mCellAgent.getNetwork().netId;
         final NativeUidRangeConfig cellConfig2 = new NativeUidRangeConfig(cellNetId2, uidRanges,
                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
@@ -16431,11 +16743,11 @@
 
         // Wifi network disconnected. mTestPackageDefaultNetworkCallback should not receive
         // any callback.
-        mWiFiNetworkAgent.disconnect();
-        mDefaultNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mWiFiAgent.disconnect();
+        mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
+        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
         mTestPackageDefaultNetworkCallback.assertNoCallback();
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
         waitForIdle();
         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
@@ -16467,15 +16779,15 @@
             cellFactory.expectRequestAdds(2);
             cellFactory.assertRequestCountEquals(2);
 
-            mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-            mWiFiNetworkAgent.connect(true);
+            mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+            mWiFiAgent.connect(true);
 
             // The cellFactory however is outscored, and should lose default internet request.
             // But it should still see mobile data preferred request.
             cellFactory.expectRequestRemove();
             cellFactory.assertRequestCountEquals(1);
 
-            mWiFiNetworkAgent.disconnect();
+            mWiFiAgent.disconnect();
             // The network satisfying the default internet request has disconnected, so the
             // cellFactory sees the default internet requests again.
             cellFactory.expectRequestAdd();
@@ -16517,7 +16829,7 @@
         final UserHandle testHandle = setupEnterpriseNetwork();
 
         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
-        final int cellNetId = mCellNetworkAgent.getNetwork().netId;
+        final int cellNetId = mCellAgent.getNetwork().netId;
         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
                 cellNetId, INetd.PERMISSION_NONE));
 
@@ -16590,28 +16902,28 @@
 
         // Register callbacks and have wifi network as default network.
         registerDefaultNetworkCallbacks();
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.connect(true);
-        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(),
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.connect(true);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(),
                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
         // Set MOBILE_DATA_PREFERRED_UIDS setting with TEST_WORK_PROFILE_APP_UID and
         // TEST_PACKAGE_UID. Both mProfileDefaultNetworkCallback and
         // mTestPackageDefaultNetworkCallback should receive callback with cell network.
         setAndUpdateMobileDataPreferredUids(Set.of(TEST_WORK_PROFILE_APP_UID, TEST_PACKAGE_UID));
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
+        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
         mDefaultNetworkCallback.assertNoCallback();
-        mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(),
+        mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(),
                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
         // Set user profile network preference with test profile. mProfileDefaultNetworkCallback
         // should receive callback with higher priority network preference (enterprise network).
@@ -16626,7 +16938,7 @@
         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
         // Set oem network preference with TEST_PACKAGE_UID. mTestPackageDefaultNetworkCallback
         // should receive callback with higher priority network preference (current default network)
@@ -16637,8 +16949,8 @@
         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
         assertNoCallbacks(mDefaultNetworkCallback, mProfileDefaultNetworkCallback);
-        mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+        assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
 
         // Set oem network preference with TEST_WORK_PROFILE_APP_UID. Both
@@ -16650,11 +16962,11 @@
         setupSetOemNetworkPreferenceForPreferenceTest(
                 networkPref, uidRanges2, "com.android.test", testHandle);
         mDefaultNetworkCallback.assertNoCallback();
-        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-        mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        assertEquals(mWiFiNetworkAgent.getNetwork(),
+        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+        mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
+        assertEquals(mWiFiAgent.getNetwork(),
                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
         // Remove oem network preference, mProfileDefaultNetworkCallback should receive callback
         // with current highest priority network preference (enterprise network) and the others
@@ -16666,23 +16978,23 @@
         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
         // Remove user profile network preference.
         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
                 r -> r.run(), listener);
         listener.expectOnComplete();
         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
-        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-        assertEquals(mCellNetworkAgent.getNetwork(),
+        mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
+        assertEquals(mCellAgent.getNetwork(),
                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
-        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
+        assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
 
         // Disconnect wifi
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         assertNoCallbacks(mProfileDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
-        mDefaultNetworkCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
+        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
     }
 
     @Test
@@ -16696,13 +17008,13 @@
     public void testUpdateRateLimit_EnableDisable() throws Exception {
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connect(true);
 
         final LinkProperties cellLp = new LinkProperties();
         cellLp.setInterfaceName(MOBILE_IFNAME);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(false);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(false);
 
         waitForIdle();
 
@@ -16735,8 +17047,8 @@
     public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connect(true);
 
         waitForIdle();
 
@@ -16751,8 +17063,8 @@
 
         final LinkProperties cellLp = new LinkProperties();
         cellLp.setInterfaceName(MOBILE_IFNAME);
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
-        mCellNetworkAgent.connect(false);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellAgent.connect(false);
         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == cellLp.getInterfaceName()
                 && it.second == rateLimitInBytesPerSec));
     }
@@ -16762,8 +17074,8 @@
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connectWithoutInternet();
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connectWithoutInternet();
 
         waitForIdle();
 
@@ -16787,8 +17099,8 @@
         // - ensure network interface is not rate limited
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connect(true);
         waitForIdle();
 
         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
@@ -16800,14 +17112,14 @@
                 it -> it.first == wifiLp.getInterfaceName()
                         && it.second == rateLimitInBytesPerSec));
 
-        mWiFiNetworkAgent.disconnect();
+        mWiFiAgent.disconnect();
         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
 
         setIngressRateLimit(-1);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connect(true);
         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
     }
 
@@ -16815,8 +17127,8 @@
     public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connect(true);
         waitForIdle();
 
         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
@@ -16845,8 +17157,8 @@
     public void testUpdateRateLimit_DoesNothingBeforeT() throws Exception {
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+        mWiFiAgent.connect(true);
         waitForIdle();
 
         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
@@ -16885,8 +17197,8 @@
 
         final String bssid1 = "AA:AA:AA:AA:AA:AA";
         final String bssid2 = "BB:BB:BB:BB:BB:BB";
-        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
-        mCellNetworkAgent.connect(true);
+        mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellAgent.connect(true);
         NetworkCapabilities wifiNc1 = new NetworkCapabilities()
                 .addCapability(NET_CAPABILITY_INTERNET)
                 .addCapability(NET_CAPABILITY_NOT_VPN)
@@ -16899,105 +17211,100 @@
                 .setTransportInfo(new WifiInfo.Builder().setBssid(bssid2).build());
         final LinkProperties wifiLp = new LinkProperties();
         wifiLp.setInterfaceName(WIFI_IFNAME);
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
-        mWiFiNetworkAgent.connect(true);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
+        mWiFiAgent.connect(true);
 
         // The default network will be switching to Wi-Fi Network.
         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI).build();
         mCm.requestNetwork(wifiRequest, wifiNetworkCallback);
-        wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+        wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
         registerDefaultNetworkCallbacks();
-        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+        mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
 
         // There is a bug in the current code where ignoring validation after roam will not
         // correctly change the default network if the result if the validation is partial or
         // captive portal. TODO : fix the bug and reinstate this code.
         if (false) {
             // Wi-Fi roaming from wifiNc1 to wifiNc2 but the network is now behind a captive portal.
-            mWiFiNetworkAgent.setNetworkCapabilities(wifiNc2, true /* sendToConnectivityService */);
+            mWiFiAgent.setNetworkCapabilities(wifiNc2, true /* sendToConnectivityService */);
             // The only thing changed in this CAPS is the BSSID, which can't be tested for in this
             // test because it's redacted.
-            wifiNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                    mWiFiNetworkAgent);
-            mDefaultNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                    mWiFiNetworkAgent);
-            mWiFiNetworkAgent.setNetworkPortal(TEST_REDIRECT_URL, false /* isStrictMode */);
-            mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
+            wifiNetworkCallback.expectCaps(mWiFiAgent);
+            mDefaultNetworkCallback.expectCaps(mWiFiAgent);
+            mWiFiAgent.setNetworkPortal(TEST_REDIRECT_URL, false /* privateDnsProbeSent */);
+            mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
             // Wi-Fi is now detected to have a portal : cell should become the default network.
-            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-            wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED,
-                    mWiFiNetworkAgent);
-            wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL,
-                    mWiFiNetworkAgent);
+            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
+            wifiNetworkCallback.expectCaps(mWiFiAgent,
+                    c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
+            wifiNetworkCallback.expectCaps(mWiFiAgent,
+                    c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
 
             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
-            mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
-            mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-            wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_CAPTIVE_PORTAL,
-                    mWiFiNetworkAgent);
+            mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
+            mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+            wifiNetworkCallback.expectCaps(mWiFiAgent,
+                    c -> !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
 
             // Wi-Fi roaming from wifiNc2 to wifiNc1, and the network now has partial connectivity.
-            mWiFiNetworkAgent.setNetworkCapabilities(wifiNc1, true);
-            wifiNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                    mWiFiNetworkAgent);
-            mDefaultNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                    mWiFiNetworkAgent);
-            mWiFiNetworkAgent.setNetworkPartial();
-            mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
+            mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
+            wifiNetworkCallback.expectCaps(mWiFiAgent);
+            mDefaultNetworkCallback.expectCaps(mWiFiAgent);
+            mWiFiAgent.setNetworkPartial();
+            mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
             // Wi-Fi now only offers partial connectivity, so in the absence of accepting partial
             // connectivity explicitly for this network, it loses default status to cell.
-            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
-            wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
-                    mWiFiNetworkAgent);
+            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
+            wifiNetworkCallback.expectCaps(mWiFiAgent,
+                    c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
 
             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
-            mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
-            mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
-            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
-            wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
-                    mWiFiNetworkAgent);
+            mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
+            mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
+            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
+            wifiNetworkCallback.expectCaps(mWiFiAgent,
+                    c -> !c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
         }
         mCm.unregisterNetworkCallback(wifiNetworkCallback);
 
         // Wi-Fi roams from wifiNc1 to wifiNc2, and now becomes really invalid. If validation
         // failures after roam are not ignored, this will cause cell to become the default network.
         // If they are ignored, this will not cause a switch until later.
-        mWiFiNetworkAgent.setNetworkCapabilities(wifiNc2, true);
-        mDefaultNetworkCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED,
-                mWiFiNetworkAgent);
-        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
-        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
+        mWiFiAgent.setNetworkCapabilities(wifiNc2, true);
+        mDefaultNetworkCallback.expectCaps(mWiFiAgent);
+        mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
+        mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
 
         if (enabled) {
             // Network validation failed, but the result will be ignored.
-            assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+            assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
                     NET_CAPABILITY_VALIDATED));
-            mWiFiNetworkAgent.setNetworkValid(false);
+            mWiFiAgent.setNetworkValid(false);
 
             // Behavior of after config_validationFailureAfterRoamIgnoreTimeMillis
             ConditionVariable waitForValidationBlock = new ConditionVariable();
             doReturn(50).when(mResources)
                     .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
             // Wi-Fi roaming from wifiNc2 to wifiNc1.
-            mWiFiNetworkAgent.setNetworkCapabilities(wifiNc1, true);
-            mWiFiNetworkAgent.setNetworkInvalid(false);
+            mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
+            mWiFiAgent.setNetworkInvalid(false);
             waitForValidationBlock.block(150);
-            mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
-            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+            mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
+            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
         } else {
-            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+            mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
         }
 
         // Wi-Fi is still connected and would become the default network if cell were to
         // disconnect. This assertion ensures that the switch to cellular was not caused by
         // Wi-Fi disconnecting (e.g., because the capability change to wifiNc2 caused it
         // to stop satisfying the default request).
-        mCellNetworkAgent.disconnect();
-        mDefaultNetworkCallback.expect(CallbackEntry.LOST, mCellNetworkAgent);
-        mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        mCellAgent.disconnect();
+        mDefaultNetworkCallback.expect(LOST, mCellAgent);
+        mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
 
     }
 
@@ -17080,8 +17387,8 @@
         lp.setInterfaceName(WIFI_IFNAME);
         lp.setMtu(mtu);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.sendLinkProperties(lp);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiAgent.sendLinkProperties(lp);
 
         waitForIdle();
         verify(mMockNetd).interfaceSetMtu(eq(WIFI_IFNAME), eq(mtu));
@@ -17094,12 +17401,12 @@
         lp.setInterfaceName(WIFI_IFNAME);
         lp.setMtu(mtu);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
 
         LinkProperties lp2 = new LinkProperties(lp);
         lp2.setMtu(mtu2);
 
-        mWiFiNetworkAgent.sendLinkProperties(lp2);
+        mWiFiAgent.sendLinkProperties(lp2);
 
         waitForIdle();
         verify(mMockNetd).interfaceSetMtu(eq(WIFI_IFNAME), eq(mtu2));
@@ -17112,8 +17419,8 @@
         lp.setInterfaceName(WIFI_IFNAME);
         lp.setMtu(mtu);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
-        mWiFiNetworkAgent.sendLinkProperties(new LinkProperties(lp));
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
+        mWiFiAgent.sendLinkProperties(new LinkProperties(lp));
 
         waitForIdle();
         verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
@@ -17126,13 +17433,13 @@
         lp.setInterfaceName(WIFI_IFNAME);
         lp.setMtu(mtu);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
 
         LinkProperties lp2 = new LinkProperties();
         assertNull(lp2.getInterfaceName());
         lp2.setMtu(mtu);
 
-        mWiFiNetworkAgent.sendLinkProperties(new LinkProperties(lp2));
+        mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
 
         waitForIdle();
         verify(mMockNetd, never()).interfaceSetMtu(any(), anyInt());
@@ -17145,16 +17452,26 @@
         lp.setInterfaceName(WIFI_IFNAME);
         lp.setMtu(mtu);
 
-        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
+        mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
 
         final String ifaceName2 = WIFI_IFNAME + "_2";
         LinkProperties lp2 = new LinkProperties();
         lp2.setInterfaceName(ifaceName2);
         lp2.setMtu(mtu);
 
-        mWiFiNetworkAgent.sendLinkProperties(new LinkProperties(lp2));
+        mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
 
         waitForIdle();
         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/IpSecServiceTest.java b/tests/unit/java/com/android/server/IpSecServiceTest.java
index 6955620..4b6857c 100644
--- a/tests/unit/java/com/android/server/IpSecServiceTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceTest.java
@@ -82,7 +82,7 @@
     private static final int MAX_NUM_ENCAP_SOCKETS = 100;
     private static final int MAX_NUM_SPIS = 100;
     private static final int TEST_UDP_ENCAP_INVALID_PORT = 100;
-    private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 100000;
+    private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 200000;
 
     private static final InetAddress INADDR_ANY;
 
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 5808beb..0680772 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -16,16 +16,25 @@
 
 package com.android.server;
 
+import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.nsd.NsdManager.FAILURE_BAD_PARAMETERS;
 import static android.net.nsd.NsdManager.FAILURE_INTERNAL_ERROR;
+import static android.net.nsd.NsdManager.FAILURE_OPERATION_NOT_RUNNING;
+
+import static com.android.testutils.ContextUtils.mockService;
 
 import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doReturn;
@@ -36,13 +45,15 @@
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 import android.compat.testing.PlatformCompatChangeRule;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.net.INetd;
-import android.net.InetAddresses;
+import android.net.Network;
+import android.net.connectivity.ConnectivityCompatChanges;
 import android.net.mdns.aidl.DiscoveryInfo;
 import android.net.mdns.aidl.GetAddressInfo;
 import android.net.mdns.aidl.IMDnsEventListener;
@@ -63,10 +74,17 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
 
 import androidx.annotation.NonNull;
 import androidx.test.filters.SmallTest;
 
+import com.android.server.NsdService.Dependencies;
+import com.android.server.connectivity.mdns.MdnsAdvertiser;
+import com.android.server.connectivity.mdns.MdnsDiscoveryManager;
+import com.android.server.connectivity.mdns.MdnsServiceBrowserListener;
+import com.android.server.connectivity.mdns.MdnsServiceInfo;
+import com.android.server.connectivity.mdns.MdnsSocketProvider;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRunner;
 import com.android.testutils.HandlerUtils;
@@ -82,7 +100,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.net.UnknownHostException;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
 import java.util.Queue;
 
 // TODOs:
@@ -96,11 +117,13 @@
     private static final long CLEANUP_DELAY_MS = 500;
     private static final long TIMEOUT_MS = 500;
     private static final String SERVICE_NAME = "a_name";
-    private static final String SERVICE_TYPE = "a_type";
+    private static final String SERVICE_TYPE = "_test._tcp";
     private static final String SERVICE_FULL_NAME = SERVICE_NAME + "." + SERVICE_TYPE;
     private static final String DOMAIN_NAME = "mytestdevice.local";
     private static final int PORT = 2201;
     private static final int IFACE_IDX_ANY = 0;
+    private static final String IPV4_ADDRESS = "192.0.2.0";
+    private static final String IPV6_ADDRESS = "2001:db8::";
 
     // Records INsdManagerCallback created when NsdService#connect is called.
     // Only accessed on the test thread, since NsdService#connect is called by the NsdManager
@@ -112,6 +135,10 @@
     @Mock Context mContext;
     @Mock ContentResolver mResolver;
     @Mock MDnsManager mMockMDnsM;
+    @Mock Dependencies mDeps;
+    @Mock MdnsDiscoveryManager mDiscoveryManager;
+    @Mock MdnsAdvertiser mAdvertiser;
+    @Mock MdnsSocketProvider mSocketProvider;
     HandlerThread mThread;
     TestHandler mHandler;
     NsdService mService;
@@ -133,9 +160,7 @@
         mThread.start();
         mHandler = new TestHandler(mThread.getLooper());
         when(mContext.getContentResolver()).thenReturn(mResolver);
-        doReturn(MDnsManager.MDNS_SERVICE).when(mContext)
-                .getSystemServiceName(MDnsManager.class);
-        doReturn(mMockMDnsM).when(mContext).getSystemService(MDnsManager.MDNS_SERVICE);
+        mockService(mContext, MDnsManager.class, MDnsManager.MDNS_SERVICE, mMockMDnsM);
         if (mContext.getSystemService(MDnsManager.class) == null) {
             // Test is using mockito-extended
             doCallRealMethod().when(mContext).getSystemService(MDnsManager.class);
@@ -146,6 +171,10 @@
         doReturn(true).when(mMockMDnsM).discover(anyInt(), anyString(), anyInt());
         doReturn(true).when(mMockMDnsM).resolve(
                 anyInt(), anyString(), anyString(), anyString(), anyInt());
+        doReturn(false).when(mDeps).isMdnsDiscoveryManagerEnabled(any(Context.class));
+        doReturn(mDiscoveryManager).when(mDeps).makeMdnsDiscoveryManager(any(), any());
+        doReturn(mSocketProvider).when(mDeps).makeMdnsSocketProvider(any(), any());
+        doReturn(mAdvertiser).when(mDeps).makeMdnsAdvertiser(any(), any(), any());
 
         mService = makeService();
     }
@@ -159,7 +188,7 @@
     }
 
     @Test
-    @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testPreSClients() throws Exception {
         // Pre S client connected, the daemon should be started.
         connectClient(mService);
@@ -186,7 +215,7 @@
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testNoDaemonStartedWhenClientsConnect() throws Exception {
         // Creating an NsdManager will not cause daemon startup.
         connectClient(mService);
@@ -220,7 +249,7 @@
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testClientRequestsAreGCedAtDisconnection() throws Exception {
         final NsdManager client = connectClient(mService);
         final INsdManagerCallback cb1 = getCallback();
@@ -263,7 +292,7 @@
     }
 
     @Test
-    @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+    @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
     public void testCleanupDelayNoRequestActive() throws Exception {
         final NsdManager client = connectClient(mService);
 
@@ -382,13 +411,42 @@
         final NsdServiceInfo resolvedService = resInfoCaptor.getValue();
         assertEquals(SERVICE_NAME, resolvedService.getServiceName());
         assertEquals("." + SERVICE_TYPE, resolvedService.getServiceType());
-        assertEquals(InetAddresses.parseNumericAddress(serviceAddress), resolvedService.getHost());
+        assertEquals(parseNumericAddress(serviceAddress), resolvedService.getHost());
         assertEquals(servicePort, resolvedService.getPort());
         assertNull(resolvedService.getNetwork());
         assertEquals(interfaceIdx, resolvedService.getInterfaceIndex());
     }
 
     @Test
+    public void testDiscoverOnBlackholeNetwork() throws Exception {
+        final NsdManager client = connectClient(mService);
+        final DiscoveryListener discListener = mock(DiscoveryListener.class);
+        client.discoverServices(SERVICE_TYPE, PROTOCOL, discListener);
+        waitForIdle();
+
+        final IMDnsEventListener eventListener = getEventListener();
+        final ArgumentCaptor<Integer> discIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).discover(discIdCaptor.capture(), eq(SERVICE_TYPE),
+                eq(0) /* interfaceIdx */);
+        // NsdManager uses a separate HandlerThread to dispatch callbacks (on ServiceHandler), so
+        // this needs to use a timeout
+        verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
+
+        final DiscoveryInfo discoveryInfo = new DiscoveryInfo(
+                discIdCaptor.getValue(),
+                IMDnsEventListener.SERVICE_FOUND,
+                SERVICE_NAME,
+                SERVICE_TYPE,
+                DOMAIN_NAME,
+                123 /* interfaceIdx */,
+                INetd.DUMMY_NET_ID); // netId of the blackhole network
+        eventListener.onServiceDiscoveryStatus(discoveryInfo);
+        waitForIdle();
+
+        verify(discListener, never()).onServiceFound(any());
+    }
+
+    @Test
     public void testServiceRegistrationSuccessfulAndFailed() throws Exception {
         final NsdManager client = connectClient(mService);
         final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
@@ -555,12 +613,549 @@
                 anyInt()/* interfaceIdx */);
     }
 
+    @Test
+    public void testStopServiceResolution() {
+        final NsdManager client = connectClient(mService);
+        final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+        final ResolveListener resolveListener = mock(ResolveListener.class);
+        client.resolveService(request, resolveListener);
+        waitForIdle();
+
+        final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+                eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+        final int resolveId = resolvIdCaptor.getValue();
+        client.stopServiceResolution(resolveListener);
+        waitForIdle();
+
+        verify(mMockMDnsM).stopOperation(resolveId);
+        verify(resolveListener, timeout(TIMEOUT_MS)).onResolutionStopped(argThat(ns ->
+                request.getServiceName().equals(ns.getServiceName())
+                        && request.getServiceType().equals(ns.getServiceType())));
+    }
+
+    @Test
+    public void testStopResolutionFailed() {
+        final NsdManager client = connectClient(mService);
+        final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+        final ResolveListener resolveListener = mock(ResolveListener.class);
+        client.resolveService(request, resolveListener);
+        waitForIdle();
+
+        final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+                eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+        final int resolveId = resolvIdCaptor.getValue();
+        doReturn(false).when(mMockMDnsM).stopOperation(anyInt());
+        client.stopServiceResolution(resolveListener);
+        waitForIdle();
+
+        verify(mMockMDnsM).stopOperation(resolveId);
+        verify(resolveListener, timeout(TIMEOUT_MS)).onStopResolutionFailed(argThat(ns ->
+                        request.getServiceName().equals(ns.getServiceName())
+                                && request.getServiceType().equals(ns.getServiceType())),
+                eq(FAILURE_OPERATION_NOT_RUNNING));
+    }
+
+    @Test @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    public void testStopResolutionDuringGettingAddress() throws RemoteException {
+        final NsdManager client = connectClient(mService);
+        final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+        final ResolveListener resolveListener = mock(ResolveListener.class);
+        client.resolveService(request, resolveListener);
+        waitForIdle();
+
+        final IMDnsEventListener eventListener = getEventListener();
+        final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+                eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+        // Resolve service successfully.
+        final ResolutionInfo resolutionInfo = new ResolutionInfo(
+                resolvIdCaptor.getValue(),
+                IMDnsEventListener.SERVICE_RESOLVED,
+                null /* serviceName */,
+                null /* serviceType */,
+                null /* domain */,
+                SERVICE_FULL_NAME,
+                DOMAIN_NAME,
+                PORT,
+                new byte[0] /* txtRecord */,
+                IFACE_IDX_ANY);
+        doReturn(true).when(mMockMDnsM).getServiceAddress(anyInt(), any(), anyInt());
+        eventListener.onServiceResolutionStatus(resolutionInfo);
+        waitForIdle();
+
+        final ArgumentCaptor<Integer> getAddrIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).getServiceAddress(getAddrIdCaptor.capture(), eq(DOMAIN_NAME),
+                eq(IFACE_IDX_ANY));
+
+        final int getAddrId = getAddrIdCaptor.getValue();
+        client.stopServiceResolution(resolveListener);
+        waitForIdle();
+
+        verify(mMockMDnsM).stopOperation(getAddrId);
+        verify(resolveListener, timeout(TIMEOUT_MS)).onResolutionStopped(argThat(ns ->
+                request.getServiceName().equals(ns.getServiceName())
+                        && request.getServiceType().equals(ns.getServiceType())));
+    }
+
+    private void verifyUpdatedServiceInfo(NsdServiceInfo info, String serviceName,
+            String serviceType, String address, int port, int interfaceIndex, Network network) {
+        assertEquals(serviceName, info.getServiceName());
+        assertEquals(serviceType, info.getServiceType());
+        assertTrue(info.getHostAddresses().contains(parseNumericAddress(address)));
+        assertEquals(port, info.getPort());
+        assertEquals(network, info.getNetwork());
+        assertEquals(interfaceIndex, info.getInterfaceIndex());
+    }
+
+    @Test
+    public void testRegisterAndUnregisterServiceInfoCallback() throws RemoteException {
+        final NsdManager client = connectClient(mService);
+        final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+        final NsdManager.ServiceInfoCallback serviceInfoCallback = mock(
+                NsdManager.ServiceInfoCallback.class);
+        client.registerServiceInfoCallback(request, Runnable::run, serviceInfoCallback);
+        waitForIdle();
+
+        final IMDnsEventListener eventListener = getEventListener();
+        final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+                eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+        // Resolve service successfully.
+        final ResolutionInfo resolutionInfo = new ResolutionInfo(
+                resolvIdCaptor.getValue(),
+                IMDnsEventListener.SERVICE_RESOLVED,
+                null /* serviceName */,
+                null /* serviceType */,
+                null /* domain */,
+                SERVICE_FULL_NAME,
+                DOMAIN_NAME,
+                PORT,
+                new byte[0] /* txtRecord */,
+                IFACE_IDX_ANY);
+        doReturn(true).when(mMockMDnsM).getServiceAddress(anyInt(), any(), anyInt());
+        eventListener.onServiceResolutionStatus(resolutionInfo);
+        waitForIdle();
+
+        final ArgumentCaptor<Integer> getAddrIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).getServiceAddress(getAddrIdCaptor.capture(), eq(DOMAIN_NAME),
+                eq(IFACE_IDX_ANY));
+
+        // First address info
+        final String v4Address = "192.0.2.1";
+        final String v6Address = "2001:db8::";
+        final GetAddressInfo addressInfo1 = new GetAddressInfo(
+                getAddrIdCaptor.getValue(),
+                IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS,
+                SERVICE_FULL_NAME,
+                v4Address,
+                IFACE_IDX_ANY,
+                999 /* netId */);
+        eventListener.onGettingServiceAddressStatus(addressInfo1);
+        waitForIdle();
+
+        final ArgumentCaptor<NsdServiceInfo> updateInfoCaptor =
+                ArgumentCaptor.forClass(NsdServiceInfo.class);
+        verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(1))
+                .onServiceUpdated(updateInfoCaptor.capture());
+        verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(0) /* info */, SERVICE_NAME,
+                "." + SERVICE_TYPE, v4Address, PORT, IFACE_IDX_ANY, new Network(999));
+
+        // Second address info
+        final GetAddressInfo addressInfo2 = new GetAddressInfo(
+                getAddrIdCaptor.getValue(),
+                IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS,
+                SERVICE_FULL_NAME,
+                v6Address,
+                IFACE_IDX_ANY,
+                999 /* netId */);
+        eventListener.onGettingServiceAddressStatus(addressInfo2);
+        waitForIdle();
+
+        verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(2))
+                .onServiceUpdated(updateInfoCaptor.capture());
+        verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(1) /* info */, SERVICE_NAME,
+                "." + SERVICE_TYPE, v6Address, PORT, IFACE_IDX_ANY, new Network(999));
+
+        client.unregisterServiceInfoCallback(serviceInfoCallback);
+        waitForIdle();
+
+        verify(serviceInfoCallback, timeout(TIMEOUT_MS)).onServiceInfoCallbackUnregistered();
+    }
+
+    @Test
+    public void testRegisterServiceCallbackFailed() throws Exception {
+        final NsdManager client = connectClient(mService);
+        final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+        final NsdManager.ServiceInfoCallback subscribeListener = mock(
+                NsdManager.ServiceInfoCallback.class);
+        client.registerServiceInfoCallback(request, Runnable::run, subscribeListener);
+        waitForIdle();
+
+        final IMDnsEventListener eventListener = getEventListener();
+        final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+                eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+        // Fail to resolve service.
+        final ResolutionInfo resolutionFailedInfo = new ResolutionInfo(
+                resolvIdCaptor.getValue(),
+                IMDnsEventListener.SERVICE_RESOLUTION_FAILED,
+                null /* serviceName */,
+                null /* serviceType */,
+                null /* domain */,
+                null /* serviceFullName */,
+                null /* domainName */,
+                0 /* port */,
+                new byte[0] /* txtRecord */,
+                IFACE_IDX_ANY);
+        eventListener.onServiceResolutionStatus(resolutionFailedInfo);
+        verify(subscribeListener, timeout(TIMEOUT_MS))
+                .onServiceInfoCallbackRegistrationFailed(eq(FAILURE_BAD_PARAMETERS));
+    }
+
+    @Test
+    public void testUnregisterNotRegisteredCallback() {
+        final NsdManager client = connectClient(mService);
+        final NsdManager.ServiceInfoCallback serviceInfoCallback = mock(
+                NsdManager.ServiceInfoCallback.class);
+
+        assertThrows(IllegalArgumentException.class, () ->
+                client.unregisterServiceInfoCallback(serviceInfoCallback));
+    }
+
+    private void setMdnsDiscoveryManagerEnabled() {
+        doReturn(true).when(mDeps).isMdnsDiscoveryManagerEnabled(any(Context.class));
+    }
+
+    private void setMdnsAdvertiserEnabled() {
+        doReturn(true).when(mDeps).isMdnsAdvertiserEnabled(any(Context.class));
+    }
+
+    @Test
+    public void testMdnsDiscoveryManagerFeature() {
+        // Create NsdService w/o feature enabled.
+        final NsdManager client = connectClient(mService);
+        final DiscoveryListener discListenerWithoutFeature = mock(DiscoveryListener.class);
+        client.discoverServices(SERVICE_TYPE, PROTOCOL, discListenerWithoutFeature);
+        waitForIdle();
+
+        final ArgumentCaptor<Integer> legacyIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).discover(legacyIdCaptor.capture(), any(), anyInt());
+        verifyNoMoreInteractions(mDiscoveryManager);
+
+        setMdnsDiscoveryManagerEnabled();
+        final DiscoveryListener discListenerWithFeature = mock(DiscoveryListener.class);
+        client.discoverServices(SERVICE_TYPE, PROTOCOL, discListenerWithFeature);
+        waitForIdle();
+
+        final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+        final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
+                ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+        verify(mDiscoveryManager).registerListener(eq(serviceTypeWithLocalDomain),
+                listenerCaptor.capture(), any());
+
+        client.stopServiceDiscovery(discListenerWithoutFeature);
+        waitForIdle();
+        verify(mMockMDnsM).stopOperation(legacyIdCaptor.getValue());
+
+        client.stopServiceDiscovery(discListenerWithFeature);
+        waitForIdle();
+        verify(mDiscoveryManager).unregisterListener(serviceTypeWithLocalDomain,
+                listenerCaptor.getValue());
+    }
+
+    @Test
+    public void testDiscoveryWithMdnsDiscoveryManager() {
+        setMdnsDiscoveryManagerEnabled();
+
+        final NsdManager client = connectClient(mService);
+        final DiscoveryListener discListener = mock(DiscoveryListener.class);
+        final Network network = new Network(999);
+        final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+        // Verify the discovery start / stop.
+        final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
+                ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+        client.discoverServices(SERVICE_TYPE, PROTOCOL, network, r -> r.run(), discListener);
+        waitForIdle();
+        verify(mSocketProvider).startMonitoringSockets();
+        verify(mDiscoveryManager).registerListener(eq(serviceTypeWithLocalDomain),
+                listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork())));
+        verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
+
+        final MdnsServiceBrowserListener listener = listenerCaptor.getValue();
+        final MdnsServiceInfo foundInfo = new MdnsServiceInfo(
+                SERVICE_NAME, /* serviceInstanceName */
+                serviceTypeWithLocalDomain.split("\\."), /* serviceType */
+                List.of(), /* subtypes */
+                new String[] {"android", "local"}, /* hostName */
+                12345, /* port */
+                IPV4_ADDRESS,
+                IPV6_ADDRESS,
+                List.of(), /* textStrings */
+                List.of(), /* textEntries */
+                1234, /* interfaceIndex */
+                network);
+
+        // Verify onServiceNameDiscovered callback
+        listener.onServiceNameDiscovered(foundInfo);
+        verify(discListener, timeout(TIMEOUT_MS)).onServiceFound(argThat(info ->
+                info.getServiceName().equals(SERVICE_NAME)
+                        && info.getServiceType().equals(SERVICE_TYPE)
+                        && info.getNetwork().equals(network)));
+
+        final MdnsServiceInfo removedInfo = new MdnsServiceInfo(
+                SERVICE_NAME, /* serviceInstanceName */
+                serviceTypeWithLocalDomain.split("\\."), /* serviceType */
+                null, /* subtypes */
+                null, /* hostName */
+                0, /* port */
+                null, /* ipv4Address */
+                null, /* ipv6Address */
+                null, /* textStrings */
+                null, /* textEntries */
+                1234, /* interfaceIndex */
+                network);
+        // Verify onServiceNameRemoved callback
+        listener.onServiceNameRemoved(removedInfo);
+        verify(discListener, timeout(TIMEOUT_MS)).onServiceLost(argThat(info ->
+                info.getServiceName().equals(SERVICE_NAME)
+                        && info.getServiceType().equals(SERVICE_TYPE)
+                        && info.getNetwork().equals(network)));
+
+        client.stopServiceDiscovery(discListener);
+        waitForIdle();
+        verify(mDiscoveryManager).unregisterListener(eq(serviceTypeWithLocalDomain), any());
+        verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStopped(SERVICE_TYPE);
+        verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).stopMonitoringSockets();
+    }
+
+    @Test
+    public void testDiscoveryWithMdnsDiscoveryManager_FailedWithInvalidServiceType() {
+        setMdnsDiscoveryManagerEnabled();
+
+        final NsdManager client = connectClient(mService);
+        final DiscoveryListener discListener = mock(DiscoveryListener.class);
+        final Network network = new Network(999);
+        final String invalidServiceType = "a_service";
+        client.discoverServices(
+                invalidServiceType, PROTOCOL, network, r -> r.run(), discListener);
+        waitForIdle();
+        verify(discListener, timeout(TIMEOUT_MS))
+                .onStartDiscoveryFailed(invalidServiceType, FAILURE_INTERNAL_ERROR);
+
+        final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+        client.discoverServices(
+                serviceTypeWithLocalDomain, PROTOCOL, network, r -> r.run(), discListener);
+        waitForIdle();
+        verify(discListener, timeout(TIMEOUT_MS))
+                .onStartDiscoveryFailed(serviceTypeWithLocalDomain, FAILURE_INTERNAL_ERROR);
+
+        final String serviceTypeWithoutTcpOrUdpEnding = "_test._com";
+        client.discoverServices(
+                serviceTypeWithoutTcpOrUdpEnding, PROTOCOL, network, r -> r.run(), discListener);
+        waitForIdle();
+        verify(discListener, timeout(TIMEOUT_MS))
+                .onStartDiscoveryFailed(serviceTypeWithoutTcpOrUdpEnding, FAILURE_INTERNAL_ERROR);
+    }
+
+    @Test
+    public void testResolutionWithMdnsDiscoveryManager() throws UnknownHostException {
+        setMdnsDiscoveryManagerEnabled();
+
+        final NsdManager client = connectClient(mService);
+        final ResolveListener resolveListener = mock(ResolveListener.class);
+        final Network network = new Network(999);
+        final String serviceType = "_nsd._service._tcp";
+        final String constructedServiceType = "_nsd._sub._service._tcp.local";
+        final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
+                ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+        final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, serviceType);
+        request.setNetwork(network);
+        client.resolveService(request, resolveListener);
+        waitForIdle();
+        verify(mSocketProvider).startMonitoringSockets();
+        verify(mDiscoveryManager).registerListener(eq(constructedServiceType),
+                listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork())));
+
+        final MdnsServiceBrowserListener listener = listenerCaptor.getValue();
+        final MdnsServiceInfo mdnsServiceInfo = new MdnsServiceInfo(
+                SERVICE_NAME,
+                constructedServiceType.split("\\."),
+                List.of(), /* subtypes */
+                new String[]{"android", "local"}, /* hostName */
+                PORT,
+                IPV4_ADDRESS,
+                IPV6_ADDRESS,
+                List.of() /* textStrings */,
+                List.of(MdnsServiceInfo.TextEntry.fromBytes(new byte[]{
+                        'k', 'e', 'y', '=', (byte) 0xFF, (byte) 0xFE})) /* textEntries */,
+                1234,
+                network);
+
+        // Verify onServiceFound callback
+        listener.onServiceFound(mdnsServiceInfo);
+        final ArgumentCaptor<NsdServiceInfo> infoCaptor =
+                ArgumentCaptor.forClass(NsdServiceInfo.class);
+        verify(resolveListener, timeout(TIMEOUT_MS)).onServiceResolved(infoCaptor.capture());
+        final NsdServiceInfo info = infoCaptor.getValue();
+        assertEquals(SERVICE_NAME, info.getServiceName());
+        assertEquals("." + serviceType, info.getServiceType());
+        assertEquals(PORT, info.getPort());
+        assertTrue(info.getAttributes().containsKey("key"));
+        assertEquals(1, info.getAttributes().size());
+        assertArrayEquals(new byte[]{(byte) 0xFF, (byte) 0xFE}, info.getAttributes().get("key"));
+        assertEquals(parseNumericAddress(IPV4_ADDRESS), info.getHost());
+        assertEquals(network, info.getNetwork());
+
+        // Verify the listener has been unregistered.
+        verify(mDiscoveryManager, timeout(TIMEOUT_MS))
+                .unregisterListener(eq(constructedServiceType), any());
+        verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).stopMonitoringSockets();
+    }
+
+    @Test
+    public void testMdnsAdvertiserFeatureFlagging() {
+        // Create NsdService w/o feature enabled.
+        final NsdManager client = connectClient(mService);
+        final NsdServiceInfo regInfo = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+        regInfo.setHost(parseNumericAddress("192.0.2.123"));
+        regInfo.setPort(12345);
+        final RegistrationListener regListenerWithoutFeature = mock(RegistrationListener.class);
+        client.registerService(regInfo, PROTOCOL, regListenerWithoutFeature);
+        waitForIdle();
+
+        final ArgumentCaptor<Integer> legacyIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMockMDnsM).registerService(legacyIdCaptor.capture(), any(), any(), anyInt(),
+                any(), anyInt());
+        verifyNoMoreInteractions(mAdvertiser);
+
+        setMdnsAdvertiserEnabled();
+        final RegistrationListener regListenerWithFeature = mock(RegistrationListener.class);
+        client.registerService(regInfo, PROTOCOL, regListenerWithFeature);
+        waitForIdle();
+
+        final ArgumentCaptor<Integer> serviceIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mAdvertiser).addService(serviceIdCaptor.capture(),
+                argThat(info -> matches(info, regInfo)));
+
+        client.unregisterService(regListenerWithoutFeature);
+        waitForIdle();
+        verify(mMockMDnsM).stopOperation(legacyIdCaptor.getValue());
+        verify(mAdvertiser, never()).removeService(anyInt());
+
+        client.unregisterService(regListenerWithFeature);
+        waitForIdle();
+        verify(mAdvertiser).removeService(serviceIdCaptor.getValue());
+    }
+
+    @Test
+    public void testAdvertiseWithMdnsAdvertiser() {
+        setMdnsAdvertiserEnabled();
+
+        final NsdManager client = connectClient(mService);
+        final RegistrationListener regListener = mock(RegistrationListener.class);
+        // final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+        final ArgumentCaptor<MdnsAdvertiser.AdvertiserCallback> cbCaptor =
+                ArgumentCaptor.forClass(MdnsAdvertiser.AdvertiserCallback.class);
+        verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture());
+
+        final NsdServiceInfo regInfo = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+        regInfo.setHost(parseNumericAddress("192.0.2.123"));
+        regInfo.setPort(12345);
+        regInfo.setAttribute("testattr", "testvalue");
+        regInfo.setNetwork(new Network(999));
+
+        client.registerService(regInfo, NsdManager.PROTOCOL_DNS_SD, Runnable::run, regListener);
+        waitForIdle();
+        verify(mSocketProvider).startMonitoringSockets();
+        final ArgumentCaptor<Integer> idCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mAdvertiser).addService(idCaptor.capture(), argThat(info ->
+                matches(info, regInfo)));
+
+        // Verify onServiceRegistered callback
+        final MdnsAdvertiser.AdvertiserCallback cb = cbCaptor.getValue();
+        cb.onRegisterServiceSucceeded(idCaptor.getValue(), regInfo);
+
+        verify(regListener, timeout(TIMEOUT_MS)).onServiceRegistered(argThat(info -> matches(info,
+                new NsdServiceInfo(regInfo.getServiceName(), null))));
+
+        client.unregisterService(regListener);
+        waitForIdle();
+        verify(mAdvertiser).removeService(idCaptor.getValue());
+        verify(regListener, timeout(TIMEOUT_MS)).onServiceUnregistered(
+                argThat(info -> matches(info, regInfo)));
+        verify(mSocketProvider, timeout(TIMEOUT_MS)).stopMonitoringSockets();
+    }
+
+    @Test
+    public void testAdvertiseWithMdnsAdvertiser_FailedWithInvalidServiceType() {
+        setMdnsAdvertiserEnabled();
+
+        final NsdManager client = connectClient(mService);
+        final RegistrationListener regListener = mock(RegistrationListener.class);
+        // final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+        final ArgumentCaptor<MdnsAdvertiser.AdvertiserCallback> cbCaptor =
+                ArgumentCaptor.forClass(MdnsAdvertiser.AdvertiserCallback.class);
+        verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture());
+
+        final NsdServiceInfo regInfo = new NsdServiceInfo(SERVICE_NAME, "invalid_type");
+        regInfo.setHost(parseNumericAddress("192.0.2.123"));
+        regInfo.setPort(12345);
+        regInfo.setAttribute("testattr", "testvalue");
+        regInfo.setNetwork(new Network(999));
+
+        client.registerService(regInfo, NsdManager.PROTOCOL_DNS_SD, Runnable::run, regListener);
+        waitForIdle();
+        verify(mAdvertiser, never()).addService(anyInt(), any());
+
+        verify(regListener, timeout(TIMEOUT_MS)).onRegistrationFailed(
+                argThat(info -> matches(info, regInfo)), eq(FAILURE_INTERNAL_ERROR));
+    }
+
+    @Test
+    public void testAdvertiseWithMdnsAdvertiser_LongServiceName() {
+        setMdnsAdvertiserEnabled();
+
+        final NsdManager client = connectClient(mService);
+        final RegistrationListener regListener = mock(RegistrationListener.class);
+        // final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+        final ArgumentCaptor<MdnsAdvertiser.AdvertiserCallback> cbCaptor =
+                ArgumentCaptor.forClass(MdnsAdvertiser.AdvertiserCallback.class);
+        verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture());
+
+        final NsdServiceInfo regInfo = new NsdServiceInfo("a".repeat(70), SERVICE_TYPE);
+        regInfo.setHost(parseNumericAddress("192.0.2.123"));
+        regInfo.setPort(12345);
+        regInfo.setAttribute("testattr", "testvalue");
+        regInfo.setNetwork(new Network(999));
+
+        client.registerService(regInfo, NsdManager.PROTOCOL_DNS_SD, Runnable::run, regListener);
+        waitForIdle();
+        final ArgumentCaptor<Integer> idCaptor = ArgumentCaptor.forClass(Integer.class);
+        // Service name is truncated to 63 characters
+        verify(mAdvertiser).addService(idCaptor.capture(),
+                argThat(info -> info.getServiceName().equals("a".repeat(63))));
+
+        // Verify onServiceRegistered callback
+        final MdnsAdvertiser.AdvertiserCallback cb = cbCaptor.getValue();
+        cb.onRegisterServiceSucceeded(idCaptor.getValue(), regInfo);
+
+        verify(regListener, timeout(TIMEOUT_MS)).onServiceRegistered(
+                argThat(info -> matches(info, new NsdServiceInfo(regInfo.getServiceName(), null))));
+    }
+
     private void waitForIdle() {
         HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS);
     }
 
     NsdService makeService() {
-        final NsdService service = new NsdService(mContext, mHandler, CLEANUP_DELAY_MS) {
+        final NsdService service = new NsdService(mContext, mHandler, CLEANUP_DELAY_MS, mDeps) {
             @Override
             public INsdServiceConnector connect(INsdManagerCallback baseCb) {
                 // Wrap the callback in a transparent mock, to mock asBinder returning a
@@ -599,6 +1194,19 @@
         verify(mMockMDnsM, timeout(cleanupDelayMs + TIMEOUT_MS)).stopDaemon();
     }
 
+    /**
+     * Return true if two service info are the same.
+     *
+     * Useful for argument matchers as {@link NsdServiceInfo} does not implement equals.
+     */
+    private boolean matches(NsdServiceInfo a, NsdServiceInfo b) {
+        return Objects.equals(a.getServiceName(), b.getServiceName())
+                && Objects.equals(a.getServiceType(), b.getServiceType())
+                && Objects.equals(a.getHost(), b.getHost())
+                && Objects.equals(a.getNetwork(), b.getNetwork())
+                && Objects.equals(a.getAttributes(), b.getAttributes());
+    }
+
     public static class TestHandler extends Handler {
         public Message lastMessage;
 
diff --git a/tests/unit/java/com/android/server/VpnManagerServiceTest.java b/tests/unit/java/com/android/server/VpnManagerServiceTest.java
index c8a93a6..deb56ef 100644
--- a/tests/unit/java/com/android/server/VpnManagerServiceTest.java
+++ b/tests/unit/java/com/android/server/VpnManagerServiceTest.java
@@ -131,6 +131,11 @@
                 Vpn vpn, VpnProfile profile) {
             return mLockdownVpnTracker;
         }
+
+        @Override
+        public @UserIdInt int getMainUserId() {
+            return UserHandle.USER_SYSTEM;
+        }
     }
 
     @Before
diff --git a/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java b/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
new file mode 100644
index 0000000..4f0b9c4
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
@@ -0,0 +1,388 @@
+/*
+ * 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 static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.AlarmManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityResources;
+import android.net.INetd;
+import android.net.ISocketKeepaliveCallback;
+import android.net.KeepalivePacketData;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.MarkMaskParcel;
+import android.net.NattKeepalivePacketData;
+import android.net.Network;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+import com.android.testutils.HandlerUtils;
+
+import libcore.util.HexEncoding;
+
+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.FileDescriptor;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+@RunWith(DevSdkIgnoreRunner.class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+public class AutomaticOnOffKeepaliveTrackerTest {
+    private static final String TAG = AutomaticOnOffKeepaliveTrackerTest.class.getSimpleName();
+    private static final int TEST_NETID = 0xA85;
+    private static final int TEST_NETID_FWMARK = 0x0A85;
+    private static final int OTHER_NETID = 0x1A85;
+    private static final int NETID_MASK = 0xffff;
+    private static final int TIMEOUT_MS = 30_000;
+    private static final int MOCK_RESOURCE_ID = 5;
+    private AutomaticOnOffKeepaliveTracker mAOOKeepaliveTracker;
+    private HandlerThread mHandlerThread;
+
+    @Mock INetd mNetd;
+    @Mock AutomaticOnOffKeepaliveTracker.Dependencies mDependencies;
+    @Mock Context mCtx;
+    @Mock AlarmManager mAlarmManager;
+    TestKeepaliveTracker mKeepaliveTracker;
+    AOOTestHandler mTestHandler;
+
+    // Hexadecimal representation of a SOCK_DIAG response with tcp info.
+    private static final String SOCK_DIAG_TCP_INET_HEX =
+            // struct nlmsghdr.
+            "14010000" +        // length = 276
+            "1400" +            // type = SOCK_DIAG_BY_FAMILY
+            "0301" +            // flags = NLM_F_REQUEST | NLM_F_DUMP
+            "00000000" +        // seqno
+            "00000000" +        // pid (0 == kernel)
+            // struct inet_diag_req_v2
+            "02" +              // family = AF_INET
+            "06" +              // state
+            "00" +              // timer
+            "00" +              // retrans
+            // inet_diag_sockid
+            "DEA5" +            // idiag_sport = 42462
+            "71B9" +            // idiag_dport = 47473
+            "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2
+            "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
+            "00000000" +            // idiag_if
+            "34ED000076270000" +    // idiag_cookie = 43387759684916
+            "00000000" +            // idiag_expires
+            "00000000" +            // idiag_rqueue
+            "00000000" +            // idiag_wqueue
+            "00000000" +            // idiag_uid
+            "00000000" +            // idiag_inode
+            // rtattr
+            "0500" +            // len = 5
+            "0800" +            // type = 8
+            "00000000" +        // data
+            "0800" +            // len = 8
+            "0F00" +            // type = 15(INET_DIAG_MARK)
+            "850A0C00" +        // data, socket mark=789125
+            "AC00" +            // len = 172
+            "0200" +            // type = 2(INET_DIAG_INFO)
+            // tcp_info
+            "01" +              // state = TCP_ESTABLISHED
+            "00" +              // ca_state = TCP_CA_OPEN
+            "05" +              // retransmits = 5
+            "00" +              // probes = 0
+            "00" +              // backoff = 0
+            "07" +              // option = TCPI_OPT_WSCALE|TCPI_OPT_SACK|TCPI_OPT_TIMESTAMPS
+            "88" +              // wscale = 8
+            "00" +              // delivery_rate_app_limited = 0
+            "4A911B00" +        // rto = 1806666
+            "00000000" +        // ato = 0
+            "2E050000" +        // sndMss = 1326
+            "18020000" +        // rcvMss = 536
+            "00000000" +        // unsacked = 0
+            "00000000" +        // acked = 0
+            "00000000" +        // lost = 0
+            "00000000" +        // retrans = 0
+            "00000000" +        // fackets = 0
+            "BB000000" +        // lastDataSent = 187
+            "00000000" +        // lastAckSent = 0
+            "BB000000" +        // lastDataRecv = 187
+            "BB000000" +        // lastDataAckRecv = 187
+            "DC050000" +        // pmtu = 1500
+            "30560100" +        // rcvSsthresh = 87600
+            "3E2C0900" +        // rttt = 601150
+            "1F960400" +        // rttvar = 300575
+            "78050000" +        // sndSsthresh = 1400
+            "0A000000" +        // sndCwnd = 10
+            "A8050000" +        // advmss = 1448
+            "03000000" +        // reordering = 3
+            "00000000" +        // rcvrtt = 0
+            "30560100" +        // rcvspace = 87600
+            "00000000" +        // totalRetrans = 0
+            "53AC000000000000" +    // pacingRate = 44115
+            "FFFFFFFFFFFFFFFF" +    // maxPacingRate = 18446744073709551615
+            "0100000000000000" +    // bytesAcked = 1
+            "0000000000000000" +    // bytesReceived = 0
+            "0A000000" +        // SegsOut = 10
+            "00000000" +        // SegsIn = 0
+            "00000000" +        // NotSentBytes = 0
+            "3E2C0900" +        // minRtt = 601150
+            "00000000" +        // DataSegsIn = 0
+            "00000000" +        // DataSegsOut = 0
+            "0000000000000000"; // deliverRate = 0
+    private static final String SOCK_DIAG_NO_TCP_INET_HEX =
+            // struct nlmsghdr
+            "14000000"     // length = 20
+            + "0300"         // type = NLMSG_DONE
+            + "0301"         // flags = NLM_F_REQUEST | NLM_F_DUMP
+            + "00000000"     // seqno
+            + "00000000"     // pid (0 == kernel)
+            // struct inet_diag_req_v2
+            + "02"           // family = AF_INET
+            + "06"           // state
+            + "00"           // timer
+            + "00";          // retrans
+    private static final byte[] SOCK_DIAG_NO_TCP_INET_BYTES =
+            HexEncoding.decode(SOCK_DIAG_NO_TCP_INET_HEX.toCharArray(), false);
+    private static final String TEST_RESPONSE_HEX =
+            SOCK_DIAG_TCP_INET_HEX + SOCK_DIAG_NO_TCP_INET_HEX;
+    private static final byte[] TEST_RESPONSE_BYTES =
+            HexEncoding.decode(TEST_RESPONSE_HEX.toCharArray(), false);
+
+    private class TestKeepaliveTracker extends KeepaliveTracker {
+        private KeepaliveInfo mKi;
+
+        TestKeepaliveTracker(@NonNull final Context context, @NonNull final Handler handler) {
+            super(context, handler);
+        }
+
+        public void setReturnedKeepaliveInfo(@NonNull final KeepaliveInfo ki) {
+            mKi = ki;
+        }
+
+        @NonNull
+        @Override
+        public KeepaliveInfo makeNattKeepaliveInfo(@Nullable final NetworkAgentInfo nai,
+                @Nullable final FileDescriptor fd, final int intervalSeconds,
+                @NonNull final ISocketKeepaliveCallback cb, @NonNull final String srcAddrString,
+                final int srcPort,
+                @NonNull final String dstAddrString, final int dstPort) {
+            if (null == mKi) {
+                throw new IllegalStateException("Must call setReturnedKeepaliveInfo");
+            }
+            return mKi;
+        }
+    }
+
+    @Before
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        doReturn(PERMISSION_GRANTED).when(mCtx).checkPermission(any() /* permission */,
+                anyInt() /* pid */, anyInt() /* uid */);
+        ConnectivityResources.setResourcesContextForTest(mCtx);
+        final Resources mockResources = mock(Resources.class);
+        doReturn(MOCK_RESOURCE_ID).when(mockResources).getIdentifier(any() /* name */,
+                any() /* defType */, any() /* defPackage */);
+        doReturn(new String[] { "0,3", "3,3" }).when(mockResources)
+                .getStringArray(MOCK_RESOURCE_ID);
+        doReturn(mockResources).when(mCtx).getResources();
+        doReturn(mNetd).when(mDependencies).getNetd();
+        doReturn(mAlarmManager).when(mDependencies).getAlarmManager(any());
+        doReturn(makeMarkMaskParcel(NETID_MASK, TEST_NETID_FWMARK)).when(mNetd)
+                .getFwmarkForNetwork(TEST_NETID);
+
+        doNothing().when(mDependencies).sendRequest(any(), any());
+
+        mHandlerThread = new HandlerThread("KeepaliveTrackerTest");
+        mHandlerThread.start();
+        mTestHandler = new AOOTestHandler(mHandlerThread.getLooper());
+        mKeepaliveTracker = new TestKeepaliveTracker(mCtx, mTestHandler);
+        doReturn(mKeepaliveTracker).when(mDependencies).newKeepaliveTracker(mCtx, mTestHandler);
+        doReturn(true).when(mDependencies).isFeatureEnabled(any(), anyBoolean());
+        mAOOKeepaliveTracker =
+                new AutomaticOnOffKeepaliveTracker(mCtx, mTestHandler, mDependencies);
+    }
+
+    private final class AOOTestHandler extends Handler {
+        public AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive mLastAutoKi = null;
+
+        AOOTestHandler(@NonNull final Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(@NonNull final Message msg) {
+            switch (msg.what) {
+                case NetworkAgent.CMD_START_SOCKET_KEEPALIVE:
+                    Log.d(TAG, "Test handler received CMD_START_SOCKET_KEEPALIVE : " + msg);
+                    mAOOKeepaliveTracker.handleStartKeepalive(msg);
+                    break;
+                case NetworkAgent.CMD_MONITOR_AUTOMATIC_KEEPALIVE:
+                    Log.d(TAG, "Test handler received CMD_MONITOR_AUTOMATIC_KEEPALIVE : " + msg);
+                    mLastAutoKi = mAOOKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj);
+                    break;
+            }
+        }
+    }
+
+    @Test
+    public void testIsAnyTcpSocketConnected_runOnNonHandlerThread() throws Exception {
+        setupResponseWithSocketExisting();
+        assertThrows(IllegalStateException.class,
+                () -> mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID));
+    }
+
+    @Test
+    public void testIsAnyTcpSocketConnected_withTargetNetId() throws Exception {
+        setupResponseWithSocketExisting();
+        mTestHandler.post(
+                () -> assertTrue(mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID)));
+    }
+
+    @Test
+    public void testIsAnyTcpSocketConnected_withIncorrectNetId() throws Exception {
+        setupResponseWithSocketExisting();
+        mTestHandler.post(
+                () -> assertFalse(mAOOKeepaliveTracker.isAnyTcpSocketConnected(OTHER_NETID)));
+    }
+
+    @Test
+    public void testIsAnyTcpSocketConnected_noSocketExists() throws Exception {
+        setupResponseWithoutSocketExisting();
+        mTestHandler.post(
+                () -> assertFalse(mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID)));
+    }
+
+    @Test
+    public void testAlarm() throws Exception {
+        final InetAddress srcAddress = InetAddress.getByAddress(
+                new byte[] { (byte) 192, 0, 0, (byte) 129 });
+        final int srcPort = 12345;
+        final InetAddress dstAddress = InetAddress.getByAddress(new byte[] { 8, 8, 8, 8});
+        final int dstPort = 12345;
+
+        final NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
+        nai.networkCapabilities = new NetworkCapabilities.Builder()
+                .addTransportType(TRANSPORT_CELLULAR).build();
+        nai.networkInfo = new NetworkInfo(TYPE_MOBILE, 0 /* subtype */, "LTE", "LTE");
+        nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "test reason",
+                "test extra info");
+        nai.linkProperties = new LinkProperties();
+        nai.linkProperties.addLinkAddress(new LinkAddress(srcAddress, 24));
+
+        final Socket socket = new Socket();
+        socket.bind(null);
+        final FileDescriptor fd = socket.getFileDescriptor$();
+        final IBinder binder = new Binder();
+        final ISocketKeepaliveCallback cb = mock(ISocketKeepaliveCallback.class);
+        doReturn(binder).when(cb).asBinder();
+        final Network underpinnedNetwork = mock(Network.class);
+
+        final KeepalivePacketData kpd = new NattKeepalivePacketData(srcAddress, srcPort,
+                dstAddress, dstPort, new byte[] {1});
+        final KeepaliveInfo ki = mKeepaliveTracker.new KeepaliveInfo(cb, nai, kpd,
+                10 /* interval */, KeepaliveInfo.TYPE_NATT, fd);
+        mKeepaliveTracker.setReturnedKeepaliveInfo(ki);
+
+        mAOOKeepaliveTracker.startNattKeepalive(nai, fd, 10 /* intervalSeconds */, cb,
+                srcAddress.toString(), srcPort, dstAddress.toString(), dstPort,
+                true /* automaticOnOffKeepalives */, underpinnedNetwork);
+        HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
+
+        final ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor =
+                ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
+        verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
+                any(), listenerCaptor.capture(), eq(mTestHandler));
+        final AlarmManager.OnAlarmListener listener = listenerCaptor.getValue();
+
+        // For realism, the listener should be posted on the handler
+        mTestHandler.post(() -> listener.onAlarm());
+        // Wait for the listener to be called. The listener enqueues a message to the handler.
+        HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
+        // Wait for the message posted by the listener to be processed.
+        HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
+
+        assertNotNull(mTestHandler.mLastAutoKi);
+        assertEquals(cb, mTestHandler.mLastAutoKi.getCallback());
+        assertEquals(underpinnedNetwork, mTestHandler.mLastAutoKi.getUnderpinnedNetwork());
+        socket.close();
+    }
+
+    private void setupResponseWithSocketExisting() throws Exception {
+        final ByteBuffer tcpBufferV6 = getByteBuffer(TEST_RESPONSE_BYTES);
+        final ByteBuffer tcpBufferV4 = getByteBuffer(TEST_RESPONSE_BYTES);
+        doReturn(tcpBufferV6, tcpBufferV4).when(mDependencies).recvSockDiagResponse(any());
+    }
+
+    private void setupResponseWithoutSocketExisting() throws Exception {
+        final ByteBuffer tcpBufferV6 = getByteBuffer(SOCK_DIAG_NO_TCP_INET_BYTES);
+        final ByteBuffer tcpBufferV4 = getByteBuffer(SOCK_DIAG_NO_TCP_INET_BYTES);
+        doReturn(tcpBufferV6, tcpBufferV4).when(mDependencies).recvSockDiagResponse(any());
+    }
+
+    private MarkMaskParcel makeMarkMaskParcel(final int mask, final int mark) {
+        final MarkMaskParcel parcel = new MarkMaskParcel();
+        parcel.mask = mask;
+        parcel.mark = mark;
+        return parcel;
+    }
+
+    private ByteBuffer getByteBuffer(final byte[] bytes) {
+        final ByteBuffer buffer = ByteBuffer.wrap(bytes);
+        buffer.order(ByteOrder.nativeOrder());
+        return buffer;
+    }
+}
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 9a5298d..e038c44 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -56,8 +56,10 @@
 import android.net.NetworkInfo;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.telephony.TelephonyManager;
+import android.testing.PollingCheck;
 import android.util.DisplayMetrics;
 import android.widget.TextView;
 
@@ -391,7 +393,15 @@
 
         final Instrumentation instr = InstrumentationRegistry.getInstrumentation();
         final UiDevice uiDevice =  UiDevice.getInstance(instr);
-        UiDevice.getInstance(instr).pressHome();
+        final Context ctx = instr.getContext();
+        final PowerManager pm = ctx.getSystemService(PowerManager.class);
+
+        // Wake up the device (it has no effect if the device is already awake).
+        uiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        uiDevice.executeShellCommand("wm dismiss-keyguard");
+        PollingCheck.check("Wait for the screen to be turned on failed, timeout=" + TEST_TIMEOUT_MS,
+                TEST_TIMEOUT_MS, () -> pm.isInteractive());
+        uiDevice.pressHome();
 
         // UiDevice.getLauncherPackageName() requires the test manifest to have a <queries> tag for
         // the launcher intent.
@@ -404,7 +414,6 @@
         // Non-"no internet" notifications are not affected
         verify(mNotificationManager).notify(eq(TEST_NOTIF_TAG), eq(NETWORK_SWITCH.eventId), any());
 
-        final Context ctx = instr.getContext();
         final String testAction = "com.android.connectivity.coverage.TEST_DIALOG";
         final Intent intent = new Intent(testAction)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 8076edb..cf02e3a 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -46,7 +46,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.AdditionalMatchers.aryEq;
 import static org.mockito.ArgumentMatchers.any;
@@ -844,7 +843,6 @@
         // When VPN is disconnected, expect rules to be torn down
         mPermissionMonitor.onVpnUidRangesRemoved(ifName, vpnRange2, VPN_UID);
         verify(mBpfNetMaps).removeUidInterfaceRules(aryEq(new int[] {MOCK_UID12}));
-        assertNull(mPermissionMonitor.getVpnInterfaceUidRanges(ifName));
     }
 
     @Test
@@ -915,7 +913,6 @@
         verify(mBpfNetMaps, times(2)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, true /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, true /* add */);
-        assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
 
         reset(mBpfNetMaps);
 
@@ -924,7 +921,6 @@
         verify(mBpfNetMaps, times(2)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, false /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, false /* add */);
-        assertTrue(mPermissionMonitor.getVpnLockdownUidRanges().isEmpty());
     }
 
     @Test
@@ -944,7 +940,6 @@
         mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange);
         verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(true) /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, true /* add */);
-        assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
 
         reset(mBpfNetMaps);
 
@@ -952,7 +947,6 @@
         // already has the rule
         mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange);
         verify(mBpfNetMaps, never()).updateUidLockdownRule(anyInt(),  anyBoolean());
-        assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
 
         reset(mBpfNetMaps);
 
@@ -960,7 +954,6 @@
         // the range 2 times.
         mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
         verify(mBpfNetMaps, never()).updateUidLockdownRule(anyInt(),  anyBoolean());
-        assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
 
         reset(mBpfNetMaps);
 
@@ -969,7 +962,6 @@
         mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
         verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(false) /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, false /* add */);
-        assertTrue(mPermissionMonitor.getVpnLockdownUidRanges().isEmpty());
     }
 
     @Test
@@ -990,7 +982,6 @@
         mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRangeDuplicates);
         verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(true) /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, true /* add */);
-        assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
 
         reset(mBpfNetMaps);
 
@@ -998,7 +989,6 @@
         // ranges we added contains duplicated uid ranges.
         mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
         verify(mBpfNetMaps, never()).updateUidLockdownRule(anyInt(), anyBoolean());
-        assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
 
         reset(mBpfNetMaps);
 
@@ -1006,7 +996,6 @@
         mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
         verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(false) /* add */);
         verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, false /* add */);
-        assertTrue(mPermissionMonitor.getVpnLockdownUidRanges().isEmpty());
     }
 
     @Test
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 3f87ffd..2d87728 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -27,11 +27,19 @@
 import static android.net.INetd.IF_STATE_UP;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static android.net.VpnManager.TYPE_VPN_PLATFORM;
+import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
+import static android.net.cts.util.IkeSessionTestUtils.TEST_IDENTITY;
+import static android.net.cts.util.IkeSessionTestUtils.TEST_KEEPALIVE_TIMEOUT_UNSET;
+import static android.net.cts.util.IkeSessionTestUtils.getTestIkeSessionParams;
 import static android.net.ipsec.ike.IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO;
 import static android.os.Build.VERSION_CODES.S_V2;
 import static android.os.UserHandle.PER_USER_RANGE;
 
 import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
+import static com.android.server.connectivity.Vpn.AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+import static com.android.server.connectivity.Vpn.DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
 import static com.android.testutils.Cleanup.testAndCleanup;
 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 import static com.android.testutils.MiscAsserts.assertThrows;
@@ -106,10 +114,13 @@
 import android.net.VpnTransportInfo;
 import android.net.ipsec.ike.ChildSessionCallback;
 import android.net.ipsec.ike.ChildSessionConfiguration;
+import android.net.ipsec.ike.IkeFqdnIdentification;
 import android.net.ipsec.ike.IkeSessionCallback;
 import android.net.ipsec.ike.IkeSessionConfiguration;
 import android.net.ipsec.ike.IkeSessionConnectionInfo;
+import android.net.ipsec.ike.IkeSessionParams;
 import android.net.ipsec.ike.IkeTrafficSelector;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
 import android.net.ipsec.ike.exceptions.IkeException;
 import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
 import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
@@ -252,7 +263,8 @@
             "VPNAPPEXCLUDED_27_com.testvpn.vpn";
     static final String PKGS_BYTES = getPackageByteString(List.of(PKGS));
     private static final Range<Integer> PRIMARY_USER_RANGE = uidRangeForUser(PRIMARY_USER.id);
-
+    // Same as IkeSessionParams#IKE_NATT_KEEPALIVE_DELAY_SEC_DEFAULT
+    private static final int IKE_NATT_KEEPALIVE_DELAY_SEC_DEFAULT = 10;
     @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
     @Mock private UserManager mUserManager;
     @Mock private PackageManager mPackageManager;
@@ -1812,6 +1824,11 @@
 
     private PlatformVpnSnapshot verifySetupPlatformVpn(
             IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6) throws Exception {
+        return verifySetupPlatformVpn(mVpnProfile, ikeConfig, mtuSupportsIpv6);
+    }
+
+    private PlatformVpnSnapshot verifySetupPlatformVpn(VpnProfile vpnProfile,
+            IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6) throws Exception {
         if (!mtuSupportsIpv6) {
             doReturn(IPV6_MIN_MTU - 1).when(mTestDeps).calculateVpnMtu(any(), anyInt(), anyInt(),
                     anyBoolean());
@@ -1820,10 +1837,11 @@
         doReturn(mMockNetworkAgent).when(mTestDeps)
                 .newNetworkAgent(
                         any(), any(), anyString(), any(), any(), any(), any(), any(), any());
+        doReturn(TEST_NETWORK).when(mMockNetworkAgent).getNetwork();
 
         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
-                .thenReturn(mVpnProfile.encode());
+                .thenReturn(vpnProfile.encode());
 
         vpn.startVpnProfile(TEST_VPN_PKG);
         final NetworkCallback nwCb = triggerOnAvailableAndGetCallback();
@@ -1850,7 +1868,7 @@
         verify(mTestDeps).newNetworkAgent(
                 any(), any(), anyString(), ncCaptor.capture(), lpCaptor.capture(),
                 any(), nacCaptor.capture(), any(), any());
-
+        verify(mIkeSessionWrapper).setUnderpinnedNetwork(TEST_NETWORK);
         // Check LinkProperties
         final LinkProperties lp = lpCaptor.getValue();
         final List<RouteInfo> expectedRoutes =
@@ -1906,6 +1924,109 @@
     }
 
     @Test
+    public void testMigrateIkeSessionFromIkeTunnConnParams_AutoTimerNoTimer()
+            throws Exception {
+        doTestMigrateIkeSession_FromIkeTunnConnParams(
+                false /* isAutomaticIpVersionSelectionEnabled */,
+                true /* isAutomaticNattKeepaliveTimerEnabled */,
+                TEST_KEEPALIVE_TIMEOUT_UNSET);
+    }
+
+    @Test
+    public void testMigrateIkeSessionFromIkeTunnConnParams_AutoTimerTimerSet()
+            throws Exception {
+        doTestMigrateIkeSession_FromIkeTunnConnParams(
+                false /* isAutomaticIpVersionSelectionEnabled */,
+                true /* isAutomaticNattKeepaliveTimerEnabled */,
+                800 /* keepaliveTimeout */);
+    }
+
+    @Test
+    public void testMigrateIkeSessionFromIkeTunnConnParams_AutoIp()
+            throws Exception {
+        doTestMigrateIkeSession_FromIkeTunnConnParams(
+                true /* isAutomaticIpVersionSelectionEnabled */,
+                false /* isAutomaticNattKeepaliveTimerEnabled */,
+                TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveTimeout */);
+    }
+
+    @Test
+    public void testMigrateIkeSession_FromNotIkeTunnConnParams_AutoTimer()
+            throws Exception {
+        doTestMigrateIkeSession_FromNotIkeTunnConnParams(
+                false /* isAutomaticIpVersionSelectionEnabled */,
+                true /* isAutomaticNattKeepaliveTimerEnabled */);
+    }
+
+    @Test
+    public void testMigrateIkeSession_FromNotIkeTunnConnParams_AutoIp()
+            throws Exception {
+        doTestMigrateIkeSession_FromNotIkeTunnConnParams(
+                true /* isAutomaticIpVersionSelectionEnabled */,
+                false /* isAutomaticNattKeepaliveTimerEnabled */);
+    }
+
+    private void doTestMigrateIkeSession_FromNotIkeTunnConnParams(
+            boolean isAutomaticIpVersionSelectionEnabled,
+            boolean isAutomaticNattKeepaliveTimerEnabled) throws Exception {
+        final Ikev2VpnProfile ikeProfile =
+                new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY)
+                        .setAuthPsk(TEST_VPN_PSK)
+                        .setBypassable(true /* isBypassable */)
+                        .setAutomaticNattKeepaliveTimerEnabled(isAutomaticNattKeepaliveTimerEnabled)
+                        .setAutomaticIpVersionSelectionEnabled(isAutomaticIpVersionSelectionEnabled)
+                        .build();
+
+        final int expectedKeepalive = isAutomaticNattKeepaliveTimerEnabled
+                ? AUTOMATIC_KEEPALIVE_DELAY_SECONDS
+                : DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
+        doTestMigrateIkeSession(ikeProfile.toVpnProfile(), expectedKeepalive,
+                isAutomaticIpVersionSelectionEnabled);
+    }
+
+    private void doTestMigrateIkeSession_FromIkeTunnConnParams(
+            boolean isAutomaticIpVersionSelectionEnabled,
+            boolean isAutomaticNattKeepaliveTimerEnabled,
+            int keepaliveInProfile) throws Exception {
+        final IkeSessionParams ikeSessionParams = getTestIkeSessionParams(true /* testIpv6 */,
+                new IkeFqdnIdentification(TEST_IDENTITY), keepaliveInProfile);
+        final IkeTunnelConnectionParams tunnelParams =
+                new IkeTunnelConnectionParams(ikeSessionParams, CHILD_PARAMS);
+        final Ikev2VpnProfile ikeProfile = new Ikev2VpnProfile.Builder(tunnelParams)
+                .setBypassable(true)
+                .setAutomaticNattKeepaliveTimerEnabled(isAutomaticNattKeepaliveTimerEnabled)
+                .setAutomaticIpVersionSelectionEnabled(isAutomaticIpVersionSelectionEnabled)
+                .build();
+
+        final int expectedKeepalive = isAutomaticNattKeepaliveTimerEnabled
+                ? AUTOMATIC_KEEPALIVE_DELAY_SECONDS
+                : ikeSessionParams.getNattKeepAliveDelaySeconds();
+        doTestMigrateIkeSession(ikeProfile.toVpnProfile(), expectedKeepalive,
+                isAutomaticIpVersionSelectionEnabled);
+    }
+
+    private void doTestMigrateIkeSession(VpnProfile profile, int expectedKeepalive,
+            boolean isAutomaticIpVersionSelectionEnabled) throws Exception {
+        final int expectedIpVersion = isAutomaticIpVersionSelectionEnabled
+                ? ESP_IP_VERSION_AUTO : ESP_IP_VERSION_AUTO;
+        final int expectedEncapType = isAutomaticIpVersionSelectionEnabled
+                ? ESP_ENCAP_TYPE_AUTO : ESP_IP_VERSION_AUTO;
+
+        final PlatformVpnSnapshot vpnSnapShot =
+                verifySetupPlatformVpn(profile,
+                        createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */),
+                        false /* mtuSupportsIpv6 */);
+        // Mock new network comes up and the cleanup task is cancelled
+        vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+
+        // Verify MOBIKE is triggered
+        verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2,
+                expectedIpVersion, expectedEncapType, expectedKeepalive);
+
+        vpnSnapShot.vpn.mVpnRunner.exitVpnRunner();
+    }
+
+    @Test
     public void testStartPlatformVpn_mtuDoesNotSupportIpv6() throws Exception {
         final PlatformVpnSnapshot vpnSnapShot =
                 verifySetupPlatformVpn(
@@ -1932,7 +2053,10 @@
         verify(mScheduledFuture).cancel(anyBoolean());
 
         // Verify MOBIKE is triggered
-        verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2);
+        verify(mIkeSessionWrapper).setNetwork(eq(TEST_NETWORK_2),
+                eq(ESP_IP_VERSION_AUTO) /* ipVersion */,
+                eq(ESP_ENCAP_TYPE_AUTO) /* encapType */,
+                eq(DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT) /* keepaliveDelay */);
 
         // Mock the MOBIKE procedure
         vpnSnapShot.ikeCb.onIkeSessionConnectionInfoChanged(createIkeConnectInfo_2());
@@ -2112,7 +2236,8 @@
 
     private void verifyMobikeTriggered(List<Network> expected) {
         final ArgumentCaptor<Network> networkCaptor = ArgumentCaptor.forClass(Network.class);
-        verify(mIkeSessionWrapper).setNetwork(networkCaptor.capture());
+        verify(mIkeSessionWrapper).setNetwork(networkCaptor.capture(),
+                anyInt() /* ipVersion */, anyInt() /* encapType */, anyInt() /* keepaliveDelay */);
         assertEquals(expected, Collections.singletonList(networkCaptor.getValue()));
     }
 
@@ -2128,7 +2253,8 @@
         connectivityDiagCallback.onDataStallSuspected(report);
 
         // Should not trigger MOBIKE if MOBIKE is not enabled
-        verify(mIkeSessionWrapper, never()).setNetwork(any());
+        verify(mIkeSessionWrapper, never()).setNetwork(any() /* network */,
+                anyInt() /* ipVersion */, anyInt() /* encapType */, anyInt() /* keepaliveDelay */);
     }
 
     @Test
@@ -2148,7 +2274,8 @@
         // Expect to skip other data stall event if MOBIKE was started.
         reset(mIkeSessionWrapper);
         connectivityDiagCallback.onDataStallSuspected(report);
-        verify(mIkeSessionWrapper, never()).setNetwork(any());
+        verify(mIkeSessionWrapper, never()).setNetwork(any() /* network */,
+                anyInt() /* ipVersion */, anyInt() /* encapType */, anyInt() /* keepaliveDelay */);
 
         reset(mIkev2SessionCreator);
 
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..1febe6d
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
@@ -0,0 +1,233 @@
+/*
+ * 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.atLeastOnce
+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)
+    }
+
+    @Test
+    fun testAddService_Conflicts() {
+        val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+        postSync { advertiser.addService(SERVICE_ID_1, SERVICE_1) }
+
+        val oneNetSocketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java)
+        verify(socketProvider).requestSocket(eq(TEST_NETWORK_1), oneNetSocketCbCaptor.capture())
+        val oneNetSocketCb = oneNetSocketCbCaptor.value
+
+        // Register a service with the same name on all networks (name conflict)
+        postSync { advertiser.addService(SERVICE_ID_2, ALL_NETWORKS_SERVICE) }
+        val allNetSocketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java)
+        verify(socketProvider).requestSocket(eq(null), allNetSocketCbCaptor.capture())
+        val allNetSocketCb = allNetSocketCbCaptor.value
+
+        // Callbacks for matching network and all networks both get the socket
+        postSync {
+            oneNetSocketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR))
+            allNetSocketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR))
+        }
+
+        val expectedRenamed = NsdServiceInfo(
+                "${ALL_NETWORKS_SERVICE.serviceName} (2)", ALL_NETWORKS_SERVICE.serviceType).apply {
+            port = ALL_NETWORKS_SERVICE.port
+            host = ALL_NETWORKS_SERVICE.host
+            network = ALL_NETWORKS_SERVICE.network
+        }
+
+        val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
+        verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
+                eq(thread.looper), any(), intAdvCbCaptor.capture())
+        verify(mockInterfaceAdvertiser1).addService(eq(SERVICE_ID_1),
+                argThat { it.matches(SERVICE_1) })
+        verify(mockInterfaceAdvertiser1).addService(eq(SERVICE_ID_2),
+                argThat { it.matches(expectedRenamed) })
+
+        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) })
+
+        doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_2)
+        postSync { intAdvCbCaptor.value.onRegisterServiceSucceeded(
+                mockInterfaceAdvertiser1, SERVICE_ID_2) }
+        verify(cb).onRegisterServiceSucceeded(eq(SERVICE_ID_2),
+                argThat { it.matches(expectedRenamed) })
+
+        postSync { oneNetSocketCb.onInterfaceDestroyed(TEST_NETWORK_1, mockSocket1) }
+        postSync { allNetSocketCb.onInterfaceDestroyed(TEST_NETWORK_1, mockSocket1) }
+
+        // destroyNow can be called multiple times
+        verify(mockInterfaceAdvertiser1, atLeastOnce()).destroyNow()
+    }
+
+    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..6c3f729 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
@@ -22,13 +22,11 @@
 import android.os.SystemClock
 import com.android.internal.util.HexDump
 import com.android.server.connectivity.mdns.MdnsAnnouncer.AnnouncementInfo
+import com.android.server.connectivity.mdns.MdnsAnnouncer.BaseAnnouncementInfo
+import com.android.server.connectivity.mdns.MdnsRecordRepository.getReverseDnsAddress
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
 import com.android.testutils.DevSdkIgnoreRunner
 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(1 /* serviceId */, announcedRecords, additionalRecords) {
         override fun getDelayMs(nextIndex: Int) =
                 if (nextIndex < FIRST_ANNOUNCES_COUNT) {
                     FIRST_ANNOUNCES_DELAY
@@ -83,10 +79,10 @@
 
     @Test
     fun testAnnounce() {
-        val replySender = MdnsReplySender(thread.looper, socket, buffer)
+        val replySender = MdnsReplySender("testiface", thread.looper, socket, buffer)
         @Suppress("UNCHECKED_CAST")
         val cb = mock(MdnsPacketRepeater.PacketRepeaterCallback::class.java)
-                as MdnsPacketRepeater.PacketRepeaterCallback<AnnouncementInfo>
+                as MdnsPacketRepeater.PacketRepeaterCallback<BaseAnnouncementInfo>
         val announcer = MdnsAnnouncer("testiface", thread.looper, replySender, cb)
         /*
         The expected packet replicates records announced when registering a service, as observed in
@@ -95,7 +91,7 @@
         scapy.raw(scapy.dns_compress(scapy.DNS(rd=0, qr=1, aa=1,
         qd = None,
         an =
-        scapy.DNSRR(type='PTR', rrname='123.0.2.192.in-addr.arpa.', rdata='Android.local',
+        scapy.DNSRR(type='PTR', rrname='123.2.0.192.in-addr.arpa.', rdata='Android.local',
             rclass=0x8001, ttl=120) /
         scapy.DNSRR(type='PTR',
             rrname='3.2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.0.1.0.0.2.ip6.arpa',
@@ -115,8 +111,8 @@
         scapy.DNSRR(type='AAAA', rrname='Android.local', rclass=0x8001, rdata='2001:db8::456',
             ttl=120),
         ar =
-        scapy.DNSRRNSEC(rrname='123.0.2.192.in-addr.arpa.', rclass=0x8001, ttl=120,
-            nextname='123.0.2.192.in-addr.arpa.', typebitmaps=[12]) /
+        scapy.DNSRRNSEC(rrname='123.2.0.192.in-addr.arpa.', rclass=0x8001, ttl=120,
+            nextname='123.2.0.192.in-addr.arpa.', typebitmaps=[12]) /
         scapy.DNSRRNSEC(
             rrname='3.2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.0.1.0.0.2.ip6.arpa',
             rclass=0x8001, ttl=120,
@@ -135,7 +131,7 @@
             typebitmaps=[1, 28]))
         )).hex().upper()
         */
-        val expected = "00008400000000090000000503313233013001320331393207696E2D61646472046172706" +
+        val expected = "00008400000000090000000503313233013201300331393207696E2D61646472046172706" +
                 "100000C800100000078000F07416E64726F6964056C6F63616C00013301320131013001300130013" +
                 "00130013001300130013001300130013001300130013001300130013001300130013001380142014" +
                 "40130013101300130013203697036C020000C8001000000780002C030013601350134C045000C800" +
@@ -153,9 +149,9 @@
         val v4Addr = parseNumericAddress("192.0.2.123")
         val v6Addr1 = parseNumericAddress("2001:DB8::123")
         val v6Addr2 = parseNumericAddress("2001:DB8::456")
-        val v4AddrRev = arrayOf("123", "0", "2", "192", "in-addr", "arpa")
-        val v6Addr1Rev = getReverseV6AddressName(v6Addr1)
-        val v6Addr2Rev = getReverseV6AddressName(v6Addr2)
+        val v4AddrRev = getReverseDnsAddress(v4Addr)
+        val v6Addr1Rev = getReverseDnsAddress(v6Addr1)
+        val v6Addr2Rev = getReverseDnsAddress(v6Addr2)
 
         val announcedRecords = listOf(
                 // Reverse address records
@@ -258,7 +254,10 @@
             verify(socket, atLeast(i + 1)).send(any())
             val now = SystemClock.elapsedRealtime()
             assertTrue(now > timeStart + startDelay + i * FIRST_ANNOUNCES_DELAY)
-            assertTrue(now < timeStart + startDelay + (i + 1) * FIRST_ANNOUNCES_DELAY)
+            // Loops can be much slower than the expected timing (>100ms delay), use
+            // TEST_TIMEOUT_MS as tolerance.
+            assertTrue(now < timeStart + startDelay + (i + 1) * FIRST_ANNOUNCES_DELAY +
+                TEST_TIMEOUT_MS)
         }
 
         // Subsequent announces should happen quickly (NEXT_ANNOUNCES_DELAY)
@@ -271,13 +270,3 @@
         }
     }
 }
-
-/**
- * Compute 2001:db8::1 --> 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.1.0.0.2.ip6.arpa
- */
-private fun getReverseV6AddressName(addr: InetAddress): Array<String> {
-    assertTrue(addr is Inet6Address)
-    return addr.address.flatMapTo(mutableListOf("arpa", "ip6")) {
-        HexDump.toHexString(it).toCharArray().map(Char::toString)
-    }.reversed().toTypedArray()
-}
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..4a806b1
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
@@ -0,0 +1,275 @@
+/*
+ * 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.net.module.util.HexDump
+import com.android.server.connectivity.mdns.MdnsAnnouncer.AnnouncementInfo
+import com.android.server.connectivity.mdns.MdnsAnnouncer.BaseAnnouncementInfo
+import com.android.server.connectivity.mdns.MdnsAnnouncer.ExitAnnouncementInfo
+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 java.net.InetSocketAddress
+import kotlin.test.assertContentEquals
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+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.anyString
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.times
+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)
+    @Suppress("UNCHECKED_CAST")
+    private val probeCbCaptor = ArgumentCaptor.forClass(PacketRepeaterCallback::class.java)
+            as ArgumentCaptor<PacketRepeaterCallback<ProbingInfo>>
+    @Suppress("UNCHECKED_CAST")
+    private val announceCbCaptor = ArgumentCaptor.forClass(PacketRepeaterCallback::class.java)
+            as ArgumentCaptor<PacketRepeaterCallback<BaseAnnouncementInfo>>
+    private val packetHandlerCaptor = ArgumentCaptor.forClass(
+            MulticastPacketReader.PacketHandler::class.java)
+
+    private val probeCb get() = probeCbCaptor.value
+    private val announceCb get() = announceCbCaptor.value
+    private val packetHandler get() = packetHandlerCaptor.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(anyString(), any(), any(), any())
+        doReturn(announcer).`when`(deps).makeMdnsAnnouncer(anyString(), any(), any(), any())
+        doReturn(prober).`when`(deps).makeMdnsProber(anyString(), any(), any(), any())
+
+        val knownServices = mutableSetOf<Int>()
+        doAnswer { inv ->
+            knownServices.add(inv.getArgument(0))
+            -1
+        }.`when`(repository).addService(anyInt(), any())
+        doAnswer { inv ->
+            knownServices.remove(inv.getArgument(0))
+            null
+        }.`when`(repository).removeService(anyInt())
+        doAnswer {
+            knownServices.toIntArray().also { knownServices.clear() }
+        }.`when`(repository).clearServices()
+        doAnswer { inv ->
+            knownServices.contains(inv.getArgument(0))
+        }.`when`(repository).hasActiveService(anyInt())
+        thread.start()
+        advertiser.start()
+
+        verify(socket).addPacketHandler(packetHandlerCaptor.capture())
+        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 testAnnouncementInfo = addServiceAndFinishProbing(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+
+        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(ExitAnnouncementInfo::class.java)
+        doReturn(testExitInfo).`when`(repository).exitService(TEST_SERVICE_ID_1)
+        advertiser.removeService(TEST_SERVICE_ID_1)
+
+        verify(prober).stop(TEST_SERVICE_ID_1)
+        verify(announcer).stop(TEST_SERVICE_ID_1)
+        verify(announcer).startSending(TEST_SERVICE_ID_1, testExitInfo, EXIT_ANNOUNCEMENT_DELAY_MS)
+
+        // Exit announcements finish: the advertiser has no left service and destroys itself
+        announceCb.onFinished(testExitInfo)
+        thread.waitForIdle(TIMEOUT_MS)
+        verify(cb).onDestroyed(socket)
+    }
+
+    @Test
+    fun testDoubleRemove() {
+        addServiceAndFinishProbing(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+
+        val testExitInfo = mock(ExitAnnouncementInfo::class.java)
+        doReturn(testExitInfo).`when`(repository).exitService(TEST_SERVICE_ID_1)
+        advertiser.removeService(TEST_SERVICE_ID_1)
+
+        verify(prober).stop(TEST_SERVICE_ID_1)
+        verify(announcer).stop(TEST_SERVICE_ID_1)
+        verify(announcer).startSending(TEST_SERVICE_ID_1, testExitInfo, EXIT_ANNOUNCEMENT_DELAY_MS)
+
+        doReturn(false).`when`(repository).hasActiveService(TEST_SERVICE_ID_1)
+        advertiser.removeService(TEST_SERVICE_ID_1)
+        // Prober, announcer were still stopped only one time
+        verify(prober, times(1)).stop(TEST_SERVICE_ID_1)
+        verify(announcer, times(1)).stop(TEST_SERVICE_ID_1)
+    }
+
+    @Test
+    fun testReplyToQuery() {
+        addServiceAndFinishProbing(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+
+        val mockReply = mock(MdnsRecordRepository.ReplyInfo::class.java)
+        doReturn(mockReply).`when`(repository).getReply(any(), any())
+
+        // Query obtained with:
+        // scapy.raw(scapy.DNS(
+        //  qd = scapy.DNSQR(qtype='PTR', qname='_testservice._tcp.local'))
+        // ).hex().upper()
+        val query = HexDump.hexStringToByteArray(
+                "0000010000010000000000000C5F7465737473657276696365045F746370056C6F63616C00000C0001"
+        )
+        val src = InetSocketAddress(parseNumericAddress("2001:db8::456"), MdnsConstants.MDNS_PORT)
+        packetHandler.handlePacket(query, query.size, src)
+
+        val packetCaptor = ArgumentCaptor.forClass(MdnsPacket::class.java)
+        verify(repository).getReply(packetCaptor.capture(), eq(src))
+
+        packetCaptor.value.let {
+            assertEquals(1, it.questions.size)
+            assertEquals(0, it.answers.size)
+            assertEquals(0, it.authorityRecords.size)
+            assertEquals(0, it.additionalRecords.size)
+
+            assertTrue(it.questions[0] is MdnsPointerRecord)
+            assertContentEquals(arrayOf("_testservice", "_tcp", "local"), it.questions[0].name)
+        }
+
+        verify(replySender).queueReply(mockReply)
+    }
+
+    @Test
+    fun testConflict() {
+        addServiceAndFinishProbing(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        doReturn(setOf(TEST_SERVICE_ID_1)).`when`(repository).getConflictingServices(any())
+
+        // Reply obtained with:
+        // scapy.raw(scapy.DNS(
+        //    qd = None,
+        //    an = scapy.DNSRR(type='TXT', rrname='_testservice._tcp.local'))
+        // ).hex().upper()
+        val query = HexDump.hexStringToByteArray("0000010000000001000000000C5F7465737473657276696" +
+                "365045F746370056C6F63616C0000100001000000000000")
+        val src = InetSocketAddress(parseNumericAddress("2001:db8::456"), MdnsConstants.MDNS_PORT)
+        packetHandler.handlePacket(query, query.size, src)
+
+        val packetCaptor = ArgumentCaptor.forClass(MdnsPacket::class.java)
+        verify(repository).getConflictingServices(packetCaptor.capture())
+
+        packetCaptor.value.let {
+            assertEquals(0, it.questions.size)
+            assertEquals(1, it.answers.size)
+            assertEquals(0, it.authorityRecords.size)
+            assertEquals(0, it.additionalRecords.size)
+
+            assertTrue(it.answers[0] is MdnsTextRecord)
+            assertContentEquals(arrayOf("_testservice", "_tcp", "local"), it.answers[0].name)
+        }
+
+        thread.waitForIdle(TIMEOUT_MS)
+        verify(cb).onServiceConflict(advertiser, TEST_SERVICE_ID_1)
+    }
+
+    @Test
+    fun testRestartProbingForConflict() {
+        val mockProbingInfo = mock(ProbingInfo::class.java)
+        doReturn(mockProbingInfo).`when`(repository).setServiceProbing(TEST_SERVICE_ID_1)
+
+        advertiser.restartProbingForConflict(TEST_SERVICE_ID_1)
+
+        verify(prober).restartForConflict(mockProbingInfo)
+    }
+
+    @Test
+    fun testRenameServiceForConflict() {
+        val mockProbingInfo = mock(ProbingInfo::class.java)
+        doReturn(mockProbingInfo).`when`(repository).renameServiceForConflict(
+                TEST_SERVICE_ID_1, TEST_SERVICE_1)
+
+        advertiser.renameServiceForConflict(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+
+        verify(prober).restartForConflict(mockProbingInfo)
+    }
+
+    private fun addServiceAndFinishProbing(serviceId: Int, serviceInfo: NsdServiceInfo):
+            AnnouncementInfo {
+        val testProbingInfo = mock(ProbingInfo::class.java)
+        doReturn(serviceId).`when`(testProbingInfo).serviceId
+        doReturn(testProbingInfo).`when`(repository).setServiceProbing(serviceId)
+
+        advertiser.addService(serviceId, serviceInfo)
+        verify(repository).addService(serviceId, serviceInfo)
+        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)
+        return testAnnouncementInfo
+    }
+}
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/MdnsPacketTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsPacketTest.kt
new file mode 100644
index 0000000..f88da1f
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsPacketTest.kt
@@ -0,0 +1,70 @@
+/*
+ * 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
+import com.android.net.module.util.HexDump
+import com.android.testutils.DevSdkIgnoreRunner
+import kotlin.test.assertContentEquals
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(DevSdkIgnoreRunner::class)
+class MdnsPacketTest {
+    @Test
+    fun testParseQuery() {
+        // Probe packet with 1 question for Android.local, and 4 additionalRecords with 4 addresses
+        // for Android.local (similar to legacy mdnsresponder probes, although it used to put 4
+        // identical questions(!!) for Android.local when there were 4 addresses).
+        val packetHex = "00000000000100000004000007416e64726f6964056c6f63616c0000ff0001c00c000100" +
+                "01000000780004c000027bc00c001c000100000078001020010db8000000000000000000000123c0" +
+                "0c001c000100000078001020010db8000000000000000000000456c00c001c000100000078001020" +
+                "010db8000000000000000000000789"
+
+        val bytes = HexDump.hexStringToByteArray(packetHex)
+        val reader = MdnsPacketReader(bytes, bytes.size)
+        val packet = MdnsPacket.parse(reader)
+
+        assertEquals(1, packet.questions.size)
+        assertEquals(0, packet.answers.size)
+        assertEquals(4, packet.authorityRecords.size)
+        assertEquals(0, packet.additionalRecords.size)
+
+        val hostname = arrayOf("Android", "local")
+        packet.questions[0].let {
+            assertTrue(it is MdnsAnyRecord)
+            assertContentEquals(hostname, it.name)
+        }
+
+        packet.authorityRecords.forEach {
+            assertTrue(it is MdnsInetAddressRecord)
+            assertContentEquals(hostname, it.name)
+            assertEquals(120000, it.ttl)
+        }
+
+        assertEquals(InetAddresses.parseNumericAddress("192.0.2.123"),
+                (packet.authorityRecords[0] as MdnsInetAddressRecord).inet4Address)
+        assertEquals(InetAddresses.parseNumericAddress("2001:db8::123"),
+                (packet.authorityRecords[1] as MdnsInetAddressRecord).inet6Address)
+        assertEquals(InetAddresses.parseNumericAddress("2001:db8::456"),
+                (packet.authorityRecords[2] as MdnsInetAddressRecord).inet6Address)
+        assertEquals(InetAddresses.parseNumericAddress("2001:db8::789"),
+                (packet.authorityRecords[3] as MdnsInetAddressRecord).inet6Address)
+    }
+}
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..a2dbbc6 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
@@ -117,7 +114,7 @@
 
     @Test
     fun testProbe() {
-        val replySender = MdnsReplySender(thread.looper, socket, buffer)
+        val replySender = MdnsReplySender("testiface", thread.looper, socket, buffer)
         val prober = TestProber(thread.looper, replySender, cb)
         val probeInfo = TestProbeInfo(
                 listOf(makeServiceRecord(TEST_SERVICE_NAME_1, 37890)))
@@ -132,7 +129,7 @@
 
     @Test
     fun testProbeMultipleRecords() {
-        val replySender = MdnsReplySender(thread.looper, socket, buffer)
+        val replySender = MdnsReplySender("testiface", thread.looper, socket, buffer)
         val prober = TestProber(thread.looper, replySender, cb)
         val probeInfo = TestProbeInfo(listOf(
                 makeServiceRecord(TEST_SERVICE_NAME_1, 37890),
@@ -170,7 +167,7 @@
 
     @Test
     fun testStopProbing() {
-        val replySender = MdnsReplySender(thread.looper, socket, buffer)
+        val replySender = MdnsReplySender("testiface", thread.looper, socket, buffer)
         val prober = TestProber(thread.looper, replySender, cb)
         val probeInfo = TestProbeInfo(
                 listOf(makeServiceRecord(TEST_SERVICE_NAME_1, 37890)),
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..ecc11ec
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
@@ -0,0 +1,470 @@
+/*
+ * 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.nsd.NsdServiceInfo
+import android.os.Build
+import android.os.HandlerThread
+import com.android.server.connectivity.mdns.MdnsAnnouncer.AnnouncementInfo
+import com.android.server.connectivity.mdns.MdnsRecordRepository.Dependencies
+import com.android.server.connectivity.mdns.MdnsRecordRepository.getReverseDnsAddress
+import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import java.net.InetSocketAddress
+import java.net.NetworkInterface
+import java.util.Collections
+import kotlin.test.assertContentEquals
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import kotlin.test.assertFalse
+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 = listOf(
+        LinkAddress(parseNumericAddress("192.0.2.111"), 24),
+        LinkAddress(parseNumericAddress("2001:db8::111"), 64),
+        LinkAddress(parseNumericAddress("2001:db8::222"), 64))
+
+private val TEST_SERVICE_1 = NsdServiceInfo().apply {
+    serviceType = "_testservice._tcp"
+    serviceName = "MyTestService"
+    port = TEST_PORT
+}
+
+private val TEST_SERVICE_2 = NsdServiceInfo().apply {
+    serviceType = "_testservice._tcp"
+    serviceName = "MyOtherTestService"
+    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.map { it.address })
+    }
+
+    @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 testInvalidReuseOfServiceId() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        assertFailsWith(IllegalArgumentException::class) {
+            repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_2)
+        }
+    }
+
+    @Test
+    fun testHasActiveService() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        assertFalse(repository.hasActiveService(TEST_SERVICE_ID_1))
+
+        repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        assertTrue(repository.hasActiveService(TEST_SERVICE_ID_1))
+
+        val probingInfo = repository.setServiceProbing(TEST_SERVICE_ID_1)
+        repository.onProbingSucceeded(probingInfo)
+        repository.onAdvertisementSent(TEST_SERVICE_ID_1)
+        assertTrue(repository.hasActiveService(TEST_SERVICE_ID_1))
+
+        repository.exitService(TEST_SERVICE_ID_1)
+        assertFalse(repository.hasActiveService(TEST_SERVICE_ID_1))
+    }
+
+    @Test
+    fun testExitAnnouncements() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        repository.onAdvertisementSent(TEST_SERVICE_ID_1)
+
+        val exitAnnouncement = repository.exitService(TEST_SERVICE_ID_1)
+        assertNotNull(exitAnnouncement)
+        assertEquals(1, repository.servicesCount)
+        val packet = exitAnnouncement.getPacket(0)
+
+        assertEquals(0x8400 /* response, authoritative */, packet.flags)
+        assertEquals(0, packet.questions.size)
+        assertEquals(0, packet.authorityRecords.size)
+        assertEquals(0, packet.additionalRecords.size)
+
+        assertContentEquals(listOf(
+                MdnsPointerRecord(
+                        arrayOf("_testservice", "_tcp", "local"),
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        0L /* ttlMillis */,
+                        arrayOf("MyTestService", "_testservice", "_tcp", "local"))
+        ), packet.answers)
+
+        repository.removeService(TEST_SERVICE_ID_1)
+        assertEquals(0, repository.servicesCount)
+    }
+
+    @Test
+    fun testExitingServiceReAdded() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        repository.onAdvertisementSent(TEST_SERVICE_ID_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)
+    }
+
+    @Test
+    fun testOnProbingSucceeded() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        val announcementInfo = repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        repository.onAdvertisementSent(TEST_SERVICE_ID_1)
+        val packet = announcementInfo.getPacket(0)
+
+        assertEquals(0x8400 /* response, authoritative */, packet.flags)
+        assertEquals(0, packet.questions.size)
+        assertEquals(0, packet.authorityRecords.size)
+
+        val serviceType = arrayOf("_testservice", "_tcp", "local")
+        val serviceName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
+        val v4AddrRev = getReverseDnsAddress(TEST_ADDRESSES[0].address)
+        val v6Addr1Rev = getReverseDnsAddress(TEST_ADDRESSES[1].address)
+        val v6Addr2Rev = getReverseDnsAddress(TEST_ADDRESSES[2].address)
+
+        assertContentEquals(listOf(
+                // Reverse address and address records for the hostname
+                MdnsPointerRecord(v4AddrRev,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        TEST_HOSTNAME),
+                MdnsInetAddressRecord(TEST_HOSTNAME,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        TEST_ADDRESSES[0].address),
+                MdnsPointerRecord(v6Addr1Rev,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        TEST_HOSTNAME),
+                MdnsInetAddressRecord(TEST_HOSTNAME,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        TEST_ADDRESSES[1].address),
+                MdnsPointerRecord(v6Addr2Rev,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        TEST_HOSTNAME),
+                MdnsInetAddressRecord(TEST_HOSTNAME,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        TEST_ADDRESSES[2].address),
+                // Service registration records (RFC6763)
+                MdnsPointerRecord(
+                        serviceType,
+                        0L /* receiptTimeMillis */,
+                        // Not a unique name owned by the announcer, so cacheFlush=false
+                        false /* cacheFlush */,
+                        4500000L /* ttlMillis */,
+                        serviceName),
+                MdnsServiceRecord(
+                        serviceName,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        0 /* servicePriority */,
+                        0 /* serviceWeight */,
+                        TEST_PORT /* servicePort */,
+                        TEST_HOSTNAME),
+                MdnsTextRecord(
+                        serviceName,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        4500000L /* ttlMillis */,
+                        emptyList() /* entries */),
+                // Service type enumeration record (RFC6763 9.)
+                MdnsPointerRecord(
+                        arrayOf("_services", "_dns-sd", "_udp", "local"),
+                        0L /* receiptTimeMillis */,
+                        false /* cacheFlush */,
+                        4500000L /* ttlMillis */,
+                        serviceType)
+        ), packet.answers)
+
+        assertContentEquals(listOf(
+                MdnsNsecRecord(v4AddrRev,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        v4AddrRev,
+                        intArrayOf(MdnsRecord.TYPE_PTR)),
+                MdnsNsecRecord(TEST_HOSTNAME,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        TEST_HOSTNAME,
+                        intArrayOf(MdnsRecord.TYPE_A, MdnsRecord.TYPE_AAAA)),
+                MdnsNsecRecord(v6Addr1Rev,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        v6Addr1Rev,
+                        intArrayOf(MdnsRecord.TYPE_PTR)),
+                MdnsNsecRecord(v6Addr2Rev,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        120000L /* ttlMillis */,
+                        v6Addr2Rev,
+                        intArrayOf(MdnsRecord.TYPE_PTR)),
+                MdnsNsecRecord(serviceName,
+                        0L /* receiptTimeMillis */,
+                        true /* cacheFlush */,
+                        4500000L /* ttlMillis */,
+                        serviceName,
+                        intArrayOf(MdnsRecord.TYPE_TXT, MdnsRecord.TYPE_SRV))
+        ), packet.additionalRecords)
+    }
+
+    @Test
+    fun testGetReverseDnsAddress() {
+        val expectedV6 = "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.0.1.0.0.2.ip6.arpa"
+                .split(".").toTypedArray()
+        assertContentEquals(expectedV6, getReverseDnsAddress(parseNumericAddress("2001:db8::1")))
+        val expectedV4 = "123.2.0.192.in-addr.arpa".split(".").toTypedArray()
+        assertContentEquals(expectedV4, getReverseDnsAddress(parseNumericAddress("192.0.2.123")))
+    }
+
+    @Test
+    fun testGetReply() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        val questions = listOf(MdnsPointerRecord(arrayOf("_testservice", "_tcp", "local"),
+                0L /* receiptTimeMillis */,
+                false /* cacheFlush */,
+                // TTL and data is empty for a question
+                0L /* ttlMillis */,
+                null /* pointer */))
+        val query = MdnsPacket(0 /* flags */, questions, listOf() /* answers */,
+                listOf() /* authorityRecords */, listOf() /* additionalRecords */)
+        val src = InetSocketAddress(parseNumericAddress("192.0.2.123"), 5353)
+        val reply = repository.getReply(query, src)
+
+        assertNotNull(reply)
+        // Source address is IPv4
+        assertEquals(MdnsConstants.getMdnsIPv4Address(), reply.destination.address)
+        assertEquals(MdnsConstants.MDNS_PORT, reply.destination.port)
+
+        // TTLs as per RFC6762 10.
+        val longTtl = 4_500_000L
+        val shortTtl = 120_000L
+        val serviceName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
+
+        assertEquals(listOf(
+                MdnsPointerRecord(
+                        arrayOf("_testservice", "_tcp", "local"),
+                        0L /* receiptTimeMillis */,
+                        false /* cacheFlush */,
+                        longTtl,
+                        serviceName),
+        ), reply.answers)
+
+        assertEquals(listOf(
+            MdnsTextRecord(
+                    serviceName,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    longTtl,
+                    listOf() /* entries */),
+            MdnsServiceRecord(
+                    serviceName,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    shortTtl,
+                    0 /* servicePriority */,
+                    0 /* serviceWeight */,
+                    TEST_PORT,
+                    TEST_HOSTNAME),
+            MdnsInetAddressRecord(
+                    TEST_HOSTNAME,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    shortTtl,
+                    TEST_ADDRESSES[0].address),
+            MdnsInetAddressRecord(
+                    TEST_HOSTNAME,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    shortTtl,
+                    TEST_ADDRESSES[1].address),
+            MdnsInetAddressRecord(
+                    TEST_HOSTNAME,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    shortTtl,
+                    TEST_ADDRESSES[2].address),
+            MdnsNsecRecord(
+                    serviceName,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    longTtl,
+                    serviceName /* nextDomain */,
+                    intArrayOf(MdnsRecord.TYPE_TXT, MdnsRecord.TYPE_SRV)),
+            MdnsNsecRecord(
+                    TEST_HOSTNAME,
+                    0L /* receiptTimeMillis */,
+                    true /* cacheFlush */,
+                    shortTtl,
+                    TEST_HOSTNAME /* nextDomain */,
+                    intArrayOf(MdnsRecord.TYPE_A, MdnsRecord.TYPE_AAAA)),
+        ), reply.additionalAnswers)
+    }
+
+    @Test
+    fun testGetConflictingServices() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2)
+
+        val packet = MdnsPacket(
+                0 /* flags */,
+                emptyList() /* questions */,
+                listOf(
+                    MdnsServiceRecord(
+                            arrayOf("MyTestService", "_testservice", "_tcp", "local"),
+                            0L /* receiptTimeMillis */, true /* cacheFlush */, 0L /* ttlMillis */,
+                            0 /* servicePriority */, 0 /* serviceWeight */,
+                            TEST_SERVICE_1.port + 1,
+                            TEST_HOSTNAME),
+                    MdnsTextRecord(
+                            arrayOf("MyOtherTestService", "_testservice", "_tcp", "local"),
+                            0L /* receiptTimeMillis */, true /* cacheFlush */, 0L /* ttlMillis */,
+                            listOf(TextEntry.fromString("somedifferent=entry"))),
+                ) /* answers */,
+                emptyList() /* authorityRecords */,
+                emptyList() /* additionalRecords */)
+
+        assertEquals(setOf(TEST_SERVICE_ID_1, TEST_SERVICE_ID_2),
+                repository.getConflictingServices(packet))
+    }
+
+    @Test
+    fun testGetConflictingServices_IdenticalService() {
+        val repository = MdnsRecordRepository(thread.looper, deps)
+        repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
+        repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2)
+
+        val otherTtlMillis = 1234L
+        val packet = MdnsPacket(
+                0 /* flags */,
+                emptyList() /* questions */,
+                listOf(
+                        MdnsServiceRecord(
+                                arrayOf("MyTestService", "_testservice", "_tcp", "local"),
+                                0L /* receiptTimeMillis */, true /* cacheFlush */,
+                                otherTtlMillis, 0 /* servicePriority */, 0 /* serviceWeight */,
+                                TEST_SERVICE_1.port,
+                                TEST_HOSTNAME),
+                        MdnsTextRecord(
+                                arrayOf("MyOtherTestService", "_testservice", "_tcp", "local"),
+                                0L /* receiptTimeMillis */, true /* cacheFlush */,
+                                otherTtlMillis, emptyList()),
+                ) /* answers */,
+                emptyList() /* authorityRecords */,
+                emptyList() /* additionalRecords */)
+
+        // Above records are identical to the actual registrations: no conflict
+        assertEquals(emptySet(), repository.getConflictingServices(packet))
+    }
+}
+
+private fun MdnsRecordRepository.initWithService(serviceId: Int, serviceInfo: NsdServiceInfo):
+        AnnouncementInfo {
+    updateAddresses(TEST_ADDRESSES)
+    addService(serviceId, serviceInfo)
+    val probingInfo = setServiceProbing(serviceId)
+    assertNotNull(probingInfo)
+    return onProbingSucceeded(probingInfo)
+}
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..635b296 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -89,14 +90,22 @@
     public void setUp() throws IOException {
         MockitoAnnotations.initMocks(this);
         mockService(mContext, ConnectivityManager.class, Context.CONNECTIVITY_SERVICE, mCm);
+        if (mContext.getSystemService(ConnectivityManager.class) == null) {
+            // Test is using mockito-extended
+            doCallRealMethod().when(mContext).getSystemService(ConnectivityManager.class);
+        }
         mockService(mContext, TetheringManager.class, Context.TETHERING_SERVICE, mTm);
+        if (mContext.getSystemService(TetheringManager.class) == null) {
+            // Test is using mockito-extended
+            doCallRealMethod().when(mContext).getSystemService(TetheringManager.class);
+        }
         doReturn(true).when(mDeps).canScanOnInterface(any());
         doReturn(mTestNetworkIfaceWrapper).when(mDeps).getNetworkInterfaceByName(TEST_IFACE_NAME);
         doReturn(mLocalOnlyIfaceWrapper).when(mDeps)
                 .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 +168,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 +182,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 +190,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 +269,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/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index d7c90d8..13a6a6f 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -2198,7 +2198,7 @@
 
     private NetworkStatsCollection getLegacyCollection(String prefix, boolean includeTags) {
         final NetworkStatsRecorder recorder = makeTestRecorder(mLegacyStatsDir, prefix,
-                mSettings.getDevConfig(), includeTags, false);
+                mSettings.getXtConfig(), includeTags, false);
         return recorder.getOrLoadCompleteLocked();
     }
 
@@ -2255,14 +2255,9 @@
     }
 
     private void mockNetworkStatsSummary(NetworkStats summary) throws Exception {
-        mockNetworkStatsSummaryDev(summary.clone());
         mockNetworkStatsSummaryXt(summary.clone());
     }
 
-    private void mockNetworkStatsSummaryDev(NetworkStats summary) throws Exception {
-        doReturn(summary).when(mStatsFactory).readNetworkStatsSummaryDev();
-    }
-
     private void mockNetworkStatsSummaryXt(NetworkStats summary) throws Exception {
         doReturn(summary).when(mStatsFactory).readNetworkStatsSummaryXt();
     }
@@ -2293,13 +2288,11 @@
         doReturn(false).when(mSettings).getCombineSubtypeEnabled();
 
         final Config config = new Config(bucketDuration, deleteAge, deleteAge);
-        doReturn(config).when(mSettings).getDevConfig();
         doReturn(config).when(mSettings).getXtConfig();
         doReturn(config).when(mSettings).getUidConfig();
         doReturn(config).when(mSettings).getUidTagConfig();
 
         doReturn(MB_IN_BYTES).when(mSettings).getGlobalAlertBytes(anyLong());
-        doReturn(MB_IN_BYTES).when(mSettings).getDevPersistBytes(anyLong());
         doReturn(MB_IN_BYTES).when(mSettings).getXtPersistBytes(anyLong());
         doReturn(MB_IN_BYTES).when(mSettings).getUidPersistBytes(anyLong());
         doReturn(MB_IN_BYTES).when(mSettings).getUidTagPersistBytes(anyLong());
diff --git a/tools/gn2bp/Android.bp.swp b/tools/gn2bp/Android.bp.swp
index f6a17a4..0ff8284 100644
--- a/tools/gn2bp/Android.bp.swp
+++ b/tools/gn2bp/Android.bp.swp
@@ -14,10 +14,49 @@
 //
 // This file is automatically generated by gen_android_bp. Do not edit.
 
+build = ["Android.extras.bp"]
+
+// GN: PACKAGE
+package {
+    default_applicable_licenses: [
+        "external_cronet_license",
+    ],
+}
+
+// GN: //components/cronet/android:cronet_api_java
+// TODO(danstahr): add the API helpers separately after the main API is checked in and thoroughly reviewed
+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/ConnectionMigrationOptions.java",
+        "components/cronet/android/api/src/android/net/http/DnsOptions.java",
+        "components/cronet/android/api/src/android/net/http/ExperimentalBidirectionalStream.java",
+        "components/cronet/android/api/src/android/net/http/ExperimentalHttpEngine.java",
+        "components/cronet/android/api/src/android/net/http/ExperimentalUrlRequest.java",
+        "components/cronet/android/api/src/android/net/http/HttpEngine.java",
+        "components/cronet/android/api/src/android/net/http/HttpException.java",
+        "components/cronet/android/api/src/android/net/http/IHttpEngineBuilder.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/QuicOptions.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",
+    ],
+}
+
 // 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 " +
@@ -37,6 +76,30 @@
     ],
 }
 
+// GN: //base/allocator:buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_allocator_buildflags__testing",
+    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 " +
+         "//base/allocator:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/allocator/buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base/allocator/partition_allocator:chromecast_buildflags
 cc_genrule {
     name: "cronet_aml_base_allocator_partition_allocator_chromecast_buildflags",
@@ -60,6 +123,30 @@
     ],
 }
 
+// GN: //base/allocator/partition_allocator:chromecast_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_allocator_partition_allocator_chromecast_buildflags__testing",
+    cmd: "echo '--flags PA_IS_CAST_ANDROID=\"false\" PA_IS_CASTOS=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base/allocator/partition_allocator:chromecast_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/allocator/partition_allocator/chromecast_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base/allocator/partition_allocator:chromeos_buildflags
 cc_genrule {
     name: "cronet_aml_base_allocator_partition_allocator_chromeos_buildflags",
@@ -83,10 +170,34 @@
     ],
 }
 
+// GN: //base/allocator/partition_allocator:chromeos_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_allocator_partition_allocator_chromeos_buildflags__testing",
+    cmd: "echo '--flags PA_IS_CHROMEOS_ASH=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base/allocator/partition_allocator:chromeos_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/allocator/partition_allocator/chromeos_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base/allocator/partition_allocator:debugging_buildflags
 cc_genrule {
     name: "cronet_aml_base_allocator_partition_allocator_debugging_buildflags",
-    cmd: "echo '--flags PA_DCHECK_IS_ON=\"true\" PA_EXPENSIVE_DCHECKS_ARE_ON=\"true\" PA_DCHECK_IS_CONFIGURABLE=\"false\"' | " +
+    cmd: "echo '--flags PA_DCHECK_IS_ON=\"false\" PA_EXPENSIVE_DCHECKS_ARE_ON=\"false\" PA_DCHECK_IS_CONFIGURABLE=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -106,6 +217,30 @@
     ],
 }
 
+// GN: //base/allocator/partition_allocator:debugging_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_allocator_partition_allocator_debugging_buildflags__testing",
+    cmd: "echo '--flags PA_DCHECK_IS_ON=\"false\" PA_EXPENSIVE_DCHECKS_ARE_ON=\"false\" PA_DCHECK_IS_CONFIGURABLE=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base/allocator/partition_allocator:debugging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base/allocator/partition_allocator:logging_buildflags
 cc_genrule {
     name: "cronet_aml_base_allocator_partition_allocator_logging_buildflags",
@@ -129,6 +264,30 @@
     ],
 }
 
+// GN: //base/allocator/partition_allocator:logging_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_allocator_partition_allocator_logging_buildflags__testing",
+    cmd: "echo '--flags PA_ENABLE_LOG_ERROR_NOT_REACHED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base/allocator/partition_allocator:logging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/allocator/partition_allocator/logging_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base/allocator/partition_allocator:partition_alloc
 cc_library_static {
     name: "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -156,7 +315,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,21 +366,30 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
         "-DIS_PARTITION_ALLOC_IMPL",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-DPA_PCSCAN_STACK_SUPPORTED",
-        "-D_DEBUG",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-O3",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -231,19 +398,33 @@
         "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",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
         android_arm: {
             srcs: [
                 "base/allocator/partition_allocator/starscan/stack/asm/arm/push_registers_asm.cc",
             ],
+            cflags: [
+                "-fstack-protector",
+            ],
         },
         android_arm64: {
             srcs: [
                 "base/allocator/partition_allocator/starscan/stack/asm/arm64/push_registers_asm.cc",
             ],
             cflags: [
+                "-fstack-protector",
                 "-march=armv8-a+memtag",
+                "-mno-outline",
+                "-mno-outline-atomics",
             ],
         },
         android_x86: {
@@ -259,16 +440,225 @@
                 "base/allocator/partition_allocator/starscan/stack/asm/x64/push_registers_asm.cc",
             ],
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //base/allocator/partition_allocator:partition_alloc__testing
+cc_library_static {
+    name: "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+    srcs: [
+        "base/allocator/partition_allocator/address_pool_manager.cc",
+        "base/allocator/partition_allocator/address_pool_manager_bitmap.cc",
+        "base/allocator/partition_allocator/address_space_randomization.cc",
+        "base/allocator/partition_allocator/allocation_guard.cc",
+        "base/allocator/partition_allocator/dangling_raw_ptr_checks.cc",
+        "base/allocator/partition_allocator/gwp_asan_support.cc",
+        "base/allocator/partition_allocator/memory_reclaimer.cc",
+        "base/allocator/partition_allocator/oom.cc",
+        "base/allocator/partition_allocator/oom_callback.cc",
+        "base/allocator/partition_allocator/page_allocator.cc",
+        "base/allocator/partition_allocator/page_allocator_internals_posix.cc",
+        "base/allocator/partition_allocator/partition_address_space.cc",
+        "base/allocator/partition_allocator/partition_alloc.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/check.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/cpu.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/debug/alias.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/files/file_util_posix.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/logging.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/memory/ref_counted.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",
+        "base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread_posix.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/time/time.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/time/time_conversion_posix.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/time/time_now_posix.cc",
+        "base/allocator/partition_allocator/partition_alloc_base/time/time_override.cc",
+        "base/allocator/partition_allocator/partition_alloc_hooks.cc",
+        "base/allocator/partition_allocator/partition_bucket.cc",
+        "base/allocator/partition_allocator/partition_oom.cc",
+        "base/allocator/partition_allocator/partition_page.cc",
+        "base/allocator/partition_allocator/partition_root.cc",
+        "base/allocator/partition_allocator/partition_stats.cc",
+        "base/allocator/partition_allocator/random.cc",
+        "base/allocator/partition_allocator/reservation_offset_table.cc",
+        "base/allocator/partition_allocator/spinning_mutex.cc",
+        "base/allocator/partition_allocator/starscan/metadata_allocator.cc",
+        "base/allocator/partition_allocator/starscan/pcscan.cc",
+        "base/allocator/partition_allocator/starscan/pcscan_internal.cc",
+        "base/allocator/partition_allocator/starscan/pcscan_scheduling.cc",
+        "base/allocator/partition_allocator/starscan/snapshot.cc",
+        "base/allocator/partition_allocator/starscan/stack/stack.cc",
+        "base/allocator/partition_allocator/starscan/stats_collector.cc",
+        "base/allocator/partition_allocator/starscan/write_protector.cc",
+        "base/allocator/partition_allocator/tagging.cc",
+        "base/allocator/partition_allocator/thread_cache.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_base_allocator_partition_allocator_chromecast_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_chromeos_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_debugging_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_logging_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_allocator_partition_allocator_chromecast_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_chromeos_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_debugging_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_logging_buildflags__testing",
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DIS_PARTITION_ALLOC_IMPL",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DPA_PCSCAN_STACK_SUPPORTED",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-O3",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                "base/allocator/partition_allocator/partition_alloc_base/files/file_path.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/time/time_android.cc",
+                "base/allocator/partition_allocator/starscan/stack/asm/arm/push_registers_asm.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+        },
+        android_arm64: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                "base/allocator/partition_allocator/partition_alloc_base/files/file_path.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/time/time_android.cc",
+                "base/allocator/partition_allocator/starscan/stack/asm/arm64/push_registers_asm.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-march=armv8-a+memtag",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+        },
+        android_x86: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                "base/allocator/partition_allocator/partition_alloc_base/files/file_path.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/time/time_android.cc",
+                "base/allocator/partition_allocator/starscan/stack/asm/x86/push_registers_asm.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-msse3",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+        },
+        android_x86_64: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                "base/allocator/partition_allocator/partition_alloc_base/files/file_path.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/time/time_android.cc",
+                "base/allocator/partition_allocator/starscan/stack/asm/x64/push_registers_asm.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+        },
+        host: {
+            srcs: [
+                "base/allocator/partition_allocator/starscan/stack/asm/x64/push_registers_asm.cc",
+            ],
+            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",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // 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 " +
@@ -288,6 +678,81 @@
     ],
 }
 
+// GN: //base/allocator/partition_allocator:partition_alloc_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_allocator_partition_allocator_partition_alloc_buildflags__testing",
+    cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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 " +
+         "//base/allocator/partition_allocator:partition_alloc_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ $$CC_OS != 'android' ]]; " +
+         "then " +
+         "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=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base/allocator/partition_allocator:partition_alloc_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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 " +
+         "//base/allocator/partition_allocator:partition_alloc_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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 " +
+         "//base/allocator/partition_allocator:partition_alloc_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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 " +
+         "//base/allocator/partition_allocator:partition_alloc_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi;",
+    host_supported: true,
+    out: [
+        "base/allocator/partition_allocator/partition_alloc_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:anchor_functions_buildflags
 cc_genrule {
     name: "cronet_aml_base_anchor_functions_buildflags",
@@ -311,6 +776,81 @@
     ],
 }
 
+// GN: //base:anchor_functions_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_anchor_functions_buildflags__testing",
+    cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags USE_LLD=\"true\" SUPPORTS_CODE_ORDERING=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:anchor_functions_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ $$CC_OS != 'android' ]]; " +
+         "then " +
+         "echo '--flags USE_LLD=\"true\" SUPPORTS_CODE_ORDERING=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:anchor_functions_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags USE_LLD=\"true\" SUPPORTS_CODE_ORDERING=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:anchor_functions_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags USE_LLD=\"true\" SUPPORTS_CODE_ORDERING=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:anchor_functions_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags USE_LLD=\"true\" SUPPORTS_CODE_ORDERING=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:anchor_functions_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi;",
+    host_supported: true,
+    out: [
+        "base/android/library_loader/anchor_functions_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:android_runtime_jni_headers
 cc_genrule {
     name: "cronet_aml_base_android_runtime_jni_headers",
@@ -321,7 +861,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 +871,58 @@
          "--input_file " +
          "java/lang/Runtime.class " +
          "--javap " +
-         "$$(find out/.path -name javap)",
+         "$$(find $${OUT_DIR:-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",
+    ],
+}
+
+// GN: //base:android_runtime_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_base_android_runtime_jni_headers__testing",
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/base/android_runtime_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--jar_file " +
+         "$(location :current_android_jar) " +
+         "--output_name " +
+         "Runnable_jni.h " +
+         "--output_name " +
+         "Runtime_jni.h " +
+         "--input_file " +
+         "java/lang/Runnable.class " +
+         "--input_file " +
+         "java/lang/Runtime.class " +
+         "--javap " +
+         "$$(find $${OUT_DIR:-out}/.path -name javap)",
+    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",
     ],
     apex_available: [
         "com.android.tethering",
@@ -353,6 +933,7 @@
 cc_library_static {
     name: "cronet_aml_base_base",
     srcs: [
+        ":cronet_aml_base_nodebug_assertion",
         ":cronet_aml_third_party_abseil_cpp_absl_base_base",
         ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity",
         ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal",
@@ -901,6 +1482,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,26 +1492,35 @@
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
         "-DBASE_IMPLEMENTATION",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
         "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-DUSE_CHROMIUM_ICU=1",
         "-DU_ENABLE_DYLOAD=0",
         "-DU_ENABLE_RESOURCE_TRACING=0",
         "-DU_ENABLE_TRACING=1",
         "-DU_STATIC_IMPLEMENTATION",
         "-DU_USING_ICU_NAMESPACE=0",
-        "-D_DEBUG",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -940,7 +1533,31 @@
         "third_party/icu/source/common/",
         "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    header_libs: [
+        "libgtest_prod_headers",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
         android_arm: {
             srcs: [
@@ -950,11 +1567,19 @@
                 "base/profiler/chrome_unwinder_android_v2.cc",
                 "base/trace_event/cfi_backtrace_android.cc",
             ],
+            cflags: [
+                "-fstack-protector",
+            ],
         },
         android_arm64: {
             srcs: [
                 "base/android/reached_code_profiler.cc",
             ],
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
         },
         android_x86: {
             srcs: [
@@ -969,12 +1594,1050 @@
                 "base/android/reached_code_profiler_stub.cc",
             ],
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //base:base__testing
+cc_library_static {
+    name: "cronet_aml_base_base__testing",
+    srcs: [
+        ":cronet_aml_base_nodebug_assertion__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+        "base/allocator/allocator_check.cc",
+        "base/allocator/allocator_extension.cc",
+        "base/allocator/dispatcher/dispatcher.cc",
+        "base/allocator/dispatcher/internal/dispatch_data.cc",
+        "base/allocator/dispatcher/reentry_guard.cc",
+        "base/allocator/partition_allocator/shim/allocator_shim.cc",
+        "base/at_exit.cc",
+        "base/barrier_closure.cc",
+        "base/base64.cc",
+        "base/base64url.cc",
+        "base/base_paths.cc",
+        "base/big_endian.cc",
+        "base/build_time.cc",
+        "base/callback_list.cc",
+        "base/check.cc",
+        "base/check_is_test.cc",
+        "base/check_op.cc",
+        "base/command_line.cc",
+        "base/containers/flat_tree.cc",
+        "base/containers/intrusive_heap.cc",
+        "base/containers/linked_list.cc",
+        "base/cpu.cc",
+        "base/cpu_reduction_experiment.cc",
+        "base/debug/activity_analyzer.cc",
+        "base/debug/activity_tracker.cc",
+        "base/debug/alias.cc",
+        "base/debug/asan_invalid_access.cc",
+        "base/debug/buffered_dwarf_reader.cc",
+        "base/debug/crash_logging.cc",
+        "base/debug/debugger.cc",
+        "base/debug/debugger_posix.cc",
+        "base/debug/dump_without_crashing.cc",
+        "base/debug/dwarf_line_no.cc",
+        "base/debug/elf_reader.cc",
+        "base/debug/proc_maps_linux.cc",
+        "base/debug/profiler.cc",
+        "base/debug/stack_trace.cc",
+        "base/debug/task_trace.cc",
+        "base/environment.cc",
+        "base/feature_list.cc",
+        "base/features.cc",
+        "base/file_descriptor_posix.cc",
+        "base/file_descriptor_store.cc",
+        "base/files/file.cc",
+        "base/files/file_descriptor_watcher_posix.cc",
+        "base/files/file_enumerator.cc",
+        "base/files/file_enumerator_posix.cc",
+        "base/files/file_path.cc",
+        "base/files/file_path_watcher.cc",
+        "base/files/file_path_watcher_inotify.cc",
+        "base/files/file_posix.cc",
+        "base/files/file_proxy.cc",
+        "base/files/file_tracing.cc",
+        "base/files/file_util.cc",
+        "base/files/file_util_posix.cc",
+        "base/files/important_file_writer.cc",
+        "base/files/important_file_writer_cleaner.cc",
+        "base/files/memory_mapped_file.cc",
+        "base/files/memory_mapped_file_posix.cc",
+        "base/files/safe_base_name.cc",
+        "base/files/scoped_file.cc",
+        "base/files/scoped_temp_dir.cc",
+        "base/functional/callback_helpers.cc",
+        "base/functional/callback_internal.cc",
+        "base/guid.cc",
+        "base/hash/hash.cc",
+        "base/hash/legacy_hash.cc",
+        "base/hash/md5_boringssl.cc",
+        "base/hash/sha1_boringssl.cc",
+        "base/json/json_file_value_serializer.cc",
+        "base/json/json_parser.cc",
+        "base/json/json_reader.cc",
+        "base/json/json_string_value_serializer.cc",
+        "base/json/json_value_converter.cc",
+        "base/json/json_writer.cc",
+        "base/json/string_escape.cc",
+        "base/json/values_util.cc",
+        "base/lazy_instance_helpers.cc",
+        "base/linux_util.cc",
+        "base/location.cc",
+        "base/logging.cc",
+        "base/memory/aligned_memory.cc",
+        "base/memory/discardable_memory.cc",
+        "base/memory/discardable_memory_allocator.cc",
+        "base/memory/discardable_shared_memory.cc",
+        "base/memory/madv_free_discardable_memory_allocator_posix.cc",
+        "base/memory/madv_free_discardable_memory_posix.cc",
+        "base/memory/memory_pressure_listener.cc",
+        "base/memory/memory_pressure_monitor.cc",
+        "base/memory/nonscannable_memory.cc",
+        "base/memory/page_size_posix.cc",
+        "base/memory/platform_shared_memory_handle.cc",
+        "base/memory/platform_shared_memory_region.cc",
+        "base/memory/raw_ptr.cc",
+        "base/memory/raw_ptr_asan_bound_arg_tracker.cc",
+        "base/memory/raw_ptr_asan_service.cc",
+        "base/memory/read_only_shared_memory_region.cc",
+        "base/memory/ref_counted.cc",
+        "base/memory/ref_counted_memory.cc",
+        "base/memory/shared_memory_mapper.cc",
+        "base/memory/shared_memory_mapping.cc",
+        "base/memory/shared_memory_security_policy.cc",
+        "base/memory/shared_memory_tracker.cc",
+        "base/memory/unsafe_shared_memory_pool.cc",
+        "base/memory/unsafe_shared_memory_region.cc",
+        "base/memory/weak_ptr.cc",
+        "base/memory/writable_shared_memory_region.cc",
+        "base/message_loop/message_pump.cc",
+        "base/message_loop/message_pump_default.cc",
+        "base/message_loop/message_pump_epoll.cc",
+        "base/message_loop/message_pump_libevent.cc",
+        "base/message_loop/watchable_io_message_pump_posix.cc",
+        "base/message_loop/work_id_provider.cc",
+        "base/metrics/bucket_ranges.cc",
+        "base/metrics/crc32.cc",
+        "base/metrics/dummy_histogram.cc",
+        "base/metrics/field_trial.cc",
+        "base/metrics/field_trial_param_associator.cc",
+        "base/metrics/field_trial_params.cc",
+        "base/metrics/histogram.cc",
+        "base/metrics/histogram_base.cc",
+        "base/metrics/histogram_delta_serialization.cc",
+        "base/metrics/histogram_functions.cc",
+        "base/metrics/histogram_samples.cc",
+        "base/metrics/histogram_snapshot_manager.cc",
+        "base/metrics/metrics_hashes.cc",
+        "base/metrics/persistent_histogram_allocator.cc",
+        "base/metrics/persistent_histogram_storage.cc",
+        "base/metrics/persistent_memory_allocator.cc",
+        "base/metrics/persistent_sample_map.cc",
+        "base/metrics/ranges_manager.cc",
+        "base/metrics/sample_map.cc",
+        "base/metrics/sample_vector.cc",
+        "base/metrics/single_sample_metrics.cc",
+        "base/metrics/sparse_histogram.cc",
+        "base/metrics/statistics_recorder.cc",
+        "base/metrics/user_metrics.cc",
+        "base/native_library.cc",
+        "base/native_library_posix.cc",
+        "base/observer_list_internal.cc",
+        "base/observer_list_threadsafe.cc",
+        "base/observer_list_types.cc",
+        "base/one_shot_event.cc",
+        "base/path_service.cc",
+        "base/pending_task.cc",
+        "base/pickle.cc",
+        "base/posix/can_lower_nice_to.cc",
+        "base/posix/file_descriptor_shuffle.cc",
+        "base/posix/global_descriptors.cc",
+        "base/posix/safe_strerror.cc",
+        "base/posix/unix_domain_socket.cc",
+        "base/power_monitor/battery_level_provider.cc",
+        "base/power_monitor/battery_state_sampler.cc",
+        "base/power_monitor/moving_average.cc",
+        "base/power_monitor/power_monitor.cc",
+        "base/power_monitor/power_monitor_device_source.cc",
+        "base/power_monitor/power_monitor_features.cc",
+        "base/power_monitor/power_monitor_source.cc",
+        "base/power_monitor/sampling_event_source.cc",
+        "base/power_monitor/timer_sampling_event_source.cc",
+        "base/process/environment_internal.cc",
+        "base/process/internal_linux.cc",
+        "base/process/kill.cc",
+        "base/process/kill_posix.cc",
+        "base/process/launch.cc",
+        "base/process/launch_posix.cc",
+        "base/process/memory.cc",
+        "base/process/memory_linux.cc",
+        "base/process/process_handle.cc",
+        "base/process/process_handle_linux.cc",
+        "base/process/process_handle_posix.cc",
+        "base/process/process_iterator.cc",
+        "base/process/process_iterator_linux.cc",
+        "base/process/process_metrics.cc",
+        "base/process/process_metrics_linux.cc",
+        "base/process/process_metrics_posix.cc",
+        "base/process/process_posix.cc",
+        "base/profiler/arm_cfi_table.cc",
+        "base/profiler/frame.cc",
+        "base/profiler/metadata_recorder.cc",
+        "base/profiler/module_cache.cc",
+        "base/profiler/module_cache_posix.cc",
+        "base/profiler/sample_metadata.cc",
+        "base/profiler/sampling_profiler_thread_token.cc",
+        "base/profiler/stack_base_address_posix.cc",
+        "base/profiler/stack_buffer.cc",
+        "base/profiler/stack_copier.cc",
+        "base/profiler/stack_copier_signal.cc",
+        "base/profiler/stack_copier_suspend.cc",
+        "base/profiler/stack_sampler.cc",
+        "base/profiler/stack_sampler_impl.cc",
+        "base/profiler/stack_sampling_profiler.cc",
+        "base/profiler/thread_delegate_posix.cc",
+        "base/profiler/unwinder.cc",
+        "base/rand_util.cc",
+        "base/rand_util_posix.cc",
+        "base/run_loop.cc",
+        "base/sampling_heap_profiler/lock_free_address_hash_set.cc",
+        "base/sampling_heap_profiler/poisson_allocation_sampler.cc",
+        "base/sampling_heap_profiler/sampling_heap_profiler.cc",
+        "base/scoped_add_feature_flags.cc",
+        "base/scoped_environment_variable_override.cc",
+        "base/scoped_native_library.cc",
+        "base/sequence_checker.cc",
+        "base/sequence_checker_impl.cc",
+        "base/sequence_token.cc",
+        "base/strings/abseil_string_conversions.cc",
+        "base/strings/abseil_string_number_conversions.cc",
+        "base/strings/escape.cc",
+        "base/strings/latin1_string_conversions.cc",
+        "base/strings/pattern.cc",
+        "base/strings/safe_sprintf.cc",
+        "base/strings/strcat.cc",
+        "base/strings/string_number_conversions.cc",
+        "base/strings/string_piece.cc",
+        "base/strings/string_split.cc",
+        "base/strings/string_util.cc",
+        "base/strings/string_util_constants.cc",
+        "base/strings/stringprintf.cc",
+        "base/strings/sys_string_conversions_posix.cc",
+        "base/strings/utf_offset_string_conversions.cc",
+        "base/strings/utf_string_conversion_utils.cc",
+        "base/strings/utf_string_conversions.cc",
+        "base/substring_set_matcher/matcher_string_pattern.cc",
+        "base/substring_set_matcher/substring_set_matcher.cc",
+        "base/supports_user_data.cc",
+        "base/sync_socket.cc",
+        "base/sync_socket_posix.cc",
+        "base/synchronization/atomic_flag.cc",
+        "base/synchronization/condition_variable_posix.cc",
+        "base/synchronization/lock.cc",
+        "base/synchronization/lock_impl_posix.cc",
+        "base/synchronization/waitable_event_posix.cc",
+        "base/synchronization/waitable_event_watcher_posix.cc",
+        "base/syslog_logging.cc",
+        "base/system/sys_info.cc",
+        "base/system/sys_info_linux.cc",
+        "base/system/sys_info_posix.cc",
+        "base/system/system_monitor.cc",
+        "base/task/cancelable_task_tracker.cc",
+        "base/task/common/checked_lock_impl.cc",
+        "base/task/common/lazy_now.cc",
+        "base/task/common/operations_controller.cc",
+        "base/task/common/scoped_defer_task_posting.cc",
+        "base/task/common/task_annotator.cc",
+        "base/task/current_thread.cc",
+        "base/task/default_delayed_task_handle_delegate.cc",
+        "base/task/deferred_sequenced_task_runner.cc",
+        "base/task/delayed_task_handle.cc",
+        "base/task/lazy_thread_pool_task_runner.cc",
+        "base/task/post_job.cc",
+        "base/task/scoped_set_task_priority_for_current_thread.cc",
+        "base/task/sequence_manager/associated_thread_id.cc",
+        "base/task/sequence_manager/atomic_flag_set.cc",
+        "base/task/sequence_manager/delayed_task_handle_delegate.cc",
+        "base/task/sequence_manager/enqueue_order_generator.cc",
+        "base/task/sequence_manager/fence.cc",
+        "base/task/sequence_manager/hierarchical_timing_wheel.cc",
+        "base/task/sequence_manager/sequence_manager.cc",
+        "base/task/sequence_manager/sequence_manager_impl.cc",
+        "base/task/sequence_manager/sequenced_task_source.cc",
+        "base/task/sequence_manager/task_order.cc",
+        "base/task/sequence_manager/task_queue.cc",
+        "base/task/sequence_manager/task_queue_impl.cc",
+        "base/task/sequence_manager/task_queue_selector.cc",
+        "base/task/sequence_manager/tasks.cc",
+        "base/task/sequence_manager/thread_controller.cc",
+        "base/task/sequence_manager/thread_controller_impl.cc",
+        "base/task/sequence_manager/thread_controller_power_monitor.cc",
+        "base/task/sequence_manager/thread_controller_with_message_pump_impl.cc",
+        "base/task/sequence_manager/time_domain.cc",
+        "base/task/sequence_manager/timing_wheel.cc",
+        "base/task/sequence_manager/wake_up_queue.cc",
+        "base/task/sequence_manager/work_deduplicator.cc",
+        "base/task/sequence_manager/work_queue.cc",
+        "base/task/sequence_manager/work_queue_sets.cc",
+        "base/task/sequenced_task_runner.cc",
+        "base/task/simple_task_executor.cc",
+        "base/task/single_thread_task_executor.cc",
+        "base/task/single_thread_task_runner.cc",
+        "base/task/task_executor.cc",
+        "base/task/task_features.cc",
+        "base/task/task_runner.cc",
+        "base/task/task_traits.cc",
+        "base/task/thread_pool.cc",
+        "base/task/thread_pool/delayed_priority_queue.cc",
+        "base/task/thread_pool/delayed_task_manager.cc",
+        "base/task/thread_pool/environment_config.cc",
+        "base/task/thread_pool/initialization_util.cc",
+        "base/task/thread_pool/job_task_source.cc",
+        "base/task/thread_pool/pooled_parallel_task_runner.cc",
+        "base/task/thread_pool/pooled_sequenced_task_runner.cc",
+        "base/task/thread_pool/pooled_single_thread_task_runner_manager.cc",
+        "base/task/thread_pool/pooled_task_runner_delegate.cc",
+        "base/task/thread_pool/priority_queue.cc",
+        "base/task/thread_pool/sequence.cc",
+        "base/task/thread_pool/service_thread.cc",
+        "base/task/thread_pool/task.cc",
+        "base/task/thread_pool/task_source.cc",
+        "base/task/thread_pool/task_source_sort_key.cc",
+        "base/task/thread_pool/task_tracker.cc",
+        "base/task/thread_pool/thread_group.cc",
+        "base/task/thread_pool/thread_group_impl.cc",
+        "base/task/thread_pool/thread_group_native.cc",
+        "base/task/thread_pool/thread_pool_impl.cc",
+        "base/task/thread_pool/thread_pool_instance.cc",
+        "base/task/thread_pool/worker_thread.cc",
+        "base/task/thread_pool/worker_thread_stack.cc",
+        "base/third_party/cityhash/city.cc",
+        "base/third_party/cityhash_v103/src/city_v103.cc",
+        "base/third_party/nspr/prtime.cc",
+        "base/third_party/superfasthash/superfasthash.c",
+        "base/threading/hang_watcher.cc",
+        "base/threading/platform_thread.cc",
+        "base/threading/platform_thread_internal_posix.cc",
+        "base/threading/platform_thread_posix.cc",
+        "base/threading/platform_thread_ref.cc",
+        "base/threading/post_task_and_reply_impl.cc",
+        "base/threading/scoped_blocking_call.cc",
+        "base/threading/scoped_blocking_call_internal.cc",
+        "base/threading/scoped_thread_priority.cc",
+        "base/threading/sequence_local_storage_map.cc",
+        "base/threading/sequence_local_storage_slot.cc",
+        "base/threading/sequenced_task_runner_handle.cc",
+        "base/threading/simple_thread.cc",
+        "base/threading/thread.cc",
+        "base/threading/thread_checker.cc",
+        "base/threading/thread_checker_impl.cc",
+        "base/threading/thread_collision_warner.cc",
+        "base/threading/thread_id_name_manager.cc",
+        "base/threading/thread_local_storage.cc",
+        "base/threading/thread_local_storage_posix.cc",
+        "base/threading/thread_restrictions.cc",
+        "base/threading/thread_task_runner_handle.cc",
+        "base/threading/watchdog.cc",
+        "base/time/clock.cc",
+        "base/time/default_clock.cc",
+        "base/time/default_tick_clock.cc",
+        "base/time/tick_clock.cc",
+        "base/time/time.cc",
+        "base/time/time_conversion_posix.cc",
+        "base/time/time_delta_from_string.cc",
+        "base/time/time_exploded_icu.cc",
+        "base/time/time_exploded_posix.cc",
+        "base/time/time_now_posix.cc",
+        "base/time/time_override.cc",
+        "base/time/time_to_iso8601.cc",
+        "base/timer/elapsed_timer.cc",
+        "base/timer/hi_res_timer_manager_posix.cc",
+        "base/timer/lap_timer.cc",
+        "base/timer/timer.cc",
+        "base/timer/wall_clock_timer.cc",
+        "base/token.cc",
+        "base/trace_event/heap_profiler_allocation_context.cc",
+        "base/trace_event/heap_profiler_allocation_context_tracker.cc",
+        "base/trace_event/memory_allocator_dump_guid.cc",
+        "base/trace_event/trace_event_stub.cc",
+        "base/trace_event/trace_id_helper.cc",
+        "base/unguessable_token.cc",
+        "base/value_iterators.cc",
+        "base/values.cc",
+        "base/version.cc",
+        "base/vlog.cc",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_base_allocator_buildflags__testing",
+        "cronet_aml_base_anchor_functions_buildflags__testing",
+        "cronet_aml_base_build_date__testing",
+        "cronet_aml_base_cfi_buildflags__testing",
+        "cronet_aml_base_clang_profiling_buildflags__testing",
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_feature_list_buildflags__testing",
+        "cronet_aml_base_ios_cronet_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_base_message_pump_buildflags__testing",
+        "cronet_aml_base_orderfile_buildflags__testing",
+        "cronet_aml_base_parsing_buildflags__testing",
+        "cronet_aml_base_power_monitor_buildflags__testing",
+        "cronet_aml_base_profiler_buildflags__testing",
+        "cronet_aml_base_sanitizer_buildflags__testing",
+        "cronet_aml_base_synchronization_buildflags__testing",
+        "cronet_aml_base_tracing_buildflags__testing",
+        "cronet_aml_build_branding_buildflags__testing",
+        "cronet_aml_build_chromecast_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_build_config_compiler_compiler_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_allocator_buildflags__testing",
+        "cronet_aml_base_anchor_functions_buildflags__testing",
+        "cronet_aml_base_build_date__testing",
+        "cronet_aml_base_cfi_buildflags__testing",
+        "cronet_aml_base_clang_profiling_buildflags__testing",
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_feature_list_buildflags__testing",
+        "cronet_aml_base_ios_cronet_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_base_message_pump_buildflags__testing",
+        "cronet_aml_base_orderfile_buildflags__testing",
+        "cronet_aml_base_parsing_buildflags__testing",
+        "cronet_aml_base_power_monitor_buildflags__testing",
+        "cronet_aml_base_profiler_buildflags__testing",
+        "cronet_aml_base_sanitizer_buildflags__testing",
+        "cronet_aml_base_synchronization_buildflags__testing",
+        "cronet_aml_base_tracing_buildflags__testing",
+        "cronet_aml_build_branding_buildflags__testing",
+        "cronet_aml_build_chromecast_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_build_config_compiler_compiler_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DBASE_IMPLEMENTATION",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libandroid",
+                "liblog",
+            ],
+        },
+        android_arm: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                ":cronet_aml_third_party_ashmem_ashmem__testing",
+                "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc",
+                "base/android/android_hardware_buffer_compat.cc",
+                "base/android/android_image_reader_compat.cc",
+                "base/android/apk_assets.cc",
+                "base/android/application_status_listener.cc",
+                "base/android/base_feature_list.cc",
+                "base/android/base_features.cc",
+                "base/android/base_jni_onload.cc",
+                "base/android/build_info.cc",
+                "base/android/bundle_utils.cc",
+                "base/android/callback_android.cc",
+                "base/android/child_process_service.cc",
+                "base/android/command_line_android.cc",
+                "base/android/content_uri_utils.cc",
+                "base/android/cpu_features.cc",
+                "base/android/early_trace_event_binding.cc",
+                "base/android/event_log.cc",
+                "base/android/feature_list_jni.cc",
+                "base/android/features_jni.cc",
+                "base/android/field_trial_list.cc",
+                "base/android/important_file_writer_android.cc",
+                "base/android/int_string_callback.cc",
+                "base/android/jank_metric_uma_recorder.cc",
+                "base/android/java_exception_reporter.cc",
+                "base/android/java_handler_thread.cc",
+                "base/android/java_heap_dump_generator.cc",
+                "base/android/java_runtime.cc",
+                "base/android/jni_android.cc",
+                "base/android/jni_array.cc",
+                "base/android/jni_registrar.cc",
+                "base/android/jni_string.cc",
+                "base/android/jni_utils.cc",
+                "base/android/jni_weak_ref.cc",
+                "base/android/library_loader/anchor_functions.cc",
+                "base/android/library_loader/library_loader_hooks.cc",
+                "base/android/library_loader/library_prefetcher.cc",
+                "base/android/library_loader/library_prefetcher_hooks.cc",
+                "base/android/locale_utils.cc",
+                "base/android/memory_pressure_listener_android.cc",
+                "base/android/native_uma_recorder.cc",
+                "base/android/path_service_android.cc",
+                "base/android/path_utils.cc",
+                "base/android/radio_utils.cc",
+                "base/android/reached_addresses_bitset.cc",
+                "base/android/reached_code_profiler.cc",
+                "base/android/remove_stale_data.cc",
+                "base/android/scoped_hardware_buffer_fence_sync.cc",
+                "base/android/scoped_hardware_buffer_handle.cc",
+                "base/android/scoped_java_ref.cc",
+                "base/android/statistics_recorder_android.cc",
+                "base/android/sys_utils.cc",
+                "base/android/task_scheduler/post_task_android.cc",
+                "base/android/task_scheduler/task_runner_android.cc",
+                "base/android/thread_instruction_count.cc",
+                "base/android/timezone_utils.cc",
+                "base/android/trace_event_binding.cc",
+                "base/android/unguessable_token_android.cc",
+                "base/base_paths_android.cc",
+                "base/debug/stack_trace_android.cc",
+                "base/files/file_util_android.cc",
+                "base/files/scoped_file_android.cc",
+                "base/memory/platform_shared_memory_mapper_android.cc",
+                "base/memory/platform_shared_memory_region_android.cc",
+                "base/message_loop/message_pump_android.cc",
+                "base/os_compat_android.cc",
+                "base/power_monitor/power_monitor_device_source_android.cc",
+                "base/process/process_android.cc",
+                "base/profiler/chrome_unwind_info_android.cc",
+                "base/profiler/chrome_unwinder_android.cc",
+                "base/profiler/chrome_unwinder_android_v2.cc",
+                "base/profiler/stack_sampler_android.cc",
+                "base/system/sys_info_android.cc",
+                "base/threading/platform_thread_android.cc",
+                "base/time/time_android.cc",
+                "base/trace_event/cfi_backtrace_android.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+            generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            export_generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        android_arm64: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                ":cronet_aml_third_party_ashmem_ashmem__testing",
+                "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc",
+                "base/android/android_hardware_buffer_compat.cc",
+                "base/android/android_image_reader_compat.cc",
+                "base/android/apk_assets.cc",
+                "base/android/application_status_listener.cc",
+                "base/android/base_feature_list.cc",
+                "base/android/base_features.cc",
+                "base/android/base_jni_onload.cc",
+                "base/android/build_info.cc",
+                "base/android/bundle_utils.cc",
+                "base/android/callback_android.cc",
+                "base/android/child_process_service.cc",
+                "base/android/command_line_android.cc",
+                "base/android/content_uri_utils.cc",
+                "base/android/cpu_features.cc",
+                "base/android/early_trace_event_binding.cc",
+                "base/android/event_log.cc",
+                "base/android/feature_list_jni.cc",
+                "base/android/features_jni.cc",
+                "base/android/field_trial_list.cc",
+                "base/android/important_file_writer_android.cc",
+                "base/android/int_string_callback.cc",
+                "base/android/jank_metric_uma_recorder.cc",
+                "base/android/java_exception_reporter.cc",
+                "base/android/java_handler_thread.cc",
+                "base/android/java_heap_dump_generator.cc",
+                "base/android/java_runtime.cc",
+                "base/android/jni_android.cc",
+                "base/android/jni_array.cc",
+                "base/android/jni_registrar.cc",
+                "base/android/jni_string.cc",
+                "base/android/jni_utils.cc",
+                "base/android/jni_weak_ref.cc",
+                "base/android/library_loader/anchor_functions.cc",
+                "base/android/library_loader/library_loader_hooks.cc",
+                "base/android/library_loader/library_prefetcher.cc",
+                "base/android/library_loader/library_prefetcher_hooks.cc",
+                "base/android/locale_utils.cc",
+                "base/android/memory_pressure_listener_android.cc",
+                "base/android/native_uma_recorder.cc",
+                "base/android/path_service_android.cc",
+                "base/android/path_utils.cc",
+                "base/android/radio_utils.cc",
+                "base/android/reached_addresses_bitset.cc",
+                "base/android/reached_code_profiler.cc",
+                "base/android/remove_stale_data.cc",
+                "base/android/scoped_hardware_buffer_fence_sync.cc",
+                "base/android/scoped_hardware_buffer_handle.cc",
+                "base/android/scoped_java_ref.cc",
+                "base/android/statistics_recorder_android.cc",
+                "base/android/sys_utils.cc",
+                "base/android/task_scheduler/post_task_android.cc",
+                "base/android/task_scheduler/task_runner_android.cc",
+                "base/android/thread_instruction_count.cc",
+                "base/android/timezone_utils.cc",
+                "base/android/trace_event_binding.cc",
+                "base/android/unguessable_token_android.cc",
+                "base/base_paths_android.cc",
+                "base/debug/stack_trace_android.cc",
+                "base/files/file_util_android.cc",
+                "base/files/scoped_file_android.cc",
+                "base/memory/platform_shared_memory_mapper_android.cc",
+                "base/memory/platform_shared_memory_region_android.cc",
+                "base/message_loop/message_pump_android.cc",
+                "base/os_compat_android.cc",
+                "base/power_monitor/power_monitor_device_source_android.cc",
+                "base/process/process_android.cc",
+                "base/profiler/stack_sampler_android.cc",
+                "base/system/sys_info_android.cc",
+                "base/threading/platform_thread_android.cc",
+                "base/time/time_android.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+            generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            export_generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        android_x86: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                ":cronet_aml_third_party_ashmem_ashmem__testing",
+                "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc",
+                "base/android/android_hardware_buffer_compat.cc",
+                "base/android/android_image_reader_compat.cc",
+                "base/android/apk_assets.cc",
+                "base/android/application_status_listener.cc",
+                "base/android/base_feature_list.cc",
+                "base/android/base_features.cc",
+                "base/android/base_jni_onload.cc",
+                "base/android/build_info.cc",
+                "base/android/bundle_utils.cc",
+                "base/android/callback_android.cc",
+                "base/android/child_process_service.cc",
+                "base/android/command_line_android.cc",
+                "base/android/content_uri_utils.cc",
+                "base/android/cpu_features.cc",
+                "base/android/early_trace_event_binding.cc",
+                "base/android/event_log.cc",
+                "base/android/feature_list_jni.cc",
+                "base/android/features_jni.cc",
+                "base/android/field_trial_list.cc",
+                "base/android/important_file_writer_android.cc",
+                "base/android/int_string_callback.cc",
+                "base/android/jank_metric_uma_recorder.cc",
+                "base/android/java_exception_reporter.cc",
+                "base/android/java_handler_thread.cc",
+                "base/android/java_heap_dump_generator.cc",
+                "base/android/java_runtime.cc",
+                "base/android/jni_android.cc",
+                "base/android/jni_array.cc",
+                "base/android/jni_registrar.cc",
+                "base/android/jni_string.cc",
+                "base/android/jni_utils.cc",
+                "base/android/jni_weak_ref.cc",
+                "base/android/library_loader/anchor_functions.cc",
+                "base/android/library_loader/library_loader_hooks.cc",
+                "base/android/library_loader/library_prefetcher.cc",
+                "base/android/library_loader/library_prefetcher_hooks.cc",
+                "base/android/locale_utils.cc",
+                "base/android/memory_pressure_listener_android.cc",
+                "base/android/native_uma_recorder.cc",
+                "base/android/path_service_android.cc",
+                "base/android/path_utils.cc",
+                "base/android/radio_utils.cc",
+                "base/android/reached_addresses_bitset.cc",
+                "base/android/reached_code_profiler_stub.cc",
+                "base/android/remove_stale_data.cc",
+                "base/android/scoped_hardware_buffer_fence_sync.cc",
+                "base/android/scoped_hardware_buffer_handle.cc",
+                "base/android/scoped_java_ref.cc",
+                "base/android/statistics_recorder_android.cc",
+                "base/android/sys_utils.cc",
+                "base/android/task_scheduler/post_task_android.cc",
+                "base/android/task_scheduler/task_runner_android.cc",
+                "base/android/thread_instruction_count.cc",
+                "base/android/timezone_utils.cc",
+                "base/android/trace_event_binding.cc",
+                "base/android/unguessable_token_android.cc",
+                "base/base_paths_android.cc",
+                "base/debug/stack_trace_android.cc",
+                "base/files/file_util_android.cc",
+                "base/files/scoped_file_android.cc",
+                "base/memory/platform_shared_memory_mapper_android.cc",
+                "base/memory/platform_shared_memory_region_android.cc",
+                "base/message_loop/message_pump_android.cc",
+                "base/os_compat_android.cc",
+                "base/power_monitor/power_monitor_device_source_android.cc",
+                "base/process/process_android.cc",
+                "base/profiler/stack_sampler_android.cc",
+                "base/system/sys_info_android.cc",
+                "base/threading/platform_thread_android.cc",
+                "base/time/time_android.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-msse3",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+            generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            export_generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        android_x86_64: {
+            srcs: [
+                ":cronet_aml_third_party_android_ndk_cpu_features__testing",
+                ":cronet_aml_third_party_ashmem_ashmem__testing",
+                "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc",
+                "base/android/android_hardware_buffer_compat.cc",
+                "base/android/android_image_reader_compat.cc",
+                "base/android/apk_assets.cc",
+                "base/android/application_status_listener.cc",
+                "base/android/base_feature_list.cc",
+                "base/android/base_features.cc",
+                "base/android/base_jni_onload.cc",
+                "base/android/build_info.cc",
+                "base/android/bundle_utils.cc",
+                "base/android/callback_android.cc",
+                "base/android/child_process_service.cc",
+                "base/android/command_line_android.cc",
+                "base/android/content_uri_utils.cc",
+                "base/android/cpu_features.cc",
+                "base/android/early_trace_event_binding.cc",
+                "base/android/event_log.cc",
+                "base/android/feature_list_jni.cc",
+                "base/android/features_jni.cc",
+                "base/android/field_trial_list.cc",
+                "base/android/important_file_writer_android.cc",
+                "base/android/int_string_callback.cc",
+                "base/android/jank_metric_uma_recorder.cc",
+                "base/android/java_exception_reporter.cc",
+                "base/android/java_handler_thread.cc",
+                "base/android/java_heap_dump_generator.cc",
+                "base/android/java_runtime.cc",
+                "base/android/jni_android.cc",
+                "base/android/jni_array.cc",
+                "base/android/jni_registrar.cc",
+                "base/android/jni_string.cc",
+                "base/android/jni_utils.cc",
+                "base/android/jni_weak_ref.cc",
+                "base/android/library_loader/anchor_functions.cc",
+                "base/android/library_loader/library_loader_hooks.cc",
+                "base/android/library_loader/library_prefetcher.cc",
+                "base/android/library_loader/library_prefetcher_hooks.cc",
+                "base/android/locale_utils.cc",
+                "base/android/memory_pressure_listener_android.cc",
+                "base/android/native_uma_recorder.cc",
+                "base/android/path_service_android.cc",
+                "base/android/path_utils.cc",
+                "base/android/radio_utils.cc",
+                "base/android/reached_addresses_bitset.cc",
+                "base/android/reached_code_profiler_stub.cc",
+                "base/android/remove_stale_data.cc",
+                "base/android/scoped_hardware_buffer_fence_sync.cc",
+                "base/android/scoped_hardware_buffer_handle.cc",
+                "base/android/scoped_java_ref.cc",
+                "base/android/statistics_recorder_android.cc",
+                "base/android/sys_utils.cc",
+                "base/android/task_scheduler/post_task_android.cc",
+                "base/android/task_scheduler/task_runner_android.cc",
+                "base/android/thread_instruction_count.cc",
+                "base/android/timezone_utils.cc",
+                "base/android/trace_event_binding.cc",
+                "base/android/unguessable_token_android.cc",
+                "base/base_paths_android.cc",
+                "base/debug/stack_trace_android.cc",
+                "base/files/file_util_android.cc",
+                "base/files/scoped_file_android.cc",
+                "base/memory/platform_shared_memory_mapper_android.cc",
+                "base/memory/platform_shared_memory_region_android.cc",
+                "base/message_loop/message_pump_android.cc",
+                "base/os_compat_android.cc",
+                "base/power_monitor/power_monitor_device_source_android.cc",
+                "base/process/process_android.cc",
+                "base/profiler/stack_sampler_android.cc",
+                "base/system/sys_info_android.cc",
+                "base/threading/platform_thread_android.cc",
+                "base/time/time_android.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            local_include_dirs: [
+                "third_party/android_ndk/sources/android/cpufeatures/",
+            ],
+            generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            export_generated_headers: [
+                "cronet_aml_base_android_runtime_jni_headers__testing",
+                "cronet_aml_base_base_jni_headers__testing",
+                "cronet_aml_base_debugging_buildflags__testing",
+                "cronet_aml_base_logging_buildflags__testing",
+                "cronet_aml_build_chromeos_buildflags__testing",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        host: {
+            srcs: [
+                "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_glibc.cc",
+                "base/base_paths_posix.cc",
+                "base/debug/stack_trace_posix.cc",
+                "base/files/file_util_linux.cc",
+                "base/files/scoped_file_linux.cc",
+                "base/memory/platform_shared_memory_mapper_posix.cc",
+                "base/memory/platform_shared_memory_region_posix.cc",
+                "base/power_monitor/power_monitor_device_source_stub.cc",
+                "base/process/process_linux.cc",
+                "base/profiler/stack_sampler_posix.cc",
+                "base/stack_canary_linux.cc",
+                "base/threading/platform_thread_linux.cc",
+            ],
+            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",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //base:base_android_java_enums_srcjar
 java_genrule {
     name: "cronet_aml_base_base_android_java_enums_srcjar",
@@ -1036,6 +2699,7 @@
         "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
         "base/android/java/src/org/chromium/base/PathService.java",
         "base/android/java/src/org/chromium/base/PathUtils.java",
+        "base/android/java/src/org/chromium/base/PiiElider.java",
         "base/android/java/src/org/chromium/base/PowerMonitor.java",
         "base/android/java/src/org/chromium/base/RadioUtils.java",
         "base/android/java/src/org/chromium/base/SysUtils.java",
@@ -1109,6 +2773,8 @@
          "--output_name " +
          "PathUtils_jni.h " +
          "--output_name " +
+         "PiiElider_jni.h " +
+         "--output_name " +
          "PowerMonitor_jni.h " +
          "--output_name " +
          "RadioUtils_jni.h " +
@@ -1189,6 +2855,282 @@
          "--input_file " +
          "$(location base/android/java/src/org/chromium/base/PathUtils.java) " +
          "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/PiiElider.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/PowerMonitor.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/RadioUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/SysUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/ThreadUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/TimezoneUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/TraceEvent.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/UnguessableToken.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java) " +
+         "--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) " +
+         "--package_prefix " +
+         "android.net.http.internal",
+    out: [
+        "base/base_jni_headers/ApkAssets_jni.h",
+        "base/base_jni_headers/ApplicationStatus_jni.h",
+        "base/base_jni_headers/BaseFeatureList_jni.h",
+        "base/base_jni_headers/BuildInfo_jni.h",
+        "base/base_jni_headers/BundleUtils_jni.h",
+        "base/base_jni_headers/Callback_jni.h",
+        "base/base_jni_headers/ChildProcessService_jni.h",
+        "base/base_jni_headers/CommandLine_jni.h",
+        "base/base_jni_headers/ContentUriUtils_jni.h",
+        "base/base_jni_headers/CpuFeatures_jni.h",
+        "base/base_jni_headers/EarlyTraceEvent_jni.h",
+        "base/base_jni_headers/EventLog_jni.h",
+        "base/base_jni_headers/FeatureList_jni.h",
+        "base/base_jni_headers/Features_jni.h",
+        "base/base_jni_headers/FieldTrialList_jni.h",
+        "base/base_jni_headers/FileUtils_jni.h",
+        "base/base_jni_headers/ImportantFileWriterAndroid_jni.h",
+        "base/base_jni_headers/IntStringCallback_jni.h",
+        "base/base_jni_headers/JNIUtils_jni.h",
+        "base/base_jni_headers/JankMetricUMARecorder_jni.h",
+        "base/base_jni_headers/JavaExceptionReporter_jni.h",
+        "base/base_jni_headers/JavaHandlerThread_jni.h",
+        "base/base_jni_headers/JavaHeapDumpGenerator_jni.h",
+        "base/base_jni_headers/LibraryLoader_jni.h",
+        "base/base_jni_headers/LibraryPrefetcher_jni.h",
+        "base/base_jni_headers/LocaleUtils_jni.h",
+        "base/base_jni_headers/MemoryPressureListener_jni.h",
+        "base/base_jni_headers/NativeUmaRecorder_jni.h",
+        "base/base_jni_headers/PathService_jni.h",
+        "base/base_jni_headers/PathUtils_jni.h",
+        "base/base_jni_headers/PiiElider_jni.h",
+        "base/base_jni_headers/PostTask_jni.h",
+        "base/base_jni_headers/PowerMonitor_jni.h",
+        "base/base_jni_headers/RadioUtils_jni.h",
+        "base/base_jni_headers/StatisticsRecorderAndroid_jni.h",
+        "base/base_jni_headers/SysUtils_jni.h",
+        "base/base_jni_headers/TaskRunnerImpl_jni.h",
+        "base/base_jni_headers/ThreadUtils_jni.h",
+        "base/base_jni_headers/TimezoneUtils_jni.h",
+        "base/base_jni_headers/TraceEvent_jni.h",
+        "base/base_jni_headers/UnguessableToken_jni.h",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //base:base_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_base_base_jni_headers__testing",
+    srcs: [
+        "base/android/java/src/org/chromium/base/ApkAssets.java",
+        "base/android/java/src/org/chromium/base/ApplicationStatus.java",
+        "base/android/java/src/org/chromium/base/BaseFeatureList.java",
+        "base/android/java/src/org/chromium/base/BuildInfo.java",
+        "base/android/java/src/org/chromium/base/BundleUtils.java",
+        "base/android/java/src/org/chromium/base/Callback.java",
+        "base/android/java/src/org/chromium/base/CommandLine.java",
+        "base/android/java/src/org/chromium/base/ContentUriUtils.java",
+        "base/android/java/src/org/chromium/base/CpuFeatures.java",
+        "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
+        "base/android/java/src/org/chromium/base/EventLog.java",
+        "base/android/java/src/org/chromium/base/FeatureList.java",
+        "base/android/java/src/org/chromium/base/Features.java",
+        "base/android/java/src/org/chromium/base/FieldTrialList.java",
+        "base/android/java/src/org/chromium/base/FileUtils.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/JNIUtils.java",
+        "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
+        "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
+        "base/android/java/src/org/chromium/base/LocaleUtils.java",
+        "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
+        "base/android/java/src/org/chromium/base/PathService.java",
+        "base/android/java/src/org/chromium/base/PathUtils.java",
+        "base/android/java/src/org/chromium/base/PiiElider.java",
+        "base/android/java/src/org/chromium/base/PowerMonitor.java",
+        "base/android/java/src/org/chromium/base/RadioUtils.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/TimezoneUtils.java",
+        "base/android/java/src/org/chromium/base/TraceEvent.java",
+        "base/android/java/src/org/chromium/base/UnguessableToken.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.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/memory/JavaHeapDumpGenerator.java",
+        "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
+        "base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java",
+        "base/android/java/src/org/chromium/base/task/PostTask.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/base/base_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "ApkAssets_jni.h " +
+         "--output_name " +
+         "ApplicationStatus_jni.h " +
+         "--output_name " +
+         "BaseFeatureList_jni.h " +
+         "--output_name " +
+         "BuildInfo_jni.h " +
+         "--output_name " +
+         "BundleUtils_jni.h " +
+         "--output_name " +
+         "Callback_jni.h " +
+         "--output_name " +
+         "CommandLine_jni.h " +
+         "--output_name " +
+         "ContentUriUtils_jni.h " +
+         "--output_name " +
+         "CpuFeatures_jni.h " +
+         "--output_name " +
+         "EarlyTraceEvent_jni.h " +
+         "--output_name " +
+         "EventLog_jni.h " +
+         "--output_name " +
+         "FeatureList_jni.h " +
+         "--output_name " +
+         "Features_jni.h " +
+         "--output_name " +
+         "FieldTrialList_jni.h " +
+         "--output_name " +
+         "FileUtils_jni.h " +
+         "--output_name " +
+         "ImportantFileWriterAndroid_jni.h " +
+         "--output_name " +
+         "IntStringCallback_jni.h " +
+         "--output_name " +
+         "JNIUtils_jni.h " +
+         "--output_name " +
+         "JavaExceptionReporter_jni.h " +
+         "--output_name " +
+         "JavaHandlerThread_jni.h " +
+         "--output_name " +
+         "LocaleUtils_jni.h " +
+         "--output_name " +
+         "MemoryPressureListener_jni.h " +
+         "--output_name " +
+         "PathService_jni.h " +
+         "--output_name " +
+         "PathUtils_jni.h " +
+         "--output_name " +
+         "PiiElider_jni.h " +
+         "--output_name " +
+         "PowerMonitor_jni.h " +
+         "--output_name " +
+         "RadioUtils_jni.h " +
+         "--output_name " +
+         "SysUtils_jni.h " +
+         "--output_name " +
+         "ThreadUtils_jni.h " +
+         "--output_name " +
+         "TimezoneUtils_jni.h " +
+         "--output_name " +
+         "TraceEvent_jni.h " +
+         "--output_name " +
+         "UnguessableToken_jni.h " +
+         "--output_name " +
+         "JankMetricUMARecorder_jni.h " +
+         "--output_name " +
+         "LibraryLoader_jni.h " +
+         "--output_name " +
+         "LibraryPrefetcher_jni.h " +
+         "--output_name " +
+         "JavaHeapDumpGenerator_jni.h " +
+         "--output_name " +
+         "NativeUmaRecorder_jni.h " +
+         "--output_name " +
+         "StatisticsRecorderAndroid_jni.h " +
+         "--output_name " +
+         "ChildProcessService_jni.h " +
+         "--output_name " +
+         "PostTask_jni.h " +
+         "--output_name " +
+         "TaskRunnerImpl_jni.h " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/ApkAssets.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/ApplicationStatus.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/BaseFeatureList.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/BuildInfo.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/BundleUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/Callback.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/CommandLine.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/ContentUriUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/CpuFeatures.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/EarlyTraceEvent.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/EventLog.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/FeatureList.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/Features.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/FieldTrialList.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/FileUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/IntStringCallback.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/JNIUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/JavaExceptionReporter.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/JavaHandlerThread.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/LocaleUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/MemoryPressureListener.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/PathService.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/PathUtils.java) " +
+         "--input_file " +
+         "$(location base/android/java/src/org/chromium/base/PiiElider.java) " +
+         "--input_file " +
          "$(location base/android/java/src/org/chromium/base/PowerMonitor.java) " +
          "--input_file " +
          "$(location base/android/java/src/org/chromium/base/RadioUtils.java) " +
@@ -1251,6 +3193,7 @@
         "base/base_jni_headers/NativeUmaRecorder_jni.h",
         "base/base_jni_headers/PathService_jni.h",
         "base/base_jni_headers/PathUtils_jni.h",
+        "base/base_jni_headers/PiiElider_jni.h",
         "base/base_jni_headers/PostTask_jni.h",
         "base/base_jni_headers/PowerMonitor_jni.h",
         "base/base_jni_headers/RadioUtils_jni.h",
@@ -1292,19 +3235,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -1312,8 +3264,25 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -1321,17 +3290,138 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //base:base_static__testing
+cc_library_static {
+    name: "cronet_aml_base_base_static__testing",
+    srcs: [
+        "base/base_switches.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        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",
+                "-fstack-protector",
+                "-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",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //base:build_date
 cc_genrule {
     name: "cronet_aml_base_build_date",
     cmd: "$(location build/write_build_date_header.py) $(out) " +
-         "1664686800",
+         "1674644139",
+    out: [
+        "base/generated_build_date.h",
+    ],
+    tool_files: [
+        "build/write_build_date_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //base:build_date__testing
+cc_genrule {
+    name: "cronet_aml_base_build_date__testing",
+    cmd: "$(location build/write_build_date_header.py) $(out) " +
+         "1674644139",
+    host_supported: true,
     out: [
         "base/generated_build_date.h",
     ],
@@ -1346,7 +3436,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 " +
@@ -1366,6 +3456,30 @@
     ],
 }
 
+// GN: //base:cfi_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_cfi_buildflags__testing",
+    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 " +
+         "//base:cfi_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/cfi_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:clang_profiling_buildflags
 cc_genrule {
     name: "cronet_aml_base_clang_profiling_buildflags",
@@ -1389,12 +3503,36 @@
     ],
 }
 
+// GN: //base:clang_profiling_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_clang_profiling_buildflags__testing",
+    cmd: "echo '--flags CLANG_PROFILING=\"false\" CLANG_PROFILING_INSIDE_SANDBOX=\"false\" USE_CLANG_COVERAGE=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:clang_profiling_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/clang_profiling_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:debugging_buildflags
 cc_genrule {
     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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1406,7 +3544,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=\"false\" UNSAFE_DEVELOPER_BUILD=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1418,7 +3556,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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"true\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1430,7 +3568,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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
          "$(location build/write_buildflag_header.py) --output " +
          "$(out) " +
          "--rulename " +
@@ -1451,6 +3589,81 @@
     ],
 }
 
+// GN: //base:debugging_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_debugging_buildflags__testing",
+    cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:debugging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ $$CC_OS != 'android' ]]; " +
+         "then " +
+         "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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:debugging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:debugging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"true\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:debugging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "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=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"true\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:debugging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi;",
+    host_supported: true,
+    out: [
+        "base/debug/debugging_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:feature_list_buildflags
 cc_genrule {
     name: "cronet_aml_base_feature_list_buildflags",
@@ -1474,10 +3687,180 @@
     ],
 }
 
+// GN: //base:feature_list_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_feature_list_buildflags__testing",
+    cmd: "echo '--flags ENABLE_BANNED_BASE_FEATURE_PREFIX=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:feature_list_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/feature_list_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //base:i18n__testing
+cc_library_static {
+    name: "cronet_aml_base_i18n__testing",
+    srcs: [
+        "base/i18n/base_i18n_switches.cc",
+        "base/i18n/break_iterator.cc",
+        "base/i18n/case_conversion.cc",
+        "base/i18n/char_iterator.cc",
+        "base/i18n/character_encoding.cc",
+        "base/i18n/encoding_detection.cc",
+        "base/i18n/file_util_icu.cc",
+        "base/i18n/i18n_constants.cc",
+        "base/i18n/icu_string_conversions.cc",
+        "base/i18n/icu_util.cc",
+        "base/i18n/message_formatter.cc",
+        "base/i18n/number_formatting.cc",
+        "base/i18n/rtl.cc",
+        "base/i18n/streaming_utf8_validator.cc",
+        "base/i18n/string_compare.cc",
+        "base/i18n/string_search.cc",
+        "base/i18n/time_formatting.cc",
+        "base/i18n/timezone.cc",
+        "base/i18n/utf8_validator_tables.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromecast_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_build_chromecast_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DBASE_I18N_IMPLEMENTATION",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+        "third_party/ced/src/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
 // 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 " +
@@ -1497,6 +3880,30 @@
     ],
 }
 
+// GN: //base:ios_cronet_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_ios_cronet_buildflags__testing",
+    cmd: "echo '--flags CRONET_BUILD=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:ios_cronet_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/message_loop/ios_cronet_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:java_features_srcjar
 java_genrule {
     name: "cronet_aml_base_java_features_srcjar",
@@ -1572,6 +3979,30 @@
     ],
 }
 
+// GN: //base:logging_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_logging_buildflags__testing",
+    cmd: "echo '--flags ENABLE_LOG_ERROR_NOT_REACHED=\"false\" USE_RUNTIME_VLOG=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:logging_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/logging_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:message_pump_buildflags
 cc_genrule {
     name: "cronet_aml_base_message_pump_buildflags",
@@ -1595,28 +4026,68 @@
     ],
 }
 
-// GN: //base/numerics:base_numerics
+// GN: //base:message_pump_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_message_pump_buildflags__testing",
+    cmd: "echo '--flags ENABLE_MESSAGE_PUMP_EPOLL=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:message_pump_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/message_loop/message_pump_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //base:nodebug_assertion
 cc_object {
-    name: "cronet_aml_base_numerics_base_numerics",
+    name: "cronet_aml_base_nodebug_assertion",
+    srcs: [
+        "base/nodebug_assertion.cc",
+    ],
+    static_libs: [
+        "cronet_aml_base_base_static",
+    ],
     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",
+        "-DBASE_IMPLEMENTATION",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -1624,8 +4095,20 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -1633,12 +4116,113 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //base:nodebug_assertion__testing
+cc_object {
+    name: "cronet_aml_base_nodebug_assertion__testing",
+    srcs: [
+        "base/nodebug_assertion.cc",
+    ],
+    static_libs: [
+        "cronet_aml_base_base_static__testing",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DBASE_IMPLEMENTATION",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //base:orderfile_buildflags
 cc_genrule {
     name: "cronet_aml_base_orderfile_buildflags",
@@ -1662,6 +4246,30 @@
     ],
 }
 
+// GN: //base:orderfile_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_orderfile_buildflags__testing",
+    cmd: "echo '--flags DEVTOOLS_INSTRUMENTATION_DUMPING=\"false\" ORDERFILE_INSTRUMENTATION=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:orderfile_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/android/orderfile/orderfile_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:parsing_buildflags
 cc_genrule {
     name: "cronet_aml_base_parsing_buildflags",
@@ -1685,6 +4293,30 @@
     ],
 }
 
+// GN: //base:parsing_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_parsing_buildflags__testing",
+    cmd: "echo '--flags BUILD_RUST_JSON_PARSER=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:parsing_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/parsing_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:power_monitor_buildflags
 cc_genrule {
     name: "cronet_aml_base_power_monitor_buildflags",
@@ -1708,6 +4340,30 @@
     ],
 }
 
+// GN: //base:power_monitor_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_power_monitor_buildflags__testing",
+    cmd: "echo '--flags HAS_BATTERY_LEVEL_PROVIDER_IMPL=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:power_monitor_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/power_monitor/power_monitor_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:profiler_buildflags
 cc_genrule {
     name: "cronet_aml_base_profiler_buildflags",
@@ -1770,6 +4426,81 @@
     ],
 }
 
+// GN: //base:profiler_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_profiler_buildflags__testing",
+    cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_ARM_CFI_TABLE=\"false\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:profiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ $$CC_OS != 'android' ]]; " +
+         "then " +
+         "echo '--flags ENABLE_ARM_CFI_TABLE=\"false\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:profiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_ARM_CFI_TABLE=\"false\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:profiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_ARM_CFI_TABLE=\"true\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:profiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_ARM_CFI_TABLE=\"false\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:profiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi;",
+    host_supported: true,
+    out: [
+        "base/profiler/profiler_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:sanitizer_buildflags
 cc_genrule {
     name: "cronet_aml_base_sanitizer_buildflags",
@@ -1793,6 +4524,30 @@
     ],
 }
 
+// GN: //base:sanitizer_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_sanitizer_buildflags__testing",
+    cmd: "echo '--flags IS_HWASAN=\"false\" USING_SANITIZER=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:sanitizer_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/sanitizer_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base:synchronization_buildflags
 cc_genrule {
     name: "cronet_aml_base_synchronization_buildflags",
@@ -1816,6 +4571,506 @@
     ],
 }
 
+// GN: //base:synchronization_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_synchronization_buildflags__testing",
+    cmd: "echo '--flags ENABLE_MUTEX_PRIORITY_INHERITANCE=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:synchronization_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "base/synchronization/synchronization_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //base/test:base_unittests_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_base_test_base_unittests_jni_headers__testing",
+    srcs: [
+        "base/test/android/java/src/org/chromium/base/ContentUriTestUtils.java",
+        "base/test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/base/test/base_unittests_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "ContentUriTestUtils_jni.h " +
+         "--output_name " +
+         "JavaHandlerThreadHelpers_jni.h " +
+         "--input_file " +
+         "$(location base/test/android/java/src/org/chromium/base/ContentUriTestUtils.java) " +
+         "--input_file " +
+         "$(location base/test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java)",
+    out: [
+        "base/test/base_unittests_jni_headers/ContentUriTestUtils_jni.h",
+        "base/test/base_unittests_jni_headers/JavaHandlerThreadHelpers_jni.h",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //base/test:test_config__testing
+cc_library_static {
+    name: "cronet_aml_base_test_test_config__testing",
+    srcs: [
+        "base/test/test_switches.cc",
+        "base/test/test_timeouts.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_clang_profiling_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_clang_profiling_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //base/test:test_support__testing
+cc_library_static {
+    name: "cronet_aml_base_test_test_support__testing",
+    srcs: [
+        ":cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+        ":cronet_aml_third_party_googletest_gmock__testing",
+        ":cronet_aml_third_party_googletest_gtest__testing",
+        "base/task/sequence_manager/test/fake_task.cc",
+        "base/task/sequence_manager/test/mock_time_domain.cc",
+        "base/task/sequence_manager/test/mock_time_message_pump.cc",
+        "base/task/sequence_manager/test/sequence_manager_for_test.cc",
+        "base/task/sequence_manager/test/test_task_queue.cc",
+        "base/test/android/java_handler_thread_helpers.cc",
+        "base/test/android/url_utils.cc",
+        "base/test/bind.cc",
+        "base/test/copy_only_int.cc",
+        "base/test/gtest_links.cc",
+        "base/test/gtest_util.cc",
+        "base/test/gtest_xml_unittest_result_printer.cc",
+        "base/test/gtest_xml_util.cc",
+        "base/test/icu_test_util.cc",
+        "base/test/launcher/test_launcher.cc",
+        "base/test/launcher/test_launcher_test_utils.cc",
+        "base/test/launcher/test_launcher_tracer.cc",
+        "base/test/launcher/test_result.cc",
+        "base/test/launcher/test_results_tracker.cc",
+        "base/test/launcher/unit_test_launcher.cc",
+        "base/test/metrics/histogram_enum_reader.cc",
+        "base/test/metrics/histogram_tester.cc",
+        "base/test/metrics/user_action_tester.cc",
+        "base/test/mock_devices_changed_observer.cc",
+        "base/test/mock_entropy_provider.cc",
+        "base/test/mock_log.cc",
+        "base/test/multiprocess_test.cc",
+        "base/test/multiprocess_test_android.cc",
+        "base/test/null_task_runner.cc",
+        "base/test/perf_log.cc",
+        "base/test/perf_test_suite.cc",
+        "base/test/perf_time_logger.cc",
+        "base/test/power_monitor_test.cc",
+        "base/test/power_monitor_test_utils.cc",
+        "base/test/reached_code_profiler_android.cc",
+        "base/test/scoped_command_line.cc",
+        "base/test/scoped_feature_list.cc",
+        "base/test/scoped_locale.cc",
+        "base/test/scoped_mock_clock_override.cc",
+        "base/test/scoped_mock_time_message_loop_task_runner.cc",
+        "base/test/scoped_path_override.cc",
+        "base/test/scoped_run_loop_timeout.cc",
+        "base/test/sequenced_task_runner_test_template.cc",
+        "base/test/simple_test_clock.cc",
+        "base/test/simple_test_tick_clock.cc",
+        "base/test/task_environment.cc",
+        "base/test/task_runner_test_template.cc",
+        "base/test/test_discardable_memory_allocator.cc",
+        "base/test/test_file_util.cc",
+        "base/test/test_file_util_android.cc",
+        "base/test/test_file_util_linux.cc",
+        "base/test/test_file_util_posix.cc",
+        "base/test/test_io_thread.cc",
+        "base/test/test_message_loop.cc",
+        "base/test/test_mock_time_task_runner.cc",
+        "base/test/test_pending_task.cc",
+        "base/test/test_shared_memory_util.cc",
+        "base/test/test_simple_task_runner.cc",
+        "base/test/test_suite.cc",
+        "base/test/test_support_android.cc",
+        "base/test/test_waitable_event.cc",
+        "base/test/thread_pool_test_helpers_android.cc",
+        "base/test/thread_test_helper.cc",
+        "base/test/values_test_util.cc",
+        "base/test/with_feature_override.cc",
+        "base/timer/mock_timer.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_base_test_base_unittests_jni_headers__testing",
+        "cronet_aml_base_test_test_support_jni_headers__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_base_test_base_unittests_jni_headers__testing",
+        "cronet_aml_base_test_test_support_jni_headers__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+        "third_party/ced/src/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/libxml/linux/include/",
+        "third_party/libxml/src/include/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //base/test:test_support_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_base_test_test_support_jni_headers__testing",
+    srcs: [
+        "base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java",
+        "base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java",
+        "base/test/android/javatests/src/org/chromium/base/test/ReachedCodeProfiler.java",
+        "base/test/android/javatests/src/org/chromium/base/test/task/ThreadPoolTestHelpers.java",
+        "base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/base/test/test_support_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "MainReturnCodeResult_jni.h " +
+         "--output_name " +
+         "MultiprocessTestClientLauncher_jni.h " +
+         "--output_name " +
+         "ReachedCodeProfiler_jni.h " +
+         "--output_name " +
+         "ThreadPoolTestHelpers_jni.h " +
+         "--output_name " +
+         "UrlUtils_jni.h " +
+         "--input_file " +
+         "$(location base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java) " +
+         "--input_file " +
+         "$(location base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java) " +
+         "--input_file " +
+         "$(location base/test/android/javatests/src/org/chromium/base/test/ReachedCodeProfiler.java) " +
+         "--input_file " +
+         "$(location base/test/android/javatests/src/org/chromium/base/test/task/ThreadPoolTestHelpers.java) " +
+         "--input_file " +
+         "$(location base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java)",
+    out: [
+        "base/test/test_support_jni_headers/MainReturnCodeResult_jni.h",
+        "base/test/test_support_jni_headers/MultiprocessTestClientLauncher_jni.h",
+        "base/test/test_support_jni_headers/ReachedCodeProfiler_jni.h",
+        "base/test/test_support_jni_headers/ThreadPoolTestHelpers_jni.h",
+        "base/test/test_support_jni_headers/UrlUtils_jni.h",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //base/third_party/double_conversion:double_conversion
 cc_library_static {
     name: "cronet_aml_base_third_party_double_conversion_double_conversion",
@@ -1835,19 +5090,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -1855,8 +5119,25 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -1864,12 +5145,121 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //base/third_party/double_conversion:double_conversion__testing
+cc_library_static {
+    name: "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+    srcs: [
+        "base/third_party/double_conversion/double-conversion/bignum-dtoa.cc",
+        "base/third_party/double_conversion/double-conversion/bignum.cc",
+        "base/third_party/double_conversion/double-conversion/cached-powers.cc",
+        "base/third_party/double_conversion/double-conversion/double-to-string.cc",
+        "base/third_party/double_conversion/double-conversion/fast-dtoa.cc",
+        "base/third_party/double_conversion/double-conversion/fixed-dtoa.cc",
+        "base/third_party/double_conversion/double-conversion/string-to-double.cc",
+        "base/third_party/double_conversion/double-conversion/strtod.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //base/third_party/dynamic_annotations:dynamic_annotations
 cc_library_static {
     name: "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
@@ -1882,17 +5272,25 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -1900,8 +5298,25 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -1909,12 +5324,107 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //base/third_party/dynamic_annotations:dynamic_annotations__testing
+cc_library_static {
+    name: "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+    srcs: [
+        "base/third_party/dynamic_annotations/dynamic_annotations.c",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        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",
+                "-fstack-protector",
+                "-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",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //base:tracing_buildflags
 cc_genrule {
     name: "cronet_aml_base_tracing_buildflags",
@@ -1938,6 +5448,81 @@
     ],
 }
 
+// GN: //base:tracing_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_base_tracing_buildflags__testing",
+    cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_BASE_TRACING=\"false\" USE_PERFETTO_CLIENT_LIBRARY=\"false\" OPTIONAL_TRACE_EVENTS_ENABLED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:tracing_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ $$CC_OS != 'android' ]]; " +
+         "then " +
+         "echo '--flags ENABLE_BASE_TRACING=\"false\" USE_PERFETTO_CLIENT_LIBRARY=\"false\" OPTIONAL_TRACE_EVENTS_ENABLED=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:tracing_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_BASE_TRACING=\"false\" USE_PERFETTO_CLIENT_LIBRARY=\"false\" OPTIONAL_TRACE_EVENTS_ENABLED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:tracing_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_BASE_TRACING=\"false\" USE_PERFETTO_CLIENT_LIBRARY=\"false\" OPTIONAL_TRACE_EVENTS_ENABLED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:tracing_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags ENABLE_BASE_TRACING=\"false\" USE_PERFETTO_CLIENT_LIBRARY=\"false\" OPTIONAL_TRACE_EVENTS_ENABLED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//base:tracing_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi;",
+    host_supported: true,
+    out: [
+        "base/tracing_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //build/android:build_config_gen
 genrule {
     name: "cronet_aml_build_android_build_config_gen",
@@ -1948,7 +5533,7 @@
         "soong_zip",
     ],
     cmd: "cp $(in) $(genDir)/BuildConfig.java && " +
-         "$(location soong_zip) -o $(out) -srcjar -f $(genDir)/BuildConfig.java",
+         "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/BuildConfig.java",
     out: [
         "BuildConfig.srcjar",
     ],
@@ -1962,7 +5547,6 @@
     ],
     cflags: [
         "-DANDROID",
-        "-D_ENABLE_ASSERTS",
         "-E",
         "-P",
     ],
@@ -2022,48 +5606,28 @@
     ],
 }
 
-// GN: //build:buildflag_header_h
-cc_object {
-    name: "cronet_aml_build_buildflag_header_h",
-    defaults: [
-        "cronet_aml_defaults",
+// GN: //build:branding_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_build_branding_buildflags__testing",
+    cmd: "echo '--flags CHROMIUM_BRANDING=\"1\" GOOGLE_CHROME_BRANDING=\"0\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build:branding_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "build/branding_buildflags.h",
     ],
-    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",
+    tool_files: [
+        "build/write_buildflag_header.py",
     ],
-    local_include_dirs: [
-        "./",
-        "buildtools/third_party/libc++/",
-        "buildtools/third_party/libc++/trunk/include",
-        "buildtools/third_party/libc++abi/trunk/include",
+    apex_available: [
+        "com.android.tethering",
     ],
-    cpp_std: "c++20",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-    },
 }
 
 // GN: //build:chromecast_buildflags
@@ -2089,6 +5653,30 @@
     ],
 }
 
+// GN: //build:chromecast_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_build_chromecast_buildflags__testing",
+    cmd: "echo '--flags IS_CASTOS=\"false\" IS_CAST_ANDROID=\"false\" ENABLE_CAST_RECEIVER=\"false\" IS_CHROMECAST=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build:chromecast_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "build/chromecast_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //build:chromeos_buildflags
 cc_genrule {
     name: "cronet_aml_build_chromeos_buildflags",
@@ -2112,6 +5700,30 @@
     ],
 }
 
+// GN: //build:chromeos_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_build_chromeos_buildflags__testing",
+    cmd: "echo '--flags IS_CHROMEOS_DEVICE=\"false\" IS_CHROMEOS_LACROS=\"false\" IS_CHROMEOS_ASH=\"false\" IS_CHROMEOS_WITH_HW_DETAILS=\"false\" IS_REVEN=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build:chromeos_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "build/chromeos_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //build/config/compiler:compiler_buildflags
 cc_genrule {
     name: "cronet_aml_build_config_compiler_compiler_buildflags",
@@ -2135,6 +5747,81 @@
     ],
 }
 
+// GN: //build/config/compiler:compiler_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_build_config_compiler_compiler_buildflags__testing",
+    cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags CLANG_PGO=\"0\" SYMBOL_LEVEL=\"1\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build/config/compiler:compiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ $$CC_OS != 'android' ]]; " +
+         "then " +
+         "echo '--flags CLANG_PGO=\"2\" SYMBOL_LEVEL=\"1\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build/config/compiler:compiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags CLANG_PGO=\"0\" SYMBOL_LEVEL=\"1\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build/config/compiler:compiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags CLANG_PGO=\"0\" SYMBOL_LEVEL=\"1\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build/config/compiler:compiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags CLANG_PGO=\"0\" SYMBOL_LEVEL=\"1\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//build/config/compiler:compiler_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi;",
+    host_supported: true,
+    out: [
+        "build/config/compiler/compiler_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //buildtools/third_party/libc++:libc++
 cc_object {
     name: "cronet_aml_buildtools_third_party_libc___libc__",
@@ -2187,19 +5874,27 @@
         "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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DLIBCXX_BUILDING_LIBCXXABI",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -2219,6 +5914,8 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
             ],
         },
         android_arm64: {
@@ -2226,6 +5923,10 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
             ],
         },
         android_x86: {
@@ -2233,6 +5934,7 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
@@ -2241,6 +5943,8 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -2253,8 +5957,155 @@
                 "-D_FILE_OFFSET_BITS=64",
                 "-D_LARGEFILE64_SOURCE",
                 "-D_LARGEFILE_SOURCE",
+                "-O2",
+                "-fstack-protector",
                 "-msse3",
             ],
+            compile_multilib: "64",
+        },
+    },
+}
+
+// GN: //buildtools/third_party/libc++:libc++__testing
+cc_object {
+    name: "cronet_aml_buildtools_third_party_libc___libc____testing",
+    srcs: [
+        "buildtools/third_party/libc++/trunk/src/algorithm.cpp",
+        "buildtools/third_party/libc++/trunk/src/any.cpp",
+        "buildtools/third_party/libc++/trunk/src/atomic.cpp",
+        "buildtools/third_party/libc++/trunk/src/barrier.cpp",
+        "buildtools/third_party/libc++/trunk/src/bind.cpp",
+        "buildtools/third_party/libc++/trunk/src/charconv.cpp",
+        "buildtools/third_party/libc++/trunk/src/chrono.cpp",
+        "buildtools/third_party/libc++/trunk/src/condition_variable.cpp",
+        "buildtools/third_party/libc++/trunk/src/condition_variable_destructor.cpp",
+        "buildtools/third_party/libc++/trunk/src/exception.cpp",
+        "buildtools/third_party/libc++/trunk/src/format.cpp",
+        "buildtools/third_party/libc++/trunk/src/functional.cpp",
+        "buildtools/third_party/libc++/trunk/src/future.cpp",
+        "buildtools/third_party/libc++/trunk/src/hash.cpp",
+        "buildtools/third_party/libc++/trunk/src/ios.cpp",
+        "buildtools/third_party/libc++/trunk/src/ios.instantiations.cpp",
+        "buildtools/third_party/libc++/trunk/src/iostream.cpp",
+        "buildtools/third_party/libc++/trunk/src/legacy_pointer_safety.cpp",
+        "buildtools/third_party/libc++/trunk/src/locale.cpp",
+        "buildtools/third_party/libc++/trunk/src/memory.cpp",
+        "buildtools/third_party/libc++/trunk/src/mutex.cpp",
+        "buildtools/third_party/libc++/trunk/src/mutex_destructor.cpp",
+        "buildtools/third_party/libc++/trunk/src/new.cpp",
+        "buildtools/third_party/libc++/trunk/src/optional.cpp",
+        "buildtools/third_party/libc++/trunk/src/random.cpp",
+        "buildtools/third_party/libc++/trunk/src/random_shuffle.cpp",
+        "buildtools/third_party/libc++/trunk/src/regex.cpp",
+        "buildtools/third_party/libc++/trunk/src/ryu/d2fixed.cpp",
+        "buildtools/third_party/libc++/trunk/src/ryu/d2s.cpp",
+        "buildtools/third_party/libc++/trunk/src/ryu/f2s.cpp",
+        "buildtools/third_party/libc++/trunk/src/shared_mutex.cpp",
+        "buildtools/third_party/libc++/trunk/src/stdexcept.cpp",
+        "buildtools/third_party/libc++/trunk/src/string.cpp",
+        "buildtools/third_party/libc++/trunk/src/strstream.cpp",
+        "buildtools/third_party/libc++/trunk/src/system_error.cpp",
+        "buildtools/third_party/libc++/trunk/src/thread.cpp",
+        "buildtools/third_party/libc++/trunk/src/typeinfo.cpp",
+        "buildtools/third_party/libc++/trunk/src/utility.cpp",
+        "buildtools/third_party/libc++/trunk/src/valarray.cpp",
+        "buildtools/third_party/libc++/trunk/src/variant.cpp",
+        "buildtools/third_party/libc++/trunk/src/vector.cpp",
+        "buildtools/third_party/libc++/trunk/src/verbose_abort.cpp",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DLIBCXX_BUILDING_LIBCXXABI",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
+        "-D_LIBCPP_BUILDING_LIBRARY",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCPP_OVERRIDABLE_FUNC_VIS=__attribute__((__visibility__(\"default\")))",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++/trunk/src/",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    cpp_std: "c++20",
+    cppflags: [
+        "-fexceptions",
+    ],
+    rtti: true,
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -2285,19 +6136,26 @@
         "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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DLIBCXXABI_SILENT_TERMINATE",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -2320,6 +6178,8 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
             ],
         },
         android_arm64: {
@@ -2330,6 +6190,10 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
             ],
         },
         android_x86: {
@@ -2340,6 +6204,7 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
@@ -2351,6 +6216,8 @@
                 "-DANDROID",
                 "-DANDROID_NDK_VERSION_ROLL=r23_1",
                 "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -2366,8 +6233,143 @@
                 "-D_FILE_OFFSET_BITS=64",
                 "-D_LARGEFILE64_SOURCE",
                 "-D_LARGEFILE_SOURCE",
+                "-O2",
+                "-fstack-protector",
                 "-msse3",
             ],
+            compile_multilib: "64",
+        },
+    },
+}
+
+// GN: //buildtools/third_party/libc++abi:libc++abi__testing
+cc_object {
+    name: "cronet_aml_buildtools_third_party_libc__abi_libc__abi__testing",
+    srcs: [
+        "buildtools/third_party/libc++abi/trunk/src/abort_message.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_aux_runtime.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_default_handlers.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_exception.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_exception_storage.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_guard.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_handlers.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_personality.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_thread_atexit.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_vector.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/cxa_virtual.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/fallback_malloc.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/private_typeinfo.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/stdlib_exception.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/stdlib_stdexcept.cpp",
+        "buildtools/third_party/libc++abi/trunk/src/stdlib_typeinfo.cpp",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DLIBCXXABI_SILENT_TERMINATE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_BUILDING_LIBRARY",
+        "-D_LIBCPP_CONSTINIT=constinit",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++/trunk/src/",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    cpp_std: "c++20",
+    cppflags: [
+        "-fexceptions",
+    ],
+    rtti: true,
+    target: {
+        android_arm: {
+            srcs: [
+                "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            srcs: [
+                "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            srcs: [
+                "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            srcs: [
+                "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+        host: {
+            srcs: [
+                "buildtools/third_party/libc++abi/trunk/src/cxa_demangle.cpp",
+            ],
+            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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -2395,6 +6397,29 @@
     ],
 }
 
+// GN: //components/cronet/android:buildflags__testing
+cc_genrule {
+    name: "cronet_aml_components_cronet_android_buildflags__testing",
+    cmd: "echo '--flags INTEGRATED_MODE=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//components/cronet/android:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    out: [
+        "components/cronet/android/buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //components/cronet/android:cronet
 cc_library_shared {
     name: "cronet_aml_components_cronet_android_cronet",
@@ -2404,14 +6429,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 +6457,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,23 +6489,32 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -2496,12 +6528,42 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
-    linker_scripts: [
-        "base/android/library_loader/anchor_functions.lds",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
     ],
-    stem: "libcronet.109.0.5386.0",
+    stem: "libcronet.108.0.5359.128",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -2509,6 +6571,7 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -2551,6 +6614,64 @@
          "--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) " +
+         "--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",
+        "components/cronet/android/cronet_jni_headers/CronetUploadDataStream_jni.h",
+        "components/cronet/android/cronet_jni_headers/CronetUrlRequestContext_jni.h",
+        "components/cronet/android/cronet_jni_headers/CronetUrlRequest_jni.h",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //components/cronet/android:cronet_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_components_cronet_android_cronet_jni_headers__testing",
+    srcs: [
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
+        "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",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/components/cronet/android/cronet_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "CronetBidirectionalStream_jni.h " +
+         "--output_name " +
+         "CronetLibraryLoader_jni.h " +
+         "--output_name " +
+         "CronetUploadDataStream_jni.h " +
+         "--output_name " +
+         "CronetUrlRequest_jni.h " +
+         "--output_name " +
+         "CronetUrlRequestContext_jni.h " +
+         "--input_file " +
+         "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java) " +
+         "--input_file " +
+         "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java) " +
+         "--input_file " +
+         "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java) " +
+         "--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)",
     out: [
         "components/cronet/android/cronet_jni_headers/CronetBidirectionalStream_jni.h",
@@ -2602,7 +6723,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 +6747,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 +6790,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 +6816,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 +6850,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 +6865,756 @@
         "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",
+        "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
+        "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
+        "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
+        "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
+        "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
+        "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
+        "net/android/java/src/org/chromium/net/DnsStatus.java",
+        "net/android/java/src/org/chromium/net/GURLUtils.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
+        "net/android/java/src/org/chromium/net/HttpUtil.java",
+        "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
+        "net/android/java/src/org/chromium/net/NetStringUtil.java",
+        "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
+        "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
+        "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
+        "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
+        "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
+        "net/android/java/src/org/chromium/net/X509Util.java",
+        "url/android/java/src/org/chromium/url/IDNStringUtil.java",
+    ],
+    cmd: "current_dir=`basename \\`pwd\\``; " +
+         "for f in $(in); " +
+         "do " +
+         "echo \"../$$current_dir/$$f\" >> $(genDir)/java.sources; " +
+         "done; " +
+         "python3 $(location base/android/jni_generator/jni_registration_generator.py) --srcjar-path " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.srcjar " +
+         "--depfile " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.d " +
+         "--sources-files " +
+         "$(genDir)/java.sources " +
+         "--include_test_only " +
+         "--use_proxy_hash " +
+         "--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: [
+        "components/cronet/android/cronet_jni_registration.h",
+        "components/cronet/android/cronet_jni_registration.srcjar",
+    ],
+    tool_files: [
+        "base/android/jni_generator/jni_generator.py",
+        "base/android/jni_generator/jni_registration_generator.py",
+        "build/android/gyp/util/__init__.py",
+        "build/android/gyp/util/build_utils.py",
+        "build/gn_helpers.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //components/cronet/android:cronet_jni_registration
+java_genrule {
+    name: "cronet_aml_components_cronet_android_cronet_jni_registration__java",
+    srcs: [
+        "base/android/java/src/org/chromium/base/ActivityState.java",
+        "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
+        "base/android/java/src/org/chromium/base/ApkAssets.java",
+        "base/android/java/src/org/chromium/base/ApplicationStatus.java",
+        "base/android/java/src/org/chromium/base/BaseFeatureList.java",
+        "base/android/java/src/org/chromium/base/BuildInfo.java",
+        "base/android/java/src/org/chromium/base/BundleUtils.java",
+        "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
+        "base/android/java/src/org/chromium/base/Callback.java",
+        "base/android/java/src/org/chromium/base/CallbackController.java",
+        "base/android/java/src/org/chromium/base/CollectionUtil.java",
+        "base/android/java/src/org/chromium/base/CommandLine.java",
+        "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
+        "base/android/java/src/org/chromium/base/Consumer.java",
+        "base/android/java/src/org/chromium/base/ContentUriUtils.java",
+        "base/android/java/src/org/chromium/base/ContextUtils.java",
+        "base/android/java/src/org/chromium/base/CpuFeatures.java",
+        "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
+        "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
+        "base/android/java/src/org/chromium/base/EventLog.java",
+        "base/android/java/src/org/chromium/base/FeatureList.java",
+        "base/android/java/src/org/chromium/base/Features.java",
+        "base/android/java/src/org/chromium/base/FieldTrialList.java",
+        "base/android/java/src/org/chromium/base/FileUtils.java",
+        "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/JNIUtils.java",
+        "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
+        "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
+        "base/android/java/src/org/chromium/base/JniException.java",
+        "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
+        "base/android/java/src/org/chromium/base/LifetimeAssert.java",
+        "base/android/java/src/org/chromium/base/LocaleUtils.java",
+        "base/android/java/src/org/chromium/base/Log.java",
+        "base/android/java/src/org/chromium/base/MathUtils.java",
+        "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
+        "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
+        "base/android/java/src/org/chromium/base/ObserverList.java",
+        "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
+        "base/android/java/src/org/chromium/base/PackageUtils.java",
+        "base/android/java/src/org/chromium/base/PathService.java",
+        "base/android/java/src/org/chromium/base/PathUtils.java",
+        "base/android/java/src/org/chromium/base/PiiElider.java",
+        "base/android/java/src/org/chromium/base/PowerMonitor.java",
+        "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
+        "base/android/java/src/org/chromium/base/Predicate.java",
+        "base/android/java/src/org/chromium/base/Promise.java",
+        "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",
+        "base/android/java/src/org/chromium/base/TraceEvent.java",
+        "base/android/java/src/org/chromium/base/UnguessableToken.java",
+        "base/android/java/src/org/chromium/base/UnownedUserData.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
+        "base/android/java/src/org/chromium/base/UserData.java",
+        "base/android/java/src/org/chromium/base/UserDataHost.java",
+        "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
+        "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
+        "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
+        "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
+        "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
+        "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",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
+        "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
+        "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
+        "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
+        "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
+        "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
+        "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
+        "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
+        "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
+        "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/supplier/BooleanSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/Supplier.java",
+        "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
+        "base/android/java/src/org/chromium/base/task/AsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
+        "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
+        "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/PostTask.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraits.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
+        "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
+        "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
+        "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
+        "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/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",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
+        "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/NativeCronetEngineBuilderImpl.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",
+        "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
+        "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
+        "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
+        "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
+        "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
+        "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
+        "net/android/java/src/org/chromium/net/DnsStatus.java",
+        "net/android/java/src/org/chromium/net/GURLUtils.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
+        "net/android/java/src/org/chromium/net/HttpUtil.java",
+        "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
+        "net/android/java/src/org/chromium/net/NetStringUtil.java",
+        "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
+        "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
+        "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
+        "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
+        "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
+        "net/android/java/src/org/chromium/net/X509Util.java",
+        "url/android/java/src/org/chromium/url/IDNStringUtil.java",
+    ],
+    cmd: "current_dir=`basename \\`pwd\\``; " +
+         "for f in $(in); " +
+         "do " +
+         "echo \"../$$current_dir/$$f\" >> $(genDir)/java.sources; " +
+         "done; " +
+         "python3 $(location base/android/jni_generator/jni_registration_generator.py) --srcjar-path " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.srcjar " +
+         "--depfile " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.d " +
+         "--sources-files " +
+         "$(genDir)/java.sources " +
+         "--include_test_only " +
+         "--use_proxy_hash " +
+         "--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: [
+        "components/cronet/android/cronet_jni_registration.srcjar",
+    ],
+    tool_files: [
+        "base/android/jni_generator/jni_generator.py",
+        "base/android/jni_generator/jni_registration_generator.py",
+        "build/android/gyp/util/__init__.py",
+        "build/android/gyp/util/build_utils.py",
+        "build/gn_helpers.py",
+    ],
+}
+
+// GN: //components/cronet/android:cronet_jni_registration
+java_genrule {
+    name: "cronet_aml_components_cronet_android_cronet_jni_registration__java__testing",
+    srcs: [
+        "base/android/java/src/org/chromium/base/ActivityState.java",
+        "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
+        "base/android/java/src/org/chromium/base/ApkAssets.java",
+        "base/android/java/src/org/chromium/base/ApplicationStatus.java",
+        "base/android/java/src/org/chromium/base/BaseFeatureList.java",
+        "base/android/java/src/org/chromium/base/BuildInfo.java",
+        "base/android/java/src/org/chromium/base/BundleUtils.java",
+        "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
+        "base/android/java/src/org/chromium/base/Callback.java",
+        "base/android/java/src/org/chromium/base/CallbackController.java",
+        "base/android/java/src/org/chromium/base/CollectionUtil.java",
+        "base/android/java/src/org/chromium/base/CommandLine.java",
+        "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
+        "base/android/java/src/org/chromium/base/Consumer.java",
+        "base/android/java/src/org/chromium/base/ContentUriUtils.java",
+        "base/android/java/src/org/chromium/base/ContextUtils.java",
+        "base/android/java/src/org/chromium/base/CpuFeatures.java",
+        "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
+        "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
+        "base/android/java/src/org/chromium/base/EventLog.java",
+        "base/android/java/src/org/chromium/base/FeatureList.java",
+        "base/android/java/src/org/chromium/base/Features.java",
+        "base/android/java/src/org/chromium/base/FieldTrialList.java",
+        "base/android/java/src/org/chromium/base/FileUtils.java",
+        "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/JNIUtils.java",
+        "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
+        "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
+        "base/android/java/src/org/chromium/base/JniException.java",
+        "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
+        "base/android/java/src/org/chromium/base/LifetimeAssert.java",
+        "base/android/java/src/org/chromium/base/LocaleUtils.java",
+        "base/android/java/src/org/chromium/base/Log.java",
+        "base/android/java/src/org/chromium/base/MathUtils.java",
+        "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
+        "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
+        "base/android/java/src/org/chromium/base/ObserverList.java",
+        "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
+        "base/android/java/src/org/chromium/base/PackageUtils.java",
+        "base/android/java/src/org/chromium/base/PathService.java",
+        "base/android/java/src/org/chromium/base/PathUtils.java",
+        "base/android/java/src/org/chromium/base/PiiElider.java",
+        "base/android/java/src/org/chromium/base/PowerMonitor.java",
+        "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
+        "base/android/java/src/org/chromium/base/Predicate.java",
+        "base/android/java/src/org/chromium/base/Promise.java",
+        "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",
+        "base/android/java/src/org/chromium/base/TraceEvent.java",
+        "base/android/java/src/org/chromium/base/UnguessableToken.java",
+        "base/android/java/src/org/chromium/base/UnownedUserData.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
+        "base/android/java/src/org/chromium/base/UserData.java",
+        "base/android/java/src/org/chromium/base/UserDataHost.java",
+        "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
+        "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
+        "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
+        "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
+        "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
+        "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",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
+        "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
+        "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
+        "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
+        "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
+        "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
+        "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
+        "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
+        "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
+        "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/supplier/BooleanSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/Supplier.java",
+        "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
+        "base/android/java/src/org/chromium/base/task/AsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
+        "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
+        "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/PostTask.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraits.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
+        "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
+        "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
+        "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
+        "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/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",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
+        "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/NativeCronetEngineBuilderImpl.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",
+        "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
+        "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
+        "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
+        "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
+        "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
+        "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
+        "net/android/java/src/org/chromium/net/DnsStatus.java",
+        "net/android/java/src/org/chromium/net/GURLUtils.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
+        "net/android/java/src/org/chromium/net/HttpUtil.java",
+        "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
+        "net/android/java/src/org/chromium/net/NetStringUtil.java",
+        "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
+        "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
+        "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
+        "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
+        "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
+        "net/android/java/src/org/chromium/net/X509Util.java",
+        "url/android/java/src/org/chromium/url/IDNStringUtil.java",
+    ],
+    cmd: "current_dir=`basename \\`pwd\\``; " +
+         "for f in $(in); " +
+         "do " +
+         "echo \"../$$current_dir/$$f\" >> $(genDir)/java.sources; " +
+         "done; " +
+         "python3 $(location base/android/jni_generator/jni_registration_generator.py) --srcjar-path " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.srcjar " +
+         "--depfile " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.d " +
+         "--sources-files " +
+         "$(genDir)/java.sources " +
+         "--include_test_only " +
+         "--use_proxy_hash " +
+         "--header-path " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.h " +
+         "--manual_jni_registration " +
+         ";sed -i -e 's/OUT_SOONG_.TEMP_SBOX_.*_OUT/GEN/g'  " +
+         "$(genDir)/components/cronet/android/cronet_jni_registration.h",
+    out: [
+        "components/cronet/android/cronet_jni_registration.srcjar",
+    ],
+    tool_files: [
+        "base/android/jni_generator/jni_generator.py",
+        "base/android/jni_generator/jni_registration_generator.py",
+        "build/android/gyp/util/__init__.py",
+        "build/android/gyp/util/build_utils.py",
+        "build/gn_helpers.py",
+    ],
+}
+
+// GN: //components/cronet/android:cronet_jni_registration__testing
+cc_genrule {
+    name: "cronet_aml_components_cronet_android_cronet_jni_registration__testing",
+    srcs: [
+        "base/android/java/src/org/chromium/base/ActivityState.java",
+        "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
+        "base/android/java/src/org/chromium/base/ApkAssets.java",
+        "base/android/java/src/org/chromium/base/ApplicationStatus.java",
+        "base/android/java/src/org/chromium/base/BaseFeatureList.java",
+        "base/android/java/src/org/chromium/base/BuildInfo.java",
+        "base/android/java/src/org/chromium/base/BundleUtils.java",
+        "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
+        "base/android/java/src/org/chromium/base/Callback.java",
+        "base/android/java/src/org/chromium/base/CallbackController.java",
+        "base/android/java/src/org/chromium/base/CollectionUtil.java",
+        "base/android/java/src/org/chromium/base/CommandLine.java",
+        "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
+        "base/android/java/src/org/chromium/base/Consumer.java",
+        "base/android/java/src/org/chromium/base/ContentUriUtils.java",
+        "base/android/java/src/org/chromium/base/ContextUtils.java",
+        "base/android/java/src/org/chromium/base/CpuFeatures.java",
+        "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
+        "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
+        "base/android/java/src/org/chromium/base/EventLog.java",
+        "base/android/java/src/org/chromium/base/FeatureList.java",
+        "base/android/java/src/org/chromium/base/Features.java",
+        "base/android/java/src/org/chromium/base/FieldTrialList.java",
+        "base/android/java/src/org/chromium/base/FileUtils.java",
+        "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/JNIUtils.java",
+        "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
+        "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
+        "base/android/java/src/org/chromium/base/JniException.java",
+        "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
+        "base/android/java/src/org/chromium/base/LifetimeAssert.java",
+        "base/android/java/src/org/chromium/base/LocaleUtils.java",
+        "base/android/java/src/org/chromium/base/Log.java",
+        "base/android/java/src/org/chromium/base/MathUtils.java",
+        "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
+        "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
+        "base/android/java/src/org/chromium/base/ObserverList.java",
+        "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
+        "base/android/java/src/org/chromium/base/PackageUtils.java",
+        "base/android/java/src/org/chromium/base/PathService.java",
+        "base/android/java/src/org/chromium/base/PathUtils.java",
+        "base/android/java/src/org/chromium/base/PiiElider.java",
+        "base/android/java/src/org/chromium/base/PowerMonitor.java",
+        "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
+        "base/android/java/src/org/chromium/base/Predicate.java",
+        "base/android/java/src/org/chromium/base/Promise.java",
+        "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",
+        "base/android/java/src/org/chromium/base/TraceEvent.java",
+        "base/android/java/src/org/chromium/base/UnguessableToken.java",
+        "base/android/java/src/org/chromium/base/UnownedUserData.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
+        "base/android/java/src/org/chromium/base/UserData.java",
+        "base/android/java/src/org/chromium/base/UserDataHost.java",
+        "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
+        "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
+        "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
+        "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
+        "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
+        "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",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
+        "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
+        "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
+        "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
+        "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
+        "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
+        "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
+        "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
+        "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
+        "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/supplier/BooleanSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/Supplier.java",
+        "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
+        "base/android/java/src/org/chromium/base/task/AsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
+        "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
+        "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/PostTask.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraits.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
+        "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
+        "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
+        "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
+        "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/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",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
+        "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/NativeCronetEngineBuilderImpl.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",
@@ -2880,311 +7692,6 @@
     ],
 }
 
-// GN: //components/cronet/android:cronet_jni_registration
-java_genrule {
-    name: "cronet_aml_components_cronet_android_cronet_jni_registration__java",
-    srcs: [
-        "base/android/java/src/org/chromium/base/ActivityState.java",
-        "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
-        "base/android/java/src/org/chromium/base/ApkAssets.java",
-        "base/android/java/src/org/chromium/base/ApplicationStatus.java",
-        "base/android/java/src/org/chromium/base/BaseFeatureList.java",
-        "base/android/java/src/org/chromium/base/BuildInfo.java",
-        "base/android/java/src/org/chromium/base/BundleUtils.java",
-        "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
-        "base/android/java/src/org/chromium/base/Callback.java",
-        "base/android/java/src/org/chromium/base/CallbackController.java",
-        "base/android/java/src/org/chromium/base/CollectionUtil.java",
-        "base/android/java/src/org/chromium/base/CommandLine.java",
-        "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
-        "base/android/java/src/org/chromium/base/Consumer.java",
-        "base/android/java/src/org/chromium/base/ContentUriUtils.java",
-        "base/android/java/src/org/chromium/base/ContextUtils.java",
-        "base/android/java/src/org/chromium/base/CpuFeatures.java",
-        "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
-        "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
-        "base/android/java/src/org/chromium/base/EventLog.java",
-        "base/android/java/src/org/chromium/base/FeatureList.java",
-        "base/android/java/src/org/chromium/base/Features.java",
-        "base/android/java/src/org/chromium/base/FieldTrialList.java",
-        "base/android/java/src/org/chromium/base/FileUtils.java",
-        "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",
-        "base/android/java/src/org/chromium/base/JniException.java",
-        "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
-        "base/android/java/src/org/chromium/base/LifetimeAssert.java",
-        "base/android/java/src/org/chromium/base/LocaleUtils.java",
-        "base/android/java/src/org/chromium/base/Log.java",
-        "base/android/java/src/org/chromium/base/MathUtils.java",
-        "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
-        "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
-        "base/android/java/src/org/chromium/base/ObserverList.java",
-        "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
-        "base/android/java/src/org/chromium/base/PackageUtils.java",
-        "base/android/java/src/org/chromium/base/PathService.java",
-        "base/android/java/src/org/chromium/base/PathUtils.java",
-        "base/android/java/src/org/chromium/base/PiiElider.java",
-        "base/android/java/src/org/chromium/base/PowerMonitor.java",
-        "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
-        "base/android/java/src/org/chromium/base/Predicate.java",
-        "base/android/java/src/org/chromium/base/Promise.java",
-        "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/ThreadUtils.java",
-        "base/android/java/src/org/chromium/base/TimeUtils.java",
-        "base/android/java/src/org/chromium/base/TimezoneUtils.java",
-        "base/android/java/src/org/chromium/base/TraceEvent.java",
-        "base/android/java/src/org/chromium/base/UnguessableToken.java",
-        "base/android/java/src/org/chromium/base/UnownedUserData.java",
-        "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
-        "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
-        "base/android/java/src/org/chromium/base/UserData.java",
-        "base/android/java/src/org/chromium/base/UserDataHost.java",
-        "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
-        "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
-        "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
-        "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
-        "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
-        "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
-        "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
-        "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
-        "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
-        "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
-        "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
-        "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
-        "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/Linker.java",
-        "base/android/java/src/org/chromium/base/library_loader/LinkerJni.java",
-        "base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
-        "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
-        "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
-        "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
-        "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
-        "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
-        "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
-        "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
-        "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
-        "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
-        "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
-        "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
-        "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
-        "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
-        "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
-        "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
-        "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
-        "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
-        "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
-        "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",
-        "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
-        "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
-        "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
-        "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
-        "base/android/java/src/org/chromium/base/supplier/Supplier.java",
-        "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
-        "base/android/java/src/org/chromium/base/task/AsyncTask.java",
-        "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
-        "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
-        "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
-        "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
-        "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
-        "base/android/java/src/org/chromium/base/task/PostTask.java",
-        "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
-        "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
-        "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
-        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
-        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
-        "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
-        "base/android/java/src/org/chromium/base/task/TaskRunner.java",
-        "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
-        "base/android/java/src/org/chromium/base/task/TaskTraits.java",
-        "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
-        "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
-        "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
-        "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
-        "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
-        "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
-        "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",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
-        "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",
-        "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
-        "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
-        "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
-        "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
-        "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
-        "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
-        "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
-        "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
-        "net/android/java/src/org/chromium/net/DnsStatus.java",
-        "net/android/java/src/org/chromium/net/GURLUtils.java",
-        "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
-        "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
-        "net/android/java/src/org/chromium/net/HttpUtil.java",
-        "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
-        "net/android/java/src/org/chromium/net/NetStringUtil.java",
-        "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
-        "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
-        "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
-        "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
-        "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
-        "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
-        "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
-        "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
-        "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
-        "net/android/java/src/org/chromium/net/X509Util.java",
-        "url/android/java/src/org/chromium/url/IDNStringUtil.java",
-    ],
-    cmd: "current_dir=`basename \\`pwd\\``; " +
-         "for f in $(in); " +
-         "do " +
-         "echo \"../$$current_dir/$$f\" >> $(genDir)/java.sources; " +
-         "done; " +
-         "python3 $(location base/android/jni_generator/jni_registration_generator.py) --srcjar-path " +
-         "$(genDir)/components/cronet/android/cronet_jni_registration.srcjar " +
-         "--depfile " +
-         "$(genDir)/components/cronet/android/cronet_jni_registration.d " +
-         "--sources-files " +
-         "$(genDir)/java.sources " +
-         "--include_test_only " +
-         "--use_proxy_hash " +
-         "--header-path " +
-         "$(genDir)/components/cronet/android/cronet_jni_registration.h " +
-         "--manual_jni_registration " +
-         ";sed -i -e 's/OUT_SOONG_.TEMP_SBOX_.*_OUT/GEN/g'  " +
-         "$(genDir)/components/cronet/android/cronet_jni_registration.h",
-    out: [
-        "components/cronet/android/cronet_jni_registration.srcjar",
-    ],
-    tool_files: [
-        "base/android/jni_generator/jni_generator.py",
-        "base/android/jni_generator/jni_registration_generator.py",
-        "build/android/gyp/util/__init__.py",
-        "build/android/gyp/util/build_utils.py",
-        "build/gn_helpers.py",
-    ],
-}
-
 // GN: //components/cronet/android:cronet_static
 cc_object {
     name: "cronet_aml_components_cronet_android_cronet_static",
@@ -3200,6 +7707,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -3221,7 +7729,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,42 +7749,59 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     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/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -3285,6 +7809,326 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //components/cronet/android:cronet_static__testing
+cc_object {
+    name: "cronet_aml_components_cronet_android_cronet_static__testing",
+    srcs: [
+        "components/cronet/android/cronet_bidirectional_stream_adapter.cc",
+        "components/cronet/android/cronet_context_adapter.cc",
+        "components/cronet/android/cronet_library_loader.cc",
+        "components/cronet/android/cronet_upload_data_stream_adapter.cc",
+        "components/cronet/android/cronet_url_request_adapter.cc",
+        "components/cronet/android/io_buffer_with_byte_buffer.cc",
+        "components/cronet/android/url_request_error.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_components_prefs_prefs__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_components_cronet_android_buildflags__testing",
+        "cronet_aml_components_cronet_android_cronet_jni_headers__testing",
+        "cronet_aml_components_cronet_android_cronet_jni_registration__testing",
+        "cronet_aml_components_cronet_cronet_buildflags__testing",
+        "cronet_aml_components_cronet_cronet_version_header_action__testing",
+        "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //components/cronet/android:cronet_unittests_android__library__testing
+cc_library_shared {
+    name: "cronet_aml_components_cronet_android_cronet_unittests_android__library__testing",
+    srcs: [
+        ":cronet_aml_buildtools_third_party_libc___libc____testing",
+        ":cronet_aml_buildtools_third_party_libc__abi_libc__abi__testing",
+        ":cronet_aml_components_cronet_android_cronet_static__testing",
+        ":cronet_aml_components_cronet_cronet_common__testing",
+        ":cronet_aml_components_cronet_cronet_common_unittests__testing",
+        ":cronet_aml_components_cronet_metrics_util__testing",
+        ":cronet_aml_components_metrics_library_support__testing",
+        ":cronet_aml_testing_android_native_test_native_test_native_code__testing",
+        ":cronet_aml_testing_android_native_test_native_test_support__testing",
+        "components/cronet/run_all_unittests.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_test_test_support__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_components_prefs_prefs__testing",
+        "cronet_aml_components_prefs_test_support__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_gtest_util__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_test_support__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_third_party_quiche_quiche_tool_support__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_components_cronet_android_buildflags__testing",
+        "cronet_aml_components_cronet_android_cronet_jni_headers__testing",
+        "cronet_aml_components_cronet_android_cronet_jni_registration__testing",
+        "cronet_aml_components_cronet_cronet_buildflags__testing",
+        "cronet_aml_components_cronet_cronet_version_header_action__testing",
+        "cronet_aml_testing_android_native_test_native_test_jni_headers__testing",
+        "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_components_cronet_android_buildflags__testing",
+        "cronet_aml_components_cronet_android_cronet_jni_headers__testing",
+        "cronet_aml_components_cronet_android_cronet_jni_registration__testing",
+        "cronet_aml_components_cronet_cronet_buildflags__testing",
+        "cronet_aml_components_cronet_cronet_version_header_action__testing",
+        "cronet_aml_testing_android_native_test_native_test_jni_headers__testing",
+        "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DUSE_REMOTE_TEST_SERVER",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/ced/src/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/protobuf/src/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    stem: "libcronet_unittests_android__library",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -3313,12 +8157,13 @@
 // GN: //components/cronet/android:implementation_api_version
 java_genrule {
     name: "cronet_aml_components_cronet_android_implementation_api_version",
-    cmd: "$(location build/util/version.py) -f " +
+    cmd: "$(location build/util/version.py) --official " +
+         "-f " +
          "$(location chrome/VERSION) " +
          "-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)",
@@ -3344,7 +8189,7 @@
         "soong_zip",
     ],
     cmd: "cp $(in) $(genDir)/IntegratedModeState.java && " +
-         "$(location soong_zip) -o $(out) -srcjar -f $(genDir)/IntegratedModeState.java",
+         "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/IntegratedModeState.java",
     out: [
         "IntegratedModeState.srcjar",
     ],
@@ -3379,15 +8224,16 @@
 // GN: //components/cronet/android:interface_api_version
 java_genrule {
     name: "cronet_aml_components_cronet_android_interface_api_version",
-    cmd: "$(location build/util/version.py) -f " +
+    cmd: "$(location build/util/version.py) --official " +
+         "-f " +
          "$(location chrome/VERSION) " +
          "-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 +8242,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",
     ],
 }
 
@@ -3410,7 +8256,7 @@
         "soong_zip",
     ],
     cmd: "cp $(in) $(genDir)/LoadState.java && " +
-         "$(location soong_zip) -o $(out) -srcjar -f $(genDir)/LoadState.java",
+         "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/LoadState.java",
     out: [
         "LoadState.srcjar",
     ],
@@ -3560,6 +8406,29 @@
     ],
 }
 
+// GN: //components/cronet:cronet_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_components_cronet_cronet_buildflags__testing",
+    cmd: "echo '--flags DISABLE_HISTOGRAM_SUPPORT=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//components/cronet:cronet_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    out: [
+        "components/cronet/cronet_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //components/cronet:cronet_common
 cc_object {
     name: "cronet_aml_components_cronet_cronet_common",
@@ -3575,6 +8444,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -3596,7 +8466,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,23 +8479,32 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -3640,8 +8518,20 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -3649,17 +8539,56 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //components/cronet:cronet_version_header
+// GN: //components/cronet:cronet_common__testing
 cc_object {
-    name: "cronet_aml_components_cronet_cronet_version_header",
+    name: "cronet_aml_components_cronet_cronet_common__testing",
+    srcs: [
+        "components/cronet/cronet_context.cc",
+        "components/cronet/cronet_prefs_manager.cc",
+        "components/cronet/cronet_upload_data_stream.cc",
+        "components/cronet/cronet_url_request.cc",
+        "components/cronet/host_cache_persistence_manager.cc",
+        "components/cronet/stale_host_resolver.cc",
+        "components/cronet/url_request_context_config.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_components_prefs_prefs__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
     generated_headers: [
-        "cronet_aml_components_cronet_cronet_version_header_action",
+        "cronet_aml_components_cronet_cronet_buildflags__testing",
+        "cronet_aml_components_cronet_cronet_version_header_action__testing",
+        "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen_headers",
     ],
     defaults: [
         "cronet_aml_defaults",
@@ -3667,28 +8596,59 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     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",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -3696,6 +8656,153 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //components/cronet:cronet_common_unittests__testing
+cc_object {
+    name: "cronet_aml_components_cronet_cronet_common_unittests__testing",
+    srcs: [
+        "components/cronet/host_cache_persistence_manager_unittest.cc",
+        "components/cronet/network_tasks_unittest.cc",
+        "components/cronet/stale_host_resolver_unittest.cc",
+        "components/cronet/url_request_context_config_unittest.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_test_test_support__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_components_prefs_prefs__testing",
+        "cronet_aml_components_prefs_test_support__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_gtest_util__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_test_support__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_third_party_quiche_quiche_tool_support__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_components_cronet_cronet_buildflags__testing",
+        "cronet_aml_components_cronet_cronet_version_header_action__testing",
+        "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen_headers",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DUSE_REMOTE_TEST_SERVER",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/ced/src/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/protobuf/src/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -3705,7 +8812,34 @@
 // GN: //components/cronet:cronet_version_header_action
 cc_genrule {
     name: "cronet_aml_components_cronet_cronet_version_header_action",
-    cmd: "$(location build/util/version.py) -f " +
+    cmd: "$(location build/util/version.py) --official " +
+         "-f " +
+         "$(location chrome/VERSION) " +
+         "-e " +
+         "'VERSION_FULL=\"%s.%s.%s.%s\" % (MAJOR,MINOR,BUILD,PATCH)' " +
+         "-o " +
+         "$(out) " +
+         "$(location components/cronet/version.h.in)",
+    out: [
+        "components/cronet/version.h",
+    ],
+    tool_files: [
+        "build/util/LASTCHANGE",
+        "build/util/android_chrome_version.py",
+        "build/util/version.py",
+        "chrome/VERSION",
+        "components/cronet/version.h.in",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //components/cronet:cronet_version_header_action__testing
+cc_genrule {
+    name: "cronet_aml_components_cronet_cronet_version_header_action__testing",
+    cmd: "$(location build/util/version.py) --official " +
+         "-f " +
          "$(location chrome/VERSION) " +
          "-e " +
          "'VERSION_FULL=\"%s.%s.%s.%s\" % (MAJOR,MINOR,BUILD,PATCH)' " +
@@ -3755,19 +8889,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -3777,8 +8920,20 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -3786,122 +8941,34 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //components/cronet/native:cronet_native_headers
+// GN: //components/cronet:metrics_util__testing
 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",
+    name: "cronet_aml_components_cronet_metrics_util__testing",
     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",
+        "components/cronet/metrics_util.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",
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
     ],
     defaults: [
         "cronet_aml_defaults",
@@ -3909,41 +8976,51 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     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",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -3951,134 +9028,7 @@
         },
         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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -4120,23 +9070,32 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -4147,8 +9106,20 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -4156,6 +9127,106 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //components/metrics:library_support__testing
+cc_object {
+    name: "cronet_aml_components_metrics_library_support__testing",
+    srcs: [
+        ":cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen",
+        "components/metrics/histogram_encoder.cc",
+        "components/metrics/library_support/histogram_manager.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libprotobuf-cpp-lite",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen_headers",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+        "third_party/protobuf/src/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -4178,6 +9249,40 @@
          "--output_name " +
          "PrefService_jni.h " +
          "--input_file " +
+         "$(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",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //components/prefs/android:jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_components_prefs_android_jni_headers__testing",
+    srcs: [
+        "components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/components/prefs/android/jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "PrefService_jni.h " +
+         "--input_file " +
          "$(location components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java)",
     out: [
         "components/prefs/android/jni_headers/PrefService_jni.h",
@@ -4255,19 +9360,28 @@
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
         "-DCOMPONENTS_PREFS_IMPLEMENTATION",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -4277,8 +9391,41 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -4286,6 +9433,344 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //components/prefs:prefs__testing
+cc_library_static {
+    name: "cronet_aml_components_prefs_prefs__testing",
+    srcs: [
+        "components/prefs/android/pref_service_android.cc",
+        "components/prefs/command_line_pref_store.cc",
+        "components/prefs/default_pref_store.cc",
+        "components/prefs/in_memory_pref_store.cc",
+        "components/prefs/json_pref_store.cc",
+        "components/prefs/overlay_user_pref_store.cc",
+        "components/prefs/persistent_pref_store.cc",
+        "components/prefs/pref_change_registrar.cc",
+        "components/prefs/pref_member.cc",
+        "components/prefs/pref_notifier_impl.cc",
+        "components/prefs/pref_registry.cc",
+        "components/prefs/pref_registry_simple.cc",
+        "components/prefs/pref_service.cc",
+        "components/prefs/pref_service_factory.cc",
+        "components/prefs/pref_store.cc",
+        "components/prefs/pref_value_map.cc",
+        "components/prefs/pref_value_store.cc",
+        "components/prefs/scoped_user_pref_update.cc",
+        "components/prefs/segregated_pref_store.cc",
+        "components/prefs/value_map_pref_store.cc",
+        "components/prefs/writeable_pref_store.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_components_prefs_android_jni_headers__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_components_prefs_android_jni_headers__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCOMPONENTS_PREFS_IMPLEMENTATION",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //components/prefs:test_support__testing
+cc_library_static {
+    name: "cronet_aml_components_prefs_test_support__testing",
+    srcs: [
+        ":cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+        ":cronet_aml_third_party_googletest_gmock__testing",
+        ":cronet_aml_third_party_googletest_gtest__testing",
+        "components/prefs/mock_pref_change_callback.cc",
+        "components/prefs/pref_store_observer_mock.cc",
+        "components/prefs/pref_test_utils.cc",
+        "components/prefs/testing_pref_service.cc",
+        "components/prefs/testing_pref_store.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_test_test_support__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_components_prefs_prefs__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+        "third_party/ced/src/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -4315,6 +9800,30 @@
     ],
 }
 
+// GN: //crypto:buildflags__testing
+cc_genrule {
+    name: "cronet_aml_crypto_buildflags__testing",
+    cmd: "echo '--flags USE_NSS_CERTS=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//crypto:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    host_supported: true,
+    out: [
+        "crypto/crypto_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //crypto:crypto
 cc_library_static {
     name: "cronet_aml_crypto_crypto",
@@ -4368,19 +9877,28 @@
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r23_1",
         "-DCRYPTO_IMPLEMENTATION",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -4390,8 +9908,41 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -4399,20 +9950,235 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //crypto:crypto__testing
+cc_library_static {
+    name: "cronet_aml_crypto_crypto__testing",
+    srcs: [
+        "crypto/aead.cc",
+        "crypto/ec_private_key.cc",
+        "crypto/ec_signature_creator.cc",
+        "crypto/ec_signature_creator_impl.cc",
+        "crypto/encryptor.cc",
+        "crypto/hkdf.cc",
+        "crypto/hmac.cc",
+        "crypto/openssl_util.cc",
+        "crypto/p224_spake.cc",
+        "crypto/random.cc",
+        "crypto/rsa_private_key.cc",
+        "crypto/secure_hash.cc",
+        "crypto/secure_util.cc",
+        "crypto/sha2.cc",
+        "crypto/signature_creator.cc",
+        "crypto/signature_verifier.cc",
+        "crypto/symmetric_key.cc",
+        "crypto/unexportable_key.cc",
+        "crypto/unexportable_key_metrics.cc",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_crypto_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_crypto_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCRYPTO_IMPLEMENTATION",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libandroid",
+                "liblog",
+            ],
+        },
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            ldflags: [
+                "-Wl,-wrap,asprintf",
+                "-Wl,-wrap,calloc",
+                "-Wl,-wrap,free",
+                "-Wl,-wrap,getcwd",
+                "-Wl,-wrap,malloc",
+                "-Wl,-wrap,malloc_usable_size",
+                "-Wl,-wrap,memalign",
+                "-Wl,-wrap,posix_memalign",
+                "-Wl,-wrap,pvalloc",
+                "-Wl,-wrap,realloc",
+                "-Wl,-wrap,realpath",
+                "-Wl,-wrap,strdup",
+                "-Wl,-wrap,strndup",
+                "-Wl,-wrap,valloc",
+                "-Wl,-wrap,vasprintf",
+            ],
+        },
+        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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //gn:default_deps
 cc_defaults {
     name: "cronet_aml_defaults",
     cflags: [
         "-DGOOGLE_PROTOBUF_NO_RTTI",
-        "-O2",
         "-Wno-ambiguous-reversed-operator",
-        "-Wno-deprecated-non-prototype",
+        "-Wno-c++11-narrowing",
         "-Wno-error=return-type",
         "-Wno-macro-redefined",
         "-Wno-missing-field-initializers",
@@ -4423,68 +10189,27 @@
         "-Wno-unreachable-code-loop-increment",
         "-Wno-unused-parameter",
         "-fPIC",
-        "-fvisibility=hidden",
     ],
     stl: "none",
+    cpp_std: "c++17",
     apex_available: [
         "com.android.tethering",
     ],
     min_sdk_version: "29",
     target: {
         android: {
+            shared_libs: [
+                "libmediandk",
+            ],
             header_libs: [
                 "jni_headers",
-                "media_ndk_headers",
             ],
         },
         host: {
             cflags: [
                 "-UANDROID",
             ],
-        },
-    },
-}
-
-// 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",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -4539,7 +10264,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,19 +10357,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",
@@ -4674,6 +10385,8 @@
         "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
         "base/android/java/src/org/chromium/base/task/TaskTraits.java",
         "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
+        "base/test/android/java/src/org/chromium/base/ITestCallback.aidl",
+        "base/test/android/java/src/org/chromium/base/ITestController.aidl",
         "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
         "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
         "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
@@ -4682,45 +10395,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 +10410,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 +10454,17 @@
         "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",
     ],
+    min_sdk_version: "30",
     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",
@@ -4811,13 +10477,294 @@
             "frameworks/base/core/java/",
         ],
         local_include_dirs: [
-            "base/android/java/src/",
+            "base/android/java/src",
+            "base/test/android/java/src",
         ],
     },
     plugins: [
         "cronet_aml_java_jni_annotation_preprocessor",
     ],
     sdk_version: "module_current",
+    javacflags: [
+        "-Aorg.chromium.chrome.skipGenJni",
+        "-Apackage_prefix=android.net.http.internal",
+    ],
+}
+
+// GN: //gn:java
+java_library {
+    name: "cronet_aml_java__testing",
+    srcs: [
+        ":cronet_aml_base_base_android_java_enums_srcjar",
+        ":cronet_aml_base_java_features_srcjar",
+        ":cronet_aml_base_java_switches_srcjar",
+        ":cronet_aml_build_android_build_config_gen",
+        ":cronet_aml_build_android_native_libraries_gen",
+        ":cronet_aml_components_cronet_android_cronet_jni_registration__java__testing",
+        ":cronet_aml_components_cronet_android_http_cache_type_java",
+        ":cronet_aml_components_cronet_android_implementation_api_version",
+        ":cronet_aml_components_cronet_android_integrated_mode_state",
+        ":cronet_aml_components_cronet_android_interface_api_version",
+        ":cronet_aml_components_cronet_android_load_states_list",
+        ":cronet_aml_components_cronet_android_net_idempotency_java",
+        ":cronet_aml_components_cronet_android_net_request_priority_java",
+        ":cronet_aml_components_cronet_android_network_quality_observation_source_java",
+        ":cronet_aml_components_cronet_android_rtt_throughput_values_java",
+        ":cronet_aml_components_cronet_android_url_request_error_java",
+        ":cronet_aml_net_android_net_android_java_enums_srcjar",
+        ":cronet_aml_net_android_net_errors_java",
+        ":cronet_aml_net_effective_connection_type_java",
+        "base/android/java/src/org/chromium/base/ActivityState.java",
+        "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
+        "base/android/java/src/org/chromium/base/ApkAssets.java",
+        "base/android/java/src/org/chromium/base/ApplicationStatus.java",
+        "base/android/java/src/org/chromium/base/BaseFeatureList.java",
+        "base/android/java/src/org/chromium/base/BuildInfo.java",
+        "base/android/java/src/org/chromium/base/BundleUtils.java",
+        "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
+        "base/android/java/src/org/chromium/base/Callback.java",
+        "base/android/java/src/org/chromium/base/CallbackController.java",
+        "base/android/java/src/org/chromium/base/CollectionUtil.java",
+        "base/android/java/src/org/chromium/base/CommandLine.java",
+        "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
+        "base/android/java/src/org/chromium/base/Consumer.java",
+        "base/android/java/src/org/chromium/base/ContentUriUtils.java",
+        "base/android/java/src/org/chromium/base/ContextUtils.java",
+        "base/android/java/src/org/chromium/base/CpuFeatures.java",
+        "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
+        "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
+        "base/android/java/src/org/chromium/base/EventLog.java",
+        "base/android/java/src/org/chromium/base/FeatureList.java",
+        "base/android/java/src/org/chromium/base/Features.java",
+        "base/android/java/src/org/chromium/base/FieldTrialList.java",
+        "base/android/java/src/org/chromium/base/FileUtils.java",
+        "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/JNIUtils.java",
+        "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
+        "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
+        "base/android/java/src/org/chromium/base/JniException.java",
+        "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
+        "base/android/java/src/org/chromium/base/LifetimeAssert.java",
+        "base/android/java/src/org/chromium/base/LocaleUtils.java",
+        "base/android/java/src/org/chromium/base/Log.java",
+        "base/android/java/src/org/chromium/base/MathUtils.java",
+        "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
+        "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
+        "base/android/java/src/org/chromium/base/ObserverList.java",
+        "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
+        "base/android/java/src/org/chromium/base/PackageUtils.java",
+        "base/android/java/src/org/chromium/base/PathService.java",
+        "base/android/java/src/org/chromium/base/PathUtils.java",
+        "base/android/java/src/org/chromium/base/PiiElider.java",
+        "base/android/java/src/org/chromium/base/PowerMonitor.java",
+        "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
+        "base/android/java/src/org/chromium/base/Predicate.java",
+        "base/android/java/src/org/chromium/base/Promise.java",
+        "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",
+        "base/android/java/src/org/chromium/base/TraceEvent.java",
+        "base/android/java/src/org/chromium/base/UnguessableToken.java",
+        "base/android/java/src/org/chromium/base/UnownedUserData.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
+        "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
+        "base/android/java/src/org/chromium/base/UserData.java",
+        "base/android/java/src/org/chromium/base/UserDataHost.java",
+        "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
+        "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
+        "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
+        "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
+        "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
+        "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
+        "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
+        "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
+        "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
+        "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",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
+        "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
+        "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
+        "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
+        "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
+        "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
+        "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
+        "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
+        "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
+        "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
+        "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
+        "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
+        "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/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",
+        "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
+        "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
+        "base/android/java/src/org/chromium/base/supplier/Supplier.java",
+        "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
+        "base/android/java/src/org/chromium/base/task/AsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
+        "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
+        "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
+        "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/PostTask.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunner.java",
+        "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraits.java",
+        "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
+        "base/test/android/java/src/org/chromium/base/ITestCallback.aidl",
+        "base/test/android/java/src/org/chromium/base/ITestController.aidl",
+        "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
+        "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
+        "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
+        "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
+        "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/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",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
+        "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/NativeCronetEngineBuilderImpl.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",
+        "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
+        "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
+        "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
+        "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
+        "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
+        "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
+        "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
+        "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
+        "net/android/java/src/org/chromium/net/DnsStatus.java",
+        "net/android/java/src/org/chromium/net/GURLUtils.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
+        "net/android/java/src/org/chromium/net/HttpUtil.java",
+        "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
+        "net/android/java/src/org/chromium/net/NetStringUtil.java",
+        "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
+        "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
+        "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
+        "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
+        "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
+        "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
+        "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: [
+        "com.android.tethering",
+    ],
+    min_sdk_version: "30",
+    libs: [
+        "androidx.annotation_annotation",
+        "androidx.annotation_annotation-experimental-nodeps",
+        "cronet_aml_api_java",
+        "framework-connectivity-t.stubs.module_lib",
+        "framework-connectivity.stubs.module_lib",
+        "framework-mediaprovider.stubs.module_lib",
+        "framework-tethering.stubs.module_lib",
+        "framework-wifi.stubs.module_lib",
+        "jsr305",
+    ],
+    aidl: {
+        include_dirs: [
+            "frameworks/base/core/java/",
+        ],
+        local_include_dirs: [
+            "base/android/java/src",
+            "base/test/android/java/src",
+        ],
+    },
+    plugins: [
+        "cronet_aml_java_jni_annotation_preprocessor",
+    ],
+    sdk_version: "module_current",
+    javacflags: [
+        "-Aorg.chromium.chrome.skipGenJni",
+    ],
 }
 
 // GN: //base/android/jni_generator:jni_processor
@@ -4882,7 +10829,7 @@
         "soong_zip",
     ],
     cmd: "cp $(in) $(genDir)/NetError.java && " +
-         "$(location soong_zip) -o $(out) -srcjar -f $(genDir)/NetError.java",
+         "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/NetError.java",
     out: [
         "NetError.srcjar",
     ],
@@ -4968,6 +10915,60 @@
     ],
 }
 
+// GN: //net/base/registry_controlled_domains:registry_controlled_domains__testing
+cc_genrule {
+    name: "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains__testing",
+    cmd: "$(location net/tools/dafsa/make_dafsa.py) --reverse " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names.gperf) " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names-reversed-inc.cc) " +
+         "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
+         "--reverse " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf) " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest1-reversed-inc.cc) " +
+         "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
+         "--reverse " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest2.gperf) " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest2-reversed-inc.cc) " +
+         "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
+         "--reverse " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest3.gperf) " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest3-reversed-inc.cc) " +
+         "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
+         "--reverse " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest4.gperf) " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest4-reversed-inc.cc) " +
+         "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
+         "--reverse " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest5.gperf) " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest5-reversed-inc.cc) " +
+         "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
+         "--reverse " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest6.gperf) " +
+         "$(location net/base/registry_controlled_domains/effective_tld_names_unittest6-reversed-inc.cc)",
+    out: [
+        "net/base/registry_controlled_domains/effective_tld_names-reversed-inc.cc",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest1-reversed-inc.cc",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest2-reversed-inc.cc",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest3-reversed-inc.cc",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest4-reversed-inc.cc",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest5-reversed-inc.cc",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest6-reversed-inc.cc",
+    ],
+    tool_files: [
+        "net/base/registry_controlled_domains/effective_tld_names.gperf",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest2.gperf",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest3.gperf",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest4.gperf",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest5.gperf",
+        "net/base/registry_controlled_domains/effective_tld_names_unittest6.gperf",
+        "net/tools/dafsa/make_dafsa.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //net:buildflags
 cc_genrule {
     name: "cronet_aml_net_buildflags",
@@ -5030,88 +11031,62 @@
     ],
 }
 
-// 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
+// GN: //net:buildflags__testing
 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",
+    name: "cronet_aml_net_buildflags__testing",
+    cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags POSIX_BYPASS_MMAP=\"true\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//net:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags POSIX_BYPASS_MMAP=\"false\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//net:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags POSIX_BYPASS_MMAP=\"true\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//net:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi; " +
+         "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
+         "then " +
+         "echo '--flags POSIX_BYPASS_MMAP=\"true\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//net:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin; " +
+         "fi;",
     out: [
-        "net/data/ssl/chrome_root_store/chrome-ev-roots-inc.cc",
-        "net/data/ssl/chrome_root_store/chrome-root-store-inc.cc",
+        "net/net_buildflags.h",
     ],
     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",
+        "build/write_buildflag_header.py",
     ],
     apex_available: [
         "com.android.tethering",
@@ -5163,6 +11138,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -5182,7 +11158,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,25 +11178,34 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-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",
+        "-DNDEBUG",
         "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -5235,10 +11219,21 @@
         "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: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -5246,51 +11241,91 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //net/dns:dns_client
+// GN: //net/dns:dns__testing
 cc_object {
-    name: "cronet_aml_net_dns_dns_client",
+    name: "cronet_aml_net_dns_dns__testing",
+    srcs: [
+        "net/dns/address_info.cc",
+        "net/dns/address_sorter_posix.cc",
+        "net/dns/context_host_resolver.cc",
+        "net/dns/dns_alias_utility.cc",
+        "net/dns/dns_client.cc",
+        "net/dns/dns_config.cc",
+        "net/dns/dns_config_service.cc",
+        "net/dns/dns_config_service_android.cc",
+        "net/dns/dns_hosts.cc",
+        "net/dns/dns_query.cc",
+        "net/dns/dns_reloader.cc",
+        "net/dns/dns_response.cc",
+        "net/dns/dns_response_result_extractor.cc",
+        "net/dns/dns_server_iterator.cc",
+        "net/dns/dns_session.cc",
+        "net/dns/dns_transaction.cc",
+        "net/dns/dns_udp_tracker.cc",
+        "net/dns/dns_util.cc",
+        "net/dns/host_cache.cc",
+        "net/dns/host_resolver.cc",
+        "net/dns/host_resolver_manager.cc",
+        "net/dns/host_resolver_mdns_listener_impl.cc",
+        "net/dns/host_resolver_mdns_task.cc",
+        "net/dns/host_resolver_nat64_task.cc",
+        "net/dns/host_resolver_proc.cc",
+        "net/dns/host_resolver_system_task.cc",
+        "net/dns/https_record_rdata.cc",
+        "net/dns/httpssvc_metrics.cc",
+        "net/dns/mapped_host_resolver.cc",
+        "net/dns/nsswitch_reader.cc",
+        "net/dns/opt_record_rdata.cc",
+        "net/dns/record_parsed.cc",
+        "net/dns/record_rdata.cc",
+        "net/dns/resolve_context.cc",
+        "net/dns/serial_worker.cc",
+        "net/dns/system_dns_config_change_notifier.cc",
+        "net/dns/test_dns_config_service.cc",
+    ],
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     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",
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
     ],
     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",
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains__testing",
+        "cronet_aml_net_buildflags__testing",
+        "cronet_aml_net_isolation_info_proto__testing_gen_headers",
+        "cronet_aml_net_net_jni_headers__testing",
+        "cronet_aml_net_net_nqe_proto__testing_gen_headers",
+        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
     ],
     defaults: [
         "cronet_aml_defaults",
@@ -5298,25 +11333,34 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-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",
+        "-DNDEBUG",
         "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -5330,10 +11374,21 @@
         "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: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -5341,291 +11396,7 @@
         },
         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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -5648,6 +11419,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -5667,7 +11439,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,25 +11459,34 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-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",
+        "-DNDEBUG",
         "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -5720,10 +11500,21 @@
         "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: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -5731,6 +11522,253 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/dns/public:public__testing
+cc_object {
+    name: "cronet_aml_net_dns_public_public__testing",
+    srcs: [
+        "net/dns/public/dns_config_overrides.cc",
+        "net/dns/public/dns_over_https_config.cc",
+        "net/dns/public/dns_over_https_server_config.cc",
+        "net/dns/public/dns_query_type.cc",
+        "net/dns/public/doh_provider_entry.cc",
+        "net/dns/public/host_resolver_results.cc",
+        "net/dns/public/resolve_error_info.cc",
+        "net/dns/public/util.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains__testing",
+        "cronet_aml_net_buildflags__testing",
+        "cronet_aml_net_isolation_info_proto__testing_gen_headers",
+        "cronet_aml_net_net_jni_headers__testing",
+        "cronet_aml_net_net_nqe_proto__testing_gen_headers",
+        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-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",
+        "-DNDEBUG",
+        "-DNET_IMPLEMENTATION",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/dns:test_support__testing
+cc_object {
+    name: "cronet_aml_net_dns_test_support__testing",
+    srcs: [
+        "net/dns/dns_test_util.cc",
+        "net/dns/host_resolver_results_test_util.cc",
+        "net/dns/mock_host_resolver.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/protobuf/src/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -5756,6 +11794,214 @@
     ],
 }
 
+// GN: //net:gtest_util__testing
+cc_library_static {
+    name: "cronet_aml_net_gtest_util__testing",
+    srcs: [
+        ":cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+        ":cronet_aml_third_party_googletest_gmock__testing",
+        ":cronet_aml_third_party_googletest_gtest__testing",
+        "net/test/scoped_disable_exit_on_dfatal.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_test_test_support__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/ced/src/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/protobuf/src/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
 // GN: //net/http:transport_security_state_generated_files
 cc_object {
     name: "cronet_aml_net_http_transport_security_state_generated_files",
@@ -5765,6 +12011,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -5784,7 +12031,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,25 +12052,34 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-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",
+        "-DNDEBUG",
         "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -5838,10 +12093,21 @@
         "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: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -5849,16 +12115,162 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //net/http:transport_security_state_generated_files__testing
+cc_object {
+    name: "cronet_aml_net_http_transport_security_state_generated_files__testing",
+    srcs: [
+        "net/http/transport_security_state.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_branding_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains__testing",
+        "cronet_aml_net_buildflags__testing",
+        "cronet_aml_net_isolation_info_proto__testing_gen_headers",
+        "cronet_aml_net_net_jni_headers__testing",
+        "cronet_aml_net_net_nqe_proto__testing_gen_headers",
+        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-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",
+        "-DNDEBUG",
+        "-DNET_IMPLEMENTATION",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/http:transport_security_state_unittest_data_default__testing
+cc_genrule {
+    name: "cronet_aml_net_http_transport_security_state_unittest_data_default__testing",
+    tools: [
+        "cronet_aml_net_tools_transport_security_state_generator_transport_security_state_generator__testing",
+    ],
+    cmd: "$(location cronet_aml_net_tools_transport_security_state_generator_transport_security_state_generator__testing) " +
+         "$(location net/http/transport_security_state_static_unittest_default.json) " +
+         "$(location net/http/transport_security_state_static_unittest_default.pins) " +
+         "$(location net/http/transport_security_state_static_unittest.template) " +
+         "$(location net/http/transport_security_state_static_unittest_default.h)",
+    out: [
+        "net/http/transport_security_state_static_unittest_default.h",
+    ],
+    tool_files: [
+        "build/gn_run_binary.py",
+        "net/http/transport_security_state_static_unittest.template",
+        "net/http/transport_security_state_static_unittest_default.json",
+        "net/http/transport_security_state_static_unittest_default.pins",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // 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 " +
@@ -5878,6 +12290,70 @@
     ],
 }
 
+// GN: //net:ios_cronet_buildflags__testing
+cc_genrule {
+    name: "cronet_aml_net_ios_cronet_buildflags__testing",
+    cmd: "echo '--flags CRONET_BUILD=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//net:ios_cronet_buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    out: [
+        "net/socket/ios_cronet_buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //net:isolation_info_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_isolation_info_proto__testing_gen",
+    srcs: [
+        "net/base/isolation_info.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/cronet/net/base/isolation_info.pb.cc",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //net:isolation_info_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_isolation_info_proto__testing_gen_headers",
+    srcs: [
+        "net/base/isolation_info.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/cronet/net/base/isolation_info.pb.h",
+    ],
+    export_include_dirs: [
+        ".",
+        "net/base",
+        "protos",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //net:isolation_info_proto
 cc_genrule {
     name: "cronet_aml_net_isolation_info_proto_gen",
@@ -5887,9 +12363,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 +12381,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 +12891,7 @@
     shared_libs: [
         "libandroid",
         "liblog",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -6434,7 +12911,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,25 +12951,34 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-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",
+        "-DNDEBUG",
         "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -6507,19 +12992,47 @@
         "third_party/boringssl/src/include/",
         "third_party/brotli/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
         android_arm: {
             srcs: [
                 "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
             ],
+            cflags: [
+                "-fstack-protector",
+            ],
         },
         android_arm64: {
             srcs: [
                 "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
             ],
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
         },
         android_x86: {
             srcs: [
@@ -6534,6 +13047,662 @@
                 "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
             ],
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net:net__testing
+cc_library_static {
+    name: "cronet_aml_net_net__testing",
+    srcs: [
+        ":cronet_aml_net_dns_dns__testing",
+        ":cronet_aml_net_dns_public_public__testing",
+        ":cronet_aml_net_http_transport_security_state_generated_files__testing",
+        ":cronet_aml_net_net_deps__testing",
+        ":cronet_aml_net_net_public_deps__testing",
+        ":cronet_aml_net_traffic_annotation_traffic_annotation__testing",
+        "net/android/android_http_util.cc",
+        "net/android/cert_verify_result_android.cc",
+        "net/android/gurl_utils.cc",
+        "net/android/http_auth_negotiate_android.cc",
+        "net/android/keystore.cc",
+        "net/android/network_change_notifier_android.cc",
+        "net/android/network_change_notifier_delegate_android.cc",
+        "net/android/network_change_notifier_factory_android.cc",
+        "net/android/network_library.cc",
+        "net/android/radio_activity_tracker.cc",
+        "net/android/traffic_stats.cc",
+        "net/base/address_family.cc",
+        "net/base/address_list.cc",
+        "net/base/address_tracker_linux.cc",
+        "net/base/auth.cc",
+        "net/base/backoff_entry.cc",
+        "net/base/backoff_entry_serializer.cc",
+        "net/base/cache_metrics.cc",
+        "net/base/chunked_upload_data_stream.cc",
+        "net/base/connection_endpoint_metadata.cc",
+        "net/base/data_url.cc",
+        "net/base/datagram_buffer.cc",
+        "net/base/elements_upload_data_stream.cc",
+        "net/base/features.cc",
+        "net/base/file_stream.cc",
+        "net/base/file_stream_context.cc",
+        "net/base/file_stream_context_posix.cc",
+        "net/base/filename_util.cc",
+        "net/base/filename_util_internal.cc",
+        "net/base/hash_value.cc",
+        "net/base/hex_utils.cc",
+        "net/base/host_mapping_rules.cc",
+        "net/base/host_port_pair.cc",
+        "net/base/io_buffer.cc",
+        "net/base/ip_address.cc",
+        "net/base/ip_endpoint.cc",
+        "net/base/isolation_info.cc",
+        "net/base/load_timing_info.cc",
+        "net/base/logging_network_change_observer.cc",
+        "net/base/lookup_string_in_fixed_set.cc",
+        "net/base/mime_sniffer.cc",
+        "net/base/mime_util.cc",
+        "net/base/net_errors.cc",
+        "net/base/net_errors_posix.cc",
+        "net/base/net_module.cc",
+        "net/base/net_string_util_icu_alternatives_android.cc",
+        "net/base/network_activity_monitor.cc",
+        "net/base/network_anonymization_key.cc",
+        "net/base/network_change_notifier.cc",
+        "net/base/network_change_notifier_posix.cc",
+        "net/base/network_delegate.cc",
+        "net/base/network_delegate_impl.cc",
+        "net/base/network_interfaces.cc",
+        "net/base/network_interfaces_getifaddrs.cc",
+        "net/base/network_interfaces_getifaddrs_android.cc",
+        "net/base/network_interfaces_linux.cc",
+        "net/base/network_interfaces_posix.cc",
+        "net/base/network_isolation_key.cc",
+        "net/base/parse_number.cc",
+        "net/base/platform_mime_util_linux.cc",
+        "net/base/port_util.cc",
+        "net/base/prioritized_dispatcher.cc",
+        "net/base/prioritized_task_runner.cc",
+        "net/base/privacy_mode.cc",
+        "net/base/proxy_server.cc",
+        "net/base/proxy_string_util.cc",
+        "net/base/registry_controlled_domains/registry_controlled_domain.cc",
+        "net/base/request_priority.cc",
+        "net/base/scheme_host_port_matcher.cc",
+        "net/base/scheme_host_port_matcher_rule.cc",
+        "net/base/schemeful_site.cc",
+        "net/base/sockaddr_storage.cc",
+        "net/base/sockaddr_util_posix.cc",
+        "net/base/transport_info.cc",
+        "net/base/upload_bytes_element_reader.cc",
+        "net/base/upload_data_stream.cc",
+        "net/base/upload_element_reader.cc",
+        "net/base/upload_file_element_reader.cc",
+        "net/base/url_util.cc",
+        "net/cert/asn1_util.cc",
+        "net/cert/caching_cert_verifier.cc",
+        "net/cert/cert_and_ct_verifier.cc",
+        "net/cert/cert_database.cc",
+        "net/cert/cert_status_flags.cc",
+        "net/cert/cert_verifier.cc",
+        "net/cert/cert_verify_proc.cc",
+        "net/cert/cert_verify_proc_android.cc",
+        "net/cert/cert_verify_proc_builtin.cc",
+        "net/cert/cert_verify_result.cc",
+        "net/cert/coalescing_cert_verifier.cc",
+        "net/cert/crl_set.cc",
+        "net/cert/ct_log_response_parser.cc",
+        "net/cert/ct_log_verifier.cc",
+        "net/cert/ct_log_verifier_util.cc",
+        "net/cert/ct_objects_extractor.cc",
+        "net/cert/ct_policy_enforcer.cc",
+        "net/cert/ct_sct_to_string.cc",
+        "net/cert/ct_serialization.cc",
+        "net/cert/ct_signed_certificate_timestamp_log_param.cc",
+        "net/cert/do_nothing_ct_verifier.cc",
+        "net/cert/ev_root_ca_metadata.cc",
+        "net/cert/internal/cert_issuer_source_aia.cc",
+        "net/cert/internal/revocation_checker.cc",
+        "net/cert/internal/system_trust_store.cc",
+        "net/cert/known_roots.cc",
+        "net/cert/merkle_audit_proof.cc",
+        "net/cert/merkle_consistency_proof.cc",
+        "net/cert/merkle_tree_leaf.cc",
+        "net/cert/multi_log_ct_verifier.cc",
+        "net/cert/multi_threaded_cert_verifier.cc",
+        "net/cert/ocsp_verify_result.cc",
+        "net/cert/pem.cc",
+        "net/cert/pki/cert_error_id.cc",
+        "net/cert/pki/cert_error_params.cc",
+        "net/cert/pki/cert_errors.cc",
+        "net/cert/pki/cert_issuer_source_static.cc",
+        "net/cert/pki/certificate_policies.cc",
+        "net/cert/pki/common_cert_errors.cc",
+        "net/cert/pki/crl.cc",
+        "net/cert/pki/extended_key_usage.cc",
+        "net/cert/pki/general_names.cc",
+        "net/cert/pki/name_constraints.cc",
+        "net/cert/pki/ocsp.cc",
+        "net/cert/pki/parse_certificate.cc",
+        "net/cert/pki/parse_name.cc",
+        "net/cert/pki/parsed_certificate.cc",
+        "net/cert/pki/path_builder.cc",
+        "net/cert/pki/revocation_util.cc",
+        "net/cert/pki/signature_algorithm.cc",
+        "net/cert/pki/simple_path_builder_delegate.cc",
+        "net/cert/pki/string_util.cc",
+        "net/cert/pki/trust_store.cc",
+        "net/cert/pki/trust_store_collection.cc",
+        "net/cert/pki/trust_store_in_memory.cc",
+        "net/cert/pki/verify_certificate_chain.cc",
+        "net/cert/pki/verify_name_match.cc",
+        "net/cert/pki/verify_signed_data.cc",
+        "net/cert/sct_status_flags.cc",
+        "net/cert/signed_certificate_timestamp.cc",
+        "net/cert/signed_certificate_timestamp_and_status.cc",
+        "net/cert/signed_tree_head.cc",
+        "net/cert/symantec_certs.cc",
+        "net/cert/test_root_certs.cc",
+        "net/cert/test_root_certs_android.cc",
+        "net/cert/trial_comparison_cert_verifier_util.cc",
+        "net/cert/x509_cert_types.cc",
+        "net/cert/x509_certificate.cc",
+        "net/cert/x509_certificate_net_log_param.cc",
+        "net/cert/x509_util.cc",
+        "net/cert/x509_util_android.cc",
+        "net/cert_net/cert_net_fetcher_url_request.cc",
+        "net/cookies/canonical_cookie.cc",
+        "net/cookies/cookie_access_delegate.cc",
+        "net/cookies/cookie_access_result.cc",
+        "net/cookies/cookie_change_dispatcher.cc",
+        "net/cookies/cookie_constants.cc",
+        "net/cookies/cookie_deletion_info.cc",
+        "net/cookies/cookie_inclusion_status.cc",
+        "net/cookies/cookie_monster.cc",
+        "net/cookies/cookie_monster_change_dispatcher.cc",
+        "net/cookies/cookie_monster_netlog_params.cc",
+        "net/cookies/cookie_options.cc",
+        "net/cookies/cookie_partition_key.cc",
+        "net/cookies/cookie_partition_key_collection.cc",
+        "net/cookies/cookie_store.cc",
+        "net/cookies/cookie_util.cc",
+        "net/cookies/parsed_cookie.cc",
+        "net/cookies/site_for_cookies.cc",
+        "net/cookies/static_cookie_policy.cc",
+        "net/der/encode_values.cc",
+        "net/der/input.cc",
+        "net/der/parse_values.cc",
+        "net/der/parser.cc",
+        "net/der/tag.cc",
+        "net/disk_cache/backend_cleanup_tracker.cc",
+        "net/disk_cache/blockfile/addr.cc",
+        "net/disk_cache/blockfile/backend_impl.cc",
+        "net/disk_cache/blockfile/bitmap.cc",
+        "net/disk_cache/blockfile/block_files.cc",
+        "net/disk_cache/blockfile/disk_format.cc",
+        "net/disk_cache/blockfile/entry_impl.cc",
+        "net/disk_cache/blockfile/eviction.cc",
+        "net/disk_cache/blockfile/file.cc",
+        "net/disk_cache/blockfile/file_lock.cc",
+        "net/disk_cache/blockfile/file_posix.cc",
+        "net/disk_cache/blockfile/in_flight_backend_io.cc",
+        "net/disk_cache/blockfile/in_flight_io.cc",
+        "net/disk_cache/blockfile/mapped_file.cc",
+        "net/disk_cache/blockfile/rankings.cc",
+        "net/disk_cache/blockfile/sparse_control.cc",
+        "net/disk_cache/blockfile/stats.cc",
+        "net/disk_cache/cache_util.cc",
+        "net/disk_cache/cache_util_posix.cc",
+        "net/disk_cache/disk_cache.cc",
+        "net/disk_cache/memory/mem_backend_impl.cc",
+        "net/disk_cache/memory/mem_entry_impl.cc",
+        "net/disk_cache/net_log_parameters.cc",
+        "net/disk_cache/simple/post_doom_waiter.cc",
+        "net/disk_cache/simple/simple_backend_impl.cc",
+        "net/disk_cache/simple/simple_entry_format.cc",
+        "net/disk_cache/simple/simple_entry_impl.cc",
+        "net/disk_cache/simple/simple_entry_operation.cc",
+        "net/disk_cache/simple/simple_file_enumerator.cc",
+        "net/disk_cache/simple/simple_file_tracker.cc",
+        "net/disk_cache/simple/simple_index.cc",
+        "net/disk_cache/simple/simple_index_file.cc",
+        "net/disk_cache/simple/simple_net_log_parameters.cc",
+        "net/disk_cache/simple/simple_synchronous_entry.cc",
+        "net/disk_cache/simple/simple_util.cc",
+        "net/disk_cache/simple/simple_util_posix.cc",
+        "net/disk_cache/simple/simple_version_upgrade.cc",
+        "net/filter/brotli_source_stream.cc",
+        "net/filter/filter_source_stream.cc",
+        "net/filter/gzip_header.cc",
+        "net/filter/gzip_source_stream.cc",
+        "net/filter/source_stream.cc",
+        "net/first_party_sets/addition_overlaps_union_find.cc",
+        "net/first_party_sets/first_party_set_entry.cc",
+        "net/first_party_sets/first_party_set_metadata.cc",
+        "net/first_party_sets/first_party_sets_cache_filter.cc",
+        "net/first_party_sets/first_party_sets_context_config.cc",
+        "net/first_party_sets/global_first_party_sets.cc",
+        "net/first_party_sets/same_party_context.cc",
+        "net/http/alternative_service.cc",
+        "net/http/bidirectional_stream.cc",
+        "net/http/bidirectional_stream_impl.cc",
+        "net/http/bidirectional_stream_request_info.cc",
+        "net/http/broken_alternative_services.cc",
+        "net/http/http_auth.cc",
+        "net/http/http_auth_cache.cc",
+        "net/http/http_auth_challenge_tokenizer.cc",
+        "net/http/http_auth_controller.cc",
+        "net/http/http_auth_filter.cc",
+        "net/http/http_auth_handler.cc",
+        "net/http/http_auth_handler_basic.cc",
+        "net/http/http_auth_handler_digest.cc",
+        "net/http/http_auth_handler_factory.cc",
+        "net/http/http_auth_handler_negotiate.cc",
+        "net/http/http_auth_handler_ntlm.cc",
+        "net/http/http_auth_handler_ntlm_portable.cc",
+        "net/http/http_auth_multi_round_parse.cc",
+        "net/http/http_auth_ntlm_mechanism.cc",
+        "net/http/http_auth_preferences.cc",
+        "net/http/http_auth_scheme.cc",
+        "net/http/http_basic_state.cc",
+        "net/http/http_basic_stream.cc",
+        "net/http/http_byte_range.cc",
+        "net/http/http_cache.cc",
+        "net/http/http_cache_lookup_manager.cc",
+        "net/http/http_cache_transaction.cc",
+        "net/http/http_cache_writers.cc",
+        "net/http/http_chunked_decoder.cc",
+        "net/http/http_content_disposition.cc",
+        "net/http/http_log_util.cc",
+        "net/http/http_network_layer.cc",
+        "net/http/http_network_session.cc",
+        "net/http/http_network_session_peer.cc",
+        "net/http/http_network_transaction.cc",
+        "net/http/http_proxy_client_socket.cc",
+        "net/http/http_proxy_connect_job.cc",
+        "net/http/http_raw_request_headers.cc",
+        "net/http/http_request_headers.cc",
+        "net/http/http_request_info.cc",
+        "net/http/http_response_body_drainer.cc",
+        "net/http/http_response_headers.cc",
+        "net/http/http_response_info.cc",
+        "net/http/http_security_headers.cc",
+        "net/http/http_server_properties.cc",
+        "net/http/http_server_properties_manager.cc",
+        "net/http/http_status_code.cc",
+        "net/http/http_stream_factory.cc",
+        "net/http/http_stream_factory_job.cc",
+        "net/http/http_stream_factory_job_controller.cc",
+        "net/http/http_stream_parser.cc",
+        "net/http/http_stream_request.cc",
+        "net/http/http_util.cc",
+        "net/http/http_vary_data.cc",
+        "net/http/partial_data.cc",
+        "net/http/proxy_client_socket.cc",
+        "net/http/proxy_fallback.cc",
+        "net/http/transport_security_persister.cc",
+        "net/http/transport_security_state_source.cc",
+        "net/http/url_security_manager.cc",
+        "net/http/url_security_manager_posix.cc",
+        "net/http/webfonts_histogram.cc",
+        "net/log/file_net_log_observer.cc",
+        "net/log/net_log.cc",
+        "net/log/net_log_capture_mode.cc",
+        "net/log/net_log_entry.cc",
+        "net/log/net_log_event_type.cc",
+        "net/log/net_log_source.cc",
+        "net/log/net_log_util.cc",
+        "net/log/net_log_values.cc",
+        "net/log/net_log_with_source.cc",
+        "net/log/trace_net_log_observer.cc",
+        "net/network_error_logging/network_error_logging_service.cc",
+        "net/nqe/cached_network_quality.cc",
+        "net/nqe/effective_connection_type.cc",
+        "net/nqe/event_creator.cc",
+        "net/nqe/network_id.cc",
+        "net/nqe/network_qualities_prefs_manager.cc",
+        "net/nqe/network_quality.cc",
+        "net/nqe/network_quality_estimator.cc",
+        "net/nqe/network_quality_estimator_params.cc",
+        "net/nqe/network_quality_estimator_util.cc",
+        "net/nqe/network_quality_observation.cc",
+        "net/nqe/network_quality_store.cc",
+        "net/nqe/observation_buffer.cc",
+        "net/nqe/pref_names.cc",
+        "net/nqe/socket_watcher.cc",
+        "net/nqe/socket_watcher_factory.cc",
+        "net/nqe/throughput_analyzer.cc",
+        "net/ntlm/ntlm.cc",
+        "net/ntlm/ntlm_buffer_reader.cc",
+        "net/ntlm/ntlm_buffer_writer.cc",
+        "net/ntlm/ntlm_client.cc",
+        "net/ntlm/ntlm_constants.cc",
+        "net/proxy_resolution/configured_proxy_resolution_request.cc",
+        "net/proxy_resolution/configured_proxy_resolution_service.cc",
+        "net/proxy_resolution/dhcp_pac_file_fetcher.cc",
+        "net/proxy_resolution/multi_threaded_proxy_resolver.cc",
+        "net/proxy_resolution/network_delegate_error_observer.cc",
+        "net/proxy_resolution/pac_file_data.cc",
+        "net/proxy_resolution/pac_file_decider.cc",
+        "net/proxy_resolution/pac_file_fetcher.cc",
+        "net/proxy_resolution/pac_file_fetcher_impl.cc",
+        "net/proxy_resolution/polling_proxy_config_service.cc",
+        "net/proxy_resolution/proxy_bypass_rules.cc",
+        "net/proxy_resolution/proxy_config.cc",
+        "net/proxy_resolution/proxy_config_service.cc",
+        "net/proxy_resolution/proxy_config_service_android.cc",
+        "net/proxy_resolution/proxy_config_service_fixed.cc",
+        "net/proxy_resolution/proxy_config_with_annotation.cc",
+        "net/proxy_resolution/proxy_info.cc",
+        "net/proxy_resolution/proxy_list.cc",
+        "net/proxy_resolution/proxy_resolver_factory.cc",
+        "net/quic/bidirectional_stream_quic_impl.cc",
+        "net/quic/crypto/proof_source_chromium.cc",
+        "net/quic/crypto/proof_verifier_chromium.cc",
+        "net/quic/dedicated_web_transport_http3_client.cc",
+        "net/quic/network_connection.cc",
+        "net/quic/platform/impl/quic_chromium_clock.cc",
+        "net/quic/properties_based_quic_server_info.cc",
+        "net/quic/quic_address_mismatch.cc",
+        "net/quic/quic_chromium_alarm_factory.cc",
+        "net/quic/quic_chromium_client_session.cc",
+        "net/quic/quic_chromium_client_stream.cc",
+        "net/quic/quic_chromium_connection_helper.cc",
+        "net/quic/quic_chromium_packet_reader.cc",
+        "net/quic/quic_chromium_packet_writer.cc",
+        "net/quic/quic_clock_skew_detector.cc",
+        "net/quic/quic_connection_logger.cc",
+        "net/quic/quic_connectivity_monitor.cc",
+        "net/quic/quic_context.cc",
+        "net/quic/quic_crypto_client_config_handle.cc",
+        "net/quic/quic_crypto_client_stream_factory.cc",
+        "net/quic/quic_event_logger.cc",
+        "net/quic/quic_http3_logger.cc",
+        "net/quic/quic_http_stream.cc",
+        "net/quic/quic_http_utils.cc",
+        "net/quic/quic_proxy_client_socket.cc",
+        "net/quic/quic_server_info.cc",
+        "net/quic/quic_session_key.cc",
+        "net/quic/quic_stream_factory.cc",
+        "net/quic/set_quic_flag.cc",
+        "net/quic/web_transport_client.cc",
+        "net/quic/web_transport_error.cc",
+        "net/reporting/reporting_browsing_data_remover.cc",
+        "net/reporting/reporting_cache.cc",
+        "net/reporting/reporting_cache_impl.cc",
+        "net/reporting/reporting_cache_observer.cc",
+        "net/reporting/reporting_context.cc",
+        "net/reporting/reporting_delegate.cc",
+        "net/reporting/reporting_delivery_agent.cc",
+        "net/reporting/reporting_endpoint.cc",
+        "net/reporting/reporting_endpoint_manager.cc",
+        "net/reporting/reporting_garbage_collector.cc",
+        "net/reporting/reporting_header_parser.cc",
+        "net/reporting/reporting_network_change_observer.cc",
+        "net/reporting/reporting_policy.cc",
+        "net/reporting/reporting_report.cc",
+        "net/reporting/reporting_service.cc",
+        "net/reporting/reporting_uploader.cc",
+        "net/socket/client_socket_factory.cc",
+        "net/socket/client_socket_handle.cc",
+        "net/socket/client_socket_pool.cc",
+        "net/socket/client_socket_pool_manager.cc",
+        "net/socket/client_socket_pool_manager_impl.cc",
+        "net/socket/connect_job.cc",
+        "net/socket/connect_job_factory.cc",
+        "net/socket/network_binding_client_socket_factory.cc",
+        "net/socket/next_proto.cc",
+        "net/socket/server_socket.cc",
+        "net/socket/socket.cc",
+        "net/socket/socket_bio_adapter.cc",
+        "net/socket/socket_descriptor.cc",
+        "net/socket/socket_net_log_params.cc",
+        "net/socket/socket_options.cc",
+        "net/socket/socket_posix.cc",
+        "net/socket/socket_tag.cc",
+        "net/socket/socks5_client_socket.cc",
+        "net/socket/socks_client_socket.cc",
+        "net/socket/socks_connect_job.cc",
+        "net/socket/ssl_client_socket.cc",
+        "net/socket/ssl_client_socket_impl.cc",
+        "net/socket/ssl_connect_job.cc",
+        "net/socket/ssl_server_socket_impl.cc",
+        "net/socket/stream_socket.cc",
+        "net/socket/tcp_client_socket.cc",
+        "net/socket/tcp_server_socket.cc",
+        "net/socket/tcp_socket_posix.cc",
+        "net/socket/transport_client_socket.cc",
+        "net/socket/transport_client_socket_pool.cc",
+        "net/socket/transport_connect_job.cc",
+        "net/socket/transport_connect_sub_job.cc",
+        "net/socket/udp_client_socket.cc",
+        "net/socket/udp_net_log_parameters.cc",
+        "net/socket/udp_server_socket.cc",
+        "net/socket/udp_socket_global_limits.cc",
+        "net/socket/udp_socket_posix.cc",
+        "net/socket/unix_domain_client_socket_posix.cc",
+        "net/socket/unix_domain_server_socket_posix.cc",
+        "net/socket/websocket_endpoint_lock_manager.cc",
+        "net/socket/websocket_transport_client_socket_pool.cc",
+        "net/spdy/alps_decoder.cc",
+        "net/spdy/bidirectional_stream_spdy_impl.cc",
+        "net/spdy/buffered_spdy_framer.cc",
+        "net/spdy/header_coalescer.cc",
+        "net/spdy/http2_priority_dependencies.cc",
+        "net/spdy/http2_push_promise_index.cc",
+        "net/spdy/multiplexed_http_stream.cc",
+        "net/spdy/multiplexed_session.cc",
+        "net/spdy/spdy_buffer.cc",
+        "net/spdy/spdy_buffer_producer.cc",
+        "net/spdy/spdy_http_stream.cc",
+        "net/spdy/spdy_http_utils.cc",
+        "net/spdy/spdy_log_util.cc",
+        "net/spdy/spdy_proxy_client_socket.cc",
+        "net/spdy/spdy_read_queue.cc",
+        "net/spdy/spdy_session.cc",
+        "net/spdy/spdy_session_key.cc",
+        "net/spdy/spdy_session_pool.cc",
+        "net/spdy/spdy_stream.cc",
+        "net/spdy/spdy_write_queue.cc",
+        "net/ssl/cert_compression.cc",
+        "net/ssl/client_cert_identity.cc",
+        "net/ssl/openssl_ssl_util.cc",
+        "net/ssl/ssl_cert_request_info.cc",
+        "net/ssl/ssl_cipher_suite_names.cc",
+        "net/ssl/ssl_client_auth_cache.cc",
+        "net/ssl/ssl_client_session_cache.cc",
+        "net/ssl/ssl_config.cc",
+        "net/ssl/ssl_config_service.cc",
+        "net/ssl/ssl_config_service_defaults.cc",
+        "net/ssl/ssl_info.cc",
+        "net/ssl/ssl_key_logger.cc",
+        "net/ssl/ssl_key_logger_impl.cc",
+        "net/ssl/ssl_platform_key_android.cc",
+        "net/ssl/ssl_platform_key_util.cc",
+        "net/ssl/ssl_private_key.cc",
+        "net/ssl/ssl_server_config.cc",
+        "net/ssl/threaded_ssl_private_key.cc",
+        "net/url_request/redirect_info.cc",
+        "net/url_request/redirect_util.cc",
+        "net/url_request/report_sender.cc",
+        "net/url_request/static_http_user_agent_settings.cc",
+        "net/url_request/url_request.cc",
+        "net/url_request/url_request_context.cc",
+        "net/url_request/url_request_context_builder.cc",
+        "net/url_request/url_request_context_getter.cc",
+        "net/url_request/url_request_error_job.cc",
+        "net/url_request/url_request_filter.cc",
+        "net/url_request/url_request_http_job.cc",
+        "net/url_request/url_request_interceptor.cc",
+        "net/url_request/url_request_job.cc",
+        "net/url_request/url_request_job_factory.cc",
+        "net/url_request/url_request_netlog_params.cc",
+        "net/url_request/url_request_redirect_job.cc",
+        "net/url_request/url_request_throttler_entry.cc",
+        "net/url_request/url_request_throttler_manager.cc",
+        "net/url_request/view_cache_helper.cc",
+        "net/url_request/websocket_handshake_userdata_key.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_branding_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains__testing",
+        "cronet_aml_net_buildflags__testing",
+        "cronet_aml_net_ios_cronet_buildflags__testing",
+        "cronet_aml_net_isolation_info_proto__testing_gen_headers",
+        "cronet_aml_net_net_jni_headers__testing",
+        "cronet_aml_net_net_nqe_proto__testing_gen_headers",
+        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_branding_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains__testing",
+        "cronet_aml_net_buildflags__testing",
+        "cronet_aml_net_ios_cronet_buildflags__testing",
+        "cronet_aml_net_isolation_info_proto__testing_gen_headers",
+        "cronet_aml_net_net_jni_headers__testing",
+        "cronet_aml_net_net_nqe_proto__testing_gen_headers",
+        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen_headers",
+        "cronet_aml_url_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-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",
+        "-DNDEBUG",
+        "-DNET_IMPLEMENTATION",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            srcs: [
+                "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
+            ],
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            srcs: [
+                "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
+            ],
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            srcs: [
+                "net/disk_cache/blockfile/mapped_file_posix.cc",
+            ],
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            srcs: [
+                "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
+            ],
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -6550,6 +13719,7 @@
         "libandroid",
         "liblog",
         "libprotobuf-cpp-lite",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -6566,7 +13736,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,25 +13752,34 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-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",
+        "-DNDEBUG",
         "-DNET_IMPLEMENTATION",
-        "-D_DEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -6612,10 +13790,21 @@
         "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: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -6623,43 +13812,109 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //net:net_export_header
+// GN: //net:net_deps__testing
 cc_object {
-    name: "cronet_aml_net_net_export_header",
+    name: "cronet_aml_net_net_deps__testing",
+    srcs: [
+        ":cronet_aml_net_isolation_info_proto__testing_gen",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libprotobuf-cpp-lite",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains__testing",
+        "cronet_aml_net_isolation_info_proto__testing_gen_headers",
+        "cronet_aml_net_net_jni_headers__testing",
+        "cronet_aml_url_buildflags__testing",
+    ],
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-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",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNET_IMPLEMENTATION",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     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/",
+        "third_party/brotli/include/",
+        "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -6667,6 +13922,7 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -6749,6 +14005,112 @@
          "--input_file " +
          "$(location net/android/java/src/org/chromium/net/ProxyChangeListener.java) " +
          "--input_file " +
+         "$(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",
+        "net/net_jni_headers/AndroidNetworkLibrary_jni.h",
+        "net/net_jni_headers/AndroidTrafficStats_jni.h",
+        "net/net_jni_headers/DnsStatus_jni.h",
+        "net/net_jni_headers/GURLUtils_jni.h",
+        "net/net_jni_headers/HttpNegotiateAuthenticator_jni.h",
+        "net/net_jni_headers/HttpUtil_jni.h",
+        "net/net_jni_headers/NetStringUtil_jni.h",
+        "net/net_jni_headers/NetworkActiveNotifier_jni.h",
+        "net/net_jni_headers/NetworkChangeNotifier_jni.h",
+        "net/net_jni_headers/ProxyChangeListener_jni.h",
+        "net/net_jni_headers/X509Util_jni.h",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //net:net_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_net_net_jni_headers__testing",
+    srcs: [
+        "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
+        "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
+        "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
+        "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
+        "net/android/java/src/org/chromium/net/DnsStatus.java",
+        "net/android/java/src/org/chromium/net/GURLUtils.java",
+        "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
+        "net/android/java/src/org/chromium/net/HttpUtil.java",
+        "net/android/java/src/org/chromium/net/NetStringUtil.java",
+        "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
+        "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
+        "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
+        "net/android/java/src/org/chromium/net/X509Util.java",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/net/net_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "AndroidCertVerifyResult_jni.h " +
+         "--output_name " +
+         "AndroidKeyStore_jni.h " +
+         "--output_name " +
+         "AndroidNetworkLibrary_jni.h " +
+         "--output_name " +
+         "AndroidTrafficStats_jni.h " +
+         "--output_name " +
+         "DnsStatus_jni.h " +
+         "--output_name " +
+         "GURLUtils_jni.h " +
+         "--output_name " +
+         "HttpNegotiateAuthenticator_jni.h " +
+         "--output_name " +
+         "HttpUtil_jni.h " +
+         "--output_name " +
+         "NetStringUtil_jni.h " +
+         "--output_name " +
+         "NetworkActiveNotifier_jni.h " +
+         "--output_name " +
+         "NetworkChangeNotifier_jni.h " +
+         "--output_name " +
+         "ProxyChangeListener_jni.h " +
+         "--output_name " +
+         "X509Util_jni.h " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/AndroidKeyStore.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/AndroidTrafficStats.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/DnsStatus.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/GURLUtils.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/HttpUtil.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/NetStringUtil.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/NetworkActiveNotifier.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/NetworkChangeNotifier.java) " +
+         "--input_file " +
+         "$(location net/android/java/src/org/chromium/net/ProxyChangeListener.java) " +
+         "--input_file " +
          "$(location net/android/java/src/org/chromium/net/X509Util.java)",
     out: [
         "net/net_jni_headers/AndroidCertVerifyResult_jni.h",
@@ -6777,6 +14139,47 @@
     ],
 }
 
+// GN: //net:net_nqe_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_net_nqe_proto__testing_gen",
+    srcs: [
+        "net/nqe/proto/network_id_proto.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/cronet/net/nqe/proto/network_id_proto.pb.cc",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //net:net_nqe_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_net_nqe_proto__testing_gen_headers",
+    srcs: [
+        "net/nqe/proto/network_id_proto.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/cronet/net/nqe/proto/network_id_proto.pb.h",
+    ],
+    export_include_dirs: [
+        ".",
+        "net/nqe/proto",
+        "protos",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //net:net_nqe_proto
 cc_genrule {
     name: "cronet_aml_net_net_nqe_proto_gen",
@@ -6786,9 +14189,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 +14207,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 +14232,7 @@
         "libandroid",
         "liblog",
         "libprotobuf-cpp-lite",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -6845,7 +14249,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,23 +14263,32 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -6890,8 +14302,20 @@
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -6899,6 +14323,116 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net:net_public_deps__testing
+cc_object {
+    name: "cronet_aml_net_net_public_deps__testing",
+    srcs: [
+        ":cronet_aml_net_net_nqe_proto__testing_gen",
+        ":cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libprotobuf-cpp-lite",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_buildflags__testing",
+        "cronet_aml_net_net_nqe_proto__testing_gen_headers",
+        "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen_headers",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -6933,19 +14467,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -6955,8 +14498,41 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -6964,12 +14540,679 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //net:preload_decoder__testing
+cc_library_static {
+    name: "cronet_aml_net_preload_decoder__testing",
+    srcs: [
+        "net/extras/preload_data/decoder.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net:quic_test_flags_utils__testing
+cc_object {
+    name: "cronet_aml_net_quic_test_flags_utils__testing",
+    srcs: [
+        "net/quic/platform/impl/quic_test_flags_utils.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net:simple_quic_tools__testing
+cc_object {
+    name: "cronet_aml_net_simple_quic_tools__testing",
+    srcs: [
+        "net/tools/quic/quic_client_message_loop_network_helper.cc",
+        "net/tools/quic/quic_simple_client.cc",
+        "net/tools/quic/quic_simple_server.cc",
+        "net/tools/quic/quic_simple_server_packet_writer.cc",
+        "net/tools/quic/quic_simple_server_session_helper.cc",
+        "net/tools/quic/quic_simple_server_socket.cc",
+        "net/tools/quic/synchronous_host_resolver.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_third_party_quiche_quiche_tool_support__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net:test_support__testing
+cc_library_static {
+    name: "cronet_aml_net_test_support__testing",
+    srcs: [
+        ":cronet_aml_net_dns_test_support__testing",
+        ":cronet_aml_net_quic_test_flags_utils__testing",
+        ":cronet_aml_net_simple_quic_tools__testing",
+        ":cronet_aml_net_tools_tld_cleanup_tld_cleanup__testing",
+        ":cronet_aml_net_traffic_annotation_traffic_annotation__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+        ":cronet_aml_third_party_googletest_gmock__testing",
+        ":cronet_aml_third_party_googletest_gtest__testing",
+        "net/base/connection_endpoint_metadata_test_util.cc",
+        "net/base/load_timing_info_test_util.cc",
+        "net/base/mock_file_stream.cc",
+        "net/base/mock_network_change_notifier.cc",
+        "net/base/test_completion_callback.cc",
+        "net/base/test_data_stream.cc",
+        "net/cert/mock_cert_net_fetcher.cc",
+        "net/cert/mock_cert_verifier.cc",
+        "net/cert/mock_client_cert_verifier.cc",
+        "net/cookies/cookie_change_dispatcher_test_helpers.cc",
+        "net/cookies/cookie_monster_store_test.cc",
+        "net/cookies/cookie_store_test_callbacks.cc",
+        "net/cookies/cookie_store_test_helpers.cc",
+        "net/cookies/test_cookie_access_delegate.cc",
+        "net/disk_cache/disk_cache_test_base.cc",
+        "net/disk_cache/disk_cache_test_util.cc",
+        "net/disk_cache/mock/mock_backend_impl.cc",
+        "net/disk_cache/mock/mock_entry_impl.cc",
+        "net/filter/filter_source_stream_test_util.cc",
+        "net/filter/mock_source_stream.cc",
+        "net/http/http_stream_factory_test_util.cc",
+        "net/http/http_transaction_test_util.cc",
+        "net/http/mock_http_cache.cc",
+        "net/http/transport_security_state_test_util.cc",
+        "net/log/test_net_log.cc",
+        "net/log/test_net_log_util.cc",
+        "net/network_error_logging/mock_persistent_nel_store.cc",
+        "net/network_error_logging/network_error_logging_test_util.cc",
+        "net/nqe/network_quality_estimator_test_util.cc",
+        "net/proxy_resolution/mock_pac_file_fetcher.cc",
+        "net/proxy_resolution/mock_proxy_resolver.cc",
+        "net/proxy_resolution/proxy_config_service_common_unittest.cc",
+        "net/quic/quic_test_packet_printer.cc",
+        "net/reporting/mock_persistent_reporting_store.cc",
+        "net/reporting/reporting_test_util.cc",
+        "net/socket/read_buffering_stream_socket.cc",
+        "net/socket/socket_test_util.cc",
+        "net/socket/transport_client_socket_test_util.cc",
+        "net/spdy/spdy_test_util_common.cc",
+        "net/ssl/client_cert_identity_test_util.cc",
+        "net/ssl/ssl_private_key_test_util.cc",
+        "net/ssl/test_ssl_config_service.cc",
+        "net/ssl/test_ssl_private_key.cc",
+        "net/test/cert_builder.cc",
+        "net/test/cert_test_util.cc",
+        "net/test/ct_test_util.cc",
+        "net/test/embedded_test_server/connection_tracker.cc",
+        "net/test/embedded_test_server/controllable_http_response.cc",
+        "net/test/embedded_test_server/default_handlers.cc",
+        "net/test/embedded_test_server/embedded_test_server.cc",
+        "net/test/embedded_test_server/embedded_test_server_connection_listener.cc",
+        "net/test/embedded_test_server/http1_connection.cc",
+        "net/test/embedded_test_server/http2_connection.cc",
+        "net/test/embedded_test_server/http_connection.cc",
+        "net/test/embedded_test_server/http_request.cc",
+        "net/test/embedded_test_server/http_response.cc",
+        "net/test/embedded_test_server/request_handler_util.cc",
+        "net/test/embedded_test_server/simple_connection_listener.cc",
+        "net/test/key_util.cc",
+        "net/test/net_test_suite.cc",
+        "net/test/quic_simple_test_server.cc",
+        "net/test/revocation_builder.cc",
+        "net/test/spawned_test_server/base_test_server.cc",
+        "net/test/spawned_test_server/remote_test_server.cc",
+        "net/test/spawned_test_server/remote_test_server_spawner_request.cc",
+        "net/test/ssl_test_util.cc",
+        "net/test/test_connection_cost_observer.cc",
+        "net/test/test_data_directory.cc",
+        "net/test/test_doh_server.cc",
+        "net/test/url_request/ssl_certificate_error_job.cc",
+        "net/test/url_request/url_request_failed_job.cc",
+        "net/test/url_request/url_request_hanging_read_job.cc",
+        "net/test/url_request/url_request_mock_data_job.cc",
+        "net/url_request/url_request_test_job.cc",
+        "net/url_request/url_request_test_util.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_test_test_support__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_gtest_util__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_third_party_quiche_quiche_tool_support__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_http_transport_security_state_unittest_data_default__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_http_transport_security_state_unittest_data_default__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DUSE_REMOTE_TEST_SERVER",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/ced/src/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/protobuf/src/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/third_party/quiche:net_quic_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_third_party_quiche_net_quic_proto__testing_gen",
+    srcs: [
+        "net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.proto",
+        "net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.proto",
+        "net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/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",
+    ],
+}
+
+// GN: //net/third_party/quiche:net_quic_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_third_party_quiche_net_quic_proto__testing_gen_headers",
+    srcs: [
+        "net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.proto",
+        "net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.proto",
+        "net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/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: [
+        ".",
+        "net/third_party/quiche/src",
+        "protos",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //net/third_party/quiche:net_quic_proto
 cc_genrule {
     name: "cronet_aml_net_third_party_quiche_net_quic_proto_gen",
@@ -6981,11 +15224,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 +15246,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: [
         ".",
@@ -7019,6 +15262,47 @@
     ],
 }
 
+// GN: //net/third_party/quiche:net_quic_test_tools_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen",
+    srcs: [
+        "net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/cronet/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.cc",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //net/third_party/quiche:net_quic_test_tools_proto__testing
+cc_genrule {
+    name: "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto__testing_gen_headers",
+    srcs: [
+        "net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/cronet/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.h",
+    ],
+    export_include_dirs: [
+        ".",
+        "net/third_party/quiche/src/quiche/quic/test_tools",
+        "protos",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //net/third_party/quiche:net_quic_test_tools_proto
 cc_genrule {
     name: "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen",
@@ -7028,9 +15312,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 +15330,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 +15622,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 +15681,7 @@
         "libandroid",
         "liblog",
         "libprotobuf-cpp-lite",
+        "libz",
     ],
     static_libs: [
         "cronet_aml_base_allocator_partition_allocator_partition_alloc",
@@ -7410,7 +15696,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,24 +15712,33 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
         "-DIS_QUICHE_IMPL",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7457,10 +15751,42 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7468,12 +15794,925 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //net/third_party/quiche:quiche__testing
+cc_library_static {
+    name: "cronet_aml_net_third_party_quiche_quiche__testing",
+    srcs: [
+        ":cronet_aml_net_third_party_quiche_net_quic_proto__testing_gen",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+        "net/third_party/quiche/overrides/quiche_platform_impl/quiche_mutex_impl.cc",
+        "net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.cc",
+        "net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.cc",
+        "net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc",
+        "net/third_party/quiche/src/quiche/common/platform/api/quiche_mutex.cc",
+        "net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_buffer_allocator.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_crypto_logging.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_data_reader.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_data_writer.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_ip_address.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_ip_address_family.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_mem_slice_storage.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_random.cc",
+        "net/third_party/quiche/src/quiche/common/quiche_text_utils.cc",
+        "net/third_party/quiche/src/quiche/common/simple_buffer_allocator.cc",
+        "net/third_party/quiche/src/quiche/common/structured_headers.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/event_forwarder.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/header_validator.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/http2_protocol.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/http2_util.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/noop_header_validator.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.cc",
+        "net/third_party/quiche/src/quiche/http2/adapter/window_manager.cc",
+        "net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/decode_buffer.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/decode_http2_structures.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/decode_status.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/frame_decoder_state.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/http2_frame_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/http2_frame_decoder_listener.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/http2_structure_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/altsvc_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/continuation_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/data_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/goaway_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/headers_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/ping_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/priority_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/priority_update_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/push_promise_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/settings_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/unknown_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/window_update_payload_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_block_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_listener.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_state.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_string_buffer.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_tables.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoding_error.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_entry_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_entry_decoder_listener.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_entry_type_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_string_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_string_decoder_listener.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_whole_entry_buffer.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_whole_entry_listener.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/http2_hpack_constants.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/huffman/huffman_spec_tables.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/varint/hpack_varint_decoder.cc",
+        "net/third_party/quiche/src/quiche/http2/hpack/varint/hpack_varint_encoder.cc",
+        "net/third_party/quiche/src/quiche/http2/http2_constants.cc",
+        "net/third_party/quiche/src/quiche/http2/http2_structures.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bandwidth_sampler.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_drain.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_misc.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_probe_bw.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_probe_rtt.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_startup.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/cubic_bytes.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/general_loss_algorithm.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/hybrid_slow_start.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/pacing_sender.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/prr_sender.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.cc",
+        "net/third_party/quiche/src/quiche/quic/core/congestion_control/uber_loss_algorithm.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aead_base_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aead_base_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_12_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_12_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_256_gcm_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_256_gcm_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_base_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/aes_base_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/cert_compressor.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/certificate_util.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_tls_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_tls_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/chacha_base_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/chacha_base_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/channel_id.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/client_proof_source.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_framer.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_handshake.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_handshake_message.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_secret_boxer.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/curve25519_key_exchange.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/key_exchange.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/null_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/null_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/p256_key_exchange.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_client_session_cache.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_compressed_certs_cache.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_client_config.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_proof.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/quic_hkdf.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/tls_client_connection.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.cc",
+        "net/third_party/quiche/src/quiche/quic/core/crypto/web_transport_fingerprint_proof_verifier.cc",
+        "net/third_party/quiche/src/quiche/quic/core/deterministic_connection_id_generator.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frequency_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_connection_close_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_crypto_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_goaway_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_handshake_done_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_max_streams_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_message_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_new_connection_id_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_new_token_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_padding_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_path_challenge_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_path_response_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_ping_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_retire_connection_id_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_rst_stream_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_stop_sending_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_stop_waiting_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_stream_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_streams_blocked_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/frames/quic_window_update_frame.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/capsule.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/http_constants.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/http_decoder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/http_encoder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_client_promised_info.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_client_push_promise_index.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_header_list.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream_body_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/spdy_server_push_utils.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc",
+        "net/third_party/quiche/src/quiche/quic/core/legacy_quic_stream_id_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_blocking_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoded_headers_accumulator.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_receiver.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_receiver.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_index_conversions.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_decoder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instructions.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_progressive_decoder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_receive_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_required_insert_count.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_send_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_static_table.cc",
+        "net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_ack_listener_interface.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_alarm.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_bandwidth.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_chaos_protector.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_clock.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_coalesced_packet.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_config.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_connection.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_connection_context.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_connection_id.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_constants.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_crypto_handshaker.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream_base.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_data_reader.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_data_writer.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_datagram_queue.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_error_codes.cc",
+        "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",
+        "net/third_party/quiche/src/quiche/quic/core/quic_packet_number.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_packets.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_path_validator.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_server_id.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_session.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_socket_address_coder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_stream_id_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_stream_send_buffer.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_buffer.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_sustained_bandwidth_recorder.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_tag.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_time.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_transmission_info.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_types.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_utils.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_version_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_versions.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.cc",
+        "net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.cc",
+        "net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc",
+        "net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc",
+        "net/third_party/quiche/src/quiche/quic/core/uber_quic_stream_id_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/uber_received_packet_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/http2_header_storage.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_pinnable_buffer_piece.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_prefixed_buffer_reader.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.cc",
+        "net/third_party/quiche/src/quiche/spdy/core/spdy_simple_arena.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libprotobuf-cpp-lite",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_third_party_quiche_net_quic_proto__testing_gen_headers",
+    ],
+    export_generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_net_third_party_quiche_net_quic_proto__testing_gen_headers",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DIS_QUICHE_IMPL",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/third_party/quiche:quiche_tool_support__testing
+cc_library_static {
+    name: "cronet_aml_net_third_party_quiche_quiche_tool_support__testing",
+    srcs: [
+        "net/third_party/quiche/overrides/quiche_platform_impl/quiche_command_line_flags_impl.cc",
+        "net/third_party/quiche/overrides/quiche_platform_impl/quiche_default_proof_providers_impl.cc",
+        "net/third_party/quiche/src/quiche/common/platform/api/quiche_file_utils.cc",
+        "net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc",
+        "net/third_party/quiche/src/quiche/quic/core/chlo_extractor.cc",
+        "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_server_stream_base.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_packet_writer_wrapper.cc",
+        "net/third_party/quiche/src/quiche/quic/core/quic_time_wait_list_manager.cc",
+        "net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_backend_response.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_client_base.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_simple_crypto_server_stream_helper.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_simple_dispatcher.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_tcp_like_trace_converter.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/quic_url.cc",
+        "net/third_party/quiche/src/quiche/quic/tools/simple_ticket_crypter.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_net_net__testing",
+        "cronet_aml_net_preload_decoder__testing",
+        "cronet_aml_net_third_party_quiche_quiche__testing",
+        "cronet_aml_net_uri_template__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_brotli_common__testing",
+        "cronet_aml_third_party_brotli_dec__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/tools/huffman_trie:huffman_trie_generator_sources__testing
+cc_object {
+    name: "cronet_aml_net_tools_huffman_trie_huffman_trie_generator_sources__testing",
+    srcs: [
+        "net/tools/huffman_trie/bit_writer.cc",
+        "net/tools/huffman_trie/huffman/huffman_builder.cc",
+        "net/tools/huffman_trie/trie/trie_bit_buffer.cc",
+        "net/tools/huffman_trie/trie/trie_writer.cc",
+        "net/tools/huffman_trie/trie_entry.cc",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    host_supported: true,
+    device_supported: false,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DCR_SYSROOT_KEY=20220331T153654Z-0",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_AURA=1",
+        "-DUSE_OZONE=1",
+        "-DUSE_UDEV",
+        "-D_FILE_OFFSET_BITS=64",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LARGEFILE64_SOURCE",
+        "-D_LARGEFILE_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fstack-protector",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+        "-msse3",
+    ],
+    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",
+}
+
+// GN: //net/tools/tld_cleanup:tld_cleanup__testing
+cc_object {
+    name: "cronet_aml_net_tools_tld_cleanup_tld_cleanup__testing",
+    srcs: [
+        "net/tools/tld_cleanup/tld_cleanup_util.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+        "cronet_aml_url_url__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/tools/transport_security_state_generator:transport_security_state_generator__testing
+cc_binary {
+    name: "cronet_aml_net_tools_transport_security_state_generator_transport_security_state_generator__testing",
+    srcs: [
+        ":cronet_aml_buildtools_third_party_libc___libc____testing",
+        ":cronet_aml_buildtools_third_party_libc__abi_libc__abi__testing",
+        ":cronet_aml_net_tools_huffman_trie_huffman_trie_generator_sources__testing",
+        ":cronet_aml_net_tools_transport_security_state_generator_transport_security_state_generator_sources__testing",
+        "net/tools/transport_security_state_generator/transport_security_state_generator.cc",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_crypto_crypto__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    host_supported: true,
+    device_supported: false,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DCR_SYSROOT_KEY=20220331T153654Z-0",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_AURA=1",
+        "-DUSE_OZONE=1",
+        "-DUSE_UDEV",
+        "-D_FILE_OFFSET_BITS=64",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LARGEFILE64_SOURCE",
+        "-D_LARGEFILE_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fstack-protector",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+        "-msse3",
+    ],
+    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",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+}
+
+// GN: //net/tools/transport_security_state_generator:transport_security_state_generator_sources__testing
+cc_object {
+    name: "cronet_aml_net_tools_transport_security_state_generator_transport_security_state_generator_sources__testing",
+    srcs: [
+        "net/tools/transport_security_state_generator/cert_util.cc",
+        "net/tools/transport_security_state_generator/input_file_parsers.cc",
+        "net/tools/transport_security_state_generator/pinset.cc",
+        "net/tools/transport_security_state_generator/pinsets.cc",
+        "net/tools/transport_security_state_generator/preloaded_state_generator.cc",
+        "net/tools/transport_security_state_generator/spki_hash.cc",
+        "net/tools/transport_security_state_generator/transport_security_state_entry.cc",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    host_supported: true,
+    device_supported: false,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DCR_SYSROOT_KEY=20220331T153654Z-0",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_AURA=1",
+        "-DUSE_OZONE=1",
+        "-DUSE_UDEV",
+        "-D_FILE_OFFSET_BITS=64",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LARGEFILE64_SOURCE",
+        "-D_LARGEFILE_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fstack-protector",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+        "-msse3",
+    ],
+    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",
+}
+
 // GN: //net/traffic_annotation:traffic_annotation
 cc_object {
     name: "cronet_aml_net_traffic_annotation_traffic_annotation",
@@ -7505,19 +16744,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7527,8 +16775,20 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7536,6 +16796,97 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //net/traffic_annotation:traffic_annotation__testing
+cc_object {
+    name: "cronet_aml_net_traffic_annotation_traffic_annotation__testing",
+    srcs: [
+        "net/traffic_annotation/network_traffic_annotation_android.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -7570,20 +16921,29 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
         "-DIS_URI_TEMPLATE_IMPL",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7593,8 +16953,41 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7602,17 +16995,34 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp:absl
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl",
-    generated_headers: [
-        "cronet_aml_build_chromeos_buildflags",
+// GN: //net:uri_template__testing
+cc_library_static {
+    name: "cronet_aml_net_uri_template__testing",
+    srcs: [
+        "net/third_party/uri_template/uri_template.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
     ],
     defaults: [
         "cronet_aml_defaults",
@@ -7620,19 +17030,29 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DIS_URI_TEMPLATE_IMPL",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7640,9 +17060,43 @@
         "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",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7650,33 +17104,116 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/algorithm:algorithm
+// GN: //testing/android/native_test:native_test_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_testing_android_native_test_native_test_jni_headers__testing",
+    srcs: [
+        "testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java",
+        "testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/testing/android/native_test/native_test_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "MainRunner_jni.h " +
+         "--output_name " +
+         "NativeTest_jni.h " +
+         "--input_file " +
+         "$(location testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java) " +
+         "--input_file " +
+         "$(location testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java)",
+    out: [
+        "testing/android/native_test/native_test_jni_headers/MainRunner_jni.h",
+        "testing/android/native_test/native_test_jni_headers/NativeTest_jni.h",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //testing/android/native_test:native_test_native_code__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_algorithm_algorithm",
+    name: "cronet_aml_testing_android_native_test_native_test_native_code__testing",
+    srcs: [
+        "testing/android/native_test/native_test_jni_onload.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_test_test_support__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_testing_android_native_test_native_test_jni_headers__testing",
+    ],
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7684,9 +17221,22 @@
         "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",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7694,33 +17244,93 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/algorithm:container
+// GN: //testing/android/native_test:native_test_support__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_algorithm_container",
+    name: "cronet_aml_testing_android_native_test_native_test_support__testing",
+    srcs: [
+        "testing/android/native_test/main_runner.cc",
+        "testing/android/native_test/native_test_launcher.cc",
+        "testing/android/native_test/native_test_util.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_i18n__testing",
+        "cronet_aml_base_test_test_config__testing",
+        "cronet_aml_base_test_test_support__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_testing_gtest_gtest__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_ced_ced__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+        "cronet_aml_third_party_libxml_xml_reader__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_testing_android_native_test_native_test_jni_headers__testing",
+    ],
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7728,9 +17338,28 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
+        "third_party/boringssl/src/include/",
+        "third_party/ced/src/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7738,33 +17367,124 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/base:atomic_hook
-cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_atomic_hook",
+// GN: //testing/gtest:gtest__testing
+cc_library_static {
+    name: "cronet_aml_testing_gtest_gtest__testing",
+    srcs: [
+        ":cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+        ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+        ":cronet_aml_third_party_googletest_gtest__testing",
+        "testing/gtest/empty.cc",
+        "testing/multiprocess_func_list.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUNIT_TEST",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7772,9 +17492,44 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googletest/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7782,6 +17537,7 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -7805,17 +17561,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7824,8 +17588,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -7833,33 +17609,46 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/base:base_internal
+// GN: //third_party/abseil-cpp/absl/base:base__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_base_internal",
+    name: "cronet_aml_third_party_abseil_cpp_absl_base_base__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/base/internal/cycleclock.cc",
+        "third_party/abseil-cpp/absl/base/internal/spinlock.cc",
+        "third_party/abseil-cpp/absl/base/internal/sysinfo.cc",
+        "third_party/abseil-cpp/absl/base/internal/thread_identity.cc",
+        "third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -7868,325 +17657,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -8204,17 +17728,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8223,8 +17755,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -8232,12 +17776,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/base:log_severity__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_base_log_severity__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/base/log_severity.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/base:malloc_internal
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal",
@@ -8251,17 +17891,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8270,8 +17918,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -8279,33 +17939,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/base:prefetch
+// GN: //third_party/abseil-cpp/absl/base:malloc_internal__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_base_prefetch",
+    name: "cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8314,18 +17983,61 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -8342,17 +18054,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8361,8 +18081,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -8370,12 +18102,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/base:raw_logging_internal__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/base/internal/raw_logging.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/base:spinlock_wait
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait",
@@ -8389,17 +18217,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8408,8 +18244,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -8417,12 +18265,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/base:spinlock_wait__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/base:strerror
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_base_strerror",
@@ -8436,17 +18380,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8455,8 +18407,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -8464,12 +18428,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/base:strerror__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_base_strerror__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/base/internal/strerror.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/base:throw_delegate
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate",
@@ -8483,17 +18543,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8502,8 +18570,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -8511,33 +18591,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/cleanup:cleanup
+// GN: //third_party/abseil-cpp/absl/base:throw_delegate__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_cleanup_cleanup",
+    name: "cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/base/internal/throw_delegate.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -8546,545 +18635,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -9103,17 +18707,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9122,8 +18734,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9131,33 +18755,43 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/container:inlined_vector
+// GN: //third_party/abseil-cpp/absl/container:hashtablez_sampler__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_container_inlined_vector",
+    name: "cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc",
+        "third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9166,281 +18800,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -9458,17 +18871,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9477,8 +18898,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9486,12 +18919,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/container:raw_hash_set__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/debugging:debugging_internal
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal",
@@ -9507,17 +19036,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9526,8 +19063,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9535,12 +19084,110 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/debugging:debugging_internal__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc",
+        "third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc",
+        "third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/debugging:demangle_internal
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal",
@@ -9554,17 +19201,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9573,8 +19228,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9582,12 +19249,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/debugging:demangle_internal__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/debugging/internal/demangle.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/debugging:examine_stack
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack",
@@ -9601,17 +19364,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9620,8 +19391,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9629,12 +19412,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/debugging:examine_stack__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/debugging:failure_signal_handler
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler",
@@ -9648,17 +19527,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9667,8 +19554,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9676,12 +19575,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/debugging:failure_signal_handler__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/debugging:stacktrace
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace",
@@ -9695,17 +19690,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9714,8 +19717,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9723,12 +19738,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/debugging:stacktrace__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/debugging/stacktrace.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/debugging:symbolize
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize",
@@ -9742,17 +19853,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9761,8 +19880,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9770,33 +19901,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/functional:any_invocable
+// GN: //third_party/abseil-cpp/absl/debugging:symbolize__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_functional_any_invocable",
+    name: "cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/debugging/symbolize.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9805,105 +19945,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -9921,17 +20016,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9940,8 +20043,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9949,12 +20064,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/hash:city__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_hash_city__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/hash/internal/city.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/hash:hash
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_hash_hash",
@@ -9968,17 +20179,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -9987,8 +20206,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -9996,12 +20227,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/hash:hash__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_hash_hash__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/hash/internal/hash.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/hash:low_level_hash
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash",
@@ -10015,17 +20342,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10034,8 +20369,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10043,33 +20390,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/memory:memory
+// GN: //third_party/abseil-cpp/absl/hash:low_level_hash__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_memory_memory",
+    name: "cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10078,105 +20434,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -10194,17 +20505,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10213,8 +20532,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10222,33 +20553,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/numeric:representation
+// GN: //third_party/abseil-cpp/absl/numeric:int128__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_numeric_representation",
+    name: "cronet_aml_third_party_abseil_cpp_absl_numeric_int128__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/numeric/int128.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10257,18 +20597,61 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -10285,17 +20668,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10304,8 +20695,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10313,33 +20716,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/profiling:sample_recorder
+// GN: //third_party/abseil-cpp/absl/profiling:exponential_biased__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_profiling_sample_recorder",
+    name: "cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/profiling/internal/exponential_biased.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10348,18 +20760,61 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -10377,17 +20832,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10396,8 +20859,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10405,33 +20880,43 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/random/internal:distribution_caller
+// GN: //third_party/abseil-cpp/absl/random:distributions__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_distribution_caller",
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_distributions__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/discrete_distribution.cc",
+        "third_party/abseil-cpp/absl/random/gaussian_distribution.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10440,284 +20925,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -10738,17 +20999,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10757,8 +21026,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10766,12 +21047,111 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/random/internal:platform__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_platform__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/internal/randen_round_keys.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/random/internal:pool_urbg
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg",
@@ -10788,17 +21168,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10807,8 +21195,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10816,12 +21216,111 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/random/internal:pool_urbg__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/internal/pool_urbg.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/random/internal:randen
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen",
@@ -10838,17 +21337,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10857,8 +21364,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10866,36 +21385,45 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/random/internal:randen_engine
+// GN: //third_party/abseil-cpp/absl/random/internal:randen__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_engine",
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/internal/randen.cc",
+    ],
+    host_supported: true,
     generated_headers: [
-        "cronet_aml_build_chromeos_buildflags",
+        "cronet_aml_build_chromeos_buildflags__testing",
     ],
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10904,18 +21432,61 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -10935,17 +21506,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -10954,8 +21533,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -10963,12 +21554,111 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/random/internal:randen_hwaes__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/internal/randen_detect.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/random/internal:randen_hwaes_impl
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl",
@@ -10985,17 +21675,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11004,8 +21702,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11013,12 +21723,111 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/random/internal:randen_hwaes_impl__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/random/internal:randen_slow
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow",
@@ -11035,17 +21844,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11054,8 +21871,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11063,33 +21892,45 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/random/internal:salted_seed_seq
+// GN: //third_party/abseil-cpp/absl/random/internal:randen_slow__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_salted_seed_seq",
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/internal/randen_slow.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11098,18 +21939,61 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -11126,17 +22010,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11145,8 +22037,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11154,33 +22058,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/random/internal:traits
+// GN: //third_party/abseil-cpp/absl/random/internal:seed_material__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_traits",
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/internal/seed_material.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11189,152 +22102,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -11352,17 +22173,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11371,8 +22200,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11380,12 +22221,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/random:seed_gen_exception__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/seed_gen_exception.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/random:seed_sequences
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences",
@@ -11402,17 +22339,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11421,8 +22366,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11430,12 +22387,111 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/random:seed_sequences__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/random/seed_sequences.cc",
+    ],
+    host_supported: true,
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/status:status
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_status_status",
@@ -11450,17 +22506,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11469,8 +22533,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11478,12 +22554,109 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/status:status__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_status_status__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/status/status.cc",
+        "third_party/abseil-cpp/absl/status/status_payload_printer.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/status:statusor
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_status_statusor",
@@ -11497,17 +22670,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11516,8 +22697,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11525,12 +22718,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/status:statusor__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_status_statusor__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/status/statusor.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/strings:cord
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_strings_cord",
@@ -11546,17 +22835,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11565,8 +22862,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11574,12 +22883,110 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/strings:cord__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cord__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/cord.cc",
+        "third_party/abseil-cpp/absl/strings/cord_analysis.cc",
+        "third_party/abseil-cpp/absl/strings/cord_buffer.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/strings:cord_internal
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal",
@@ -11599,17 +23006,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11618,8 +23033,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11627,12 +23054,114 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/strings:cord_internal__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/internal/cord_internal.cc",
+        "third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.cc",
+        "third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc",
+        "third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc",
+        "third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.cc",
+        "third_party/abseil-cpp/absl/strings/internal/cord_rep_crc.cc",
+        "third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/strings:cordz_functions
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions",
@@ -11646,17 +23175,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11665,8 +23202,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11674,12 +23223,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/strings:cordz_functions__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/strings:cordz_handle
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle",
@@ -11693,17 +23338,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11712,8 +23365,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11721,12 +23386,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/strings:cordz_handle__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/internal/cordz_handle.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/strings:cordz_info
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info",
@@ -11740,17 +23501,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11759,8 +23528,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11768,33 +23549,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/strings:cordz_statistics
+// GN: //third_party/abseil-cpp/absl/strings:cordz_info__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_statistics",
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/internal/cordz_info.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11803,105 +23593,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -11921,17 +23666,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11940,8 +23693,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -11949,33 +23714,44 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/strings:str_format
+// GN: //third_party/abseil-cpp/absl/strings:internal__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_strings_str_format",
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/internal/escaping.cc",
+        "third_party/abseil-cpp/absl/strings/internal/ostringstream.cc",
+        "third_party/abseil-cpp/absl/strings/internal/utf8.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -11984,18 +23760,61 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -12017,17 +23836,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12036,8 +23863,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12045,12 +23884,113 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/strings:str_format_internal__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc",
+        "third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc",
+        "third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc",
+        "third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc",
+        "third_party/abseil-cpp/absl/strings/internal/str_format/output.cc",
+        "third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/strings:strings
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_strings_strings",
@@ -12060,7 +24000,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,17 +24016,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12096,8 +24043,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12105,12 +24064,120 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/strings:strings__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_strings_strings__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/strings/ascii.cc",
+        "third_party/abseil-cpp/absl/strings/charconv.cc",
+        "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/memutil.cc",
+        "third_party/abseil-cpp/absl/strings/match.cc",
+        "third_party/abseil-cpp/absl/strings/numbers.cc",
+        "third_party/abseil-cpp/absl/strings/str_cat.cc",
+        "third_party/abseil-cpp/absl/strings/str_replace.cc",
+        "third_party/abseil-cpp/absl/strings/str_split.cc",
+        "third_party/abseil-cpp/absl/strings/string_view.cc",
+        "third_party/abseil-cpp/absl/strings/substitute.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/synchronization:graphcycles_internal
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal",
@@ -12124,17 +24191,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12143,8 +24218,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12152,33 +24239,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/synchronization:kernel_timeout_internal
+// GN: //third_party/abseil-cpp/absl/synchronization:graphcycles_internal__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_synchronization_kernel_timeout_internal",
+    name: "cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12187,18 +24283,61 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -12221,17 +24360,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12240,8 +24387,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12249,12 +24408,114 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/synchronization:synchronization__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/synchronization/barrier.cc",
+        "third_party/abseil-cpp/absl/synchronization/blocking_counter.cc",
+        "third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc",
+        "third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc",
+        "third_party/abseil-cpp/absl/synchronization/internal/waiter.cc",
+        "third_party/abseil-cpp/absl/synchronization/mutex.cc",
+        "third_party/abseil-cpp/absl/synchronization/notification.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/time/internal/cctz:civil_time
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time",
@@ -12268,17 +24529,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12287,8 +24556,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12296,12 +24577,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/time/internal/cctz:civil_time__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/time/internal/cctz:time_zone
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone",
@@ -12323,17 +24700,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12342,8 +24727,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12351,12 +24748,116 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/time/internal/cctz:time_zone__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc",
+        "third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/time:time
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_time_time",
@@ -12374,17 +24875,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12393,8 +24902,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12402,12 +24923,112 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/time:time__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_time_time__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/time/civil_time.cc",
+        "third_party/abseil-cpp/absl/time/clock.cc",
+        "third_party/abseil-cpp/absl/time/duration.cc",
+        "third_party/abseil-cpp/absl/time/format.cc",
+        "third_party/abseil-cpp/absl/time/time.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/types:bad_optional_access
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access",
@@ -12421,17 +25042,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12440,8 +25069,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12449,12 +25090,108 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/abseil-cpp/absl/types:bad_optional_access__testing
+cc_object {
+    name: "cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/types/bad_optional_access.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DABSL_ALLOCATOR_NOTHROW=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/abseil-cpp/",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/abseil-cpp/absl/types:bad_variant_access
 cc_object {
     name: "cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access",
@@ -12468,17 +25205,25 @@
         "-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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12487,8 +25232,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12496,33 +25253,42 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/abseil-cpp/absl/types:compare
+// GN: //third_party/abseil-cpp/absl/types:bad_variant_access__testing
 cc_object {
-    name: "cronet_aml_third_party_abseil_cpp_absl_types_compare",
+    name: "cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access__testing",
+    srcs: [
+        "third_party/abseil-cpp/absl/types/bad_variant_access.cc",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12531,193 +25297,60 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/abseil-cpp/",
     ],
-    cpp_std: "c++20",
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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: {
+        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",
+                "-O2",
+                "-fstack-protector",
                 "-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",
-    target: {
-        android_x86: {
-            cflags: [
-                "-msse3",
-            ],
-        },
-        android_x86_64: {
-            cflags: [
-                "-msse3",
-            ],
+            compile_multilib: "64",
         },
     },
 }
@@ -12734,17 +25367,25 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12753,8 +25394,20 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/android_ndk/sources/android/cpufeatures/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12762,6 +25415,74 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/android_ndk:cpu_features__testing
+cc_object {
+    name: "cronet_aml_third_party_android_ndk_cpu_features__testing",
+    srcs: [
+        "third_party/android_ndk/sources/android/cpufeatures/cpu-features.c",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/android_ndk/sources/android/cpufeatures/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -12780,19 +25501,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -12800,8 +25530,20 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -12809,6 +25551,76 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/ashmem:ashmem__testing
+cc_object {
+    name: "cronet_aml_third_party_ashmem_ashmem__testing",
+    srcs: [
+        "third_party/ashmem/ashmem-dev.c",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -13096,18 +25908,26 @@
         "-DBORINGSSL_ALLOW_CXX_RUNTIME",
         "-DBORINGSSL_IMPLEMENTATION",
         "-DBORINGSSL_NO_STATIC_INITIALIZER",
-        "-DCR_CLANG_REVISION=\"llvmorg-16-init-8697-g60809cd2-1\"",
-        "-DCR_LIBCXX_REVISION=47b31179d10646029c260702650a25d24f555acc",
-        "-DDCHECK_ALWAYS_ON=1",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -13116,8 +25936,25 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -13125,12 +25962,382 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/boringssl:boringssl__testing
+cc_library_static {
+    name: "cronet_aml_third_party_boringssl_boringssl__testing",
+    srcs: [
+        ":cronet_aml_third_party_boringssl_boringssl_asm__testing",
+        "third_party/boringssl/err_data.c",
+        "third_party/boringssl/src/crypto/asn1/a_bitstr.c",
+        "third_party/boringssl/src/crypto/asn1/a_bool.c",
+        "third_party/boringssl/src/crypto/asn1/a_d2i_fp.c",
+        "third_party/boringssl/src/crypto/asn1/a_dup.c",
+        "third_party/boringssl/src/crypto/asn1/a_gentm.c",
+        "third_party/boringssl/src/crypto/asn1/a_i2d_fp.c",
+        "third_party/boringssl/src/crypto/asn1/a_int.c",
+        "third_party/boringssl/src/crypto/asn1/a_mbstr.c",
+        "third_party/boringssl/src/crypto/asn1/a_object.c",
+        "third_party/boringssl/src/crypto/asn1/a_octet.c",
+        "third_party/boringssl/src/crypto/asn1/a_print.c",
+        "third_party/boringssl/src/crypto/asn1/a_strex.c",
+        "third_party/boringssl/src/crypto/asn1/a_strnid.c",
+        "third_party/boringssl/src/crypto/asn1/a_time.c",
+        "third_party/boringssl/src/crypto/asn1/a_type.c",
+        "third_party/boringssl/src/crypto/asn1/a_utctm.c",
+        "third_party/boringssl/src/crypto/asn1/a_utf8.c",
+        "third_party/boringssl/src/crypto/asn1/asn1_lib.c",
+        "third_party/boringssl/src/crypto/asn1/asn1_par.c",
+        "third_party/boringssl/src/crypto/asn1/asn_pack.c",
+        "third_party/boringssl/src/crypto/asn1/f_int.c",
+        "third_party/boringssl/src/crypto/asn1/f_string.c",
+        "third_party/boringssl/src/crypto/asn1/posix_time.c",
+        "third_party/boringssl/src/crypto/asn1/tasn_dec.c",
+        "third_party/boringssl/src/crypto/asn1/tasn_enc.c",
+        "third_party/boringssl/src/crypto/asn1/tasn_fre.c",
+        "third_party/boringssl/src/crypto/asn1/tasn_new.c",
+        "third_party/boringssl/src/crypto/asn1/tasn_typ.c",
+        "third_party/boringssl/src/crypto/asn1/tasn_utl.c",
+        "third_party/boringssl/src/crypto/base64/base64.c",
+        "third_party/boringssl/src/crypto/bio/bio.c",
+        "third_party/boringssl/src/crypto/bio/bio_mem.c",
+        "third_party/boringssl/src/crypto/bio/connect.c",
+        "third_party/boringssl/src/crypto/bio/fd.c",
+        "third_party/boringssl/src/crypto/bio/file.c",
+        "third_party/boringssl/src/crypto/bio/hexdump.c",
+        "third_party/boringssl/src/crypto/bio/pair.c",
+        "third_party/boringssl/src/crypto/bio/printf.c",
+        "third_party/boringssl/src/crypto/bio/socket.c",
+        "third_party/boringssl/src/crypto/bio/socket_helper.c",
+        "third_party/boringssl/src/crypto/blake2/blake2.c",
+        "third_party/boringssl/src/crypto/bn_extra/bn_asn1.c",
+        "third_party/boringssl/src/crypto/bn_extra/convert.c",
+        "third_party/boringssl/src/crypto/buf/buf.c",
+        "third_party/boringssl/src/crypto/bytestring/asn1_compat.c",
+        "third_party/boringssl/src/crypto/bytestring/ber.c",
+        "third_party/boringssl/src/crypto/bytestring/cbb.c",
+        "third_party/boringssl/src/crypto/bytestring/cbs.c",
+        "third_party/boringssl/src/crypto/bytestring/unicode.c",
+        "third_party/boringssl/src/crypto/chacha/chacha.c",
+        "third_party/boringssl/src/crypto/cipher_extra/cipher_extra.c",
+        "third_party/boringssl/src/crypto/cipher_extra/derive_key.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_aesctrhmac.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_aesgcmsiv.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_chacha20poly1305.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_des.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_null.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_rc2.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_rc4.c",
+        "third_party/boringssl/src/crypto/cipher_extra/e_tls.c",
+        "third_party/boringssl/src/crypto/cipher_extra/tls_cbc.c",
+        "third_party/boringssl/src/crypto/conf/conf.c",
+        "third_party/boringssl/src/crypto/cpu_aarch64_apple.c",
+        "third_party/boringssl/src/crypto/cpu_aarch64_fuchsia.c",
+        "third_party/boringssl/src/crypto/cpu_aarch64_linux.c",
+        "third_party/boringssl/src/crypto/cpu_aarch64_win.c",
+        "third_party/boringssl/src/crypto/cpu_arm.c",
+        "third_party/boringssl/src/crypto/cpu_arm_linux.c",
+        "third_party/boringssl/src/crypto/cpu_intel.c",
+        "third_party/boringssl/src/crypto/cpu_ppc64le.c",
+        "third_party/boringssl/src/crypto/crypto.c",
+        "third_party/boringssl/src/crypto/curve25519/curve25519.c",
+        "third_party/boringssl/src/crypto/curve25519/spake25519.c",
+        "third_party/boringssl/src/crypto/des/des.c",
+        "third_party/boringssl/src/crypto/dh_extra/dh_asn1.c",
+        "third_party/boringssl/src/crypto/dh_extra/params.c",
+        "third_party/boringssl/src/crypto/digest_extra/digest_extra.c",
+        "third_party/boringssl/src/crypto/dsa/dsa.c",
+        "third_party/boringssl/src/crypto/dsa/dsa_asn1.c",
+        "third_party/boringssl/src/crypto/ec_extra/ec_asn1.c",
+        "third_party/boringssl/src/crypto/ec_extra/ec_derive.c",
+        "third_party/boringssl/src/crypto/ec_extra/hash_to_curve.c",
+        "third_party/boringssl/src/crypto/ecdh_extra/ecdh_extra.c",
+        "third_party/boringssl/src/crypto/ecdsa_extra/ecdsa_asn1.c",
+        "third_party/boringssl/src/crypto/engine/engine.c",
+        "third_party/boringssl/src/crypto/err/err.c",
+        "third_party/boringssl/src/crypto/evp/evp.c",
+        "third_party/boringssl/src/crypto/evp/evp_asn1.c",
+        "third_party/boringssl/src/crypto/evp/evp_ctx.c",
+        "third_party/boringssl/src/crypto/evp/p_dsa_asn1.c",
+        "third_party/boringssl/src/crypto/evp/p_ec.c",
+        "third_party/boringssl/src/crypto/evp/p_ec_asn1.c",
+        "third_party/boringssl/src/crypto/evp/p_ed25519.c",
+        "third_party/boringssl/src/crypto/evp/p_ed25519_asn1.c",
+        "third_party/boringssl/src/crypto/evp/p_hkdf.c",
+        "third_party/boringssl/src/crypto/evp/p_rsa.c",
+        "third_party/boringssl/src/crypto/evp/p_rsa_asn1.c",
+        "third_party/boringssl/src/crypto/evp/p_x25519.c",
+        "third_party/boringssl/src/crypto/evp/p_x25519_asn1.c",
+        "third_party/boringssl/src/crypto/evp/pbkdf.c",
+        "third_party/boringssl/src/crypto/evp/print.c",
+        "third_party/boringssl/src/crypto/evp/scrypt.c",
+        "third_party/boringssl/src/crypto/evp/sign.c",
+        "third_party/boringssl/src/crypto/ex_data.c",
+        "third_party/boringssl/src/crypto/fipsmodule/bcm.c",
+        "third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c",
+        "third_party/boringssl/src/crypto/hkdf/hkdf.c",
+        "third_party/boringssl/src/crypto/hpke/hpke.c",
+        "third_party/boringssl/src/crypto/hrss/hrss.c",
+        "third_party/boringssl/src/crypto/lhash/lhash.c",
+        "third_party/boringssl/src/crypto/mem.c",
+        "third_party/boringssl/src/crypto/obj/obj.c",
+        "third_party/boringssl/src/crypto/obj/obj_xref.c",
+        "third_party/boringssl/src/crypto/pem/pem_all.c",
+        "third_party/boringssl/src/crypto/pem/pem_info.c",
+        "third_party/boringssl/src/crypto/pem/pem_lib.c",
+        "third_party/boringssl/src/crypto/pem/pem_oth.c",
+        "third_party/boringssl/src/crypto/pem/pem_pk8.c",
+        "third_party/boringssl/src/crypto/pem/pem_pkey.c",
+        "third_party/boringssl/src/crypto/pem/pem_x509.c",
+        "third_party/boringssl/src/crypto/pem/pem_xaux.c",
+        "third_party/boringssl/src/crypto/pkcs7/pkcs7.c",
+        "third_party/boringssl/src/crypto/pkcs7/pkcs7_x509.c",
+        "third_party/boringssl/src/crypto/pkcs8/p5_pbev2.c",
+        "third_party/boringssl/src/crypto/pkcs8/pkcs8.c",
+        "third_party/boringssl/src/crypto/pkcs8/pkcs8_x509.c",
+        "third_party/boringssl/src/crypto/poly1305/poly1305.c",
+        "third_party/boringssl/src/crypto/poly1305/poly1305_arm.c",
+        "third_party/boringssl/src/crypto/poly1305/poly1305_vec.c",
+        "third_party/boringssl/src/crypto/pool/pool.c",
+        "third_party/boringssl/src/crypto/rand_extra/deterministic.c",
+        "third_party/boringssl/src/crypto/rand_extra/forkunsafe.c",
+        "third_party/boringssl/src/crypto/rand_extra/fuchsia.c",
+        "third_party/boringssl/src/crypto/rand_extra/passive.c",
+        "third_party/boringssl/src/crypto/rand_extra/rand_extra.c",
+        "third_party/boringssl/src/crypto/rand_extra/windows.c",
+        "third_party/boringssl/src/crypto/rc4/rc4.c",
+        "third_party/boringssl/src/crypto/refcount_c11.c",
+        "third_party/boringssl/src/crypto/refcount_lock.c",
+        "third_party/boringssl/src/crypto/rsa_extra/rsa_asn1.c",
+        "third_party/boringssl/src/crypto/rsa_extra/rsa_print.c",
+        "third_party/boringssl/src/crypto/siphash/siphash.c",
+        "third_party/boringssl/src/crypto/stack/stack.c",
+        "third_party/boringssl/src/crypto/thread.c",
+        "third_party/boringssl/src/crypto/thread_none.c",
+        "third_party/boringssl/src/crypto/thread_pthread.c",
+        "third_party/boringssl/src/crypto/thread_win.c",
+        "third_party/boringssl/src/crypto/trust_token/pmbtoken.c",
+        "third_party/boringssl/src/crypto/trust_token/trust_token.c",
+        "third_party/boringssl/src/crypto/trust_token/voprf.c",
+        "third_party/boringssl/src/crypto/x509/a_digest.c",
+        "third_party/boringssl/src/crypto/x509/a_sign.c",
+        "third_party/boringssl/src/crypto/x509/a_verify.c",
+        "third_party/boringssl/src/crypto/x509/algorithm.c",
+        "third_party/boringssl/src/crypto/x509/asn1_gen.c",
+        "third_party/boringssl/src/crypto/x509/by_dir.c",
+        "third_party/boringssl/src/crypto/x509/by_file.c",
+        "third_party/boringssl/src/crypto/x509/i2d_pr.c",
+        "third_party/boringssl/src/crypto/x509/name_print.c",
+        "third_party/boringssl/src/crypto/x509/rsa_pss.c",
+        "third_party/boringssl/src/crypto/x509/t_crl.c",
+        "third_party/boringssl/src/crypto/x509/t_req.c",
+        "third_party/boringssl/src/crypto/x509/t_x509.c",
+        "third_party/boringssl/src/crypto/x509/t_x509a.c",
+        "third_party/boringssl/src/crypto/x509/x509.c",
+        "third_party/boringssl/src/crypto/x509/x509_att.c",
+        "third_party/boringssl/src/crypto/x509/x509_cmp.c",
+        "third_party/boringssl/src/crypto/x509/x509_d2.c",
+        "third_party/boringssl/src/crypto/x509/x509_def.c",
+        "third_party/boringssl/src/crypto/x509/x509_ext.c",
+        "third_party/boringssl/src/crypto/x509/x509_lu.c",
+        "third_party/boringssl/src/crypto/x509/x509_obj.c",
+        "third_party/boringssl/src/crypto/x509/x509_req.c",
+        "third_party/boringssl/src/crypto/x509/x509_set.c",
+        "third_party/boringssl/src/crypto/x509/x509_trs.c",
+        "third_party/boringssl/src/crypto/x509/x509_txt.c",
+        "third_party/boringssl/src/crypto/x509/x509_v3.c",
+        "third_party/boringssl/src/crypto/x509/x509_vfy.c",
+        "third_party/boringssl/src/crypto/x509/x509_vpm.c",
+        "third_party/boringssl/src/crypto/x509/x509cset.c",
+        "third_party/boringssl/src/crypto/x509/x509name.c",
+        "third_party/boringssl/src/crypto/x509/x509rset.c",
+        "third_party/boringssl/src/crypto/x509/x509spki.c",
+        "third_party/boringssl/src/crypto/x509/x_algor.c",
+        "third_party/boringssl/src/crypto/x509/x_all.c",
+        "third_party/boringssl/src/crypto/x509/x_attrib.c",
+        "third_party/boringssl/src/crypto/x509/x_crl.c",
+        "third_party/boringssl/src/crypto/x509/x_exten.c",
+        "third_party/boringssl/src/crypto/x509/x_info.c",
+        "third_party/boringssl/src/crypto/x509/x_name.c",
+        "third_party/boringssl/src/crypto/x509/x_pkey.c",
+        "third_party/boringssl/src/crypto/x509/x_pubkey.c",
+        "third_party/boringssl/src/crypto/x509/x_req.c",
+        "third_party/boringssl/src/crypto/x509/x_sig.c",
+        "third_party/boringssl/src/crypto/x509/x_spki.c",
+        "third_party/boringssl/src/crypto/x509/x_val.c",
+        "third_party/boringssl/src/crypto/x509/x_x509.c",
+        "third_party/boringssl/src/crypto/x509/x_x509a.c",
+        "third_party/boringssl/src/crypto/x509v3/pcy_cache.c",
+        "third_party/boringssl/src/crypto/x509v3/pcy_data.c",
+        "third_party/boringssl/src/crypto/x509v3/pcy_map.c",
+        "third_party/boringssl/src/crypto/x509v3/pcy_node.c",
+        "third_party/boringssl/src/crypto/x509v3/pcy_tree.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_akey.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_akeya.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_alt.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_bcons.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_bitst.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_conf.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_cpols.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_crld.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_enum.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_extku.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_genn.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_ia5.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_info.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_int.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_lib.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_ncons.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_ocsp.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_pci.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_pcia.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_pcons.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_pmaps.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_prn.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_purp.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_skey.c",
+        "third_party/boringssl/src/crypto/x509v3/v3_utl.c",
+        "third_party/boringssl/src/ssl/bio_ssl.cc",
+        "third_party/boringssl/src/ssl/d1_both.cc",
+        "third_party/boringssl/src/ssl/d1_lib.cc",
+        "third_party/boringssl/src/ssl/d1_pkt.cc",
+        "third_party/boringssl/src/ssl/d1_srtp.cc",
+        "third_party/boringssl/src/ssl/dtls_method.cc",
+        "third_party/boringssl/src/ssl/dtls_record.cc",
+        "third_party/boringssl/src/ssl/encrypted_client_hello.cc",
+        "third_party/boringssl/src/ssl/extensions.cc",
+        "third_party/boringssl/src/ssl/handoff.cc",
+        "third_party/boringssl/src/ssl/handshake.cc",
+        "third_party/boringssl/src/ssl/handshake_client.cc",
+        "third_party/boringssl/src/ssl/handshake_server.cc",
+        "third_party/boringssl/src/ssl/s3_both.cc",
+        "third_party/boringssl/src/ssl/s3_lib.cc",
+        "third_party/boringssl/src/ssl/s3_pkt.cc",
+        "third_party/boringssl/src/ssl/ssl_aead_ctx.cc",
+        "third_party/boringssl/src/ssl/ssl_asn1.cc",
+        "third_party/boringssl/src/ssl/ssl_buffer.cc",
+        "third_party/boringssl/src/ssl/ssl_cert.cc",
+        "third_party/boringssl/src/ssl/ssl_cipher.cc",
+        "third_party/boringssl/src/ssl/ssl_file.cc",
+        "third_party/boringssl/src/ssl/ssl_key_share.cc",
+        "third_party/boringssl/src/ssl/ssl_lib.cc",
+        "third_party/boringssl/src/ssl/ssl_privkey.cc",
+        "third_party/boringssl/src/ssl/ssl_session.cc",
+        "third_party/boringssl/src/ssl/ssl_stat.cc",
+        "third_party/boringssl/src/ssl/ssl_transcript.cc",
+        "third_party/boringssl/src/ssl/ssl_versions.cc",
+        "third_party/boringssl/src/ssl/ssl_x509.cc",
+        "third_party/boringssl/src/ssl/t1_enc.cc",
+        "third_party/boringssl/src/ssl/tls13_both.cc",
+        "third_party/boringssl/src/ssl/tls13_client.cc",
+        "third_party/boringssl/src/ssl/tls13_enc.cc",
+        "third_party/boringssl/src/ssl/tls13_server.cc",
+        "third_party/boringssl/src/ssl/tls_method.cc",
+        "third_party/boringssl/src/ssl/tls_record.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DBORINGSSL_ALLOW_CXX_RUNTIME",
+        "-DBORINGSSL_IMPLEMENTATION",
+        "-DBORINGSSL_NO_STATIC_INITIALIZER",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DOPENSSL_SMALL",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/boringssl/src/include/",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/boringssl:boringssl_asm
 cc_object {
     name: "cronet_aml_third_party_boringssl_boringssl_asm",
@@ -13140,19 +26347,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -13161,7 +26377,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: [
@@ -13179,6 +26395,9 @@
                 "third_party/boringssl/src/crypto/curve25519/asm/x25519-asm-arm.S",
                 "third_party/boringssl/src/crypto/poly1305/poly1305_arm_asm.S",
             ],
+            cflags: [
+                "-fstack-protector",
+            ],
         },
         android_arm64: {
             srcs: [
@@ -13196,6 +26415,11 @@
                 "third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S",
                 "third_party/boringssl/linux-aarch64/crypto/test/trampoline-armv8.S",
             ],
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
         },
         android_x86: {
             srcs: [
@@ -13241,53 +26465,193 @@
                 "third_party/boringssl/src/crypto/hrss/asm/poly_rq_mul.S",
             ],
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/boringssl/src/third_party/fiat:fiat_license
+// GN: //third_party/boringssl:boringssl_asm__testing
 cc_object {
-    name: "cronet_aml_third_party_boringssl_src_third_party_fiat_fiat_license",
+    name: "cronet_aml_third_party_boringssl_boringssl_asm__testing",
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
         "buildtools/third_party/libc++/",
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
     target: {
-        android_x86: {
+        android_arm: {
+            srcs: [
+                "third_party/boringssl/linux-arm/crypto/chacha/chacha-armv4.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/aesv8-armx32.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/armv4-mont.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/ghash-armv4.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/ghashv8-armx32.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/sha1-armv4-large.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/sha256-armv4.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/sha512-armv4.S",
+                "third_party/boringssl/linux-arm/crypto/fipsmodule/vpaes-armv7.S",
+                "third_party/boringssl/linux-arm/crypto/test/trampoline-armv4.S",
+                "third_party/boringssl/src/crypto/curve25519/asm/x25519-asm-arm.S",
+                "third_party/boringssl/src/crypto/poly1305/poly1305_arm_asm.S",
+            ],
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            srcs: [
+                "third_party/boringssl/linux-aarch64/crypto/chacha/chacha-armv8.S",
+                "third_party/boringssl/linux-aarch64/crypto/cipher_extra/chacha20_poly1305_armv8.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/armv8-mont.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/p256-armv8-asm.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/p256_beeu-armv8-asm.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha1-armv8.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha256-armv8.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha512-armv8.S",
+                "third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S",
+                "third_party/boringssl/linux-aarch64/crypto/test/trampoline-armv8.S",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            srcs: [
+                "third_party/boringssl/linux-x86/crypto/chacha/chacha-x86.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/aesni-x86.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/bn-586.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/co-586.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-x86.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/md5-586.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/sha1-586.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/sha256-586.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/sha512-586.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/vpaes-x86.S",
+                "third_party/boringssl/linux-x86/crypto/fipsmodule/x86-mont.S",
+                "third_party/boringssl/linux-x86/crypto/test/trampoline-x86.S",
+            ],
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
+            srcs: [
+                "third_party/boringssl/linux-x86_64/crypto/chacha/chacha-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S",
+                "third_party/boringssl/linux-x86_64/crypto/test/trampoline-x86_64.S",
+                "third_party/boringssl/src/crypto/hrss/asm/poly_rq_mul.S",
+            ],
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-msse3",
             ],
         },
+        host: {
+            srcs: [
+                "third_party/boringssl/linux-x86_64/crypto/chacha/chacha-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S",
+                "third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S",
+                "third_party/boringssl/linux-x86_64/crypto/test/trampoline-x86_64.S",
+                "third_party/boringssl/src/crypto/hrss/asm/poly_rq_mul.S",
+            ],
+            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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -13308,19 +26672,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -13329,8 +26702,25 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/brotli/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -13338,6 +26728,87 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/brotli:common__testing
+cc_library_static {
+    name: "cronet_aml_third_party_brotli_common__testing",
+    srcs: [
+        "third_party/brotli/common/constants.c",
+        "third_party/brotli/common/context.c",
+        "third_party/brotli/common/dictionary.c",
+        "third_party/brotli/common/platform.c",
+        "third_party/brotli/common/shared_dictionary.c",
+        "third_party/brotli/common/transform.c",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/brotli/include/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -13362,17 +26833,25 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -13381,8 +26860,25 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/brotli/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -13390,43 +26886,77 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/brotli:headers
-cc_object {
-    name: "cronet_aml_third_party_brotli_headers",
+// GN: //third_party/brotli:dec__testing
+cc_library_static {
+    name: "cronet_aml_third_party_brotli_dec__testing",
+    srcs: [
+        "third_party/brotli/dec/bit_reader.c",
+        "third_party/brotli/dec/decode.c",
+        "third_party/brotli/dec/huffman.c",
+        "third_party/brotli/dec/state.c",
+    ],
+    static_libs: [
+        "cronet_aml_third_party_brotli_common__testing",
+    ],
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
         "buildtools/third_party/libc++/",
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/brotli/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -13434,6 +26964,290 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/ced:ced__testing
+cc_library_static {
+    name: "cronet_aml_third_party_ced_ced__testing",
+    srcs: [
+        "third_party/ced/src/compact_enc_det/compact_enc_det.cc",
+        "third_party/ced/src/compact_enc_det/compact_enc_det_hint_code.cc",
+        "third_party/ced/src/util/encodings/encodings.cc",
+        "third_party/ced/src/util/languages/languages.cc",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCOMPILER_GCC",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DHTML5_MODE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/ced/src/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/googletest:gmock__testing
+cc_object {
+    name: "cronet_aml_third_party_googletest_gmock__testing",
+    srcs: [
+        "third_party/googletest/src/googlemock/src/gmock-cardinalities.cc",
+        "third_party/googletest/src/googlemock/src/gmock-internal-utils.cc",
+        "third_party/googletest/src/googlemock/src/gmock-matchers.cc",
+        "third_party/googletest/src/googlemock/src/gmock-spec-builders.cc",
+        "third_party/googletest/src/googlemock/src/gmock.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/googletest/custom/",
+        "third_party/googletest/src/googlemock/include/",
+        "third_party/googletest/src/googletest/include/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/googletest:gtest__testing
+cc_object {
+    name: "cronet_aml_third_party_googletest_gtest__testing",
+    srcs: [
+        "third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.cc",
+        "third_party/googletest/custom/gtest/internal/custom/gtest_port_wrapper.cc",
+        "third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.cc",
+        "third_party/googletest/src/googletest/src/gtest-assertion-result.cc",
+        "third_party/googletest/src/googletest/src/gtest-death-test.cc",
+        "third_party/googletest/src/googletest/src/gtest-filepath.cc",
+        "third_party/googletest/src/googletest/src/gtest-matchers.cc",
+        "third_party/googletest/src/googletest/src/gtest-printers.cc",
+        "third_party/googletest/src/googletest/src/gtest-test-part.cc",
+        "third_party/googletest/src/googletest/src/gtest-typed-test.cc",
+        "third_party/googletest/src/googletest/src/gtest.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_build_chromeos_buildflags__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGTEST_API_=",
+        "-DGTEST_HAS_ABSL=1",
+        "-DGTEST_HAS_POSIX_RE=0",
+        "-DGTEST_HAS_TR1_TUPLE=0",
+        "-DGTEST_LANG_CXX11=1",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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/",
+        "third_party/googletest/custom/",
+        "third_party/googletest/src/googletest/",
+        "third_party/googletest/src/googletest/include/",
+    ],
+    cpp_std: "c++17",
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -13694,13 +27508,16 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_DLOPEN=0",
         "-DHAVE_SYS_UIO_H",
         "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-DUCONFIG_ONLY_HTML_CONVERSION=1",
         "-DUCONFIG_USE_WINDOWS_LCID_MAPPING_API=0",
         "-DUSE_CHROMIUM_ICU=1",
@@ -13711,12 +27528,17 @@
         "-DU_I18N_IMPLEMENTATION",
         "-DU_STATIC_IMPLEMENTATION",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -13726,9 +27548,26 @@
         "third_party/icu/source/common/",
         "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     rtti: true,
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -13736,12 +27575,368 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/icu:icui18n__testing
+cc_library_static {
+    name: "cronet_aml_third_party_icu_icui18n__testing",
+    srcs: [
+        "third_party/icu/source/i18n/alphaindex.cpp",
+        "third_party/icu/source/i18n/anytrans.cpp",
+        "third_party/icu/source/i18n/astro.cpp",
+        "third_party/icu/source/i18n/basictz.cpp",
+        "third_party/icu/source/i18n/bocsu.cpp",
+        "third_party/icu/source/i18n/brktrans.cpp",
+        "third_party/icu/source/i18n/buddhcal.cpp",
+        "third_party/icu/source/i18n/calendar.cpp",
+        "third_party/icu/source/i18n/casetrn.cpp",
+        "third_party/icu/source/i18n/cecal.cpp",
+        "third_party/icu/source/i18n/chnsecal.cpp",
+        "third_party/icu/source/i18n/choicfmt.cpp",
+        "third_party/icu/source/i18n/coleitr.cpp",
+        "third_party/icu/source/i18n/coll.cpp",
+        "third_party/icu/source/i18n/collation.cpp",
+        "third_party/icu/source/i18n/collationbuilder.cpp",
+        "third_party/icu/source/i18n/collationcompare.cpp",
+        "third_party/icu/source/i18n/collationdata.cpp",
+        "third_party/icu/source/i18n/collationdatabuilder.cpp",
+        "third_party/icu/source/i18n/collationdatareader.cpp",
+        "third_party/icu/source/i18n/collationdatawriter.cpp",
+        "third_party/icu/source/i18n/collationfastlatin.cpp",
+        "third_party/icu/source/i18n/collationfastlatinbuilder.cpp",
+        "third_party/icu/source/i18n/collationfcd.cpp",
+        "third_party/icu/source/i18n/collationiterator.cpp",
+        "third_party/icu/source/i18n/collationkeys.cpp",
+        "third_party/icu/source/i18n/collationroot.cpp",
+        "third_party/icu/source/i18n/collationrootelements.cpp",
+        "third_party/icu/source/i18n/collationruleparser.cpp",
+        "third_party/icu/source/i18n/collationsets.cpp",
+        "third_party/icu/source/i18n/collationsettings.cpp",
+        "third_party/icu/source/i18n/collationtailoring.cpp",
+        "third_party/icu/source/i18n/collationweights.cpp",
+        "third_party/icu/source/i18n/compactdecimalformat.cpp",
+        "third_party/icu/source/i18n/coptccal.cpp",
+        "third_party/icu/source/i18n/cpdtrans.cpp",
+        "third_party/icu/source/i18n/csdetect.cpp",
+        "third_party/icu/source/i18n/csmatch.cpp",
+        "third_party/icu/source/i18n/csr2022.cpp",
+        "third_party/icu/source/i18n/csrecog.cpp",
+        "third_party/icu/source/i18n/csrmbcs.cpp",
+        "third_party/icu/source/i18n/csrsbcs.cpp",
+        "third_party/icu/source/i18n/csrucode.cpp",
+        "third_party/icu/source/i18n/csrutf8.cpp",
+        "third_party/icu/source/i18n/curramt.cpp",
+        "third_party/icu/source/i18n/currfmt.cpp",
+        "third_party/icu/source/i18n/currpinf.cpp",
+        "third_party/icu/source/i18n/currunit.cpp",
+        "third_party/icu/source/i18n/dangical.cpp",
+        "third_party/icu/source/i18n/datefmt.cpp",
+        "third_party/icu/source/i18n/dayperiodrules.cpp",
+        "third_party/icu/source/i18n/dcfmtsym.cpp",
+        "third_party/icu/source/i18n/decContext.cpp",
+        "third_party/icu/source/i18n/decNumber.cpp",
+        "third_party/icu/source/i18n/decimfmt.cpp",
+        "third_party/icu/source/i18n/double-conversion-bignum-dtoa.cpp",
+        "third_party/icu/source/i18n/double-conversion-bignum.cpp",
+        "third_party/icu/source/i18n/double-conversion-cached-powers.cpp",
+        "third_party/icu/source/i18n/double-conversion-double-to-string.cpp",
+        "third_party/icu/source/i18n/double-conversion-fast-dtoa.cpp",
+        "third_party/icu/source/i18n/double-conversion-string-to-double.cpp",
+        "third_party/icu/source/i18n/double-conversion-strtod.cpp",
+        "third_party/icu/source/i18n/dtfmtsym.cpp",
+        "third_party/icu/source/i18n/dtitvfmt.cpp",
+        "third_party/icu/source/i18n/dtitvinf.cpp",
+        "third_party/icu/source/i18n/dtptngen.cpp",
+        "third_party/icu/source/i18n/dtrule.cpp",
+        "third_party/icu/source/i18n/erarules.cpp",
+        "third_party/icu/source/i18n/esctrn.cpp",
+        "third_party/icu/source/i18n/ethpccal.cpp",
+        "third_party/icu/source/i18n/fmtable.cpp",
+        "third_party/icu/source/i18n/fmtable_cnv.cpp",
+        "third_party/icu/source/i18n/format.cpp",
+        "third_party/icu/source/i18n/formatted_string_builder.cpp",
+        "third_party/icu/source/i18n/formattedval_iterimpl.cpp",
+        "third_party/icu/source/i18n/formattedval_sbimpl.cpp",
+        "third_party/icu/source/i18n/formattedvalue.cpp",
+        "third_party/icu/source/i18n/fphdlimp.cpp",
+        "third_party/icu/source/i18n/fpositer.cpp",
+        "third_party/icu/source/i18n/funcrepl.cpp",
+        "third_party/icu/source/i18n/gender.cpp",
+        "third_party/icu/source/i18n/gregocal.cpp",
+        "third_party/icu/source/i18n/gregoimp.cpp",
+        "third_party/icu/source/i18n/hebrwcal.cpp",
+        "third_party/icu/source/i18n/indiancal.cpp",
+        "third_party/icu/source/i18n/inputext.cpp",
+        "third_party/icu/source/i18n/islamcal.cpp",
+        "third_party/icu/source/i18n/japancal.cpp",
+        "third_party/icu/source/i18n/listformatter.cpp",
+        "third_party/icu/source/i18n/measfmt.cpp",
+        "third_party/icu/source/i18n/measunit.cpp",
+        "third_party/icu/source/i18n/measunit_extra.cpp",
+        "third_party/icu/source/i18n/measure.cpp",
+        "third_party/icu/source/i18n/msgfmt.cpp",
+        "third_party/icu/source/i18n/name2uni.cpp",
+        "third_party/icu/source/i18n/nfrs.cpp",
+        "third_party/icu/source/i18n/nfrule.cpp",
+        "third_party/icu/source/i18n/nfsubs.cpp",
+        "third_party/icu/source/i18n/nortrans.cpp",
+        "third_party/icu/source/i18n/nultrans.cpp",
+        "third_party/icu/source/i18n/number_affixutils.cpp",
+        "third_party/icu/source/i18n/number_asformat.cpp",
+        "third_party/icu/source/i18n/number_capi.cpp",
+        "third_party/icu/source/i18n/number_compact.cpp",
+        "third_party/icu/source/i18n/number_currencysymbols.cpp",
+        "third_party/icu/source/i18n/number_decimalquantity.cpp",
+        "third_party/icu/source/i18n/number_decimfmtprops.cpp",
+        "third_party/icu/source/i18n/number_fluent.cpp",
+        "third_party/icu/source/i18n/number_formatimpl.cpp",
+        "third_party/icu/source/i18n/number_grouping.cpp",
+        "third_party/icu/source/i18n/number_integerwidth.cpp",
+        "third_party/icu/source/i18n/number_longnames.cpp",
+        "third_party/icu/source/i18n/number_mapper.cpp",
+        "third_party/icu/source/i18n/number_modifiers.cpp",
+        "third_party/icu/source/i18n/number_multiplier.cpp",
+        "third_party/icu/source/i18n/number_notation.cpp",
+        "third_party/icu/source/i18n/number_output.cpp",
+        "third_party/icu/source/i18n/number_padding.cpp",
+        "third_party/icu/source/i18n/number_patternmodifier.cpp",
+        "third_party/icu/source/i18n/number_patternstring.cpp",
+        "third_party/icu/source/i18n/number_rounding.cpp",
+        "third_party/icu/source/i18n/number_scientific.cpp",
+        "third_party/icu/source/i18n/number_skeletons.cpp",
+        "third_party/icu/source/i18n/number_symbolswrapper.cpp",
+        "third_party/icu/source/i18n/number_usageprefs.cpp",
+        "third_party/icu/source/i18n/number_utils.cpp",
+        "third_party/icu/source/i18n/numfmt.cpp",
+        "third_party/icu/source/i18n/numparse_affixes.cpp",
+        "third_party/icu/source/i18n/numparse_compositions.cpp",
+        "third_party/icu/source/i18n/numparse_currency.cpp",
+        "third_party/icu/source/i18n/numparse_decimal.cpp",
+        "third_party/icu/source/i18n/numparse_impl.cpp",
+        "third_party/icu/source/i18n/numparse_parsednumber.cpp",
+        "third_party/icu/source/i18n/numparse_scientific.cpp",
+        "third_party/icu/source/i18n/numparse_symbols.cpp",
+        "third_party/icu/source/i18n/numparse_validators.cpp",
+        "third_party/icu/source/i18n/numrange_capi.cpp",
+        "third_party/icu/source/i18n/numrange_fluent.cpp",
+        "third_party/icu/source/i18n/numrange_impl.cpp",
+        "third_party/icu/source/i18n/numsys.cpp",
+        "third_party/icu/source/i18n/olsontz.cpp",
+        "third_party/icu/source/i18n/persncal.cpp",
+        "third_party/icu/source/i18n/pluralranges.cpp",
+        "third_party/icu/source/i18n/plurfmt.cpp",
+        "third_party/icu/source/i18n/plurrule.cpp",
+        "third_party/icu/source/i18n/quant.cpp",
+        "third_party/icu/source/i18n/quantityformatter.cpp",
+        "third_party/icu/source/i18n/rbnf.cpp",
+        "third_party/icu/source/i18n/rbt.cpp",
+        "third_party/icu/source/i18n/rbt_data.cpp",
+        "third_party/icu/source/i18n/rbt_pars.cpp",
+        "third_party/icu/source/i18n/rbt_rule.cpp",
+        "third_party/icu/source/i18n/rbt_set.cpp",
+        "third_party/icu/source/i18n/rbtz.cpp",
+        "third_party/icu/source/i18n/regexcmp.cpp",
+        "third_party/icu/source/i18n/regeximp.cpp",
+        "third_party/icu/source/i18n/regexst.cpp",
+        "third_party/icu/source/i18n/regextxt.cpp",
+        "third_party/icu/source/i18n/region.cpp",
+        "third_party/icu/source/i18n/reldatefmt.cpp",
+        "third_party/icu/source/i18n/reldtfmt.cpp",
+        "third_party/icu/source/i18n/rematch.cpp",
+        "third_party/icu/source/i18n/remtrans.cpp",
+        "third_party/icu/source/i18n/repattrn.cpp",
+        "third_party/icu/source/i18n/rulebasedcollator.cpp",
+        "third_party/icu/source/i18n/scientificnumberformatter.cpp",
+        "third_party/icu/source/i18n/scriptset.cpp",
+        "third_party/icu/source/i18n/search.cpp",
+        "third_party/icu/source/i18n/selfmt.cpp",
+        "third_party/icu/source/i18n/sharedbreakiterator.cpp",
+        "third_party/icu/source/i18n/simpletz.cpp",
+        "third_party/icu/source/i18n/smpdtfmt.cpp",
+        "third_party/icu/source/i18n/smpdtfst.cpp",
+        "third_party/icu/source/i18n/sortkey.cpp",
+        "third_party/icu/source/i18n/standardplural.cpp",
+        "third_party/icu/source/i18n/string_segment.cpp",
+        "third_party/icu/source/i18n/strmatch.cpp",
+        "third_party/icu/source/i18n/strrepl.cpp",
+        "third_party/icu/source/i18n/stsearch.cpp",
+        "third_party/icu/source/i18n/taiwncal.cpp",
+        "third_party/icu/source/i18n/timezone.cpp",
+        "third_party/icu/source/i18n/titletrn.cpp",
+        "third_party/icu/source/i18n/tmunit.cpp",
+        "third_party/icu/source/i18n/tmutamt.cpp",
+        "third_party/icu/source/i18n/tmutfmt.cpp",
+        "third_party/icu/source/i18n/tolowtrn.cpp",
+        "third_party/icu/source/i18n/toupptrn.cpp",
+        "third_party/icu/source/i18n/translit.cpp",
+        "third_party/icu/source/i18n/transreg.cpp",
+        "third_party/icu/source/i18n/tridpars.cpp",
+        "third_party/icu/source/i18n/tzfmt.cpp",
+        "third_party/icu/source/i18n/tzgnames.cpp",
+        "third_party/icu/source/i18n/tznames.cpp",
+        "third_party/icu/source/i18n/tznames_impl.cpp",
+        "third_party/icu/source/i18n/tzrule.cpp",
+        "third_party/icu/source/i18n/tztrans.cpp",
+        "third_party/icu/source/i18n/ucal.cpp",
+        "third_party/icu/source/i18n/ucln_in.cpp",
+        "third_party/icu/source/i18n/ucol.cpp",
+        "third_party/icu/source/i18n/ucol_res.cpp",
+        "third_party/icu/source/i18n/ucol_sit.cpp",
+        "third_party/icu/source/i18n/ucoleitr.cpp",
+        "third_party/icu/source/i18n/ucsdet.cpp",
+        "third_party/icu/source/i18n/udat.cpp",
+        "third_party/icu/source/i18n/udateintervalformat.cpp",
+        "third_party/icu/source/i18n/udatpg.cpp",
+        "third_party/icu/source/i18n/ufieldpositer.cpp",
+        "third_party/icu/source/i18n/uitercollationiterator.cpp",
+        "third_party/icu/source/i18n/ulistformatter.cpp",
+        "third_party/icu/source/i18n/ulocdata.cpp",
+        "third_party/icu/source/i18n/umsg.cpp",
+        "third_party/icu/source/i18n/unesctrn.cpp",
+        "third_party/icu/source/i18n/uni2name.cpp",
+        "third_party/icu/source/i18n/units_complexconverter.cpp",
+        "third_party/icu/source/i18n/units_converter.cpp",
+        "third_party/icu/source/i18n/units_data.cpp",
+        "third_party/icu/source/i18n/units_router.cpp",
+        "third_party/icu/source/i18n/unum.cpp",
+        "third_party/icu/source/i18n/unumsys.cpp",
+        "third_party/icu/source/i18n/upluralrules.cpp",
+        "third_party/icu/source/i18n/uregex.cpp",
+        "third_party/icu/source/i18n/uregexc.cpp",
+        "third_party/icu/source/i18n/uregion.cpp",
+        "third_party/icu/source/i18n/usearch.cpp",
+        "third_party/icu/source/i18n/uspoof.cpp",
+        "third_party/icu/source/i18n/uspoof_build.cpp",
+        "third_party/icu/source/i18n/uspoof_conf.cpp",
+        "third_party/icu/source/i18n/uspoof_impl.cpp",
+        "third_party/icu/source/i18n/utf16collationiterator.cpp",
+        "third_party/icu/source/i18n/utf8collationiterator.cpp",
+        "third_party/icu/source/i18n/utmscale.cpp",
+        "third_party/icu/source/i18n/utrans.cpp",
+        "third_party/icu/source/i18n/vtzone.cpp",
+        "third_party/icu/source/i18n/vzone.cpp",
+        "third_party/icu/source/i18n/windtfmt.cpp",
+        "third_party/icu/source/i18n/winnmfmt.cpp",
+        "third_party/icu/source/i18n/wintzimpl.cpp",
+        "third_party/icu/source/i18n/zonemeta.cpp",
+        "third_party/icu/source/i18n/zrule.cpp",
+        "third_party/icu/source/i18n/ztrans.cpp",
+    ],
+    static_libs: [
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_DLOPEN=0",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUCONFIG_ONLY_HTML_CONVERSION=1",
+        "-DUCONFIG_USE_WINDOWS_LCID_MAPPING_API=0",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_CHARSET_IS_UTF8=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_I18N_IMPLEMENTATION",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    rtti: true,
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/icu:icuuc_private
 cc_library_static {
     name: "cronet_aml_third_party_icu_icuuc_private",
@@ -13952,13 +28147,16 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_DLOPEN=0",
         "-DHAVE_SYS_UIO_H",
         "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-DUCONFIG_ONLY_HTML_CONVERSION=1",
         "-DUCONFIG_USE_WINDOWS_LCID_MAPPING_API=0",
         "-DUSE_CHROMIUM_ICU=1",
@@ -13970,12 +28168,17 @@
         "-DU_ICUDATAENTRY_IN_COMMON",
         "-DU_STATIC_IMPLEMENTATION",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -13985,9 +28188,26 @@
         "third_party/icu/source/common/",
         "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     rtti: true,
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -13995,53 +28215,322 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
-// GN: //third_party/icu:icuuc_public
-cc_object {
-    name: "cronet_aml_third_party_icu_icuuc_public",
+// GN: //third_party/icu:icuuc_private__testing
+cc_library_static {
+    name: "cronet_aml_third_party_icu_icuuc_private__testing",
+    srcs: [
+        "third_party/icu/source/common/appendable.cpp",
+        "third_party/icu/source/common/bmpset.cpp",
+        "third_party/icu/source/common/brkeng.cpp",
+        "third_party/icu/source/common/brkiter.cpp",
+        "third_party/icu/source/common/bytesinkutil.cpp",
+        "third_party/icu/source/common/bytestream.cpp",
+        "third_party/icu/source/common/bytestrie.cpp",
+        "third_party/icu/source/common/bytestriebuilder.cpp",
+        "third_party/icu/source/common/bytestrieiterator.cpp",
+        "third_party/icu/source/common/caniter.cpp",
+        "third_party/icu/source/common/characterproperties.cpp",
+        "third_party/icu/source/common/chariter.cpp",
+        "third_party/icu/source/common/charstr.cpp",
+        "third_party/icu/source/common/cmemory.cpp",
+        "third_party/icu/source/common/cstr.cpp",
+        "third_party/icu/source/common/cstring.cpp",
+        "third_party/icu/source/common/cwchar.cpp",
+        "third_party/icu/source/common/dictbe.cpp",
+        "third_party/icu/source/common/dictionarydata.cpp",
+        "third_party/icu/source/common/dtintrv.cpp",
+        "third_party/icu/source/common/edits.cpp",
+        "third_party/icu/source/common/emojiprops.cpp",
+        "third_party/icu/source/common/errorcode.cpp",
+        "third_party/icu/source/common/filteredbrk.cpp",
+        "third_party/icu/source/common/filterednormalizer2.cpp",
+        "third_party/icu/source/common/icudataver.cpp",
+        "third_party/icu/source/common/icuplug.cpp",
+        "third_party/icu/source/common/loadednormalizer2impl.cpp",
+        "third_party/icu/source/common/localebuilder.cpp",
+        "third_party/icu/source/common/localematcher.cpp",
+        "third_party/icu/source/common/localeprioritylist.cpp",
+        "third_party/icu/source/common/locavailable.cpp",
+        "third_party/icu/source/common/locbased.cpp",
+        "third_party/icu/source/common/locdispnames.cpp",
+        "third_party/icu/source/common/locdistance.cpp",
+        "third_party/icu/source/common/locdspnm.cpp",
+        "third_party/icu/source/common/locid.cpp",
+        "third_party/icu/source/common/loclikely.cpp",
+        "third_party/icu/source/common/loclikelysubtags.cpp",
+        "third_party/icu/source/common/locmap.cpp",
+        "third_party/icu/source/common/locresdata.cpp",
+        "third_party/icu/source/common/locutil.cpp",
+        "third_party/icu/source/common/lsr.cpp",
+        "third_party/icu/source/common/lstmbe.cpp",
+        "third_party/icu/source/common/messagepattern.cpp",
+        "third_party/icu/source/common/normalizer2.cpp",
+        "third_party/icu/source/common/normalizer2impl.cpp",
+        "third_party/icu/source/common/normlzr.cpp",
+        "third_party/icu/source/common/parsepos.cpp",
+        "third_party/icu/source/common/patternprops.cpp",
+        "third_party/icu/source/common/pluralmap.cpp",
+        "third_party/icu/source/common/propname.cpp",
+        "third_party/icu/source/common/propsvec.cpp",
+        "third_party/icu/source/common/punycode.cpp",
+        "third_party/icu/source/common/putil.cpp",
+        "third_party/icu/source/common/rbbi.cpp",
+        "third_party/icu/source/common/rbbi_cache.cpp",
+        "third_party/icu/source/common/rbbidata.cpp",
+        "third_party/icu/source/common/rbbinode.cpp",
+        "third_party/icu/source/common/rbbirb.cpp",
+        "third_party/icu/source/common/rbbiscan.cpp",
+        "third_party/icu/source/common/rbbisetb.cpp",
+        "third_party/icu/source/common/rbbistbl.cpp",
+        "third_party/icu/source/common/rbbitblb.cpp",
+        "third_party/icu/source/common/resbund.cpp",
+        "third_party/icu/source/common/resbund_cnv.cpp",
+        "third_party/icu/source/common/resource.cpp",
+        "third_party/icu/source/common/restrace.cpp",
+        "third_party/icu/source/common/ruleiter.cpp",
+        "third_party/icu/source/common/schriter.cpp",
+        "third_party/icu/source/common/serv.cpp",
+        "third_party/icu/source/common/servlk.cpp",
+        "third_party/icu/source/common/servlkf.cpp",
+        "third_party/icu/source/common/servls.cpp",
+        "third_party/icu/source/common/servnotf.cpp",
+        "third_party/icu/source/common/servrbf.cpp",
+        "third_party/icu/source/common/servslkf.cpp",
+        "third_party/icu/source/common/sharedobject.cpp",
+        "third_party/icu/source/common/simpleformatter.cpp",
+        "third_party/icu/source/common/static_unicode_sets.cpp",
+        "third_party/icu/source/common/stringpiece.cpp",
+        "third_party/icu/source/common/stringtriebuilder.cpp",
+        "third_party/icu/source/common/uarrsort.cpp",
+        "third_party/icu/source/common/ubidi.cpp",
+        "third_party/icu/source/common/ubidi_props.cpp",
+        "third_party/icu/source/common/ubidiln.cpp",
+        "third_party/icu/source/common/ubiditransform.cpp",
+        "third_party/icu/source/common/ubidiwrt.cpp",
+        "third_party/icu/source/common/ubrk.cpp",
+        "third_party/icu/source/common/ucase.cpp",
+        "third_party/icu/source/common/ucasemap.cpp",
+        "third_party/icu/source/common/ucasemap_titlecase_brkiter.cpp",
+        "third_party/icu/source/common/ucat.cpp",
+        "third_party/icu/source/common/uchar.cpp",
+        "third_party/icu/source/common/ucharstrie.cpp",
+        "third_party/icu/source/common/ucharstriebuilder.cpp",
+        "third_party/icu/source/common/ucharstrieiterator.cpp",
+        "third_party/icu/source/common/uchriter.cpp",
+        "third_party/icu/source/common/ucln_cmn.cpp",
+        "third_party/icu/source/common/ucmndata.cpp",
+        "third_party/icu/source/common/ucnv.cpp",
+        "third_party/icu/source/common/ucnv2022.cpp",
+        "third_party/icu/source/common/ucnv_bld.cpp",
+        "third_party/icu/source/common/ucnv_cb.cpp",
+        "third_party/icu/source/common/ucnv_cnv.cpp",
+        "third_party/icu/source/common/ucnv_ct.cpp",
+        "third_party/icu/source/common/ucnv_err.cpp",
+        "third_party/icu/source/common/ucnv_ext.cpp",
+        "third_party/icu/source/common/ucnv_io.cpp",
+        "third_party/icu/source/common/ucnv_lmb.cpp",
+        "third_party/icu/source/common/ucnv_set.cpp",
+        "third_party/icu/source/common/ucnv_u16.cpp",
+        "third_party/icu/source/common/ucnv_u32.cpp",
+        "third_party/icu/source/common/ucnv_u7.cpp",
+        "third_party/icu/source/common/ucnv_u8.cpp",
+        "third_party/icu/source/common/ucnvbocu.cpp",
+        "third_party/icu/source/common/ucnvdisp.cpp",
+        "third_party/icu/source/common/ucnvhz.cpp",
+        "third_party/icu/source/common/ucnvisci.cpp",
+        "third_party/icu/source/common/ucnvlat1.cpp",
+        "third_party/icu/source/common/ucnvmbcs.cpp",
+        "third_party/icu/source/common/ucnvscsu.cpp",
+        "third_party/icu/source/common/ucnvsel.cpp",
+        "third_party/icu/source/common/ucol_swp.cpp",
+        "third_party/icu/source/common/ucptrie.cpp",
+        "third_party/icu/source/common/ucurr.cpp",
+        "third_party/icu/source/common/udata.cpp",
+        "third_party/icu/source/common/udatamem.cpp",
+        "third_party/icu/source/common/udataswp.cpp",
+        "third_party/icu/source/common/uenum.cpp",
+        "third_party/icu/source/common/uhash.cpp",
+        "third_party/icu/source/common/uhash_us.cpp",
+        "third_party/icu/source/common/uidna.cpp",
+        "third_party/icu/source/common/uinit.cpp",
+        "third_party/icu/source/common/uinvchar.cpp",
+        "third_party/icu/source/common/uiter.cpp",
+        "third_party/icu/source/common/ulist.cpp",
+        "third_party/icu/source/common/uloc.cpp",
+        "third_party/icu/source/common/uloc_keytype.cpp",
+        "third_party/icu/source/common/uloc_tag.cpp",
+        "third_party/icu/source/common/umapfile.cpp",
+        "third_party/icu/source/common/umath.cpp",
+        "third_party/icu/source/common/umutablecptrie.cpp",
+        "third_party/icu/source/common/umutex.cpp",
+        "third_party/icu/source/common/unames.cpp",
+        "third_party/icu/source/common/unifiedcache.cpp",
+        "third_party/icu/source/common/unifilt.cpp",
+        "third_party/icu/source/common/unifunct.cpp",
+        "third_party/icu/source/common/uniset.cpp",
+        "third_party/icu/source/common/uniset_closure.cpp",
+        "third_party/icu/source/common/uniset_props.cpp",
+        "third_party/icu/source/common/unisetspan.cpp",
+        "third_party/icu/source/common/unistr.cpp",
+        "third_party/icu/source/common/unistr_case.cpp",
+        "third_party/icu/source/common/unistr_case_locale.cpp",
+        "third_party/icu/source/common/unistr_cnv.cpp",
+        "third_party/icu/source/common/unistr_props.cpp",
+        "third_party/icu/source/common/unistr_titlecase_brkiter.cpp",
+        "third_party/icu/source/common/unorm.cpp",
+        "third_party/icu/source/common/unormcmp.cpp",
+        "third_party/icu/source/common/uobject.cpp",
+        "third_party/icu/source/common/uprops.cpp",
+        "third_party/icu/source/common/ures_cnv.cpp",
+        "third_party/icu/source/common/uresbund.cpp",
+        "third_party/icu/source/common/uresdata.cpp",
+        "third_party/icu/source/common/usc_impl.cpp",
+        "third_party/icu/source/common/uscript.cpp",
+        "third_party/icu/source/common/uscript_props.cpp",
+        "third_party/icu/source/common/uset.cpp",
+        "third_party/icu/source/common/uset_props.cpp",
+        "third_party/icu/source/common/usetiter.cpp",
+        "third_party/icu/source/common/ushape.cpp",
+        "third_party/icu/source/common/usprep.cpp",
+        "third_party/icu/source/common/ustack.cpp",
+        "third_party/icu/source/common/ustr_cnv.cpp",
+        "third_party/icu/source/common/ustr_titlecase_brkiter.cpp",
+        "third_party/icu/source/common/ustr_wcs.cpp",
+        "third_party/icu/source/common/ustrcase.cpp",
+        "third_party/icu/source/common/ustrcase_locale.cpp",
+        "third_party/icu/source/common/ustrenum.cpp",
+        "third_party/icu/source/common/ustrfmt.cpp",
+        "third_party/icu/source/common/ustring.cpp",
+        "third_party/icu/source/common/ustrtrns.cpp",
+        "third_party/icu/source/common/utext.cpp",
+        "third_party/icu/source/common/utf_impl.cpp",
+        "third_party/icu/source/common/util.cpp",
+        "third_party/icu/source/common/util_props.cpp",
+        "third_party/icu/source/common/utrace.cpp",
+        "third_party/icu/source/common/utrie.cpp",
+        "third_party/icu/source/common/utrie2.cpp",
+        "third_party/icu/source/common/utrie2_builder.cpp",
+        "third_party/icu/source/common/utrie_swap.cpp",
+        "third_party/icu/source/common/uts46.cpp",
+        "third_party/icu/source/common/utypes.cpp",
+        "third_party/icu/source/common/uvector.cpp",
+        "third_party/icu/source/common/uvectr32.cpp",
+        "third_party/icu/source/common/uvectr64.cpp",
+        "third_party/icu/source/common/wintz.cpp",
+        "third_party/icu/source/stubdata/stubdata.cpp",
+    ],
+    host_supported: true,
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_DLOPEN=0",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUCONFIG_ONLY_HTML_CONVERSION=1",
+        "-DUCONFIG_USE_WINDOWS_LCID_MAPPING_API=0",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_CHARSET_IS_UTF8=1",
+        "-DU_COMMON_IMPLEMENTATION",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_ICUDATAENTRY_IN_COMMON",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
         "-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",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
         "buildtools/third_party/libc++/",
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
     ],
-    cpp_std: "c++20",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    rtti: true,
     target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
                 "-msse3",
             ],
         },
         android_x86_64: {
             cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
                 "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
     },
 }
 
@@ -14070,18 +28559,26 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_CONFIG_H",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -14090,8 +28587,25 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/libevent/android/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -14099,12 +28613,582 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/libevent:libevent__testing
+cc_library_static {
+    name: "cronet_aml_third_party_libevent_libevent__testing",
+    srcs: [
+        "third_party/libevent/buffer.c",
+        "third_party/libevent/epoll.c",
+        "third_party/libevent/evbuffer.c",
+        "third_party/libevent/evdns.c",
+        "third_party/libevent/event.c",
+        "third_party/libevent/event_tagging.c",
+        "third_party/libevent/evrpc.c",
+        "third_party/libevent/evutil.c",
+        "third_party/libevent/http.c",
+        "third_party/libevent/log.c",
+        "third_party/libevent/poll.c",
+        "third_party/libevent/select.c",
+        "third_party/libevent/signal.c",
+        "third_party/libevent/strlcpy.c",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_CONFIG_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+            ],
+            local_include_dirs: [
+                "third_party/libevent/android/",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+            local_include_dirs: [
+                "third_party/libevent/android/",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-msse3",
+            ],
+            local_include_dirs: [
+                "third_party/libevent/android/",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            local_include_dirs: [
+                "third_party/libevent/android/",
+            ],
+        },
+        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",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            local_include_dirs: [
+                "third_party/libevent/linux/",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
+// GN: //third_party/libxml:libxml__testing
+cc_library_static {
+    name: "cronet_aml_third_party_libxml_libxml__testing",
+    srcs: [
+        "third_party/libxml/src/HTMLparser.c",
+        "third_party/libxml/src/HTMLtree.c",
+        "third_party/libxml/src/SAX2.c",
+        "third_party/libxml/src/buf.c",
+        "third_party/libxml/src/chvalid.c",
+        "third_party/libxml/src/dict.c",
+        "third_party/libxml/src/encoding.c",
+        "third_party/libxml/src/entities.c",
+        "third_party/libxml/src/error.c",
+        "third_party/libxml/src/globals.c",
+        "third_party/libxml/src/hash.c",
+        "third_party/libxml/src/list.c",
+        "third_party/libxml/src/parser.c",
+        "third_party/libxml/src/parserInternals.c",
+        "third_party/libxml/src/pattern.c",
+        "third_party/libxml/src/threads.c",
+        "third_party/libxml/src/tree.c",
+        "third_party/libxml/src/uri.c",
+        "third_party/libxml/src/valid.c",
+        "third_party/libxml/src/xmlIO.c",
+        "third_party/libxml/src/xmlmemory.c",
+        "third_party/libxml/src/xmlreader.c",
+        "third_party/libxml/src/xmlsave.c",
+        "third_party/libxml/src/xmlstring.c",
+        "third_party/libxml/src/xmlunicode.c",
+        "third_party/libxml/src/xmlwriter.c",
+        "third_party/libxml/src/xpath.c",
+    ],
+    shared_libs: [
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_REENTRANT",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/libxml/linux/",
+        "third_party/libxml/linux/include/",
+        "third_party/libxml/src/include/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/libxml:libxml_utils__testing
+cc_library_static {
+    name: "cronet_aml_third_party_libxml_libxml_utils__testing",
+    srcs: [
+        "third_party/libxml/chromium/libxml_utils.cc",
+    ],
+    shared_libs: [
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/libxml/linux/include/",
+        "third_party/libxml/src/include/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/libxml:xml_reader__testing
+cc_library_static {
+    name: "cronet_aml_third_party_libxml_xml_reader__testing",
+    srcs: [
+        "third_party/libxml/chromium/xml_reader.cc",
+    ],
+    shared_libs: [
+        "libz",
+    ],
+    static_libs: [
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libxml_libxml__testing",
+        "cronet_aml_third_party_libxml_libxml_utils__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-DUSE_CHROMIUM_ICU=1",
+        "-DU_ENABLE_DYLOAD=0",
+        "-DU_ENABLE_RESOURCE_TRACING=0",
+        "-DU_ENABLE_TRACING=1",
+        "-DU_STATIC_IMPLEMENTATION",
+        "-DU_USING_ICU_NAMESPACE=0",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/icu/source/common/",
+        "third_party/icu/source/i18n/",
+        "third_party/libxml/linux/include/",
+        "third_party/libxml/src/include/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/metrics_proto:metrics_proto__testing
+cc_genrule {
+    name: "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen",
+    srcs: [
+        "third_party/metrics_proto/call_stack_profile.proto",
+        "third_party/metrics_proto/cast_logs.proto",
+        "third_party/metrics_proto/chrome_os_app_list_launch_event.proto",
+        "third_party/metrics_proto/chrome_searchbox_stats.proto",
+        "third_party/metrics_proto/chrome_user_metrics_extension.proto",
+        "third_party/metrics_proto/custom_tab_session.proto",
+        "third_party/metrics_proto/execution_context.proto",
+        "third_party/metrics_proto/extension_install.proto",
+        "third_party/metrics_proto/histogram_event.proto",
+        "third_party/metrics_proto/omnibox_event.proto",
+        "third_party/metrics_proto/omnibox_focus_type.proto",
+        "third_party/metrics_proto/omnibox_input_type.proto",
+        "third_party/metrics_proto/perf_data.proto",
+        "third_party/metrics_proto/perf_stat.proto",
+        "third_party/metrics_proto/printer_event.proto",
+        "third_party/metrics_proto/reporting_info.proto",
+        "third_party/metrics_proto/sampled_profile.proto",
+        "third_party/metrics_proto/structured_data.proto",
+        "third_party/metrics_proto/system_profile.proto",
+        "third_party/metrics_proto/trace_log.proto",
+        "third_party/metrics_proto/translate_event.proto",
+        "third_party/metrics_proto/ukm/aggregate.proto",
+        "third_party/metrics_proto/ukm/entry.proto",
+        "third_party/metrics_proto/ukm/report.proto",
+        "third_party/metrics_proto/ukm/source.proto",
+        "third_party/metrics_proto/user_action_event.proto",
+        "third_party/metrics_proto/user_demographics.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/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",
+    ],
+}
+
+// GN: //third_party/metrics_proto:metrics_proto__testing
+cc_genrule {
+    name: "cronet_aml_third_party_metrics_proto_metrics_proto__testing_gen_headers",
+    srcs: [
+        "third_party/metrics_proto/call_stack_profile.proto",
+        "third_party/metrics_proto/cast_logs.proto",
+        "third_party/metrics_proto/chrome_os_app_list_launch_event.proto",
+        "third_party/metrics_proto/chrome_searchbox_stats.proto",
+        "third_party/metrics_proto/chrome_user_metrics_extension.proto",
+        "third_party/metrics_proto/custom_tab_session.proto",
+        "third_party/metrics_proto/execution_context.proto",
+        "third_party/metrics_proto/extension_install.proto",
+        "third_party/metrics_proto/histogram_event.proto",
+        "third_party/metrics_proto/omnibox_event.proto",
+        "third_party/metrics_proto/omnibox_focus_type.proto",
+        "third_party/metrics_proto/omnibox_input_type.proto",
+        "third_party/metrics_proto/perf_data.proto",
+        "third_party/metrics_proto/perf_stat.proto",
+        "third_party/metrics_proto/printer_event.proto",
+        "third_party/metrics_proto/reporting_info.proto",
+        "third_party/metrics_proto/sampled_profile.proto",
+        "third_party/metrics_proto/structured_data.proto",
+        "third_party/metrics_proto/system_profile.proto",
+        "third_party/metrics_proto/trace_log.proto",
+        "third_party/metrics_proto/translate_event.proto",
+        "third_party/metrics_proto/ukm/aggregate.proto",
+        "third_party/metrics_proto/ukm/entry.proto",
+        "third_party/metrics_proto/ukm/report.proto",
+        "third_party/metrics_proto/ukm/source.proto",
+        "third_party/metrics_proto/user_action_event.proto",
+        "third_party/metrics_proto/user_demographics.proto",
+    ],
+    tools: [
+        "cronet_aml_third_party_protobuf_protoc",
+    ],
+    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/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: [
+        ".",
+        "protos",
+        "third_party/metrics_proto",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //third_party/metrics_proto:metrics_proto
 cc_genrule {
     name: "cronet_aml_third_party_metrics_proto_metrics_proto_gen",
@@ -14140,35 +29224,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 +29294,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,19 +29346,28 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -14282,8 +29375,25 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -14291,12 +29401,114 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
     },
 }
 
+// GN: //third_party/modp_b64:modp_b64__testing
+cc_library_static {
+    name: "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    srcs: [
+        "third_party/modp_b64/modp_b64.cc",
+    ],
+    host_supported: true,
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+    ],
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-DANDROID",
+                "-DANDROID_NDK_VERSION_ROLL=r23_1",
+                "-DHAVE_SYS_UIO_H",
+                "-Oz",
+                "-fstack-protector",
+                "-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",
+                "-O2",
+                "-fstack-protector",
+                "-msse3",
+            ],
+            compile_multilib: "64",
+        },
+    },
+}
+
 // GN: //third_party/protobuf:protobuf_full
 cc_library_static {
     name: "cronet_aml_third_party_protobuf_protobuf_full",
@@ -14386,8 +29598,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,28 +29607,37 @@
         "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",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_ZLIB",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-DUSE_AURA=1",
         "-DUSE_OZONE=1",
         "-DUSE_UDEV",
-        "-D_DEBUG",
         "-D_FILE_OFFSET_BITS=64",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fstack-protector",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
         "-msse3",
     ],
     local_include_dirs: [
@@ -14425,9 +29646,13 @@
         "buildtools/third_party/libc++/trunk/include",
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/protobuf/src/",
-        "third_party/zlib/",
     ],
     cpp_std: "c++20",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
 }
 
 // GN: //third_party/protobuf:protobuf_lite
@@ -14476,21 +29701,29 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
         "-DHAVE_SYS_UIO_H",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -14499,8 +29732,25 @@
         "buildtools/third_party/libc++abi/trunk/include",
         "third_party/protobuf/src/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -14508,6 +29758,117 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //third_party/protobuf:protobuf_lite__testing
+cc_library_static {
+    name: "cronet_aml_third_party_protobuf_protobuf_lite__testing",
+    srcs: [
+        "third_party/protobuf/src/google/protobuf/any_lite.cc",
+        "third_party/protobuf/src/google/protobuf/arena.cc",
+        "third_party/protobuf/src/google/protobuf/arenastring.cc",
+        "third_party/protobuf/src/google/protobuf/arenaz_sampler.cc",
+        "third_party/protobuf/src/google/protobuf/extension_set.cc",
+        "third_party/protobuf/src/google/protobuf/generated_enum_util.cc",
+        "third_party/protobuf/src/google/protobuf/generated_message_tctable_lite.cc",
+        "third_party/protobuf/src/google/protobuf/generated_message_util.cc",
+        "third_party/protobuf/src/google/protobuf/implicit_weak_message.cc",
+        "third_party/protobuf/src/google/protobuf/inlined_string_field.cc",
+        "third_party/protobuf/src/google/protobuf/io/coded_stream.cc",
+        "third_party/protobuf/src/google/protobuf/io/io_win32.cc",
+        "third_party/protobuf/src/google/protobuf/io/strtod.cc",
+        "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.cc",
+        "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc",
+        "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
+        "third_party/protobuf/src/google/protobuf/map.cc",
+        "third_party/protobuf/src/google/protobuf/message_lite.cc",
+        "third_party/protobuf/src/google/protobuf/parse_context.cc",
+        "third_party/protobuf/src/google/protobuf/repeated_field.cc",
+        "third_party/protobuf/src/google/protobuf/repeated_ptr_field.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/bytestream.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/common.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/int128.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/status.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/statusor.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/stringpiece.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/strutil.cc",
+        "third_party/protobuf/src/google/protobuf/stubs/time.cc",
+        "third_party/protobuf/src/google/protobuf/wire_format_lite.cc",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+        "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    local_include_dirs: [
+        "./",
+        "buildtools/third_party/libc++/",
+        "buildtools/third_party/libc++/trunk/include",
+        "buildtools/third_party/libc++abi/trunk/include",
+        "third_party/protobuf/src/",
+    ],
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -14522,10 +29883,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,27 +29896,36 @@
         "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",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-DUSE_AURA=1",
         "-DUSE_OZONE=1",
         "-DUSE_UDEV",
-        "-D_DEBUG",
         "-D_FILE_OFFSET_BITS=64",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fstack-protector",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
         "-msse3",
     ],
     local_include_dirs: [
@@ -14564,6 +29936,11 @@
         "third_party/protobuf/src/",
     ],
     cpp_std: "c++20",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+    ],
 }
 
 // GN: //third_party/protobuf:protoc_lib
@@ -14656,9 +30033,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,27 +30045,36 @@
         "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",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
         "-DGOOGLE_PROTOBUF_NO_RTTI",
         "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
         "-DHAVE_PTHREAD",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
         "-DUSE_AURA=1",
         "-DUSE_OZONE=1",
         "-DUSE_UDEV",
-        "-D_DEBUG",
         "-D_FILE_OFFSET_BITS=64",
         "-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",
+        "-O2",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fstack-protector",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
         "-msse3",
     ],
     local_include_dirs: [
@@ -14697,598 +30085,11 @@
         "third_party/protobuf/src/",
     ],
     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",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
     ],
-    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
@@ -15314,6 +30115,29 @@
     ],
 }
 
+// GN: //url:buildflags__testing
+cc_genrule {
+    name: "cronet_aml_url_buildflags__testing",
+    cmd: "echo '--flags USE_PLATFORM_ICU_ALTERNATIVES=\"true\"' | " +
+         "$(location build/write_buildflag_header.py) --output " +
+         "$(out) " +
+         "--rulename " +
+         "//url:buildflags " +
+         "--gen-dir " +
+         ". " +
+         "--definitions " +
+         "/dev/stdin",
+    out: [
+        "url/buildflags.h",
+    ],
+    tool_files: [
+        "build/write_buildflag_header.py",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
 // GN: //url:url
 cc_library_static {
     name: "cronet_aml_url_url",
@@ -15377,20 +30201,29 @@
     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",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
         "-DIS_URL_IMPL",
-        "-D_DEBUG",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
         "-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",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
     ],
     local_include_dirs: [
         "./",
@@ -15400,8 +30233,41 @@
         "third_party/abseil-cpp/",
         "third_party/boringssl/src/include/",
     ],
-    cpp_std: "c++20",
+    cpp_std: "c++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
     target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
         android_x86: {
             cflags: [
                 "-msse3",
@@ -15409,6 +30275,151 @@
         },
         android_x86_64: {
             cflags: [
+                "-fstack-protector",
+                "-msse3",
+            ],
+        },
+    },
+}
+
+// GN: //url:url__testing
+cc_library_static {
+    name: "cronet_aml_url_url__testing",
+    srcs: [
+        "url/gurl.cc",
+        "url/origin.cc",
+        "url/scheme_host_port.cc",
+        "url/third_party/mozilla/url_parse.cc",
+        "url/url_canon.cc",
+        "url/url_canon_etc.cc",
+        "url/url_canon_filesystemurl.cc",
+        "url/url_canon_fileurl.cc",
+        "url/url_canon_host.cc",
+        "url/url_canon_internal.cc",
+        "url/url_canon_ip.cc",
+        "url/url_canon_mailtourl.cc",
+        "url/url_canon_path.cc",
+        "url/url_canon_pathurl.cc",
+        "url/url_canon_query.cc",
+        "url/url_canon_relative.cc",
+        "url/url_canon_stdstring.cc",
+        "url/url_canon_stdurl.cc",
+        "url/url_constants.cc",
+        "url/url_idna_icu_alternatives_android.cc",
+        "url/url_parse_file.cc",
+        "url/url_util.cc",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+    ],
+    static_libs: [
+        "cronet_aml_base_allocator_partition_allocator_partition_alloc__testing",
+        "cronet_aml_base_base__testing",
+        "cronet_aml_base_base_static__testing",
+        "cronet_aml_base_third_party_double_conversion_double_conversion__testing",
+        "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations__testing",
+        "cronet_aml_third_party_boringssl_boringssl__testing",
+        "cronet_aml_third_party_icu_icui18n__testing",
+        "cronet_aml_third_party_icu_icuuc_private__testing",
+        "cronet_aml_third_party_libevent_libevent__testing",
+        "cronet_aml_third_party_modp_b64_modp_b64__testing",
+    ],
+    generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_url_buildflags__testing",
+        "cronet_aml_url_url_jni_headers__testing",
+    ],
+    export_generated_headers: [
+        "cronet_aml_base_debugging_buildflags__testing",
+        "cronet_aml_base_logging_buildflags__testing",
+        "cronet_aml_build_chromeos_buildflags__testing",
+        "cronet_aml_url_buildflags__testing",
+        "cronet_aml_url_url_jni_headers__testing",
+    ],
+    defaults: [
+        "cronet_aml_defaults",
+    ],
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r23_1",
+        "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
+        "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DIS_URL_IMPL",
+        "-DNDEBUG",
+        "-DNO_UNWIND_TABLES",
+        "-DNVALGRIND",
+        "-DOFFICIAL_BUILD",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Oz",
+        "-fdata-sections",
+        "-ffunction-sections",
+        "-fno-asynchronous-unwind-tables",
+        "-fno-unwind-tables",
+        "-fvisibility-inlines-hidden",
+        "-fvisibility=hidden",
+        "-g1",
+    ],
+    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++17",
+    ldflags: [
+        "-Wl,--as-needed",
+        "-Wl,--gc-sections",
+        "-Wl,--icf=all",
+        "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+        "-Wl,-wrap,asprintf",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+        "-Wl,-wrap,getcwd",
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,malloc_usable_size",
+        "-Wl,-wrap,memalign",
+        "-Wl,-wrap,posix_memalign",
+        "-Wl,-wrap,pvalloc",
+        "-Wl,-wrap,realloc",
+        "-Wl,-wrap,realpath",
+        "-Wl,-wrap,strdup",
+        "-Wl,-wrap,strndup",
+        "-Wl,-wrap,valloc",
+        "-Wl,-wrap,vasprintf",
+    ],
+    target: {
+        android_arm: {
+            cflags: [
+                "-fstack-protector",
+            ],
+        },
+        android_arm64: {
+            cflags: [
+                "-fstack-protector",
+                "-mno-outline",
+                "-mno-outline-atomics",
+            ],
+        },
+        android_x86: {
+            cflags: [
+                "-msse3",
+            ],
+        },
+        android_x86_64: {
+            cflags: [
+                "-fstack-protector",
                 "-msse3",
             ],
         },
@@ -15436,6 +30447,46 @@
          "--input_file " +
          "$(location url/android/java/src/org/chromium/url/IDNStringUtil.java) " +
          "--input_file " +
+         "$(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",
+    ],
+    tool_files: [
+        "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",
+    ],
+    apex_available: [
+        "com.android.tethering",
+    ],
+}
+
+// GN: //url:url_jni_headers__testing
+cc_genrule {
+    name: "cronet_aml_url_url_jni_headers__testing",
+    srcs: [
+        "url/android/java/src/org/chromium/url/IDNStringUtil.java",
+        "url/android/java/src/org/chromium/url/Origin.java",
+    ],
+    cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
+         "long " +
+         "--output_dir " +
+         "$(genDir)/url/url_jni_headers " +
+         "--includes " +
+         "base/android/jni_generator/jni_generator_helper.h " +
+         "--use_proxy_hash " +
+         "--output_name " +
+         "IDNStringUtil_jni.h " +
+         "--output_name " +
+         "Origin_jni.h " +
+         "--input_file " +
+         "$(location url/android/java/src/org/chromium/url/IDNStringUtil.java) " +
+         "--input_file " +
          "$(location url/android/java/src/org/chromium/url/Origin.java)",
     out: [
         "url/url_jni_headers/IDNStringUtil_jni.h",
@@ -15453,3 +30504,51 @@
     ],
 }
 
+// GN: LICENSE
+license {
+    name: "external_cronet_license",
+    license_kinds: [
+        "SPDX-license-identifier-AFL-2.0",
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-BSL-1.0",
+        "SPDX-license-identifier-ICU",
+        "SPDX-license-identifier-ISC",
+        "SPDX-license-identifier-MIT",
+        "SPDX-license-identifier-MPL",
+        "SPDX-license-identifier-MPL-1.1",
+        "SPDX-license-identifier-MPL-2.0",
+        "SPDX-license-identifier-NCSA",
+        "SPDX-license-identifier-OpenSSL",
+        "SPDX-license-identifier-Unicode-DFS",
+        "legacy_unencumbered",
+    ],
+    license_text: [
+        "LICENSE",
+        "base/third_party/double_conversion/LICENSE",
+        "base/third_party/dynamic_annotations/LICENSE",
+        "base/third_party/icu/LICENSE",
+        "base/third_party/nspr/LICENSE",
+        "base/third_party/superfasthash/LICENSE",
+        "base/third_party/symbolize/LICENSE",
+        "base/third_party/valgrind/LICENSE",
+        "base/third_party/xdg_user_dirs/LICENSE",
+        "net/third_party/quiche/src/LICENSE",
+        "net/third_party/uri_template/LICENSE",
+        "third_party/abseil-cpp/LICENSE",
+        "third_party/ashmem/LICENSE",
+        "third_party/boringssl/src/LICENSE",
+        "third_party/boringssl/src/third_party/fiat/LICENSE",
+        "third_party/boringssl/src/third_party/googletest/LICENSE",
+        "third_party/boringssl/src/third_party/wycheproof_testvectors/LICENSE",
+        "third_party/brotli/LICENSE",
+        "third_party/icu/LICENSE",
+        "third_party/icu/scripts/LICENSE",
+        "third_party/libevent/LICENSE",
+        "third_party/metrics_proto/LICENSE",
+        "third_party/modp_b64/LICENSE",
+        "third_party/protobuf/LICENSE",
+        "third_party/protobuf/third_party/utf8_range/LICENSE",
+    ],
+}
+
diff --git a/tools/gn2bp/desc_arm.json b/tools/gn2bp/desc_arm.json
index 996b5f5..87b86e3 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..7b8bfe3 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..df8635a 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..707b9c7 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..2c970a5 100755
--- a/tools/gn2bp/gen_android_bp
+++ b/tools/gn2bp/gen_android_bp
@@ -40,11 +40,18 @@
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 # Default targets to translate to the blueprint file.
-default_targets = [
+DEFAULT_TARGETS = [
     '//components/cronet/android:cronet',
-    '//components/cronet:cronet_package',
+    '//components/cronet/android:cronet_android_mainline',
 ]
 
+DEFAULT_TESTS = [
+  '//components/cronet/android:cronet_unittests_android__library',
+]
+
+EXTRAS_ANDROID_BP_FILE = "Android.extras.bp"
+
+CRONET_API_MODULE_NAME = "cronet_aml_api_java"
 # Defines a custom init_rc argument to be applied to the corresponding output
 # blueprint target.
 target_initrc = {
@@ -93,11 +100,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 +112,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'
@@ -126,22 +133,59 @@
   "-msse3",
   # needed for zlib:zlib
   "-msse4.2",
+  # flags to reduce binary size
+  "-O1",
+  "-O2",
+  "-O3",
+  "-Oz",
+  "-g1",
+  "-g2",
+  "-fdata-sections",
+  "-ffunction-sections",
+  "-fvisibility=hidden",
+  "-fvisibility-inlines-hidden",
+  "-fstack-protector",
+  "-mno-outline",
+  "-mno-outline-atomics",
+  "-fno-asynchronous-unwind-tables",
+  "-fno-unwind-tables",
 ]
 
+# Linker flags which are passed through to the blueprint.
+ldflag_allowlist = [
+  # flags to reduce binary size
+  "-Wl,--as-needed",
+  "-Wl,--gc-sections",
+  "-Wl,--icf=all",
+]
+
+def get_linker_script_ldflag(script_path):
+  return f'-Wl,--script,{tree_path}/{script_path}'
+
 # Additional arguments to apply to Android.bp rules.
 additional_args = {
-    # TODO: remove if not needed.
-    'cronet_aml_components_cronet_android_cronet': [
-        ('linker_scripts', {
-            'base/android/library_loader/anchor_functions.lds',
-        }),
-    ],
     'cronet_aml_net_net': [
         ('export_static_lib_headers', {
             'cronet_aml_net_third_party_quiche_quiche',
             '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 +218,42 @@
 builtin_deps = {
     '//buildtools/third_party/libunwind:libunwind':
         lambda m, a: None, # disable libunwind
+    '//buildtools/third_party/libunwind:libunwind__testing':
+        lambda m, a: None, # disable libunwind
+    '//net/data/ssl/chrome_root_store:gen_root_store_inc':
+        lambda m, a: None,
+    '//net/data/ssl/chrome_root_store:gen_root_store_inc__testing':
+        lambda m, a: None,
     '//net/tools/root_store_tool:root_store_tool':
         lambda m, a: None,
+    '//net/tools/root_store_tool:root_store_tool__testing':
+        lambda m, a: None,
+    '//third_party/zlib:zlib':
+        enable_zlib,
+    '//third_party/zlib:zlib__testing':
+        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.
 # ----------------------------------------------------------------------------
@@ -270,6 +327,10 @@
     self.export_system_include_dirs = set()
     self.generated_headers = set()
     self.export_generated_headers = set()
+    self.ldflags = set()
+    self.compile_multilib = None
+    if name == 'host':
+      self.compile_multilib = '64'
 
   def to_string(self, output):
     nested_out = []
@@ -287,8 +348,12 @@
     self._output_field(nested_out, 'export_system_include_dirs')
     self._output_field(nested_out, 'generated_headers')
     self._output_field(nested_out, 'export_generated_headers')
+    self._output_field(nested_out, 'ldflags')
 
     if nested_out:
+      # This is added here to make sure it doesn't add a `host` arch-specific module just for
+      # `compile_multilib` flag.
+      self._output_field(nested_out, 'compile_multilib')
       output.append('    %s: {' % self.name)
       for line in nested_out:
         output.append('    %s' % line)
@@ -323,6 +388,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()
@@ -348,6 +414,7 @@
     self.min_sdk_version = None
     self.proto = dict()
     self.linker_scripts = set()
+    self.ldflags = set()
     # The genrule_XXX below are properties that must to be propagated back
     # on the module(s) that depend on the genrule.
     self.genrule_headers = set()
@@ -368,6 +435,10 @@
     self.plugins = set()
     self.processor_class = None
     self.sdk_version = None
+    self.javacflags = set()
+    self.license_kinds = set()
+    self.license_text = set()
+    self.default_applicable_licenses = set()
 
   def to_string(self, output):
     if self.comment:
@@ -393,6 +464,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')
@@ -413,6 +485,7 @@
     self._output_field(output, 'stubs')
     self._output_field(output, 'proto')
     self._output_field(output, 'linker_scripts')
+    self._output_field(output, 'ldflags')
     self._output_field(output, 'cppflags')
     self._output_field(output, 'libs')
     self._output_field(output, 'stem')
@@ -421,6 +494,10 @@
     self._output_field(output, 'plugins')
     self._output_field(output, 'processor_class')
     self._output_field(output, 'sdk_version')
+    self._output_field(output, 'javacflags')
+    self._output_field(output, 'license_kinds')
+    self._output_field(output, 'license_text')
+    self._output_field(output, 'default_applicable_licenses')
     if self.rtti:
       self._output_field(output, 'rtti')
 
@@ -455,6 +532,12 @@
     else:
       self.shared_libs.add(lib)
 
+  def is_test(self):
+    if gn_utils.TESTING_SUFFIX in self.name:
+      name_without_prefix = self.name[:self.name.find(gn_utils.TESTING_SUFFIX)]
+      return any([name_without_prefix == label_to_module_name(target) for target in DEFAULT_TESTS])
+    return False
+
   def _output_field(self, output, name, sort=True):
     value = getattr(self, name)
     return write_blueprint_key_value(output, name, value, sort)
@@ -508,7 +591,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):
@@ -719,7 +807,7 @@
   module.out.add(stem + '.srcjar')
   module.cmd = NEWLINE.join([
     f'cp $(in) $(genDir)/{stem}.java &&',
-    f'$(location soong_zip) -o $(out) -srcjar -f $(genDir)/{stem}.java'
+    f'$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/{stem}.java'
   ])
   module.tools.add('soong_zip')
   blueprint.add_module(module)
@@ -869,6 +957,9 @@
     files = self.target.sources.union(self.target.inputs)
     return {gn_utils.label_to_path(file) for file in files if is_supported_source_file(file)}
 
+  def get_tools(self):
+    return set()
+
   def get_tool_files(self):
     # gn treats inputs and sources for actions equally.
     # soong only supports source files inside srcs, non-source files are added as
@@ -915,7 +1006,40 @@
     self._set_value_arg('--output', '$(out)')
     super()._sanitize_args()
 
+class GnRunBinary(BaseActionSanitizer):
+  def __init__(self, target, arch):
+    super().__init__(target, arch)
+    self.binary_to_target = {
+      "clang_x64/transport_security_state_generator":
+            "cronet_aml_net_tools_transport_security_state_generator_transport_security_state_generator__testing",
+    }
+    self.binary = self.binary_to_target[self.target.args[0]]
+
+  def _replace_gen_with_location_tag(self, arg):
+    if arg.startswith("gen/"):
+      return "$(location %s)" % arg.replace("gen/", "")
+    return arg
+
+  def _sanitize_args(self):
+    self._update_all_args(self._sanitize_filepath_with_location_tag)
+    self._update_all_args(self._replace_gen_with_location_tag)
+    self._set_arg_at(0, '$(location %s)' % self.binary)
+    super()._sanitize_args()
+
+  def get_tools(self):
+    tools = super().get_tools()
+    tools.add(self.binary)
+    return tools
+
+  def get_cmd(self):
+    # Remove the script and use the binary right away
+    return NEWLINE.join(self.target.args)
+
 class JniGeneratorSanitizer(BaseActionSanitizer):
+  def __init__(self, target, arch, is_test_target):
+    self.is_test_target = is_test_target
+    super().__init__(target, arch)
+
   def _add_location_tag_to_filepath(self, arg):
     if not arg.endswith('.class'):
       # --input_file supports both .class specifiers or source files as arguments.
@@ -924,15 +1048,17 @@
     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._append_arg('--javap', '$$(find $${OUT_DIR:-out}/.path -name javap)')
     self._update_value_arg('--output_dir', self._sanitize_filepath)
     self._update_value_arg('--includes', self._sanitize_filepath, False)
     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)
+    if not self.is_test_target:
+      # Only jarjar platform code
+      self._append_arg('--package_prefix', 'android.net.http.internal')
     super()._sanitize_args()
 
   def _sanitize_outputs(self):
@@ -945,9 +1071,17 @@
     # 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):
+  def __init__(self, target, arch, is_test_target):
+    self.is_test_target = is_test_target
+    super().__init__(target, arch)
+
   def _sanitize_inputs(self):
     self.target.inputs = [file for file in self.target.inputs if not file.startswith('//out/')]
 
@@ -959,6 +1093,9 @@
     # 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')
+    if not self.is_test_target:
+      # Only jarjar platform code
+      self._append_arg('--package_prefix', 'android.net.http.internal')
     super()._sanitize_args()
 
   def get_cmd(self):
@@ -983,7 +1120,10 @@
 
 class JavaJniRegistrationGeneratorSanitizer(JniRegistrationGeneratorSanitizer):
   def get_name(self):
-    return label_to_module_name(self.target.name) + "__java"
+    name = super().get_name() + "__java"
+    if self.is_test_target:
+      name += gn_utils.TESTING_SUFFIX
+    return name
 
   def _sanitize_outputs(self):
     self.target.outputs = [out for out in self.target.outputs if
@@ -1034,18 +1174,18 @@
     self._set_value_arg('--output', '$(out)')
     super()._sanitize_args()
 
-def get_action_sanitizer(target, type, arch):
+def get_action_sanitizer(target, type, arch, is_test_target):
   if target.script == "//build/write_buildflag_header.py":
     return WriteBuildFlagHeaderSanitizer(target, arch)
   elif target.script == "//build/write_build_date_header.py":
     return WriteBuildDateHeaderSanitizer(target, arch)
   elif target.script == '//base/android/jni_generator/jni_generator.py':
-    return JniGeneratorSanitizer(target, arch)
+    return JniGeneratorSanitizer(target, arch, is_test_target)
   elif target.script == '//base/android/jni_generator/jni_registration_generator.py':
     if type == 'java_genrule':
-      return JavaJniRegistrationGeneratorSanitizer(target, arch)
+      return JavaJniRegistrationGeneratorSanitizer(target, arch, is_test_target)
     else:
-      return JniRegistrationGeneratorSanitizer(target, arch)
+      return JniRegistrationGeneratorSanitizer(target, arch, is_test_target)
   elif target.script == "//build/util/version.py":
     return VersionSanitizer(target, arch)
   elif target.script == "//build/android/gyp/java_cpp_enum.py":
@@ -1058,11 +1198,13 @@
     return JavaCppStringSanitizer(target, arch)
   elif target.script == '//build/android/gyp/write_native_libraries_java.py':
     return WriteNativeLibrariesJavaSanitizer(target, arch)
+  elif target.script == '//build/gn_run_binary.py':
+    return GnRunBinary(target, arch)
   else:
     # TODO: throw exception here once all script hacks have been converted.
     return BaseActionSanitizer(target, arch)
 
-def create_action_foreach_modules(blueprint, target):
+def create_action_foreach_modules(blueprint, target, is_test_target):
   """ The following assumes that rebase_path exists in the args.
   The args of an action_foreach contains hints about which output files are generated
   by which source files.
@@ -1093,10 +1235,10 @@
         new_args.append(arg)
 
   target.args = new_args
-  return create_action_module(blueprint, target, 'cc_genrule')
+  return create_action_module(blueprint, target, 'cc_genrule', is_test_target)
 
-def create_action_module_internal(target, type, arch=None):
-  sanitizer = get_action_sanitizer(target, type, arch)
+def create_action_module_internal(target, type, is_test_target, arch=None):
+  sanitizer = get_action_sanitizer(target, type, arch, is_test_target)
   sanitizer.sanitize()
 
   module = Module(type, sanitizer.get_name(), target.name)
@@ -1106,6 +1248,7 @@
     module.genrule_headers.add(module.name)
   module.srcs = sanitizer.get_srcs()
   module.tool_files = sanitizer.get_tool_files()
+  module.tools = sanitizer.get_tools()
 
   return module
 
@@ -1165,7 +1308,7 @@
   merged_module.cmd = merge_cmd(modules, genrule_type)
   return merged_module
 
-def create_action_module(blueprint, target, genrule_type):
+def create_action_module(blueprint, target, genrule_type, is_test_target):
   '''
   Create module for action target and add to the blueprint. If target has arch specific attributes
   this function merge them and create a single module.
@@ -1176,12 +1319,13 @@
   '''
   # TODO: Handle this target correctly, this target generates java_genrule but this target has
   # different value for cpu-family arg between archs
-  if target.name == '//build/android:native_libraries_gen':
-    module = create_action_module_internal(target, genrule_type, target.arch['android_arm'])
+  if target.name in ['//build/android:native_libraries_gen',
+                     '//build/android:native_libraries_gen__testing']:
+    module = create_action_module_internal(target, genrule_type, is_test_target, target.arch['android_arm'])
     blueprint.add_module(module)
     return module
 
-  modules = {arch_name: create_action_module_internal(target, genrule_type, arch)
+  modules = {arch_name: create_action_module_internal(target, genrule_type, is_test_target, arch)
              for arch_name, arch in target.arch.items()}
   module = merge_modules(modules, genrule_type)
   blueprint.add_module(module)
@@ -1194,8 +1338,17 @@
   cflags |= set("-D%s" % define.replace("\"", "\\\"") for define in defines)
   return cflags
 
-def set_module_flags(module, cflags, defines):
+def _set_linker_script(module, libs):
+  for lib in libs:
+    if lib.endswith(".lds"):
+      module.ldflags.add(get_linker_script_ldflag(gn_utils.label_to_path(lib)))
+
+def set_module_flags(module, module_type, cflags, defines, ldflags, libs):
   module.cflags.update(_get_cflags(cflags, defines))
+  if module_type != 'cc_object':
+    module.ldflags.update({flag for flag in ldflags
+            if flag in ldflag_allowlist or flag.startswith("-Wl,-wrap,")})
+    _set_linker_script(module, libs)
   # TODO: implement proper cflag parsing.
   for flag in cflags:
     if '-std=' in flag:
@@ -1214,14 +1367,13 @@
   # 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]
 
 
-def create_modules_from_target(blueprint, gn, gn_target_name):
+def create_modules_from_target(blueprint, gn, gn_target_name, is_test_target):
   """Generate module(s) for a given GN target.
 
     Given a GN target name, generate one or more corresponding modules into a
@@ -1260,9 +1412,9 @@
     if module is None:
       return None
   elif target.type == 'action':
-    module = create_action_module(blueprint, target, 'cc_genrule')
+    module = create_action_module(blueprint, target, 'cc_genrule', is_test_target)
   elif target.type == 'action_foreach':
-    module = create_action_foreach_modules(blueprint, target)
+    module = create_action_foreach_modules(blueprint, target, is_test_target)
   elif target.type == 'copy':
     # TODO: careful now! copy targets are not supported yet, but this will stop
     # traversing the dependency tree. For //base:base, this is not a big
@@ -1277,26 +1429,24 @@
 
   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
 
   if target.type in gn_utils.LINKER_UNIT_TYPES:
-    set_module_flags(module, target.cflags, target.defines)
+    set_module_flags(module, module.type, target.cflags, target.defines, target.ldflags, target.libs)
     set_module_include_dirs(module, target.cflags, target.include_dirs)
     # TODO: set_module_xxx is confusing, apply similar function to module and target in better way.
     for arch_name, arch in target.arch.items():
-      set_module_flags(module.target[arch_name], arch.cflags, arch.defines)
+      # TODO(aymanm): Make libs arch-specific.
+      set_module_flags(module.target[arch_name], module.type,
+                       arch.cflags, arch.defines, arch.ldflags, [])
       # -Xclang -target-feature -Xclang +mte are used to enable MTE (Memory Tagging Extensions).
       # Flags which does not start with '-' could not be in the cflags so enabling MTE by
       # -march and -mcpu Feature Modifiers. MTE is only available on arm64. This is needed for
@@ -1337,6 +1487,11 @@
     # So setting the output name based on the output_name from the desc.json
     module.stem = 'lib' + target.output_name
 
+  if module.is_test():
+    # Tests output should be a shared library in the format of 'lib[module_name]'
+    module.stem = 'lib' + target.get_target_name()[
+                          :target.get_target_name().find(gn_utils.TESTING_SUFFIX)]
+
   # dep_name is an unmangled GN target name (e.g. //foo:bar(toolchain)).
   # Currently, only one module is generated from target even target has multiple toolchains.
   # And module is generated based on the first visited target.
@@ -1349,7 +1504,7 @@
       builtin_deps[dep_name](module, None)
       continue
 
-    dep_module = create_modules_from_target(blueprint, gn, dep_name)
+    dep_module = create_modules_from_target(blueprint, gn, dep_name, is_test_target)
 
     if dep_module is None:
       continue
@@ -1404,20 +1559,19 @@
       if dep_name in builtin_deps:
         builtin_deps[dep_name](module, arch_name)
         continue
-      dep_module = create_modules_from_target(blueprint, gn, dep_name)
+      dep_module = create_modules_from_target(blueprint, gn, dep_name, is_test_target)
       # Arch-specific dependencies currently only include cc_library_static.
       # Revisit this approach once we need to support more target types.
       if dep_module.type == 'cc_library_static':
         module.target[arch_name].static_libs.add(dep_module.name)
       elif dep_module.type == 'cc_genrule':
-        if dep_module.name.endswith(arch_name):
-          module.target[arch_name].generated_headers.update(dep_module.genrule_headers)
-          module.target[arch_name].srcs.update(dep_module.genrule_srcs)
-          module.target[arch_name].shared_libs.update(dep_module.genrule_shared_libs)
-          module.target[arch_name].header_libs.update(dep_module.genrule_header_libs)
-          if module.type not in ["cc_object"]:
-            module.target[arch_name].export_generated_headers.update(
-              dep_module.genrule_headers)
+        module.target[arch_name].generated_headers.update(dep_module.genrule_headers)
+        module.target[arch_name].srcs.update(dep_module.genrule_srcs)
+        module.target[arch_name].shared_libs.update(dep_module.genrule_shared_libs)
+        module.target[arch_name].header_libs.update(dep_module.genrule_header_libs)
+        if module.type not in ["cc_object"]:
+          module.target[arch_name].export_generated_headers.update(
+            dep_module.genrule_headers)
       elif dep_module.type == 'cc_object':
         if dep_module.has_input_files():
           # Only add it as part of srcs if the dep_module has input files otherwise
@@ -1453,53 +1607,96 @@
   blueprint.add_module(module)
   return module
 
-def create_java_module(blueprint, gn):
+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, is_test_target):
   bp_module_name = module_prefix + 'java'
+  if is_test_target:
+    bp_module_name += gn_utils.TESTING_SUFFIX
   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.aidl["local_include_dirs"] = gn.aidl_local_include_dirs
   module.sdk_version = "module_current"
+  module.min_sdk_version = 30
   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")
+  if not is_test_target:
+    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)
     else:
-      module.srcs.add(':' + create_action_module(blueprint, target, 'java_genrule').name)
+      module.srcs.add(':' + create_action_module(blueprint, target, 'java_genrule', is_test_target).name)
   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)
+  # TODO add the API helpers separately after the main API is checked in and thoroughly reviewed
+  source_module.srcs.update([gn_utils.label_to_path(source)
+                             for source in get_api_java_sources(gn)
+                             if "apihelpers" not in source])
+  source_module.comment += "\n// TODO(danstahr): add the API helpers separately after the main" \
+                           " API is checked in and thoroughly reviewed"
+  source_module.srcs.update([
+    ':' + create_action_module(blueprint, gn.get_target(dep), 'java_genrule', False).name
+    for dep in get_api_java_actions(gn)])
+  blueprint.add_module(source_module)
+  return source_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):
+def create_blueprint_for_targets(gn, targets, test_targets):
   """Generate a blueprint for a list of GN targets."""
   blueprint = Blueprint()
 
@@ -1515,19 +1712,19 @@
       '-Wno-sign-promo',
       '-Wno-unused-parameter',
       '-Wno-null-pointer-subtraction', # Needed to libevent
-      '-Wno-deprecated-non-prototype', # needed for zlib
-      '-fvisibility=hidden',
       '-Wno-ambiguous-reversed-operator', # needed for icui18n
       '-Wno-unreachable-code-loop-increment', # needed for icui18n
-      '-O2',
       '-fPIC',
+      '-Wno-c++11-narrowing',
   ]
   # 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
@@ -1537,14 +1734,22 @@
       '-UANDROID',
   ]
   defaults.stl = 'none'
+  defaults.cpp_std = 'c++17'
   defaults.min_sdk_version = 29
   defaults.apex_available.add(tethering_apex)
   blueprint.add_module(defaults)
 
   for target in targets:
-    create_modules_from_target(blueprint, gn, target)
+    create_modules_from_target(blueprint, gn, target, is_test_target=False)
 
-  create_java_module(blueprint, gn)
+  for test_target in test_targets:
+    create_modules_from_target(blueprint, gn, test_target + gn_utils.TESTING_SUFFIX, is_test_target=True)
+
+  create_java_api_module(blueprint, gn)
+  java_module = create_java_module(blueprint, gn, is_test_target=False)
+  java_module.libs.add(CRONET_API_MODULE_NAME)
+  java_module_testing = create_java_module(blueprint, gn, is_test_target=True)
+  java_module_testing.libs.add(CRONET_API_MODULE_NAME)
   for module in blueprint.modules.values():
     if 'cronet_jni_registration' in module.name:
       update_jni_registration_module(module, gn)
@@ -1569,6 +1774,55 @@
 
   return blueprint
 
+def create_license_module(blueprint):
+  module = Module("license", "external_cronet_license", "LICENSE")
+  module.license_kinds.update({
+      'SPDX-license-identifier-MPL',
+      'SPDX-license-identifier-MPL-1.1',
+      'SPDX-license-identifier-ISC',
+      'SPDX-license-identifier-AFL-2.0',
+      'SPDX-license-identifier-MPL-2.0',
+      'SPDX-license-identifier-BSD',
+      'SPDX-license-identifier-Apache-2.0',
+      'SPDX-license-identifier-BSL-1.0',
+      'SPDX-license-identifier-Unicode-DFS',
+      'SPDX-license-identifier-NCSA',
+      'SPDX-license-identifier-OpenSSL',
+      'SPDX-license-identifier-MIT',
+      "SPDX-license-identifier-ICU",
+      'legacy_unencumbered',
+  })
+  module.license_text.update({
+      "LICENSE",
+      "net/third_party/uri_template/LICENSE",
+      "net/third_party/quiche/src/LICENSE",
+      "base/third_party/symbolize/LICENSE",
+      "base/third_party/superfasthash/LICENSE",
+      "base/third_party/xdg_user_dirs/LICENSE",
+      "base/third_party/double_conversion/LICENSE",
+      "base/third_party/nspr/LICENSE",
+      "base/third_party/dynamic_annotations/LICENSE",
+      "base/third_party/icu/LICENSE",
+      "base/third_party/valgrind/LICENSE",
+      "third_party/brotli/LICENSE",
+      "third_party/protobuf/LICENSE",
+      "third_party/protobuf/third_party/utf8_range/LICENSE",
+      "third_party/metrics_proto/LICENSE",
+      "third_party/boringssl/src/LICENSE",
+      "third_party/boringssl/src/third_party/googletest/LICENSE",
+      "third_party/boringssl/src/third_party/wycheproof_testvectors/LICENSE",
+      "third_party/boringssl/src/third_party/fiat/LICENSE",
+      "third_party/libevent/LICENSE",
+      "third_party/ashmem/LICENSE",
+      "third_party/icu/LICENSE",
+      "third_party/icu/scripts/LICENSE",
+      "third_party/abseil-cpp/LICENSE",
+      "third_party/modp_b64/LICENSE",
+  })
+  default_license = Module("package", "", "PACKAGE")
+  default_license.default_applicable_licenses.add(module.name)
+  blueprint.add_module(module)
+  blueprint.add_module(default_license)
 
 def main():
   parser = argparse.ArgumentParser(
@@ -1606,21 +1860,23 @@
   if args.verbose:
     log.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', level=log.DEBUG)
 
-  targets = args.targets or default_targets
+  targets = args.targets or DEFAULT_TARGETS
   gn = gn_utils.GnParser(builtin_deps)
   for desc_file in args.desc:
     with open(desc_file) as f:
       desc = json.load(f)
     for target in targets:
       gn.parse_gn_desc(desc, target)
-  blueprint = create_blueprint_for_targets(gn, targets)
+    for test_target in DEFAULT_TESTS:
+      gn.parse_gn_desc(desc, test_target, is_test_target=True)
+  blueprint = create_blueprint_for_targets(gn, targets, DEFAULT_TESTS)
   project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
   tool_name = os.path.relpath(os.path.abspath(__file__), project_root)
 
   # Add any proto groups to the blueprint.
   for l_name, t_names in proto_groups.items():
     create_proto_group_modules(blueprint, gn, l_name, t_names)
-
+  create_license_module(blueprint)
   output = [
       """// Copyright (C) 2022 The Android Open Source Project
 //
@@ -1637,6 +1893,8 @@
 // limitations under the License.
 //
 // This file is automatically generated by %s. Do not edit.
+
+build = ["Android.extras.bp"]
 """ % (tool_name)
   ]
   blueprint.to_string(output)
diff --git a/tools/gn2bp/gen_desc_json.sh b/tools/gn2bp/gen_desc_json.sh
new file mode 100755
index 0000000..bf9b21d
--- /dev/null
+++ b/tools/gn2bp/gen_desc_json.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+set -x
+
+# Run this script inside a full chromium checkout.
+
+OUT_PATH="out/cronet"
+
+#######################################
+# Apply patches in external/cronet.
+# Globals:
+#   ANDROID_BUILD_TOP
+# Arguments:
+#   None
+#######################################
+function apply_patches() {
+  local -r patch_root="${ANDROID_BUILD_TOP}/external/cronet/patches"
+
+  local upstream_patches
+  upstream_patches=$(ls "${patch_root}/upstream-next")
+  local patch
+  for patch in ${upstream_patches}; do
+    git am --3way "${patch_root}/upstream-next/${patch}"
+  done
+
+  local local_patches
+  local_patches=$(ls "${patch_root}/local")
+  for patch in ${local_patches}; do
+    git am --3way "${patch_root}/local/${patch}"
+  done
+}
+
+#######################################
+# 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"
+    "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"
+    "enable_reporting = true"
+    "use_hashed_jni_names = true"
+    "enable_base_tracing = false"
+    "is_cronet_build = true"
+    "is_debug = false"
+    "is_official_build = true"
+    "use_nss_certs = false"
+    "clang_use_default_sample_profile = false"
+    "media_use_ffmpeg=false"
+    "use_thin_lto=false"
+    "enable_resource_allowlist_generation=false"
+    "enable_jdk_library_desugaring=false"
+    "exclude_unwind_tables=true"
+    "symbol_level=1"
+  )
+  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}"
+}
+
+apply_patches
+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..09a7b80 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'
@@ -45,6 +46,8 @@
 }
 ARCH_REGEX = r'(android_x86_64|android_x86|android_arm|android_arm64|host)'
 RESPONSE_FILE = '{{response_file_name}}'
+TESTING_SUFFIX = "__testing"
+AIDL_INCLUDE_DIRS_REGEX = r'--includes=\[(.*)\]'
 
 def repo_root():
   """Returns an absolute path to the repository root."""
@@ -52,6 +55,18 @@
       os.path.realpath(os.path.dirname(__file__)), os.path.pardir)
 
 
+def _clean_string(str):
+  return str.replace('\\', '').replace('../../', '').replace('"', '').strip()
+
+
+def _extract_includes_from_aidl_args(args):
+  for arg in args:
+    is_match = re.match(AIDL_INCLUDE_DIRS_REGEX, arg)
+    if is_match:
+      local_includes = is_match.group(1).split(",")
+      return [_clean_string(local_include) for local_include in local_includes]
+  return []
+
 def label_to_path(label):
   """Turn a GN output label (e.g., //some_dir/file.cc) into a path."""
   assert label.startswith('//')
@@ -77,7 +92,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(
@@ -118,6 +133,7 @@
         self.deps = set()
         self.transitive_static_libs_deps = set()
         self.source_set_deps = set()
+        self.ldflags = set()
 
         # These are valid only for type == 'action'
         self.inputs = set()
@@ -206,7 +222,7 @@
                   'libs', 'proto_paths'):
         self.__dict__[key].update(other.__dict__.get(key, []))
 
-      for key_in_arch in ('cflags', 'defines', 'include_dirs', 'source_set_deps'):
+      for key_in_arch in ('cflags', 'defines', 'include_dirs', 'source_set_deps', 'ldflags'):
         self.arch[arch].__dict__[key_in_arch].update(
           other.arch[arch].__dict__.get(key_in_arch, []))
 
@@ -249,9 +265,12 @@
         return
 
       for key in ('sources', 'cflags', 'defines', 'include_dirs', 'deps', 'source_set_deps',
-                  'inputs', 'outputs', 'args', 'script', 'response_file_contents'):
+                  'inputs', 'outputs', 'args', 'script', 'response_file_contents', 'ldflags'):
         self._finalize_attribute(key)
 
+    def get_target_name(self):
+      return self.name[self.name.find(":") + 1:]
+
 
   def __init__(self, builtin_deps):
     self.builtin_deps = builtin_deps
@@ -260,8 +279,9 @@
     self.source_sets = {}
     self.actions = {}
     self.proto_libs = {}
-    self.java_sources = set()
-    self.java_actions = set()
+    self.java_sources = collections.defaultdict(set)
+    self.aidl_local_include_dirs = set()
+    self.java_actions = collections.defaultdict(set)
 
   def _get_response_file_contents(self, action_desc):
     # response_file_contents are formatted as:
@@ -307,7 +327,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, is_test_target=False):
     """Parses a gn desc tree and resolves all target dependencies.
 
         It bubbles up variables from source_set dependencies as described in the
@@ -320,7 +340,11 @@
     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
+
+    if is_test_target:
+      target_name += TESTING_SUFFIX
 
     target = self.all_targets.get(target_name)
     if target is None:
@@ -390,7 +414,7 @@
 
     target.arch[arch].cflags.update(desc.get('cflags', []) + desc.get('cflags_cc', []))
     target.libs.update(desc.get('libs', []))
-    target.ldflags.update(desc.get('ldflags', []))
+    target.arch[arch].ldflags.update(desc.get('ldflags', []))
     target.arch[arch].defines.update(desc.get('defines', []))
     target.arch[arch].include_dirs.update(desc.get('include_dirs', []))
     target.output_name = desc.get('output_name', None)
@@ -399,7 +423,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, is_test_target)
       if dep.type == 'proto_library':
         target.proto_deps.add(dep.name)
         target.transitive_proto_deps.add(dep.name)
@@ -410,6 +434,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 +473,23 @@
         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)
+          if not is_test_target:
+            # TODO(aymanm): Fix collecting sources for testing modules for java.
+            # Don't collect java source files for test targets.
+            # We only need a specific set of java sources which are hardcoded in gen_android_bp
+            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.
+        # GN uses an action to compile aidl files. However, this is not needed in soong
+        # as 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)
+        if '_aidl' in dep.name:
+          self.java_sources[java_group_name].update(dep.arch[arch].sources)
+          self.aidl_local_include_dirs.update(_extract_includes_from_aidl_args(dep.arch[arch].args))
         else:
-          self.java_actions.add(dep.name)
+          if not is_test_target:
+            # TODO(aymanm): Fix collecting actions for testing modules for java.
+            # Don't collect java actions for test targets.
+            self.java_actions[java_group_name].add(dep.name)
     return target
 
   def get_proto_exports(self, proto_desc):