Support adjustable VCN safe mode timeout

Bug: 317406085
Test: atest FrameworksVcnTests(new tests), CtsVcnTestCases
Change-Id: I8f5b6cb4e8286331626d4d39b864f0298657cab6
This commit is contained in:
Yan Yan 2023-12-21 22:57:28 +00:00
commit f9532ffdbb
6 changed files with 121 additions and 3 deletions

View file

@ -5,4 +5,11 @@ flag {
namespace: "vcn"
description: "Feature flag for safe mode configurability"
bug: "276358140"
}
flag {
name: "safe_mode_timeout_config"
namespace: "vcn"
description: "Feature flag for adjustable safe mode timeout"
bug: "317406085"
}

View file

@ -114,6 +114,20 @@ public class VcnManager {
public static final String VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY =
"vcn_restricted_transports";
/**
* Key for number of seconds to wait before entering safe mode
*
* <p>A VcnGatewayConnection will enter safe mode when it takes over the configured timeout to
* enter {@link ConnectedState}.
*
* <p>Defaults to 30, unless overridden by carrier config
*
* @hide
*/
@NonNull
public static final String VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY =
"vcn_safe_mode_timeout_seconds_key";
/**
* Key for maximum number of parallel SAs for tunnel aggregation
*
@ -135,6 +149,7 @@ public class VcnManager {
VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY,
VCN_TUNNEL_AGGREGATION_SA_COUNT_MAX_KEY,
};

View file

@ -74,6 +74,10 @@ public class VcnContext {
return mFeatureFlags;
}
public boolean isFlagSafeModeTimeoutConfigEnabled() {
return mFeatureFlags.safeModeTimeoutConfig();
}
/**
* Verifies that the caller is running on the VcnContext Thread.
*

View file

@ -1242,9 +1242,28 @@ public class VcnGatewayConnection extends StateMachine {
createScheduledAlarm(
SAFEMODE_TIMEOUT_ALARM,
delayedMessage,
mVcnContext.isInTestMode()
? TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS_TEST_MODE)
: TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
getSafeModeTimeoutMs(mVcnContext, mLastSnapshot, mSubscriptionGroup));
}
/** Gets the safe mode timeout */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public static long getSafeModeTimeoutMs(
VcnContext vcnContext, TelephonySubscriptionSnapshot snapshot, ParcelUuid subGrp) {
final int defaultSeconds =
vcnContext.isInTestMode()
? SAFEMODE_TIMEOUT_SECONDS_TEST_MODE
: SAFEMODE_TIMEOUT_SECONDS;
final PersistableBundleWrapper carrierConfig = snapshot.getCarrierConfigForSubGrp(subGrp);
int resultSeconds = defaultSeconds;
if (vcnContext.isFlagSafeModeTimeoutConfigEnabled() && carrierConfig != null) {
resultSeconds =
carrierConfig.getInt(
VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY, defaultSeconds);
}
return TimeUnit.SECONDS.toMillis(resultSeconds);
}
private void cancelSafeModeAlarm() {

View file

@ -27,15 +27,18 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
import static com.android.server.vcn.VcnGatewayConnection.SAFEMODE_TIMEOUT_SECONDS;
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
@ -55,6 +58,7 @@ import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.os.ParcelUuid;
@ -81,6 +85,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/** Tests for TelephonySubscriptionTracker */
@RunWith(AndroidJUnit4.class)
@ -352,4 +357,71 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
any(Executor.class),
any(ConnectivityDiagnosticsCallback.class));
}
private void verifyGetSafeModeTimeoutMs(
boolean isInTestMode,
boolean isConfigTimeoutSupported,
PersistableBundleWrapper carrierConfig,
long expectedTimeoutMs)
throws Exception {
doReturn(isInTestMode).when(mVcnContext).isInTestMode();
doReturn(isConfigTimeoutSupported).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class);
doReturn(carrierConfig).when(snapshot).getCarrierConfigForSubGrp(TEST_SUB_GRP);
final long result =
VcnGatewayConnection.getSafeModeTimeoutMs(mVcnContext, snapshot, TEST_SUB_GRP);
assertEquals(expectedTimeoutMs, result);
}
@Test
public void testGetSafeModeTimeoutMs_configTimeoutUnsupported() throws Exception {
verifyGetSafeModeTimeoutMs(
false /* isInTestMode */,
false /* isConfigTimeoutSupported */,
null /* carrierConfig */,
TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
}
@Test
public void testGetSafeModeTimeoutMs_configTimeoutSupported() throws Exception {
final int carrierConfigTimeoutSeconds = 20;
final PersistableBundleWrapper carrierConfig = mock(PersistableBundleWrapper.class);
doReturn(carrierConfigTimeoutSeconds)
.when(carrierConfig)
.getInt(eq(VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY), anyInt());
verifyGetSafeModeTimeoutMs(
false /* isInTestMode */,
true /* isConfigTimeoutSupported */,
carrierConfig,
TimeUnit.SECONDS.toMillis(carrierConfigTimeoutSeconds));
}
@Test
public void testGetSafeModeTimeoutMs_configTimeoutSupported_carrierConfigNull()
throws Exception {
verifyGetSafeModeTimeoutMs(
false /* isInTestMode */,
true /* isConfigTimeoutSupported */,
null /* carrierConfig */,
TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
}
@Test
public void testGetSafeModeTimeoutMs_configTimeoutOverrideTestModeDefault() throws Exception {
final int carrierConfigTimeoutSeconds = 20;
final PersistableBundleWrapper carrierConfig = mock(PersistableBundleWrapper.class);
doReturn(carrierConfigTimeoutSeconds)
.when(carrierConfig)
.getInt(eq(VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY), anyInt());
verifyGetSafeModeTimeoutMs(
true /* isInTestMode */,
true /* isConfigTimeoutSupported */,
carrierConfig,
TimeUnit.SECONDS.toMillis(carrierConfigTimeoutSeconds));
}
}

View file

@ -226,6 +226,7 @@ public class VcnGatewayConnectionTestBase {
doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper();
doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider();
doReturn(mFeatureFlags).when(mVcnContext).getFeatureFlags();
doReturn(true).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
doReturn(mUnderlyingNetworkController)
.when(mDeps)