diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java index f3d7dd19ecc26570f1802c2711a980d3404eaeee..ed9fa65dee15f8bc538686b0a609aa1b45bb3651 100644 --- a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java +++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java @@ -209,6 +209,18 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { mPollIpSecStateIntervalMs = getPollIpSecStateIntervalMs(carrierConfig); } + @Override + public void onLinkPropertiesOrCapabilitiesChanged() { + if (!isStarted()) return; + + reschedulePolling(); + } + + private void reschedulePolling() { + mHandler.removeCallbacksAndEqualMessages(mCancellationToken); + mHandler.postDelayed(new PollIpSecStateRunnable(), mCancellationToken, 0L); + } + @Override protected void start() { super.start(); diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java index 4bacf3b8abe55f210f93779098e8f5bb2ff3c2d6..a1b212f8d3d75eadf143e4ef9f043b85ccc37845 100644 --- a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java +++ b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java @@ -186,6 +186,11 @@ public abstract class NetworkMetricMonitor implements AutoCloseable { // Subclasses MUST override it if they care } + /** Called when LinkProperties or NetworkCapabilities have changed */ + public void onLinkPropertiesOrCapabilitiesChanged() { + // Subclasses MUST override it if they care + } + public boolean isValidationFailed() { return mIsValidationFailed; } diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java index 2f4cf5e5d8c7adcbacfe31a2d75e16ba54a346d0..78e06d46c74c6219be02f9f5015fcd29adf4e145 100644 --- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java +++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java @@ -25,6 +25,7 @@ import android.net.IpSecTransform; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; +import android.net.vcn.Flags; import android.net.vcn.VcnManager; import android.net.vcn.VcnUnderlyingNetworkTemplate; import android.os.Handler; @@ -295,6 +296,12 @@ public class UnderlyingNetworkEvaluator { updatePriorityClass( underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig); + + if (Flags.evaluateIpsecLossOnLpNcChange()) { + for (NetworkMetricMonitor monitor : mMetricMonitors) { + monitor.onLinkPropertiesOrCapabilitiesChanged(); + } + } } /** Set the LinkProperties */ @@ -308,6 +315,12 @@ public class UnderlyingNetworkEvaluator { updatePriorityClass( underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig); + + if (Flags.evaluateIpsecLossOnLpNcChange()) { + for (NetworkMetricMonitor monitor : mMetricMonitors) { + monitor.onLinkPropertiesOrCapabilitiesChanged(); + } + } } /** Set whether the network is blocked */ diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java index 5107943c35280584a4caa87bf3c2e0d7729758bd..fdf8fb8d3c41c1b80c658d7362e671a46303eb14 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java @@ -34,6 +34,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -417,4 +418,31 @@ public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase { checkGetPacketLossRate(oldState, 20000, 14000, 4096, 19); checkGetPacketLossRate(oldState, 20000, 14000, 3000, 10); } + + // Verify the polling event is scheduled with expected delays + private void verifyPollEventDelayAndScheduleNext(long expectedDelayMs) { + if (expectedDelayMs > 0) { + mTestLooper.dispatchAll(); + verify(mIpSecTransform, never()).requestIpSecTransformState(any(), any()); + mTestLooper.moveTimeForward(expectedDelayMs); + } + + mTestLooper.dispatchAll(); + verify(mIpSecTransform).requestIpSecTransformState(any(), any()); + reset(mIpSecTransform); + } + + @Test + public void testOnLinkPropertiesOrCapabilitiesChange() throws Exception { + // Start the monitor; verify the 1st poll is scheduled without delay + startMonitorAndCaptureStateReceiver(); + verifyPollEventDelayAndScheduleNext(0 /* expectedDelayMs */); + + // Verify the 2nd poll is rescheduled without delay + mIpSecPacketLossDetector.onLinkPropertiesOrCapabilitiesChanged(); + verifyPollEventDelayAndScheduleNext(0 /* expectedDelayMs */); + + // Verify the 3rd poll is scheduled with configured delay + verifyPollEventDelayAndScheduleNext(POLL_IPSEC_STATE_INTERVAL_MS); + } } diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java index 444208edc4732ccdc03f8edc6c9b685d77190677..af6daa17e22366f6120de59367bb15fe2f6aba80 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java @@ -122,6 +122,7 @@ public abstract class NetworkEvaluationTestBase { MockitoAnnotations.initMocks(this); mSetFlagsRule.enableFlags(Flags.FLAG_VALIDATE_NETWORK_ON_IPSEC_LOSS); + mSetFlagsRule.enableFlags(Flags.FLAG_EVALUATE_IPSEC_LOSS_ON_LP_NC_CHANGE); when(mNetwork.getNetId()).thenReturn(-1); diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java index aa81efe9a1ce42c429d8ebd383acf92ef8c67287..1d6872195e81bc087b2199517be4cc7fb3d38c74 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java @@ -31,6 +31,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -333,4 +334,36 @@ public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase { .compare(penalized, notPenalized); assertEquals(1, result); } + + @Test + public void testNotifyNetworkMetricMonitorOnLpChange() throws Exception { + // Clear calls invoked when initializing mNetworkEvaluator + reset(mIpSecPacketLossDetector); + + final UnderlyingNetworkEvaluator evaluator = newUnderlyingNetworkEvaluator(); + evaluator.setNetworkCapabilities( + CELL_NETWORK_CAPABILITIES, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + + verify(mIpSecPacketLossDetector).onLinkPropertiesOrCapabilitiesChanged(); + } + + @Test + public void testNotifyNetworkMetricMonitorOnNcChange() throws Exception { + // Clear calls invoked when initializing mNetworkEvaluator + reset(mIpSecPacketLossDetector); + + final UnderlyingNetworkEvaluator evaluator = newUnderlyingNetworkEvaluator(); + evaluator.setLinkProperties( + LINK_PROPERTIES, + VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES, + SUB_GROUP, + mSubscriptionSnapshot, + mCarrierConfig); + + verify(mIpSecPacketLossDetector).onLinkPropertiesOrCapabilitiesChanged(); + } }