Merge "Store registered network callbacks and unregister all at tearDown"
diff --git a/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt
index 2701ed0..279bcc8 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt
@@ -17,10 +17,10 @@
 package android.net.http.cts
 
 import android.net.http.ConnectionMigrationOptions
+import android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_ENABLED
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import kotlin.test.Test
-import kotlin.test.assertNotNull
-import kotlin.test.assertTrue
+import kotlin.test.assertEquals
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
@@ -29,18 +29,20 @@
     @Test
     fun testConnectionMigrationOptions_enableDefaultNetworkMigration_returnSetValue() {
         val options =
-            ConnectionMigrationOptions.Builder().setEnableDefaultNetworkMigration(true).build()
+            ConnectionMigrationOptions.Builder()
+                    .setDefaultNetworkMigrationEnabled(MIGRATION_OPTION_ENABLED)
+                    .build()
 
-        assertNotNull(options.enableDefaultNetworkMigration)
-        assertTrue(options.enableDefaultNetworkMigration!!)
+        assertEquals(MIGRATION_OPTION_ENABLED, options.defaultNetworkMigrationEnabled)
     }
 
     @Test
     fun testConnectionMigrationOptions_enablePathDegradationMigration_returnSetValue() {
         val options =
-            ConnectionMigrationOptions.Builder().setEnablePathDegradationMigration(true).build()
+            ConnectionMigrationOptions.Builder()
+                    .setPathDegradationMigrationEnabled(MIGRATION_OPTION_ENABLED)
+                    .build()
 
-        assertNotNull(options.enablePathDegradationMigration)
-        assertTrue(options.enablePathDegradationMigration!!)
+        assertEquals(MIGRATION_OPTION_ENABLED, options.pathDegradationMigrationEnabled)
     }
 }
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 b96e931..7b17ca6 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
@@ -17,13 +17,14 @@
 package android.net.http.cts
 
 import android.net.http.DnsOptions
+import android.net.http.DnsOptions.DNS_OPTION_ENABLED
+import android.net.http.DnsOptions.DNS_OPTION_UNSPECIFIED
 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)
@@ -33,20 +34,22 @@
     fun testDnsOptions_defaultValues() {
         val options = DnsOptions.Builder().build()
 
-        assertNull(options.persistHostCache)
+        assertEquals(DNS_OPTION_UNSPECIFIED, options.persistHostCacheEnabled)
         assertNull(options.persistHostCachePeriod)
-        assertNull(options.enableStaleDns)
+        assertEquals(DNS_OPTION_UNSPECIFIED, options.staleDnsEnabled)
         assertNull(options.staleDnsOptions)
-        assertNull(options.useHttpStackDnsResolver)
-        assertNull(options.preestablishConnectionsToStaleDnsResults)
+        assertEquals(DNS_OPTION_UNSPECIFIED, options.useHttpStackDnsResolverEnabled)
+        assertEquals(DNS_OPTION_UNSPECIFIED,
+                options.preestablishConnectionsToStaleDnsResultsEnabled)
     }
 
     @Test
     fun testDnsOptions_persistHostCache_returnSetValue() {
-        val options = DnsOptions.Builder().setPersistHostCache(true).build()
+        val options = DnsOptions.Builder()
+                .setPersistHostCacheEnabled(DNS_OPTION_ENABLED)
+                .build()
 
-        assertNotNull(options.persistHostCache)
-        assertTrue(options.persistHostCache!!)
+        assertEquals(DNS_OPTION_ENABLED, options.persistHostCacheEnabled)
     }
 
     @Test
@@ -59,44 +62,48 @@
 
     @Test
     fun testDnsOptions_enableStaleDns_returnSetValue() {
-        val options = DnsOptions.Builder().setEnableStaleDns(true).build()
+        val options = DnsOptions.Builder()
+                .setStaleDnsEnabled(DNS_OPTION_ENABLED)
+                .build()
 
-        assertNotNull(options.enableStaleDns)
-        assertTrue(options.enableStaleDns!!)
+        assertEquals(DNS_OPTION_ENABLED, options.staleDnsEnabled)
     }
 
     @Test
     fun testDnsOptions_useHttpStackDnsResolver_returnsSetValue() {
-        val options = DnsOptions.Builder().setUseHttpStackDnsResolver(true).build()
+        val options = DnsOptions.Builder()
+                .setUseHttpStackDnsResolverEnabled(DNS_OPTION_ENABLED)
+                .build()
 
-        assertNotNull(options.useHttpStackDnsResolver)
-        assertTrue(options.useHttpStackDnsResolver!!)
+        assertEquals(DNS_OPTION_ENABLED, options.useHttpStackDnsResolverEnabled)
     }
 
     @Test
     fun testDnsOptions_preestablishConnectionsToStaleDnsResults_returnsSetValue() {
-        val options = DnsOptions.Builder().setPreestablishConnectionsToStaleDnsResults(true).build()
+        val options = DnsOptions.Builder()
+                .setPreestablishConnectionsToStaleDnsResultsEnabled(DNS_OPTION_ENABLED)
+                .build()
 
-        assertNotNull(options.preestablishConnectionsToStaleDnsResults)
-        assertTrue(options.preestablishConnectionsToStaleDnsResults!!)
+        assertEquals(DNS_OPTION_ENABLED,
+                options.preestablishConnectionsToStaleDnsResultsEnabled)
     }
 
     @Test
     fun testStaleDnsOptions_defaultValues() {
         val options = DnsOptions.StaleDnsOptions.Builder().build()
 
-        assertNull(options.allowCrossNetworkUsage)
-        assertNull(options.freshLookupTimeoutMillis)
-        assertNull(options.maxExpiredDelayMillis)
-        assertNull(options.useStaleOnNameNotResolved)
+        assertEquals(DNS_OPTION_UNSPECIFIED, options.allowCrossNetworkUsageEnabled)
+        assertNull(options.freshLookupTimeout)
+        assertNull(options.maxExpiredDelay)
+        assertEquals(DNS_OPTION_UNSPECIFIED, options.useStaleOnNameNotResolvedEnabled)
     }
 
     @Test
     fun testStaleDnsOptions_allowCrossNetworkUsage_returnsSetValue() {
-        val options = DnsOptions.StaleDnsOptions.Builder().setAllowCrossNetworkUsage(true).build()
+        val options = DnsOptions.StaleDnsOptions.Builder()
+                .setAllowCrossNetworkUsageEnabled(DNS_OPTION_ENABLED).build()
 
-        assertNotNull(options.allowCrossNetworkUsage)
-        assertTrue(options.allowCrossNetworkUsage!!)
+        assertEquals(DNS_OPTION_ENABLED, options.allowCrossNetworkUsageEnabled)
     }
 
     @Test
@@ -104,17 +111,17 @@
         val duration = Duration.ofMillis(12345)
         val options = DnsOptions.StaleDnsOptions.Builder().setFreshLookupTimeout(duration).build()
 
-        assertNotNull(options.freshLookupTimeoutMillis)
-        assertEquals(duration.toMillis(), options.freshLookupTimeoutMillis!!)
+        assertNotNull(options.freshLookupTimeout)
+        assertEquals(duration, options.freshLookupTimeout!!)
     }
 
     @Test
     fun testStaleDnsOptions_useStaleOnNameNotResolved_returnsSetValue() {
-        val options =
-                DnsOptions.StaleDnsOptions.Builder().setUseStaleOnNameNotResolved(true).build()
+        val options = DnsOptions.StaleDnsOptions.Builder()
+                .setUseStaleOnNameNotResolvedEnabled(DNS_OPTION_ENABLED)
+                .build()
 
-        assertNotNull(options.useStaleOnNameNotResolved)
-        assertTrue(options.useStaleOnNameNotResolved!!)
+        assertEquals(DNS_OPTION_ENABLED, options.useStaleOnNameNotResolvedEnabled)
     }
 
     @Test
@@ -122,7 +129,7 @@
         val duration = Duration.ofMillis(12345)
         val options = DnsOptions.StaleDnsOptions.Builder().setMaxExpiredDelay(duration).build()
 
-        assertNotNull(options.maxExpiredDelayMillis)
-        assertEquals(duration.toMillis(), options.maxExpiredDelayMillis!!)
+        assertNotNull(options.maxExpiredDelay)
+        assertEquals(duration, options.maxExpiredDelay!!)
     }
 }
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 1888962..5f9b7d4 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt
@@ -26,7 +26,7 @@
     @Test
     fun testQuicOptions_defaultValues() {
         val quicOptions = QuicOptions.Builder().build()
-        assertThat(quicOptions.quicHostAllowlist).isEmpty()
+        assertThat(quicOptions.allowedQuicHosts).isEmpty()
         assertThat(quicOptions.handshakeUserAgent).isNull()
         // TODO(danstahr): idleConnectionTimeout getter should be public
         // assertThat(quicOptions.idleConnectionTimeout).isNull()
@@ -41,7 +41,7 @@
                 .addAllowedQuicHost("foo")
                 .addAllowedQuicHost("baz")
                 .build()
-        assertThat(quicOptions.quicHostAllowlist)
+        assertThat(quicOptions.allowedQuicHosts)
                 .containsExactly("foo", "bar", "baz")
                 .inOrder()
     }
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 18ceb24..d9af171 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
@@ -158,7 +158,7 @@
         UploadDataProvider dataProvider = InMemoryUploadDataProvider.fromUtf8String("test");
         builder.setUploadDataProvider(dataProvider, DIRECT_EXECUTOR);
         builder.addHeader("Content-Type", "text/plain;charset=UTF-8");
-        builder.setAllowDirectExecutor(true);
+        builder.setDirectExecutorAllowed(true);
         builder.build().start();
         callback.blockForDone();
 
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestBidirectionalStreamCallback.java b/Cronet/tests/cts/src/android/net/http/cts/util/TestBidirectionalStreamCallback.java
index e82b24d..1e7333c 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/util/TestBidirectionalStreamCallback.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestBidirectionalStreamCallback.java
@@ -26,6 +26,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.net.http.BidirectionalStream;
+import android.net.http.HeaderBlock;
 import android.net.http.HttpException;
 import android.net.http.UrlResponseInfo;
 import android.os.ConditionVariable;
@@ -43,7 +44,7 @@
  * the stream completes on another thread. Allows to cancel, block stream or throw an exception from
  * an arbitrary step.
  */
-public class TestBidirectionalStreamCallback extends BidirectionalStream.Callback {
+public class TestBidirectionalStreamCallback implements BidirectionalStream.Callback {
     private static final int TIMEOUT_MS = 12_000;
     public UrlResponseInfo mResponseInfo;
     public HttpException mError;
@@ -56,7 +57,7 @@
     public int mHttpResponseDataLength;
     public String mResponseAsString = "";
 
-    public UrlResponseInfo.HeaderBlock mTrailers;
+    public HeaderBlock mTrailers;
 
     private static final int READ_BUFFER_SIZE = 32 * 1024;
 
@@ -337,7 +338,7 @@
     public void onResponseTrailersReceived(
             BidirectionalStream stream,
             UrlResponseInfo info,
-            UrlResponseInfo.HeaderBlock trailers) {
+            HeaderBlock trailers) {
         checkOnValidThread();
         assertFalse(stream.isDone());
         assertNull(mError);
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/current.txt b/Tethering/common/TetheringLib/cronet_enabled/api/current.txt
index 7bdc0e4..c55fb56 100644
--- a/Tethering/common/TetheringLib/cronet_enabled/api/current.txt
+++ b/Tethering/common/TetheringLib/cronet_enabled/api/current.txt
@@ -5,21 +5,18 @@
     ctor public BidirectionalStream();
     method public abstract void cancel();
     method public abstract void flush();
+    method @NonNull public abstract android.net.http.HeaderBlock getHeaders();
+    method @NonNull public abstract String getHttpMethod();
+    method public abstract int getPriority();
+    method public abstract int getTrafficStatsTag();
+    method public abstract int getTrafficStatsUid();
+    method public abstract boolean hasTrafficStatsTag();
+    method public abstract boolean hasTrafficStatsUid();
+    method public abstract boolean isDelayRequestHeadersUntilFirstFlushEnabled();
     method public abstract boolean isDone();
     method public abstract void read(@NonNull java.nio.ByteBuffer);
     method public abstract void start();
     method public abstract void write(@NonNull java.nio.ByteBuffer, boolean);
-  }
-
-  public abstract static class BidirectionalStream.Builder {
-    ctor public BidirectionalStream.Builder();
-    method @NonNull public abstract android.net.http.BidirectionalStream.Builder addHeader(@NonNull String, @NonNull String);
-    method @NonNull public abstract android.net.http.BidirectionalStream build();
-    method @NonNull public abstract android.net.http.BidirectionalStream.Builder delayRequestHeadersUntilFirstFlush(boolean);
-    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setHttpMethod(@NonNull String);
-    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setPriority(int);
-    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setTrafficStatsTag(int);
-    method @NonNull 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
@@ -27,16 +24,26 @@
     field public static final int STREAM_PRIORITY_MEDIUM = 3; // 0x3
   }
 
-  public abstract static class BidirectionalStream.Callback {
-    ctor public BidirectionalStream.Callback();
+  public abstract static class BidirectionalStream.Builder {
+    ctor public BidirectionalStream.Builder();
+    method @NonNull public abstract android.net.http.BidirectionalStream.Builder addHeader(@NonNull String, @NonNull String);
+    method @NonNull public abstract android.net.http.BidirectionalStream build();
+    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setDelayRequestHeadersUntilFirstFlushEnabled(boolean);
+    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setHttpMethod(@NonNull String);
+    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setPriority(int);
+    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setTrafficStatsTag(int);
+    method @NonNull public abstract android.net.http.BidirectionalStream.Builder setTrafficStatsUid(int);
+  }
+
+  public static interface BidirectionalStream.Callback {
     method public void onCanceled(@NonNull android.net.http.BidirectionalStream, @Nullable android.net.http.UrlResponseInfo);
-    method public abstract void onFailed(@NonNull android.net.http.BidirectionalStream, @Nullable android.net.http.UrlResponseInfo, @NonNull android.net.http.HttpException);
-    method public abstract void onReadCompleted(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull java.nio.ByteBuffer, boolean);
-    method public abstract void onResponseHeadersReceived(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo);
-    method public void onResponseTrailersReceived(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull android.net.http.UrlResponseInfo.HeaderBlock);
-    method public abstract void onStreamReady(@NonNull android.net.http.BidirectionalStream);
-    method public abstract void onSucceeded(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo);
-    method public abstract void onWriteCompleted(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull java.nio.ByteBuffer, boolean);
+    method public void onFailed(@NonNull android.net.http.BidirectionalStream, @Nullable android.net.http.UrlResponseInfo, @NonNull android.net.http.HttpException);
+    method public void onReadCompleted(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull java.nio.ByteBuffer, boolean);
+    method public void onResponseHeadersReceived(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo);
+    method public void onResponseTrailersReceived(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull android.net.http.HeaderBlock);
+    method public void onStreamReady(@NonNull android.net.http.BidirectionalStream);
+    method public void onSucceeded(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo);
+    method public void onWriteCompleted(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull java.nio.ByteBuffer, boolean);
   }
 
   public abstract class CallbackException extends android.net.http.HttpException {
@@ -44,53 +51,65 @@
   }
 
   public class ConnectionMigrationOptions {
-    method @Nullable public Boolean getAllowNonDefaultNetworkUsage();
-    method @Nullable public Boolean getEnableDefaultNetworkMigration();
-    method @Nullable public Boolean getEnablePathDegradationMigration();
+    method public int getAllowNonDefaultNetworkUsageEnabled();
+    method public int getDefaultNetworkMigrationEnabled();
+    method public int getPathDegradationMigrationEnabled();
+    field public static final int MIGRATION_OPTION_DISABLED = 2; // 0x2
+    field public static final int MIGRATION_OPTION_ENABLED = 1; // 0x1
+    field public static final int MIGRATION_OPTION_UNSPECIFIED = 0; // 0x0
   }
 
   public static final class ConnectionMigrationOptions.Builder {
     ctor public ConnectionMigrationOptions.Builder();
     method @NonNull public android.net.http.ConnectionMigrationOptions build();
-    method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setAllowNonDefaultNetworkUsage(boolean);
-    method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setEnableDefaultNetworkMigration(boolean);
-    method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setEnablePathDegradationMigration(boolean);
+    method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setAllowNonDefaultNetworkUsageEnabled(int);
+    method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setDefaultNetworkMigrationEnabled(int);
+    method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setPathDegradationMigrationEnabled(int);
   }
 
   public final class DnsOptions {
-    method @Nullable public Boolean getEnableStaleDns();
-    method @Nullable public Boolean getPersistHostCache();
+    method public int getPersistHostCacheEnabled();
     method @Nullable public java.time.Duration getPersistHostCachePeriod();
-    method @Nullable public Boolean getPreestablishConnectionsToStaleDnsResults();
+    method public int getPreestablishConnectionsToStaleDnsResultsEnabled();
+    method public int getStaleDnsEnabled();
     method @Nullable public android.net.http.DnsOptions.StaleDnsOptions getStaleDnsOptions();
-    method @Nullable public Boolean getUseHttpStackDnsResolver();
+    method public int getUseHttpStackDnsResolverEnabled();
+    field public static final int DNS_OPTION_DISABLED = 2; // 0x2
+    field public static final int DNS_OPTION_ENABLED = 1; // 0x1
+    field public static final int DNS_OPTION_UNSPECIFIED = 0; // 0x0
   }
 
   public static final class DnsOptions.Builder {
     ctor public DnsOptions.Builder();
     method @NonNull public android.net.http.DnsOptions build();
-    method @NonNull public android.net.http.DnsOptions.Builder setEnableStaleDns(boolean);
-    method @NonNull public android.net.http.DnsOptions.Builder setPersistHostCache(boolean);
+    method @NonNull public android.net.http.DnsOptions.Builder setPersistHostCacheEnabled(int);
     method @NonNull public android.net.http.DnsOptions.Builder setPersistHostCachePeriod(@NonNull java.time.Duration);
-    method @NonNull public android.net.http.DnsOptions.Builder setPreestablishConnectionsToStaleDnsResults(boolean);
+    method @NonNull public android.net.http.DnsOptions.Builder setPreestablishConnectionsToStaleDnsResultsEnabled(int);
+    method @NonNull public android.net.http.DnsOptions.Builder setStaleDnsEnabled(int);
     method @NonNull public android.net.http.DnsOptions.Builder setStaleDnsOptions(@NonNull android.net.http.DnsOptions.StaleDnsOptions);
-    method @NonNull public android.net.http.DnsOptions.Builder setUseHttpStackDnsResolver(boolean);
+    method @NonNull public android.net.http.DnsOptions.Builder setUseHttpStackDnsResolverEnabled(int);
   }
 
   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();
+    method public int getAllowCrossNetworkUsageEnabled();
+    method @Nullable public java.time.Duration getFreshLookupTimeout();
+    method @Nullable public java.time.Duration getMaxExpiredDelay();
+    method public int getUseStaleOnNameNotResolvedEnabled();
   }
 
   public static final class DnsOptions.StaleDnsOptions.Builder {
     ctor public DnsOptions.StaleDnsOptions.Builder();
     method @NonNull public android.net.http.DnsOptions.StaleDnsOptions build();
-    method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setAllowCrossNetworkUsage(boolean);
+    method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setAllowCrossNetworkUsageEnabled(int);
     method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setFreshLookupTimeout(@NonNull java.time.Duration);
     method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setMaxExpiredDelay(@NonNull java.time.Duration);
-    method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setUseStaleOnNameNotResolved(boolean);
+    method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setUseStaleOnNameNotResolvedEnabled(int);
+  }
+
+  public abstract class HeaderBlock {
+    ctor public HeaderBlock();
+    method @NonNull public abstract java.util.List<java.util.Map.Entry<java.lang.String,java.lang.String>> getAsList();
+    method @NonNull public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> getAsMap();
   }
 
   public abstract class HttpEngine {
@@ -156,9 +175,10 @@
   }
 
   public class QuicOptions {
+    method @NonNull public java.util.Set<java.lang.String> getAllowedQuicHosts();
     method @Nullable public String getHandshakeUserAgent();
+    method @Nullable public java.time.Duration getIdleConnectionTimeout();
     method @Nullable public Integer getInMemoryServerConfigsCacheSize();
-    method @NonNull public java.util.Set<java.lang.String> getQuicHostAllowlist();
   }
 
   public static final class QuicOptions.Builder {
@@ -189,28 +209,37 @@
   public abstract class UrlRequest {
     method public abstract void cancel();
     method public abstract void followRedirect();
+    method @NonNull public abstract android.net.http.HeaderBlock getHeaders();
+    method @Nullable public abstract String getHttpMethod();
+    method public abstract int getPriority();
     method public abstract void getStatus(@NonNull android.net.http.UrlRequest.StatusListener);
+    method public abstract int getTrafficStatsTag();
+    method public abstract int getTrafficStatsUid();
+    method public abstract boolean hasTrafficStatsTag();
+    method public abstract boolean hasTrafficStatsUid();
+    method public abstract boolean isCacheDisabled();
+    method public abstract boolean isDirectExecutorAllowed();
     method public abstract boolean isDone();
     method public abstract void read(@NonNull java.nio.ByteBuffer);
     method public abstract void start();
+    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.Builder {
     method @NonNull public abstract android.net.http.UrlRequest.Builder addHeader(@NonNull String, @NonNull String);
     method @NonNull public abstract android.net.http.UrlRequest.Builder bindToNetwork(@Nullable android.net.Network);
     method @NonNull public abstract android.net.http.UrlRequest build();
-    method @NonNull public abstract android.net.http.UrlRequest.Builder setAllowDirectExecutor(boolean);
-    method @NonNull public abstract android.net.http.UrlRequest.Builder setDisableCache(boolean);
+    method @NonNull public abstract android.net.http.UrlRequest.Builder setCacheDisabled(boolean);
+    method @NonNull public abstract android.net.http.UrlRequest.Builder setDirectExecutorAllowed(boolean);
     method @NonNull public abstract android.net.http.UrlRequest.Builder setHttpMethod(@NonNull String);
     method @NonNull public abstract android.net.http.UrlRequest.Builder setPriority(int);
     method @NonNull public abstract android.net.http.UrlRequest.Builder setTrafficStatsTag(int);
     method @NonNull public abstract android.net.http.UrlRequest.Builder setTrafficStatsUid(int);
     method @NonNull public abstract android.net.http.UrlRequest.Builder setUploadDataProvider(@NonNull android.net.http.UploadDataProvider, @NonNull 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 {
@@ -248,7 +277,7 @@
 
   public abstract class UrlResponseInfo {
     ctor public UrlResponseInfo();
-    method @NonNull public abstract android.net.http.UrlResponseInfo.HeaderBlock getHeaders();
+    method @NonNull public abstract android.net.http.HeaderBlock getHeaders();
     method public abstract int getHttpStatusCode();
     method @NonNull public abstract String getHttpStatusText();
     method @NonNull public abstract String getNegotiatedProtocol();
@@ -258,11 +287,5 @@
     method public abstract boolean wasCached();
   }
 
-  public abstract static class UrlResponseInfo.HeaderBlock {
-    ctor public UrlResponseInfo.HeaderBlock();
-    method @NonNull public abstract java.util.List<java.util.Map.Entry<java.lang.String,java.lang.String>> getAsList();
-    method @NonNull public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> getAsMap();
-  }
-
 }
 
diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java
index edfd21c..947a092 100644
--- a/framework-t/src/android/net/NetworkIdentity.java
+++ b/framework-t/src/android/net/NetworkIdentity.java
@@ -32,6 +32,7 @@
 import android.net.wifi.WifiInfo;
 import android.service.NetworkIdentityProto;
 import android.telephony.TelephonyManager;
+import android.util.Log;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.net.module.util.BitUtils;
@@ -406,10 +407,18 @@
             setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
 
             if (mType == TYPE_WIFI) {
-                final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
-                        .getTransportInfo();
+                final NetworkCapabilities nc = snapshot.getNetworkCapabilities();
+                final TransportInfo transportInfo = nc.getTransportInfo();
                 if (transportInfo instanceof WifiInfo) {
                     final WifiInfo info = (WifiInfo) transportInfo;
+                    // Log.wtf to catch trying to set a null wifiNetworkKey into NetworkIdentity.
+                    // See b/266598304. The problematic data that has null wifi network key is
+                    // thrown out when storing data, which is handled by the service.
+                    if (info.getNetworkKey() == null) {
+                        Log.wtf(TAG, "WifiInfo contains a null wifiNetworkKey and it will"
+                                + " be set into NetworkIdentity, netId=" + snapshot.getNetwork()
+                                + "NetworkCapabilities=" + nc);
+                    }
                     setWifiNetworkKey(info.getNetworkKey());
                 }
             } else if (mType == TYPE_TEST) {
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index 55fcc4a..d90bd8d 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -700,7 +700,15 @@
      *                  to know details about the key.
      */
     private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
-        Objects.requireNonNull(wifiNetworkKey);
+        // Note that this code accepts null wifi network keys because of a past bug where wifi
+        // code was sending a null network key for some connected networks, which isn't expected
+        // and ended up stored in the data on many devices.
+        // A null network key in the data matches a wildcard template (one where
+        // {@code mMatchWifiNetworkKeys} is empty), but not one where {@code MatchWifiNetworkKeys}
+        // contains null. See b/266598304.
+        if (wifiNetworkKey == null) {
+            return CollectionUtils.isEmpty(mMatchWifiNetworkKeys);
+        }
         return CollectionUtils.isEmpty(mMatchWifiNetworkKeys)
                 || CollectionUtils.contains(mMatchWifiNetworkKeys, wifiNetworkKey);
     }
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index 8b70a94..c92e9a9 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -22,6 +22,8 @@
 import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
 import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
 
+import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -1343,8 +1345,9 @@
          * @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 */);
+            return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
+                    NAMESPACE_CONNECTIVITY, MDNS_DISCOVERY_MANAGER_VERSION,
+                    false /* defaultEnabled */);
         }
 
         /**
@@ -1354,8 +1357,8 @@
          * @return true if the MdnsAdvertiser feature is enabled.
          */
         public boolean isMdnsAdvertiserEnabled(Context context) {
-            return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
-                    MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
+            return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
+                    NAMESPACE_CONNECTIVITY, MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
         }
 
         /**
diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
index f6a55c8..e7af569 100644
--- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
+++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
@@ -92,7 +92,7 @@
     @Override
     public String[] getAvailableInterfaces() throws RemoteException {
         PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
-        return mTracker.getInterfaces(checkUseRestrictedNetworksPermission());
+        return mTracker.getClientModeInterfaces(checkUseRestrictedNetworksPermission());
     }
 
     /**
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 852cf42..d520757 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -385,7 +385,7 @@
         return mFactory.hasInterface(iface);
     }
 
-    String[] getInterfaces(boolean includeRestricted) {
+    String[] getClientModeInterfaces(boolean includeRestricted) {
         return mFactory.getAvailableInterfaces(includeRestricted);
     }
 
@@ -428,9 +428,12 @@
                 // Remote process has already died
                 return;
             }
-            for (String iface : getInterfaces(canUseRestrictedNetworks)) {
+            for (String iface : getClientModeInterfaces(canUseRestrictedNetworks)) {
                 unicastInterfaceStateChange(listener, iface);
             }
+            if (mTetheringInterfaceMode == INTERFACE_MODE_SERVER) {
+                unicastInterfaceStateChange(listener, mTetheringInterface);
+            }
 
             unicastEthernetStateChange(listener, mEthernetState);
         });
diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java
index e0abdf1..5952eae 100644
--- a/service-t/src/com/android/server/net/NetworkStatsFactory.java
+++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java
@@ -34,8 +34,6 @@
 
 import java.io.IOException;
 import java.net.ProtocolException;
-import java.util.Arrays;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -147,36 +145,6 @@
     }
 
     /**
-     * Get a set of interfaces containing specified ifaces and stacked interfaces.
-     *
-     * <p>The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces
-     * on which the specified ones are stacked. Stacked interfaces are those noted with
-     * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method
-     * is called are guaranteed to be included.
-     */
-    public String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) {
-        if (requiredIfaces == NetworkStats.INTERFACES_ALL) {
-            return null;
-        }
-
-        HashSet<String> relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces));
-        // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse
-        // elements as they existed upon construction exactly once, and may
-        // (but are not guaranteed to) reflect any modifications subsequent to construction".
-        // This is enough here.
-        for (Map.Entry<String, String> entry : mStackedIfaces.entrySet()) {
-            if (relatedIfaces.contains(entry.getKey())) {
-                relatedIfaces.add(entry.getValue());
-            } else if (relatedIfaces.contains(entry.getValue())) {
-                relatedIfaces.add(entry.getKey());
-            }
-        }
-
-        String[] outArray = new String[relatedIfaces.size()];
-        return relatedIfaces.toArray(outArray);
-    }
-
-    /**
      * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}.
      * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map)
      */
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 4c841b2..961337d 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -106,6 +106,7 @@
 import android.net.TetherStatsParcel;
 import android.net.TetheringManager;
 import android.net.TrafficStats;
+import android.net.TransportInfo;
 import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
 import android.net.netstats.IUsageCallback;
@@ -113,6 +114,7 @@
 import android.net.netstats.provider.INetworkStatsProvider;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.net.netstats.provider.NetworkStatsProvider;
+import android.net.wifi.WifiInfo;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -1730,11 +1732,7 @@
         PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             final String[] ifaceArray = getAllIfacesSinceBoot(transport);
-            // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked
-            // interfaces, so this is not useful, remove it.
-            final String[] ifacesToQuery =
-                    mStatsFactory.augmentWithStackedInterfaces(ifaceArray);
-            final NetworkStats stats = getNetworkStatsUidDetail(ifacesToQuery);
+            final NetworkStats stats = getNetworkStatsUidDetail(ifaceArray);
             // Clear the interfaces of the stats before returning, so callers won't get this
             // information. This is because no caller needs this information for now, and it
             // makes it easier to change the implementation later by using the histories in the
@@ -2126,6 +2124,14 @@
             final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
                     isDefault, ratType);
 
+            // If WifiInfo contains a null network key then this identity should not be added into
+            // the network identity set. See b/266598304.
+            final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
+                    .getTransportInfo();
+            if (transportInfo instanceof WifiInfo) {
+                final WifiInfo info = (WifiInfo) transportInfo;
+                if (info.getNetworkKey() == null) continue;
+            }
             // Traffic occurring on the base interface is always counted for
             // both total usage and UID details.
             final String baseIface = snapshot.getLinkProperties().getInterfaceName();
diff --git a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
index 7c24c95..dc22369 100644
--- a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
+++ b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
@@ -37,8 +37,6 @@
 import android.net.cts.NetworkValidationTestUtil.setHttpsUrlDeviceConfig
 import android.net.cts.NetworkValidationTestUtil.setUrlExpirationDeviceConfig
 import android.net.cts.util.CtsNetUtils
-import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
-import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
 import android.platform.test.annotations.AppModeFull
 import android.provider.DeviceConfig
 import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
@@ -47,28 +45,30 @@
 import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
 import androidx.test.runner.AndroidJUnit4
 import com.android.modules.utils.build.SdkLevel.isAtLeastR
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
 import com.android.testutils.DeviceConfigRule
-import com.android.testutils.RecorderCallback
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
 import com.android.testutils.TestHttpServer
 import com.android.testutils.TestHttpServer.Request
 import com.android.testutils.TestableNetworkCallback
 import com.android.testutils.runAsShell
 import fi.iki.elonen.NanoHTTPD.Response.Status
-import junit.framework.AssertionFailedError
-import org.junit.After
-import org.junit.Assume.assumeTrue
-import org.junit.Assume.assumeFalse
-import org.junit.Before
-import org.junit.BeforeClass
-import org.junit.Rule
-import org.junit.runner.RunWith
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.TimeUnit
 import java.util.concurrent.TimeoutException
+import junit.framework.AssertionFailedError
 import kotlin.test.Test
 import kotlin.test.assertNotEquals
 import kotlin.test.assertNotNull
 import kotlin.test.assertTrue
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.BeforeClass
+import org.junit.Rule
+import org.junit.runner.RunWith
 
 private const val TEST_HTTPS_URL_PATH = "/https_path"
 private const val TEST_HTTP_URL_PATH = "/http_path"
@@ -151,8 +151,8 @@
                 .build()
         val cellCb = TestableNetworkCallback(timeoutMs = TEST_TIMEOUT_MS)
         cm.registerNetworkCallback(cellReq, cellCb)
-        val cb = cellCb.eventuallyExpectOrNull<RecorderCallback.CallbackEntry.CapabilitiesChanged> {
-            it.network == cellNetwork && it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
+        val cb = cellCb.poll { it.network == cellNetwork &&
+                it is CapabilitiesChanged && it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
         }
         assertNotNull(cb, "Mobile network $cellNetwork has no access to the internet. " +
                 "Check the mobile data connection.")
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 7985dc4..0bb6000 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -2434,11 +2434,11 @@
         runWithShellPermissionIdentity(() -> registerDefaultNetworkCallbackForUid(
                 otherUid, otherUidCallback, handler), NETWORK_SETTINGS);
 
-        final Network defaultNetwork = mCm.getActiveNetwork();
+        final Network defaultNetwork = myUidCallback.expect(CallbackEntry.AVAILABLE).getNetwork();
         final List<DetailedBlockedStatusCallback> allCallbacks =
                 List.of(myUidCallback, otherUidCallback);
         for (DetailedBlockedStatusCallback callback : allCallbacks) {
-            callback.expectAvailableCallbacksWithBlockedReasonNone(defaultNetwork);
+            callback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE);
         }
 
         final Range<Integer> myUidRange = new Range<>(myUid, myUid);
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index b924f65..67bdd17 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -644,10 +644,9 @@
 
         val listener = EthernetStateListener()
         addInterfaceStateListener(listener)
-        // TODO(b/236895792): THIS IS A BUG! Existing server mode interfaces are not reported when
-        // an InterfaceStateListener is registered.
         // Note: using eventuallyExpect as there may be other interfaces present.
-        // listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_SERVER)
+        listener.eventuallyExpect(InterfaceStateChanged(iface.name,
+                STATE_LINK_UP, ROLE_SERVER, /* IpConfiguration */ null))
 
         releaseTetheredInterface()
         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 408c546..3f197c4 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -19,6 +19,8 @@
 import android.app.compat.CompatChanges
 import android.net.ConnectivityManager
 import android.net.ConnectivityManager.NetworkCallback
+import android.net.InetAddresses.parseNumericAddress
+import android.net.LinkAddress
 import android.net.LinkProperties
 import android.net.LocalSocket
 import android.net.LocalSocketAddress
@@ -27,6 +29,7 @@
 import android.net.NetworkCapabilities
 import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
 import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
 import android.net.NetworkCapabilities.TRANSPORT_TEST
 import android.net.NetworkRequest
 import android.net.TestNetworkInterface
@@ -62,18 +65,28 @@
 import android.os.HandlerThread
 import android.os.Process.myTid
 import android.platform.test.annotations.AppModeFull
+import android.system.ErrnoException
+import android.system.Os
+import android.system.OsConstants.AF_INET6
+import android.system.OsConstants.ENETUNREACH
+import android.system.OsConstants.IPPROTO_UDP
+import android.system.OsConstants.SOCK_DGRAM
 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.modules.utils.build.SdkLevel.isAtLeastU
 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.RecorderCallback.CallbackEntry.CapabilitiesChanged
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
 import com.android.testutils.TestableNetworkAgent
+import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
 import com.android.testutils.TestableNetworkCallback
 import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk30
 import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk33
@@ -82,6 +95,7 @@
 import com.android.testutils.waitForIdle
 import java.io.File
 import java.io.IOException
+import java.net.NetworkInterface
 import java.net.ServerSocket
 import java.nio.charset.StandardCharsets
 import java.util.Random
@@ -353,24 +367,56 @@
                 .build(), cb)
         val agent = registerTestNetworkAgent(iface.interfaceName)
         val network = agent.network ?: fail("Registered agent should have a network")
+
+        cb.eventuallyExpect<LinkPropertiesChanged>(TIMEOUT_MS) {
+            it.lp.linkAddresses.isNotEmpty()
+        }
+
         // The network has no INTERNET capability, so will be marked validated immediately
-        cb.expectAvailableThenValidatedCallbacks(network, TIMEOUT_MS)
+        // It does not matter if validated capabilities come before/after the link addresses change
+        cb.eventuallyExpect<CapabilitiesChanged>(TIMEOUT_MS, from = 0) {
+            it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
+        }
         return TestTapNetwork(iface, cb, agent, network)
     }
 
     private fun registerTestNetworkAgent(ifaceName: String): TestableNetworkAgent {
+        val lp = LinkProperties().apply {
+            interfaceName = ifaceName
+        }
+
         val agent = TestableNetworkAgent(context, handlerThread.looper,
                 NetworkCapabilities().apply {
                     removeCapability(NET_CAPABILITY_TRUSTED)
                     addTransportType(TRANSPORT_TEST)
                     setNetworkSpecifier(TestNetworkSpecifier(ifaceName))
-                },
-                LinkProperties().apply {
-                    interfaceName = ifaceName
-                },
-                NetworkAgentConfig.Builder().build())
-        agent.register()
+                }, lp, NetworkAgentConfig.Builder().build())
+        val network = agent.register()
         agent.markConnected()
+        agent.expectCallback<OnNetworkCreated>()
+
+        // Wait until the link-local address can be used. Address flags are not available without
+        // elevated permissions, so check that bindSocket works.
+        PollingCheck.check("No usable v6 address on interface after $TIMEOUT_MS ms", TIMEOUT_MS) {
+            val sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
+            tryTest {
+                network.bindSocket(sock)
+                Os.connect(sock, parseNumericAddress("ff02::fb%$ifaceName"), 12345)
+                true
+            }.catch<ErrnoException> {
+                if (it.errno != ENETUNREACH) {
+                    throw it
+                }
+                false
+            } cleanup {
+                Os.close(sock)
+            }
+        }
+
+        lp.setLinkAddresses(NetworkInterface.getByName(ifaceName).interfaceAddresses.map {
+            LinkAddress(it.address, it.networkPrefixLength.toInt())
+        })
+        agent.sendLinkProperties(lp)
         return agent
     }
 
@@ -378,8 +424,9 @@
     fun tearDown() {
         if (TestUtils.shouldTestTApis()) {
             runAsShell(MANAGE_TEST_NETWORKS) {
-                testNetwork1.close(cm)
-                testNetwork2.close(cm)
+                // Avoid throwing here if initializing failed in setUp
+                if (this::testNetwork1.isInitialized) testNetwork1.close(cm)
+                if (this::testNetwork2.isInitialized) testNetwork2.close(cm)
             }
         }
         handlerThread.waitForIdle(TIMEOUT_MS)
@@ -465,7 +512,12 @@
         assertTrue(resolvedService.attributes.containsKey("nullBinaryDataAttr"))
         assertNull(resolvedService.attributes["nullBinaryDataAttr"])
         assertTrue(resolvedService.attributes.containsKey("emptyBinaryDataAttr"))
-        assertNull(resolvedService.attributes["emptyBinaryDataAttr"])
+        // TODO: change the check to target SDK U when this is what the code implements
+        if (isAtLeastU()) {
+            assertArrayEquals(byteArrayOf(), resolvedService.attributes["emptyBinaryDataAttr"])
+        } else {
+            assertNull(resolvedService.attributes["emptyBinaryDataAttr"])
+        }
         assertEquals(localPort, resolvedService.port)
 
         // Unregister the service
@@ -882,9 +934,7 @@
         // This test requires shims supporting U+ APIs (NsdManager.registerServiceInfoCallback)
         assumeTrue(TestUtils.shouldTestUApis())
 
-        // Ensure Wi-Fi network connected and get addresses
-        val wifiNetwork = ctsNetUtils.ensureWifiConnected()
-        val lp = cm.getLinkProperties(wifiNetwork)
+        val lp = cm.getLinkProperties(testNetwork1.network)
         assertNotNull(lp)
         val addresses = lp.addresses
         assertFalse(addresses.isEmpty())
@@ -892,24 +942,24 @@
         val si = NsdServiceInfo().apply {
             serviceType = this@NsdManagerTest.serviceType
             serviceName = this@NsdManagerTest.serviceName
-            network = wifiNetwork
+            network = testNetwork1.network
             port = 12345 // Test won't try to connect so port does not matter
         }
 
-        // Register service on Wi-Fi network
+        // Register service on the network
         val registrationRecord = NsdRegistrationRecord()
         registerService(registrationRecord, si)
 
         val discoveryRecord = NsdDiscoveryRecord()
         val cbRecord = NsdServiceInfoCallbackRecord()
         tryTest {
-            // Discover service on Wi-Fi network.
+            // Discover service on the network.
             nsdShim.discoverServices(nsdManager, serviceType, NsdManager.PROTOCOL_DNS_SD,
-                    wifiNetwork, Executor { it.run() }, discoveryRecord)
+                    testNetwork1.network, Executor { it.run() }, discoveryRecord)
             val foundInfo = discoveryRecord.waitForServiceDiscovered(
-                    serviceName, wifiNetwork)
+                    serviceName, testNetwork1.network)
 
-            // Register service callback and check the addresses are the same as Wi-Fi addresses
+            // Register service callback and check the addresses are the same as network addresses
             nsdShim.registerServiceInfoCallback(nsdManager, foundInfo, { it.run() }, cbRecord)
             val serviceInfoCb = cbRecord.expectCallback<ServiceUpdated>()
             assertEquals(foundInfo.serviceName, serviceInfoCb.serviceInfo.serviceName)
diff --git a/tests/unit/java/android/net/NetworkTemplateTest.kt b/tests/unit/java/android/net/NetworkTemplateTest.kt
index edbcea9..fc25fd8 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -130,10 +130,17 @@
                 mockContext, buildWifiNetworkState(null, TEST_WIFI_KEY1), true, 0)
         val identWifiImsi1Key1 = buildNetworkIdentity(
                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_WIFI_KEY1), true, 0)
+        // This identity with a null wifiNetworkKey is to test matchesWifiNetworkKey won't crash
+        // the system when a null wifiNetworkKey is provided, which happens because of a bug in wifi
+        // and it should still match the wifi wildcard template. See b/266598304.
+        val identWifiNullKey = buildNetworkIdentity(
+                mockContext, buildWifiNetworkState(null /* subscriberId */,
+                null /* wifiNetworkKey */), true, 0)
 
         templateWifiWildcard.assertDoesNotMatch(identMobileImsi1)
         templateWifiWildcard.assertMatches(identWifiImsiNullKey1)
         templateWifiWildcard.assertMatches(identWifiImsi1Key1)
+        templateWifiWildcard.assertMatches(identWifiNullKey)
     }
 
     @Test
@@ -148,6 +155,9 @@
                 .setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build()
         val templateWifiKeyAllImsi1 = NetworkTemplate.Builder(MATCH_WIFI)
                 .setSubscriberIds(setOf(TEST_IMSI1)).build()
+        val templateNullWifiKey = NetworkTemplate(MATCH_WIFI,
+                emptyArray<String>() /* subscriberIds */, arrayOf(null) /* wifiNetworkKeys */,
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
 
         val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1),
                 false, TelephonyManager.NETWORK_TYPE_UMTS)
@@ -159,6 +169,12 @@
                 mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_WIFI_KEY1), true, 0)
         val identWifiImsi1Key2 = buildNetworkIdentity(
                 mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_WIFI_KEY2), true, 0)
+        // This identity with a null wifiNetworkKey is to test the matchesWifiNetworkKey won't crash
+        // the system when a null wifiNetworkKey is provided, which would happen in some unknown
+        // cases, see b/266598304.
+        val identWifiNullKey = buildNetworkIdentity(
+                mockContext, buildWifiNetworkState(null /* subscriberId */,
+                null /* wifiNetworkKey */), true, 0)
 
         // Verify that template with WiFi Network Key only matches any subscriberId and
         // specific WiFi Network Key.
@@ -191,6 +207,12 @@
         templateWifiKeyAllImsi1.assertMatches(identWifiImsi1Key1)
         templateWifiKeyAllImsi1.assertDoesNotMatch(identWifiImsi2Key1)
         templateWifiKeyAllImsi1.assertMatches(identWifiImsi1Key2)
+
+        // Test a network identity with null wifiNetworkKey won't crash.
+        // It should not match a template with wifiNetworkKeys is non-null.
+        // Also, it should not match a template with wifiNetworkKeys that contains null.
+        templateWifiKey1.assertDoesNotMatch(identWifiNullKey)
+        templateNullWifiKey.assertDoesNotMatch(identWifiNullKey)
     }
 
     @Test
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 2d87728..1f965d9 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -25,6 +25,8 @@
 import static android.net.ConnectivityManager.NetworkCallback;
 import static android.net.INetd.IF_STATE_DOWN;
 import static android.net.INetd.IF_STATE_UP;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static android.net.VpnManager.TYPE_VPN_PLATFORM;
 import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
@@ -36,6 +38,8 @@
 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 android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
 
 import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
 import static com.android.server.connectivity.Vpn.AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
@@ -107,6 +111,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo.DetailedState;
 import android.net.RouteInfo;
+import android.net.TelephonyNetworkSpecifier;
 import android.net.UidRangeParcel;
 import android.net.VpnManager;
 import android.net.VpnProfileState;
@@ -126,6 +131,7 @@
 import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
 import android.net.ipsec.ike.exceptions.IkeProtocolException;
 import android.net.ipsec.ike.exceptions.IkeTimeoutException;
+import android.net.wifi.WifiInfo;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.ConditionVariable;
@@ -139,6 +145,10 @@
 import android.os.test.TestLooper;
 import android.provider.Settings;
 import android.security.Credentials;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Pair;
@@ -265,6 +275,9 @@
     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;
+    private static final int TEST_KEEPALIVE_TIMER = 800;
+    private static final int TEST_SUB_ID = 1234;
+
     @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
     @Mock private UserManager mUserManager;
     @Mock private PackageManager mPackageManager;
@@ -278,6 +291,10 @@
     @Mock private Vpn.VpnNetworkAgentWrapper mMockNetworkAgent;
     @Mock private ConnectivityManager mConnectivityManager;
     @Mock private ConnectivityDiagnosticsManager mCdm;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private TelephonyManager mTmPerSub;
+    @Mock private CarrierConfigManager mConfigManager;
+    @Mock private SubscriptionManager mSubscriptionManager;
     @Mock private IpSecService mIpSecService;
     @Mock private VpnProfileStore mVpnProfileStore;
     @Mock private ScheduledThreadPoolExecutor mExecutor;
@@ -286,7 +303,6 @@
     private final VpnProfile mVpnProfile;
 
     private IpSecManager mIpSecManager;
-
     private TestDeps mTestDeps;
 
     public VpnTest() throws Exception {
@@ -322,6 +338,11 @@
         mockService(IpSecManager.class, Context.IPSEC_SERVICE, mIpSecManager);
         mockService(ConnectivityDiagnosticsManager.class, Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
                 mCdm);
+        mockService(TelephonyManager.class, Context.TELEPHONY_SERVICE, mTelephonyManager);
+        mockService(CarrierConfigManager.class, Context.CARRIER_CONFIG_SERVICE, mConfigManager);
+        mockService(SubscriptionManager.class, Context.TELEPHONY_SUBSCRIPTION_SERVICE,
+                mSubscriptionManager);
+        doReturn(mTmPerSub).when(mTelephonyManager).createForSubscriptionId(anyInt());
         when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
                 .thenReturn(Resources.getSystem().getString(
                         R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
@@ -1924,7 +1945,7 @@
     }
 
     @Test
-    public void testMigrateIkeSessionFromIkeTunnConnParams_AutoTimerNoTimer()
+    public void testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerNoTimer()
             throws Exception {
         doTestMigrateIkeSession_FromIkeTunnConnParams(
                 false /* isAutomaticIpVersionSelectionEnabled */,
@@ -1933,21 +1954,21 @@
     }
 
     @Test
-    public void testMigrateIkeSessionFromIkeTunnConnParams_AutoTimerTimerSet()
+    public void testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerTimerSet()
             throws Exception {
         doTestMigrateIkeSession_FromIkeTunnConnParams(
                 false /* isAutomaticIpVersionSelectionEnabled */,
                 true /* isAutomaticNattKeepaliveTimerEnabled */,
-                800 /* keepaliveTimeout */);
+                TEST_KEEPALIVE_TIMER);
     }
 
     @Test
-    public void testMigrateIkeSessionFromIkeTunnConnParams_AutoIp()
+    public void testMigrateIkeSession_FromIkeTunnConnParams_AutoIp()
             throws Exception {
         doTestMigrateIkeSession_FromIkeTunnConnParams(
                 true /* isAutomaticIpVersionSelectionEnabled */,
                 false /* isAutomaticNattKeepaliveTimerEnabled */,
-                TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveTimeout */);
+                TEST_KEEPALIVE_TIMEOUT_UNSET);
     }
 
     @Test
@@ -2016,9 +2037,12 @@
                 verifySetupPlatformVpn(profile,
                         createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */),
                         false /* mtuSupportsIpv6 */);
-        // Mock new network comes up and the cleanup task is cancelled
+        // Simulate a new network coming up
         vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+        verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt());
 
+        vpnSnapShot.nwCb.onCapabilitiesChanged(
+                TEST_NETWORK_2, new NetworkCapabilities.Builder().build());
         // Verify MOBIKE is triggered
         verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2,
                 expectedIpVersion, expectedEncapType, expectedKeepalive);
@@ -2026,6 +2050,102 @@
         vpnSnapShot.vpn.mVpnRunner.exitVpnRunner();
     }
 
+    private void mockCarrierConfig(int subId, int keepaliveTimer, int simStatus) {
+        final SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+        doReturn(subId).when(subscriptionInfo).getSubscriptionId();
+        doReturn(List.of(subscriptionInfo)).when(mSubscriptionManager)
+                .getActiveSubscriptionInfoList();
+
+        doReturn(simStatus).when(mTmPerSub).getSimApplicationState();
+
+        final PersistableBundle persistableBundle = new PersistableBundle();
+        persistableBundle.putInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT, keepaliveTimer);
+        // For CarrierConfigManager.isConfigForIdentifiedCarrier check
+        persistableBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+        doReturn(persistableBundle).when(mConfigManager).getConfigForSubId(subId);
+    }
+
+    private CarrierConfigManager.CarrierConfigChangeListener getCarrierConfigListener() {
+        final ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerCaptor =
+                ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+        verify(mConfigManager).registerCarrierConfigChangeListener(any(), listenerCaptor.capture());
+
+        return listenerCaptor.getValue();
+    }
+
+    @Test
+    public void testNattKeepaliveTimerFromCarrierConfig_noSubId() throws Exception {
+        doTestNattKeepaliveTimerFromCarrierConfig(new NetworkCapabilities(),
+                TelephonyManager.SIM_STATE_LOADED, AUTOMATIC_KEEPALIVE_DELAY_SECONDS);
+    }
+
+    @Test
+    public void testNattKeepaliveTimerFromCarrierConfig_simAbsent() throws Exception {
+        doTestNattKeepaliveTimerFromCarrierConfig(new NetworkCapabilities.Builder().build(),
+                TelephonyManager.SIM_STATE_ABSENT, AUTOMATIC_KEEPALIVE_DELAY_SECONDS);
+    }
+
+    @Test
+    public void testNattKeepaliveTimerFromCarrierConfig() throws Exception {
+        final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+                .addTransportType(TRANSPORT_CELLULAR)
+                .setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
+                        .setSubscriptionId(TEST_SUB_ID)
+                        .build())
+                .build();
+        doTestNattKeepaliveTimerFromCarrierConfig(nc,
+                TelephonyManager.SIM_STATE_LOADED, TEST_KEEPALIVE_TIMER);
+    }
+
+    @Test
+    public void testNattKeepaliveTimerFromCarrierConfig_NotCell() throws Exception {
+        final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+                .addTransportType(TRANSPORT_WIFI)
+                .setTransportInfo(new WifiInfo.Builder().build())
+                .build();
+        doTestNattKeepaliveTimerFromCarrierConfig(nc,
+                TelephonyManager.SIM_STATE_LOADED, AUTOMATIC_KEEPALIVE_DELAY_SECONDS);
+    }
+
+    private void doTestNattKeepaliveTimerFromCarrierConfig(NetworkCapabilities nc, int simState,
+            int expectedKeepaliveTimer) throws Exception {
+        final Ikev2VpnProfile ikeProfile =
+                new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY)
+                        .setAuthPsk(TEST_VPN_PSK)
+                        .setBypassable(true /* isBypassable */)
+                        .setAutomaticNattKeepaliveTimerEnabled(true)
+                        .build();
+
+        final PlatformVpnSnapshot vpnSnapShot =
+                verifySetupPlatformVpn(ikeProfile.toVpnProfile(),
+                        createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */),
+                        false /* mtuSupportsIpv6 */);
+
+        final CarrierConfigManager.CarrierConfigChangeListener listener =
+                getCarrierConfigListener();
+
+        // Simulate a new network coming up
+        vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+        // Migration will not be started until receiving network capabilities change.
+        verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt());
+
+        reset(mIkeSessionWrapper);
+        mockCarrierConfig(TEST_SUB_ID, TEST_KEEPALIVE_TIMER, simState);
+        vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK_2, nc);
+        verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2,
+                ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, expectedKeepaliveTimer);
+
+        reset(mExecutor);
+        reset(mIkeSessionWrapper);
+
+        // Trigger carrier config change
+        listener.onCarrierConfigChanged(1 /* logicalSlotIndex */, TEST_SUB_ID,
+                -1 /* carrierId */, -1 /* specificCarrierId */);
+        verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2,
+                ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, expectedKeepaliveTimer);
+    }
+
     @Test
     public void testStartPlatformVpn_mtuDoesNotSupportIpv6() throws Exception {
         final PlatformVpnSnapshot vpnSnapShot =
@@ -2051,7 +2171,10 @@
         // Mock new network comes up and the cleanup task is cancelled
         vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
         verify(mScheduledFuture).cancel(anyBoolean());
+        verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt());
 
+        vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK_2,
+                new NetworkCapabilities.Builder().build());
         // Verify MOBIKE is triggered
         verify(mIkeSessionWrapper).setNetwork(eq(TEST_NETWORK_2),
                 eq(ESP_IP_VERSION_AUTO) /* ipVersion */,
@@ -2146,7 +2269,11 @@
         // Mock network switch
         vpnSnapShot.nwCb.onLost(TEST_NETWORK);
         vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+        // The old IKE Session will not be killed until receiving network capabilities change.
+        verify(mIkeSessionWrapper, never()).kill();
 
+        vpnSnapShot.nwCb.onCapabilitiesChanged(
+                TEST_NETWORK_2, new NetworkCapabilities.Builder().build());
         // Verify the old IKE Session is killed
         verify(mIkeSessionWrapper).kill();
 
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 13a6a6f..8046263 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -82,7 +82,6 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -395,10 +394,6 @@
         verify(mNetd).registerUnsolicitedEventListener(alertObserver.capture());
         mAlertObserver = alertObserver.getValue();
 
-        // Make augmentWithStackedInterfaces returns the interfaces that was passed to it.
-        doAnswer(inv -> ((String[]) inv.getArgument(0)).clone())
-                .when(mStatsFactory).augmentWithStackedInterfaces(any());
-
         // Catch TetheringEventCallback during systemReady().
         ArgumentCaptor<TetheringManager.TetheringEventCallback> tetheringEventCbCaptor =
                 ArgumentCaptor.forClass(TetheringManager.TetheringEventCallback.class);