diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 05ea6f962f..529c51d6bd 100644 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -2152,7 +2152,10 @@ public class ConnectivityService extends IConnectivityManager.Stub mL2capNetworkProvider = mDeps.makeL2capNetworkProvider(mContext); - mCloseQuicConnection = mDeps.isFeatureEnabled(context, CLOSE_QUIC_CONNECTION); + // QUIC connection close is triggered by freezer (U+) or background firewall chain (V+). + // TODO: Allow other firewall chains to close QUIC connection and enable this flag on T+ + mCloseQuicConnection = mDeps.isAtLeastU() + && mDeps.isFeatureNotChickenedOut(context, CLOSE_QUIC_CONNECTION); if (mCloseQuicConnection) { mQuicConnectionCloser = mDeps.makeQuicConnectionCloser(mNetworkForNetId, mHandler); } else { diff --git a/service/src/com/android/server/connectivity/QuicConnectionCloser.java b/service/src/com/android/server/connectivity/QuicConnectionCloser.java index c582d60f4f..c4fe5b8621 100644 --- a/service/src/com/android/server/connectivity/QuicConnectionCloser.java +++ b/service/src/com/android/server/connectivity/QuicConnectionCloser.java @@ -254,8 +254,14 @@ public class QuicConnectionCloser { Log.d(TAG, "Close QUIC socket for " + info + ", destroySocket=" + destroySocket); final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(info.netId); - if (nai == null || !nai.linkProperties.getAddresses().contains(info.src.getAddress())) { + if (nai == null) return; // The network has gone away already + + final boolean isLoopbackConnection = info.dst.getAddress().isLoopbackAddress(); + final boolean lpContainsSourceAddress = + nai.linkProperties.getAddresses().contains(info.src.getAddress()); + if (!isLoopbackConnection && !lpContainsSourceAddress) { // The device should not send a packet with an unused source address. + // Loopback connections are closed exceptionally to simplify device local testing. return; } diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java index 3a3b256fc9..2ddaa50245 100644 --- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java +++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java @@ -4358,8 +4358,11 @@ public class ConnectivityManagerTest { }); } + // This test is skipped on U and older releases because QUIC connection close can be triggered + // by the freezer (U+) or the background firewall chain (V+), but the freezer cannot be tested. + // TODO: Enable this test on T+ once other firewall chains can trigger QUIC connection close. @Test - @IgnoreUpTo(Build.VERSION_CODES.R) + @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @ConnectivityModuleTest @AppModeFull(reason = "Cannot create test network in instant app mode") public void testRegisterQuicConnectionClosePayload_blockNetwork() throws Exception { @@ -4384,8 +4387,9 @@ public class ConnectivityManagerTest { true /* blockNetwork */, false /* expectPacketSent */); } + // TODO: Enable this test on T+ once other firewall chains can trigger QUIC connection close. @Test - @IgnoreUpTo(Build.VERSION_CODES.R) + @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @ConnectivityModuleTest @AppModeFull(reason = "Cannot create test network in instant app mode") public void testRegisterQuicConnectionClosePayload_closeSocket() throws Exception { diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java index 7108d2dcf2..ce04e94d7c 100755 --- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java @@ -2188,7 +2188,6 @@ public class ConnectivityServiceTest { case ConnectivityFlags.USE_DECLARED_METHODS_FOR_CALLBACKS: case ConnectivityFlags.QUEUE_CALLBACKS_FOR_FROZEN_APPS: case ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN: - case ConnectivityFlags.CLOSE_QUIC_CONNECTION: case ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION: return true; default: @@ -2209,6 +2208,7 @@ public class ConnectivityServiceTest { case ConnectivityFlags.USE_DECLARED_METHODS_FOR_CALLBACKS: case ConnectivityFlags.QUEUE_CALLBACKS_FOR_FROZEN_APPS: case ConnectivityFlags.QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER: + case ConnectivityFlags.CLOSE_QUIC_CONNECTION: return true; default: throw new UnsupportedOperationException("Unknown flag " + name