Merge changes Iddc8975b,I2cedd584 into main

* changes:
  Add diagnostics on failure for PrivateDns test
  Wait for default route for wifi check
diff --git a/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt
index 8e27c62..c42d9e5 100644
--- a/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt
+++ b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt
@@ -19,7 +19,7 @@
 import android.Manifest.permission.NETWORK_SETTINGS
 import android.content.pm.PackageManager.FEATURE_TELEPHONY
 import android.content.pm.PackageManager.FEATURE_WIFI
-import android.net.LinkAddress
+import android.net.InetAddresses.parseNumericAddress
 import android.net.Network
 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
 import android.net.NetworkCapabilities.TRANSPORT_WIFI
@@ -66,7 +66,8 @@
     // Skip IPv6 checks on virtual devices which do not support it. Tests that require IPv6 will
     // still fail even if the preparer does not.
     private fun ipv6Unsupported(wifiSsid: String?) = ConnectUtil.VIRTUAL_SSIDS.contains(
-        WifiInfo.sanitizeSsid(wifiSsid))
+        WifiInfo.sanitizeSsid(wifiSsid)
+    )
 
     @Test
     fun testCheckWifiSetup() {
@@ -89,13 +90,25 @@
                 pos = 0,
                 timeoutMs = 30_000L
             ) {
-                it is LinkPropertiesChanged &&
-                it.network == network &&
-                it.lp.allLinkAddresses.any(LinkAddress::isIpv4) &&
-                        (ipv6Unsupported(ssid) || it.lp.hasGlobalIpv6Address())
+                if (it !is LinkPropertiesChanged || it.network != network) {
+                    false
+                } else {
+                    // Same check as used by DnsResolver for AI_ADDRCONFIG (have_ipv4)
+                    val ipv4Reachable = it.lp.isReachable(parseNumericAddress("8.8.8.8"))
+                    // Same check as used by DnsResolver for AI_ADDRCONFIG (have_ipv6)
+                    val ipv6Reachable = it.lp.isReachable(parseNumericAddress("2000::"))
+                    ipv4Reachable && (ipv6Unsupported(ssid) || ipv6Reachable)
+                }
             }
-            assertNotNull(lpChange, "Wifi network $network needs an IPv4 address" +
-                    if (ipv6Unsupported(ssid)) "" else " and a global IPv6 address")
+            assertNotNull(
+                lpChange,
+                "Wifi network $network needs an IPv4 address and default route" +
+                        if (ipv6Unsupported(ssid)) {
+                            ""
+                        } else {
+                            " and a global IPv6 address and default route"
+                        }
+            )
 
             Pair(network, ssid)
         }
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
index d4ea78c..c7d6850 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
@@ -419,15 +419,29 @@
      * @param exceptionContext An exception to write a stacktrace to the dump for context.
      */
     fun collectDumpsysConnectivity(exceptionContext: Throwable? = null) {
-        Log.i(TAG, "Collecting dumpsys connectivity for test artifacts")
+        collectDumpsys("connectivity --dump-priority HIGH", exceptionContext)
+    }
+
+    /**
+     * Add a dumpsys to the test data dump.
+     *
+     * <p>The dump will be collected immediately, and exported to a test artifact file when the
+     * test ends.
+     * @param dumpsysCmd The dumpsys command to run (for example "connectivity").
+     * @param exceptionContext An exception to write a stacktrace to the dump for context.
+     */
+    fun collectDumpsys(dumpsysCmd: String, exceptionContext: Throwable? = null) {
+        Log.i(TAG, "Collecting dumpsys $dumpsysCmd for test artifacts")
         PrintWriter(buffer).let {
-            it.println("--- Dumpsys connectivity at ${ZonedDateTime.now()} ---")
+            it.println("--- Dumpsys $dumpsysCmd at ${ZonedDateTime.now()} ---")
             maybeWriteExceptionContext(it, exceptionContext)
             it.flush()
         }
         ParcelFileDescriptor.AutoCloseInputStream(
             InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand(
-                "dumpsys connectivity --dump-priority HIGH")).use {
+                "dumpsys $dumpsysCmd"
+            )
+        ).use {
             it.copyTo(buffer)
         }
     }
@@ -446,4 +460,4 @@
         writer.println("At: ")
         exceptionContext.printStackTrace(writer)
     }
-}
\ No newline at end of file
+}
diff --git a/tests/cts/net/src/android/net/cts/DnsResolverTest.java b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
index fa44ae9..b66b853 100644
--- a/tests/cts/net/src/android/net/cts/DnsResolverTest.java
+++ b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
@@ -58,6 +58,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.net.module.util.DnsPacket;
+import com.android.testutils.ConnectivityDiagnosticsCollector;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 import com.android.testutils.DeviceConfigRule;
@@ -394,7 +395,22 @@
     @Test
     @DnsResolverModuleTest
     public void testRawQueryNXDomainWithPrivateDns() throws Exception {
-        doTestRawQueryNXDomainWithPrivateDns(mExecutor);
+        try {
+            doTestRawQueryNXDomainWithPrivateDns(mExecutor);
+        } catch (Throwable e) {
+            final ConnectivityDiagnosticsCollector collector =
+                    ConnectivityDiagnosticsCollector.getInstance();
+            if (collector != null) {
+                // IWLAN on U QPR3 release may cause failures in this test, see
+                // CarrierConfigSetupTest which is supposed to avoid the issue. Collect IWLAN
+                // related dumpsys if the test still fails.
+                collector.collectDumpsys("carrier_config", e);
+                collector.collectDumpsys("telecom", e);
+                collector.collectDumpsys("telephony_ims", e);
+                collector.collectDumpsys("telephony.registry", e);
+            }
+            throw e;
+        }
     }
 
     @Test