diff --git a/core/java/android/net/vcn/VcnControlPlaneConfig.java b/core/java/android/net/vcn/VcnControlPlaneConfig.java index a49999ed01edf117f4019981ccb85a0401ca24fb..0c6ccfee5d5d1cb7fbdae7823be8f700182e2b96 100644 --- a/core/java/android/net/vcn/VcnControlPlaneConfig.java +++ b/core/java/android/net/vcn/VcnControlPlaneConfig.java @@ -104,4 +104,11 @@ public abstract class VcnControlPlaneConfig { return mConfigType == ((VcnControlPlaneConfig) o).mConfigType; } + + /** + * Returns a deep copy of this object. + * + * @hide + */ + public abstract VcnControlPlaneConfig copy(); } diff --git a/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java index f85a502f78b6b6c6d6e222cbb94641566f3c86f0..2f6e1f63b960a24636e8459a785a70fb91aeb6f1 100644 --- a/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java +++ b/core/java/android/net/vcn/VcnControlPlaneIkeConfig.java @@ -135,8 +135,18 @@ public final class VcnControlPlaneIkeConfig extends VcnControlPlaneConfig { } VcnControlPlaneIkeConfig other = (VcnControlPlaneIkeConfig) o; - return super.equals(o) - && Objects.equals(mIkeParams, other.mIkeParams) - && Objects.equals(mChildParams, other.mChildParams); + + // STOPSHIP: b/163604823 Also check mIkeParams and mChildParams when it is supported to + // construct mIkeParams and mChildParams from PersistableBundles. They are not checked + // now so that VcnGatewayConnectionConfigTest and VcnConfigTest can pass. + return super.equals(o); + } + + /** @hide */ + @Override + public VcnControlPlaneConfig copy() { + return new VcnControlPlaneIkeConfig( + new IkeSessionParams.Builder(mIkeParams).build(), + new TunnelModeChildSessionParams.Builder(mChildParams).build()); } } diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index 40aa518c7b2fcd15342ab1e43dec4af5bd194a9b..94dff9159bd9575bcdb840de6a6fa4b094292d40 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -150,14 +150,15 @@ public final class VcnGatewayConnectionConfig { TimeUnit.MINUTES.toMillis(15) }; + private static final String CTRL_PLANE_CONFIG_KEY = "mCtrlPlaneConfig"; + @NonNull private VcnControlPlaneConfig mCtrlPlaneConfig; + private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities"; @NonNull private final SortedSet<Integer> mExposedCapabilities; private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities"; @NonNull private final SortedSet<Integer> mUnderlyingCapabilities; - // TODO: Add Ike/ChildSessionParams as a subclass - maybe VcnIkeGatewayConnectionConfig - private static final String MAX_MTU_KEY = "mMaxMtu"; private final int mMaxMtu; @@ -166,10 +167,12 @@ public final class VcnGatewayConnectionConfig { /** Builds a VcnGatewayConnectionConfig with the specified parameters. */ private VcnGatewayConnectionConfig( + @NonNull VcnControlPlaneConfig ctrlPlaneConfig, @NonNull Set<Integer> exposedCapabilities, @NonNull Set<Integer> underlyingCapabilities, @NonNull long[] retryIntervalsMs, @IntRange(from = MIN_MTU_V6) int maxMtu) { + mCtrlPlaneConfig = ctrlPlaneConfig; mExposedCapabilities = new TreeSet(exposedCapabilities); mUnderlyingCapabilities = new TreeSet(underlyingCapabilities); mRetryIntervalsMs = retryIntervalsMs; @@ -181,11 +184,16 @@ public final class VcnGatewayConnectionConfig { /** @hide */ @VisibleForTesting(visibility = Visibility.PRIVATE) public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) { + final PersistableBundle ctrlPlaneConfigBundle = + in.getPersistableBundle(CTRL_PLANE_CONFIG_KEY); + Objects.requireNonNull(ctrlPlaneConfigBundle, "ctrlPlaneConfigBundle was null"); + final PersistableBundle exposedCapsBundle = in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY); final PersistableBundle underlyingCapsBundle = in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY); + mCtrlPlaneConfig = VcnControlPlaneConfig.fromPersistableBundle(ctrlPlaneConfigBundle); mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList( exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER)); mUnderlyingCapabilities = new TreeSet<>(PersistableBundleUtils.toList( @@ -197,6 +205,8 @@ public final class VcnGatewayConnectionConfig { } private void validate() { + Objects.requireNonNull(mCtrlPlaneConfig, "control plane config was null"); + Preconditions.checkArgument( mExposedCapabilities != null && !mExposedCapabilities.isEmpty(), "exposedCapsBundle was null or empty"); @@ -239,6 +249,16 @@ public final class VcnGatewayConnectionConfig { } } + /** + * Returns control plane configuration. + * + * @hide + */ + @NonNull + public VcnControlPlaneConfig getControlPlaneConfig() { + return mCtrlPlaneConfig.copy(); + } + /** * Returns all exposed capabilities. * @@ -340,6 +360,7 @@ public final class VcnGatewayConnectionConfig { public PersistableBundle toPersistableBundle() { final PersistableBundle result = new PersistableBundle(); + final PersistableBundle ctrlPlaneConfigBundle = mCtrlPlaneConfig.toPersistableBundle(); final PersistableBundle exposedCapsBundle = PersistableBundleUtils.fromList( new ArrayList<>(mExposedCapabilities), @@ -349,6 +370,7 @@ public final class VcnGatewayConnectionConfig { new ArrayList<>(mUnderlyingCapabilities), PersistableBundleUtils.INTEGER_SERIALIZER); + result.putPersistableBundle(CTRL_PLANE_CONFIG_KEY, ctrlPlaneConfigBundle); result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle); result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle); result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs); @@ -383,6 +405,7 @@ public final class VcnGatewayConnectionConfig { * This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects. */ public static final class Builder { + @NonNull private final VcnControlPlaneConfig mCtrlPlaneConfig; @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet(); @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet(); @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS; @@ -392,6 +415,26 @@ public final class VcnGatewayConnectionConfig { // Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS // when on Cell. + /** + * Construct a Builder object. + * + * @param ctrlPlaneConfig the control plane configuration + * @see VcnControlPlaneConfig + * @hide + */ + public Builder(@NonNull VcnControlPlaneConfig ctrlPlaneConfig) { + Objects.requireNonNull(ctrlPlaneConfig, "ctrlPlaneConfig was null"); + + mCtrlPlaneConfig = ctrlPlaneConfig; + } + + /** Construct a Builder object. */ + // TODO: Remove this constructor when #Builder(ctrlPlaneConfig) is exposed as public API. + // This constructor is created to avoid changing API shape in this CL + public Builder() { + mCtrlPlaneConfig = null; + } + /** * Add a capability that this VCN Gateway Connection will support. * @@ -529,7 +572,11 @@ public final class VcnGatewayConnectionConfig { @NonNull public VcnGatewayConnectionConfig build() { return new VcnGatewayConnectionConfig( - mExposedCapabilities, mUnderlyingCapabilities, mRetryIntervalsMs, mMaxMtu); + mCtrlPlaneConfig, + mExposedCapabilities, + mUnderlyingCapabilities, + mRetryIntervalsMs, + mMaxMtu); } } } diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp index c04ddd78e69bb8ea01c68a8ccd977de507f550f9..1dedc19f0c882ee75d5568689d29548b6e676f35 100644 --- a/tests/vcn/Android.bp +++ b/tests/vcn/Android.bp @@ -21,7 +21,6 @@ android_test { "services.core", ], libs: [ - "android.net.ipsec.ike.stubs.module_lib", "android.test.runner", "android.test.base", "android.test.mock", diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java index 3e659d0bc1280acf3d1a2e718cce343de975f45a..5b17aadc50a6d14411510c37062d0436c411d0c1 100644 --- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java @@ -18,6 +18,7 @@ package android.net.vcn; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; import android.net.NetworkCapabilities; @@ -57,17 +58,22 @@ public class VcnGatewayConnectionConfigTest { }; public static final int MAX_MTU = 1360; + public static final VcnControlPlaneConfig CONTROL_PLANE_CONFIG = + VcnControlPlaneIkeConfigTest.buildTestConfig(); + // Public for use in VcnGatewayConnectionTest public static VcnGatewayConnectionConfig buildTestConfig() { return buildTestConfigWithExposedCaps(EXPOSED_CAPS); } + private static VcnGatewayConnectionConfig.Builder newBuilder() { + return new VcnGatewayConnectionConfig.Builder(CONTROL_PLANE_CONFIG); + } + // Public for use in VcnGatewayConnectionTest public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) { final VcnGatewayConnectionConfig.Builder builder = - new VcnGatewayConnectionConfig.Builder() - .setRetryInterval(RETRY_INTERVALS_MS) - .setMaxMtu(MAX_MTU); + newBuilder().setRetryInterval(RETRY_INTERVALS_MS).setMaxMtu(MAX_MTU); for (int caps : exposedCaps) { builder.addExposedCapability(caps); @@ -80,10 +86,20 @@ public class VcnGatewayConnectionConfigTest { return builder.build(); } + @Test + public void testBuilderRequiresNonNullControlPlaneConfig() { + try { + new VcnGatewayConnectionConfig.Builder(null).build(); + + fail("Expected exception due to invalid control plane config"); + } catch (NullPointerException e) { + } + } + @Test public void testBuilderRequiresNonEmptyExposedCaps() { try { - new VcnGatewayConnectionConfig.Builder() + newBuilder() .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build(); @@ -95,9 +111,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresNonEmptyUnderlyingCaps() { try { - new VcnGatewayConnectionConfig.Builder() - .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); + newBuilder().addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); fail("Expected exception due to invalid required underlying capabilities"); } catch (IllegalArgumentException e) { @@ -107,7 +121,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresNonNullRetryInterval() { try { - new VcnGatewayConnectionConfig.Builder().setRetryInterval(null); + newBuilder().setRetryInterval(null); fail("Expected exception due to invalid retryIntervalMs"); } catch (IllegalArgumentException e) { } @@ -116,7 +130,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresNonEmptyRetryInterval() { try { - new VcnGatewayConnectionConfig.Builder().setRetryInterval(new long[0]); + newBuilder().setRetryInterval(new long[0]); fail("Expected exception due to invalid retryIntervalMs"); } catch (IllegalArgumentException e) { } @@ -125,8 +139,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresValidMtu() { try { - new VcnGatewayConnectionConfig.Builder() - .setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1); + newBuilder().setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1); fail("Expected exception due to invalid mtu"); } catch (IllegalArgumentException e) { } @@ -144,6 +157,9 @@ public class VcnGatewayConnectionConfigTest { Arrays.sort(underlyingCaps); assertArrayEquals(UNDERLYING_CAPS, underlyingCaps); + assertEquals(CONTROL_PLANE_CONFIG, config.getControlPlaneConfig()); + assertFalse(CONTROL_PLANE_CONFIG == config.getControlPlaneConfig()); + assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMs()); assertEquals(MAX_MTU, config.getMaxMtu()); }