Keep alive improvements - Use new network capabilities instead of old network capabilities for fetching the keep alive timer, when updating the ike underlying network with onNetworkSetByUser(). Flag: Flag EXEMPT BugFix Bug: 396209794 Test: atest com.android.internal.net.ipsec.test.ike.net.IkeConnectionControllerTest#testKeepaliveDelayUpdatesOnNetworkSwitchWithAutoKeeplive Change-Id: Ib5eccc1b9ae43d16f434f6aed7d5f42c44c0f9e3
diff --git a/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionController.java b/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionController.java index 847d27b..64c381a 100644 --- a/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionController.java +++ b/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionController.java
@@ -182,6 +182,7 @@ //Must only be touched on the IkeSessionStateMachine thread. private Network mUnderpinnedNetwork; + private int mKeepaliveDelaySeconds; private IkeNattKeepalive mIkeNattKeepalive; private static final SparseArray<String> NAT_STATUS_TO_STR; @@ -213,6 +214,7 @@ mUseCallerConfiguredNetwork = config.ikeParams.getConfiguredNetwork() != null; mIpVersion = config.ikeParams.getIpVersion(); mEncapType = config.ikeParams.getEncapType(); + mKeepaliveDelaySeconds = config.ikeParams.getNattKeepAliveDelaySeconds(); mDscp = config.ikeParams.getDscp(); mUnderpinnedNetwork = null; @@ -637,6 +639,12 @@ return Collections.unmodifiableSet(mIkeSaRecords); } + /** Returns the keepalive config */ + @VisibleForTesting + public IkeAlarmConfig getKeepaliveAlarmConfig() { + return mKeepaliveAlarmConfig; + } + /** * Updates the underlying network * @@ -691,15 +699,7 @@ mIpVersion = ipVersion; mEncapType = encapType; - - if (keepaliveDelaySeconds == IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO) { - keepaliveDelaySeconds = getKeepaliveDelaySec(mIkeContext, mIkeParams, mNc); - } - final long keepaliveDelayMs = TimeUnit.SECONDS.toMillis(keepaliveDelaySeconds); - if (keepaliveDelayMs != mKeepaliveAlarmConfig.delayMs) { - mKeepaliveAlarmConfig = mKeepaliveAlarmConfig.buildCopyWithDelayMs(keepaliveDelayMs); - restartKeepaliveIfRunning(); - } + mKeepaliveDelaySeconds = keepaliveDelaySeconds; // Switch to monitor a new network. This call is never expected to trigger a callback mNetworkCallback.setNetwork(network, linkProperties, networkCapabilities); @@ -1233,6 +1233,23 @@ mNetwork = network; mNc = networkCapabilities; + try { + if (mKeepaliveDelaySeconds == IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO) { + mKeepaliveDelaySeconds = getKeepaliveDelaySec(mIkeContext, mIkeParams, mNc); + } + + final long keepaliveDelayMs = TimeUnit.SECONDS.toMillis(mKeepaliveDelaySeconds); + + if (keepaliveDelayMs != mKeepaliveAlarmConfig.delayMs) { + mKeepaliveAlarmConfig = + mKeepaliveAlarmConfig.buildCopyWithDelayMs(keepaliveDelayMs); + restartKeepaliveIfRunning(); + } + } catch (IkeException e) { + mCallback.onError(wrapAsIkeException(e)); + return; + } + // If there is no local address on the Network, report a fatal error and return if (!hasLocalIpV4Address(linkProperties) && !linkProperties.hasGlobalIpv6Address()) { mCallback.onError(
diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionControllerTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionControllerTest.java index 52324fd..85a95ba 100644 --- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionControllerTest.java +++ b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/net/IkeConnectionControllerTest.java
@@ -112,6 +112,7 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.util.HashSet; +import java.util.concurrent.TimeUnit; public class IkeConnectionControllerTest extends IkeSessionTestBase { @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); @@ -217,7 +218,9 @@ mIkeConnectionCtrl = buildIkeConnectionCtrl(); mIkeConnectionCtrl.setUp(); - verify(mMockIkeParams).getNattKeepAliveDelaySeconds(); + // getNattKeepAliveDelaySeconds is called once in IkeConnectionController#setUp() and once + // at constructor of IkeConnectionController + verify(mMockIkeParams, times(2)).getNattKeepAliveDelaySeconds(); mIkeConnectionCtrl.registerIkeSaRecord(mMockIkeSaRecord); } @@ -1152,10 +1155,14 @@ IkeNetworkCallbackBase callback = enableMobilityAndReturnCb(true /* isDefaultNetwork */); onNetworkSetByUserWithDefaultParams(mIkeConnectionCtrl, newNetwork); - // hasIkeOption and getNattKeepAliveDelaySeconds were already called once by - // IkeConnectionController#setUp() so check they were called a second time - verify(mMockIkeParams, times(2)).hasIkeOption(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES); - verify(mMockIkeParams, times(2)).getNattKeepAliveDelaySeconds(); + // hasIkeOption was already called once by IkeConnectionController#setUp() so check it was + // called second time + verify(mMockIkeParams, times(2)).hasIkeOption( + IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES); + // getNattKeepAliveDelaySeconds was already called once each by + // IkeConnectionController#setUp() and at constructor of IkeConnectionController, so check + // it was called third time + verify(mMockIkeParams, times(3)).getNattKeepAliveDelaySeconds(); verifyNetworkAndAddressesAfterMobilityEvent( newNetwork, UPDATED_LOCAL_ADDRESS, REMOTE_ADDRESS, callback); verify(mMockConnectionCtrlCb).onUnderlyingNetworkUpdated(); @@ -1782,4 +1789,46 @@ mIkeConnectionCtrl.dump(new PrintWriter(stringWriter), ""); assertFalse(stringWriter.toString().isEmpty()); } + + private Network createMockNetwork(int transportType) throws Exception { + Network network = mock(Network.class); + NetworkCapabilities caps = mock(NetworkCapabilities.class); + when(caps.hasTransport(transportType)).thenReturn(true); + when(mMockConnectManager.getNetworkCapabilities(network)).thenReturn(caps); + + setupLocalAddressForNetwork(network, LOCAL_ADDRESS); + setupRemoteAddressForNetwork(network, REMOTE_ADDRESS); + + return network; + } + + @Test + public void testKeepaliveDelayUpdatesOnNetworkSwitchWithAutoKeeplive() throws Exception { + mIkeConnectionCtrl.enableMobility(); + + when(mMockIkeParams.getNattKeepAliveDelaySeconds()).thenReturn(200); + doReturn(true).when(mMockIkeParams).hasIkeOption(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES); + + // Migrate IKE to a mocked Wifi netwpork + onNetworkSetByUserWithDefaultParams(mIkeConnectionCtrl, createMockNetwork(TRANSPORT_WIFI)); + + // Validate the keep alive time set for wifi + assertEquals( + TimeUnit.SECONDS.toMillis(AUTO_KEEPALIVE_DELAY_SEC_WIFI), + mIkeConnectionCtrl.getKeepaliveAlarmConfig().delayMs); + + final int carrierConfigCellDelaySeconds = 100; + doReturn(carrierConfigCellDelaySeconds) + .when(mIkeContext) + .getDeviceConfigPropertyInt(anyString(), anyInt(), anyInt(), anyInt()); + + // Migrate IKE to a mocked cell netwpork + onNetworkSetByUserWithDefaultParams( + mIkeConnectionCtrl, createMockNetwork(TRANSPORT_CELLULAR)); + + // Validate the keep alive time set for celll + assertEquals( + TimeUnit.SECONDS.toMillis(carrierConfigCellDelaySeconds), + mIkeConnectionCtrl.getKeepaliveAlarmConfig().delayMs); + } }