Merge "Use filegroup defaults for framework sources"
diff --git a/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
index 7b17ca6..8af544e 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
@@ -89,6 +89,21 @@
     }
 
     @Test
+    fun testDnsOptions_setStaleDnsOptions_returnsSetValues() {
+        val staleOptions = DnsOptions.StaleDnsOptions.Builder()
+                .setAllowCrossNetworkUsageEnabled(DNS_OPTION_ENABLED)
+                .setFreshLookupTimeout(Duration.ofMillis(1234))
+                .build()
+        val options = DnsOptions.Builder()
+                .setStaleDnsEnabled(DNS_OPTION_ENABLED)
+                .setStaleDnsOptions(staleOptions)
+                .build()
+
+        assertEquals(DNS_OPTION_ENABLED, options.staleDnsEnabled)
+        assertEquals(staleOptions, options.staleDnsOptions)
+    }
+
+    @Test
     fun testStaleDnsOptions_defaultValues() {
         val options = DnsOptions.StaleDnsOptions.Builder().build()
 
diff --git a/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java b/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
index 816596c..0be3ea1 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
@@ -30,6 +30,8 @@
 
 import android.content.Context;
 import android.net.Network;
+import android.net.http.ConnectionMigrationOptions;
+import android.net.http.DnsOptions;
 import android.net.http.HttpEngine;
 import android.net.http.UrlRequest;
 import android.net.http.UrlResponseInfo;
@@ -301,4 +303,34 @@
         UrlResponseInfo info = mCallback.mResponseInfo;
         assertOKStatusCode(info);
     }
+
+    @Test
+    public void testHttpEngine_setConnectionMigrationOptions_requestSucceeds() {
+        ConnectionMigrationOptions options = new ConnectionMigrationOptions.Builder().build();
+        mEngine = mEngineBuilder.setConnectionMigrationOptions(options).build();
+        UrlRequest.Builder builder =
+                mEngine.newUrlRequestBuilder(
+                        mTestServer.getSuccessUrl(), mCallback.getExecutor(), mCallback);
+        mRequest = builder.build();
+        mRequest.start();
+
+        mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+        UrlResponseInfo info = mCallback.mResponseInfo;
+        assertOKStatusCode(info);
+    }
+
+    @Test
+    public void testHttpEngine_setDnsOptions_requestSucceeds() {
+        DnsOptions options = new DnsOptions.Builder().build();
+        mEngine = mEngineBuilder.setDnsOptions(options).build();
+        UrlRequest.Builder builder =
+                mEngine.newUrlRequestBuilder(
+                        mTestServer.getSuccessUrl(), mCallback.getExecutor(), mCallback);
+        mRequest = builder.build();
+        mRequest.start();
+
+        mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+        UrlResponseInfo info = mCallback.mResponseInfo;
+        assertOKStatusCode(info);
+    }
 }
\ No newline at end of file
diff --git a/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt
index 5f9b7d4..a05aecd 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt
@@ -18,6 +18,7 @@
 import android.net.http.QuicOptions
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.google.common.truth.Truth.assertThat
+import java.time.Duration
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -28,8 +29,7 @@
         val quicOptions = QuicOptions.Builder().build()
         assertThat(quicOptions.allowedQuicHosts).isEmpty()
         assertThat(quicOptions.handshakeUserAgent).isNull()
-        // TODO(danstahr): idleConnectionTimeout getter should be public
-        // assertThat(quicOptions.idleConnectionTimeout).isNull()
+        assertThat(quicOptions.idleConnectionTimeout).isNull()
         assertThat(quicOptions.inMemoryServerConfigsCacheSize).isNull()
     }
 
@@ -46,8 +46,6 @@
                 .inOrder()
     }
 
-    // TODO(danstahr): idleConnectionTimeout getter should be public
-    /*
     @Test
     fun testQuicOptions_idleConnectionTimeout_returnsSetValue() {
         val timeout = Duration.ofMinutes(10)
@@ -57,7 +55,6 @@
         assertThat(quicOptions.idleConnectionTimeout)
                 .isEqualTo(timeout)
     }
-    */
 
     @Test
     fun testQuicOptions_inMemoryServerConfigsCacheSize_returnsSetValue() {
diff --git a/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java b/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
index 2ec035b..e24121f 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
@@ -288,6 +288,24 @@
     }
 
     @Test
+    public void testUrlRequest_redirects() throws Exception {
+        int expectedNumRedirects = 5;
+        String url =
+                mTestServer.getRedirectingAssetUrl("html/hello_world.html", expectedNumRedirects);
+
+        UrlRequest request = createUrlRequestBuilder(url).build();
+        request.start();
+
+        mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+        UrlResponseInfo info = mCallback.mResponseInfo;
+        assertOKStatusCode(info);
+        assertThat(mCallback.mResponseAsString).contains("hello world");
+        assertThat(info.getUrlChain()).hasSize(expectedNumRedirects + 1);
+        assertThat(info.getUrlChain().get(0)).isEqualTo(url);
+        assertThat(info.getUrlChain().get(expectedNumRedirects)).isEqualTo(info.getUrl());
+    }
+
+    @Test
     public void testUrlRequestPost_withRedirect() throws Exception {
         String body = Strings.repeat(
                 "Hello, this is a really interesting body, so write this 100 times.", 100);
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
index 95afa56..98c873d 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
@@ -48,7 +48,6 @@
 import android.stats.connectivity.ErrorCode;
 import android.stats.connectivity.UpstreamType;
 import android.stats.connectivity.UserType;
-import android.util.Pair;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -99,11 +98,8 @@
         mTetheringMetrics.sendReport(downstream);
     }
 
-    private void runDownstreamTypesTest(final Pair<Integer, DownstreamType> testPair)
+    private void runDownstreamTypesTest(final int type, final DownstreamType expectedResult)
             throws Exception {
-        final int type = testPair.first;
-        final DownstreamType expectedResult = testPair.second;
-
         mTetheringMetrics.createBuilder(type, TEST_CALLER_PKG);
         updateErrorAndSendReport(type, TETHER_ERROR_NO_ERROR);
         verifyReport(expectedResult, ErrorCode.EC_NO_ERROR, UserType.USER_UNKNOWN);
@@ -112,22 +108,16 @@
 
     @Test
     public void testDownstreamTypes() throws Exception {
-        runDownstreamTypesTest(new Pair<>(TETHERING_WIFI, DownstreamType.DS_TETHERING_WIFI));
-        runDownstreamTypesTest(new Pair<>(TETHERING_WIFI_P2P,
-                DownstreamType.DS_TETHERING_WIFI_P2P));
-        runDownstreamTypesTest(new Pair<>(TETHERING_BLUETOOTH,
-                DownstreamType.DS_TETHERING_BLUETOOTH));
-        runDownstreamTypesTest(new Pair<>(TETHERING_USB, DownstreamType.DS_TETHERING_USB));
-        runDownstreamTypesTest(new Pair<>(TETHERING_NCM, DownstreamType.DS_TETHERING_NCM));
-        runDownstreamTypesTest(new Pair<>(TETHERING_ETHERNET,
-                DownstreamType.DS_TETHERING_ETHERNET));
+        runDownstreamTypesTest(TETHERING_WIFI, DownstreamType.DS_TETHERING_WIFI);
+        runDownstreamTypesTest(TETHERING_WIFI_P2P, DownstreamType.DS_TETHERING_WIFI_P2P);
+        runDownstreamTypesTest(TETHERING_BLUETOOTH, DownstreamType.DS_TETHERING_BLUETOOTH);
+        runDownstreamTypesTest(TETHERING_USB, DownstreamType.DS_TETHERING_USB);
+        runDownstreamTypesTest(TETHERING_NCM, DownstreamType.DS_TETHERING_NCM);
+        runDownstreamTypesTest(TETHERING_ETHERNET, DownstreamType.DS_TETHERING_ETHERNET);
     }
 
-    private void runErrorCodesTest(final Pair<Integer, ErrorCode> testPair)
+    private void runErrorCodesTest(final int errorCode, final ErrorCode expectedResult)
             throws Exception {
-        final int errorCode = testPair.first;
-        final ErrorCode expectedResult = testPair.second;
-
         mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG);
         updateErrorAndSendReport(TETHERING_WIFI, errorCode);
         verifyReport(DownstreamType.DS_TETHERING_WIFI, expectedResult, UserType.USER_UNKNOWN);
@@ -135,39 +125,31 @@
 
     @Test
     public void testErrorCodes() throws Exception {
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_NO_ERROR, ErrorCode.EC_NO_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_UNKNOWN_IFACE, ErrorCode.EC_UNKNOWN_IFACE));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_SERVICE_UNAVAIL, ErrorCode.EC_SERVICE_UNAVAIL));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_UNSUPPORTED, ErrorCode.EC_UNSUPPORTED));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_UNAVAIL_IFACE, ErrorCode.EC_UNAVAIL_IFACE));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_INTERNAL_ERROR, ErrorCode.EC_INTERNAL_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_TETHER_IFACE_ERROR,
-                ErrorCode.EC_TETHER_IFACE_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_UNTETHER_IFACE_ERROR,
-                ErrorCode.EC_UNTETHER_IFACE_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_ENABLE_FORWARDING_ERROR,
-                ErrorCode.EC_ENABLE_FORWARDING_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_DISABLE_FORWARDING_ERROR,
-                ErrorCode.EC_DISABLE_FORWARDING_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_IFACE_CFG_ERROR, ErrorCode.EC_IFACE_CFG_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_PROVISIONING_FAILED,
-                ErrorCode.EC_PROVISIONING_FAILED));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_DHCPSERVER_ERROR,
-                ErrorCode.EC_DHCPSERVER_ERROR));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_ENTITLEMENT_UNKNOWN,
-                ErrorCode.EC_ENTITLEMENT_UNKNOWN));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
-                ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION,
-                ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION));
-        runErrorCodesTest(new Pair<>(TETHER_ERROR_UNKNOWN_TYPE, ErrorCode.EC_UNKNOWN_TYPE));
+        runErrorCodesTest(TETHER_ERROR_NO_ERROR, ErrorCode.EC_NO_ERROR);
+        runErrorCodesTest(TETHER_ERROR_UNKNOWN_IFACE, ErrorCode.EC_UNKNOWN_IFACE);
+        runErrorCodesTest(TETHER_ERROR_SERVICE_UNAVAIL, ErrorCode.EC_SERVICE_UNAVAIL);
+        runErrorCodesTest(TETHER_ERROR_UNSUPPORTED, ErrorCode.EC_UNSUPPORTED);
+        runErrorCodesTest(TETHER_ERROR_UNAVAIL_IFACE, ErrorCode.EC_UNAVAIL_IFACE);
+        runErrorCodesTest(TETHER_ERROR_INTERNAL_ERROR, ErrorCode.EC_INTERNAL_ERROR);
+        runErrorCodesTest(TETHER_ERROR_TETHER_IFACE_ERROR, ErrorCode.EC_TETHER_IFACE_ERROR);
+        runErrorCodesTest(TETHER_ERROR_UNTETHER_IFACE_ERROR, ErrorCode.EC_UNTETHER_IFACE_ERROR);
+        runErrorCodesTest(TETHER_ERROR_ENABLE_FORWARDING_ERROR,
+                ErrorCode.EC_ENABLE_FORWARDING_ERROR);
+        runErrorCodesTest(TETHER_ERROR_DISABLE_FORWARDING_ERROR,
+                ErrorCode.EC_DISABLE_FORWARDING_ERROR);
+        runErrorCodesTest(TETHER_ERROR_IFACE_CFG_ERROR, ErrorCode.EC_IFACE_CFG_ERROR);
+        runErrorCodesTest(TETHER_ERROR_PROVISIONING_FAILED, ErrorCode.EC_PROVISIONING_FAILED);
+        runErrorCodesTest(TETHER_ERROR_DHCPSERVER_ERROR, ErrorCode.EC_DHCPSERVER_ERROR);
+        runErrorCodesTest(TETHER_ERROR_ENTITLEMENT_UNKNOWN, ErrorCode.EC_ENTITLEMENT_UNKNOWN);
+        runErrorCodesTest(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
+                ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION);
+        runErrorCodesTest(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION,
+                ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION);
+        runErrorCodesTest(TETHER_ERROR_UNKNOWN_TYPE, ErrorCode.EC_UNKNOWN_TYPE);
     }
 
-    private void runUserTypesTest(final Pair<String, UserType> testPair)
+    private void runUserTypesTest(final String callerPkg, final UserType expectedResult)
             throws Exception {
-        final String callerPkg = testPair.first;
-        final UserType expectedResult = testPair.second;
-
         mTetheringMetrics.createBuilder(TETHERING_WIFI, callerPkg);
         updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
         verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR, expectedResult);
@@ -176,10 +158,10 @@
 
     @Test
     public void testUserTypes() throws Exception {
-        runUserTypesTest(new Pair<>(TEST_CALLER_PKG, UserType.USER_UNKNOWN));
-        runUserTypesTest(new Pair<>(SETTINGS_PKG, UserType.USER_SETTINGS));
-        runUserTypesTest(new Pair<>(SYSTEMUI_PKG, UserType.USER_SYSTEMUI));
-        runUserTypesTest(new Pair<>(GMS_PKG, UserType.USER_GMS));
+        runUserTypesTest(TEST_CALLER_PKG, UserType.USER_UNKNOWN);
+        runUserTypesTest(SETTINGS_PKG, UserType.USER_SETTINGS);
+        runUserTypesTest(SYSTEMUI_PKG, UserType.USER_SYSTEMUI);
+        runUserTypesTest(GMS_PKG, UserType.USER_GMS);
     }
 
     @Test
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index e969cd6..2af30dd 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -10734,6 +10734,18 @@
                         callback));
     }
 
+    private boolean hasUnderlyingTestNetworks(NetworkCapabilities nc) {
+        final List<Network> underlyingNetworks = nc.getUnderlyingNetworks();
+        if (underlyingNetworks == null) return false;
+
+        for (Network network : underlyingNetworks) {
+            if (getNetworkCapabilitiesInternal(network).hasTransport(TRANSPORT_TEST)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public void simulateDataStall(int detectionMethod, long timestampMillis,
             @NonNull Network network, @NonNull PersistableBundle extras) {
@@ -10744,14 +10756,18 @@
                 android.Manifest.permission.MANAGE_TEST_NETWORKS,
                 android.Manifest.permission.NETWORK_STACK);
         final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
-        if (!nc.hasTransport(TRANSPORT_TEST)) {
-            throw new SecurityException("Data Stall simulation is only possible for test networks");
+        if (!nc.hasTransport(TRANSPORT_TEST) && !hasUnderlyingTestNetworks(nc)) {
+            throw new SecurityException(
+                    "Data Stall simulation is only possible for test networks or networks built on"
+                            + " top of test networks");
         }
 
         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
-        if (nai == null || nai.creatorUid != mDeps.getCallingUid()) {
-            throw new SecurityException("Data Stall simulation is only possible for network "
-                + "creators");
+        if (nai == null
+                || (nai.creatorUid != mDeps.getCallingUid()
+                        && nai.creatorUid != Process.SYSTEM_UID)) {
+            throw new SecurityException(
+                    "Data Stall simulation is only possible for network " + "creators");
         }
 
         // Instead of passing the data stall directly to the ConnectivityDiagnostics handler, treat