| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package android.net.vcn; |
| |
| import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE; |
| import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED; |
| |
| import static com.android.internal.annotations.VisibleForTesting.Visibility; |
| |
| import android.annotation.IntDef; |
| import android.annotation.IntRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.SuppressLint; |
| import android.net.Network; |
| import android.net.NetworkCapabilities; |
| import android.net.ipsec.ike.IkeTunnelConnectionParams; |
| import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtils; |
| import android.os.PersistableBundle; |
| import android.util.ArraySet; |
| |
| import com.android.internal.annotations.VisibleForTesting; |
| import com.android.internal.util.ArrayUtils; |
| import com.android.internal.util.Preconditions; |
| import com.android.server.vcn.util.PersistableBundleUtils; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Objects; |
| import java.util.Set; |
| import java.util.SortedSet; |
| import java.util.TreeSet; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * This class represents a configuration for a connection to a Virtual Carrier Network gateway. |
| * |
| * <p>Each VcnGatewayConnectionConfig represents a single logical connection to a carrier gateway, |
| * and may provide one or more telephony services (as represented by network capabilities). Each |
| * gateway is expected to provide mobility for a given session as the device roams across {@link |
| * Network}s. |
| * |
| * <p>A VCN connection based on this configuration will be brought up dynamically based on device |
| * settings, and filed NetworkRequests. Underlying Networks must provide INTERNET connectivity, and |
| * must be part of the subscription group under which this configuration is registered (see {@link |
| * VcnManager#setVcnConfig}). |
| * |
| * <p>As an abstraction of a cellular network, services that can be provided by a VCN network are |
| * limited to services provided by cellular networks: |
| * |
| * <ul> |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_MMS} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_SUPL} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_DUN} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_FOTA} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_IMS} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_CBS} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_IA} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_RCS} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_XCAP} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_EIMS} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_INTERNET} |
| * <li>{@link NetworkCapabilities#NET_CAPABILITY_MCX} |
| * </ul> |
| */ |
| public final class VcnGatewayConnectionConfig { |
| /** @hide */ |
| public static final int MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET = -1; |
| |
| /** @hide */ |
| public static final int MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS = 120; |
| |
| // TODO: Use MIN_MTU_V6 once it is public, @hide |
| @VisibleForTesting(visibility = Visibility.PRIVATE) |
| static final int MIN_MTU_V6 = 1280; |
| |
| /** |
| * The set of allowed capabilities for exposed capabilities. |
| * |
| * @hide |
| */ |
| public static final Set<Integer> ALLOWED_CAPABILITIES; |
| |
| static { |
| Set<Integer> allowedCaps = new ArraySet<>(); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MMS); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_SUPL); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_DUN); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_FOTA); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IMS); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_CBS); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IA); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_RCS); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_XCAP); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_EIMS); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_INTERNET); |
| allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MCX); |
| |
| ALLOWED_CAPABILITIES = Collections.unmodifiableSet(allowedCaps); |
| } |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef( |
| prefix = {"NET_CAPABILITY_"}, |
| value = { |
| NetworkCapabilities.NET_CAPABILITY_MMS, |
| NetworkCapabilities.NET_CAPABILITY_SUPL, |
| NetworkCapabilities.NET_CAPABILITY_DUN, |
| NetworkCapabilities.NET_CAPABILITY_FOTA, |
| NetworkCapabilities.NET_CAPABILITY_IMS, |
| NetworkCapabilities.NET_CAPABILITY_CBS, |
| NetworkCapabilities.NET_CAPABILITY_IA, |
| NetworkCapabilities.NET_CAPABILITY_RCS, |
| NetworkCapabilities.NET_CAPABILITY_XCAP, |
| NetworkCapabilities.NET_CAPABILITY_EIMS, |
| NetworkCapabilities.NET_CAPABILITY_INTERNET, |
| NetworkCapabilities.NET_CAPABILITY_MCX, |
| }) |
| public @interface VcnSupportedCapability {} |
| |
| /** |
| * Perform mobility update to attempt recovery from suspected data stalls. |
| * |
| * <p>If set, the gateway connection will monitor the data stall detection of the VCN network. |
| * When there is a suspected data stall, the gateway connection will attempt recovery by |
| * performing a mobility update on the underlying IKE session. |
| */ |
| public static final int VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY = 0; |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef( |
| prefix = {"VCN_GATEWAY_OPTION_"}, |
| value = { |
| VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY, |
| }) |
| public @interface VcnGatewayOption {} |
| |
| private static final Set<Integer> ALLOWED_GATEWAY_OPTIONS = new ArraySet<>(); |
| |
| static { |
| ALLOWED_GATEWAY_OPTIONS.add(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY); |
| } |
| |
| private static final int DEFAULT_MAX_MTU = 1500; |
| |
| /** |
| * The maximum number of retry intervals that may be specified. |
| * |
| * <p>Limited to ensure an upper bound on config sizes. |
| */ |
| private static final int MAX_RETRY_INTERVAL_COUNT = 10; |
| |
| /** |
| * The minimum allowable repeating retry interval |
| * |
| * <p>To ensure the device is not constantly being woken up, this retry interval MUST be greater |
| * than this value. |
| * |
| * @see {@link Builder#setRetryIntervalsMillis()} |
| */ |
| private static final long MINIMUM_REPEATING_RETRY_INTERVAL_MS = TimeUnit.MINUTES.toMillis(15); |
| |
| private static final long[] DEFAULT_RETRY_INTERVALS_MS = |
| new long[] { |
| TimeUnit.SECONDS.toMillis(1), |
| TimeUnit.SECONDS.toMillis(2), |
| TimeUnit.SECONDS.toMillis(5), |
| TimeUnit.SECONDS.toMillis(30), |
| TimeUnit.MINUTES.toMillis(1), |
| TimeUnit.MINUTES.toMillis(5), |
| TimeUnit.MINUTES.toMillis(15) |
| }; |
| |
| /** @hide */ |
| @VisibleForTesting(visibility = Visibility.PRIVATE) |
| public static final List<VcnUnderlyingNetworkTemplate> DEFAULT_UNDERLYING_NETWORK_TEMPLATES = |
| new ArrayList<>(); |
| |
| static { |
| DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( |
| new VcnCellUnderlyingNetworkTemplate.Builder() |
| .setOpportunistic(MATCH_REQUIRED) |
| .build()); |
| |
| DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( |
| new VcnWifiUnderlyingNetworkTemplate.Builder() |
| .build()); |
| |
| DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( |
| new VcnCellUnderlyingNetworkTemplate.Builder() |
| .build()); |
| } |
| |
| private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName"; |
| @NonNull private final String mGatewayConnectionName; |
| |
| private static final String TUNNEL_CONNECTION_PARAMS_KEY = "mTunnelConnectionParams"; |
| @NonNull private IkeTunnelConnectionParams mTunnelConnectionParams; |
| |
| private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities"; |
| @NonNull private final SortedSet<Integer> mExposedCapabilities; |
| |
| /** @hide */ |
| @VisibleForTesting(visibility = Visibility.PRIVATE) |
| public static final String UNDERLYING_NETWORK_TEMPLATES_KEY = "mUnderlyingNetworkTemplates"; |
| |
| @NonNull private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates; |
| |
| private static final String MAX_MTU_KEY = "mMaxMtu"; |
| private final int mMaxMtu; |
| |
| private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs"; |
| @NonNull private final long[] mRetryIntervalsMs; |
| |
| private static final String MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY = |
| "mMinUdpPort4500NatTimeoutSeconds"; |
| private final int mMinUdpPort4500NatTimeoutSeconds; |
| |
| private static final String GATEWAY_OPTIONS_KEY = "mGatewayOptions"; |
| @NonNull private final Set<Integer> mGatewayOptions; |
| |
| /** Builds a VcnGatewayConnectionConfig with the specified parameters. */ |
| private VcnGatewayConnectionConfig( |
| @NonNull String gatewayConnectionName, |
| @NonNull IkeTunnelConnectionParams tunnelConnectionParams, |
| @NonNull Set<Integer> exposedCapabilities, |
| @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, |
| @NonNull long[] retryIntervalsMs, |
| @IntRange(from = MIN_MTU_V6) int maxMtu, |
| @NonNull int minUdpPort4500NatTimeoutSeconds, |
| @NonNull Set<Integer> gatewayOptions) { |
| mGatewayConnectionName = gatewayConnectionName; |
| mTunnelConnectionParams = tunnelConnectionParams; |
| mExposedCapabilities = new TreeSet(exposedCapabilities); |
| mRetryIntervalsMs = retryIntervalsMs; |
| mMaxMtu = maxMtu; |
| mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds; |
| mGatewayOptions = Collections.unmodifiableSet(new ArraySet(gatewayOptions)); |
| |
| mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates); |
| if (mUnderlyingNetworkTemplates.isEmpty()) { |
| mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); |
| } |
| |
| validate(); |
| } |
| |
| // Null check MUST be done for all new fields added to VcnGatewayConnectionConfig, to avoid |
| // crashes when parsing PersistableBundle built on old platforms. |
| /** @hide */ |
| @VisibleForTesting(visibility = Visibility.PRIVATE) |
| public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) { |
| final PersistableBundle tunnelConnectionParamsBundle = |
| in.getPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY); |
| Objects.requireNonNull( |
| tunnelConnectionParamsBundle, "tunnelConnectionParamsBundle was null"); |
| |
| final PersistableBundle exposedCapsBundle = |
| in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY); |
| mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY); |
| mTunnelConnectionParams = |
| TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle); |
| mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList( |
| exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER)); |
| |
| final PersistableBundle networkTemplatesBundle = |
| in.getPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY); |
| |
| if (networkTemplatesBundle == null) { |
| // UNDERLYING_NETWORK_TEMPLATES_KEY was added in Android T. Thus |
| // VcnGatewayConnectionConfig created on old platforms will not have this data and will |
| // be assigned with the default value |
| mUnderlyingNetworkTemplates = new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); |
| } else { |
| mUnderlyingNetworkTemplates = |
| PersistableBundleUtils.toList( |
| networkTemplatesBundle, |
| VcnUnderlyingNetworkTemplate::fromPersistableBundle); |
| } |
| |
| final PersistableBundle gatewayOptionsBundle = in.getPersistableBundle(GATEWAY_OPTIONS_KEY); |
| |
| if (gatewayOptionsBundle == null) { |
| // GATEWAY_OPTIONS_KEY was added in Android U. Thus VcnGatewayConnectionConfig created |
| // on old platforms will not have this data and will be assigned with the default value |
| mGatewayOptions = Collections.emptySet(); |
| } else { |
| mGatewayOptions = |
| new ArraySet<>( |
| PersistableBundleUtils.toList( |
| gatewayOptionsBundle, |
| PersistableBundleUtils.INTEGER_DESERIALIZER)); |
| } |
| |
| mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY); |
| mMaxMtu = in.getInt(MAX_MTU_KEY); |
| mMinUdpPort4500NatTimeoutSeconds = |
| in.getInt( |
| MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY, |
| MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET); |
| |
| validate(); |
| } |
| |
| private void validate() { |
| Objects.requireNonNull(mGatewayConnectionName, "gatewayConnectionName was null"); |
| Objects.requireNonNull(mTunnelConnectionParams, "tunnel connection parameter was null"); |
| |
| Preconditions.checkArgument( |
| mExposedCapabilities != null && !mExposedCapabilities.isEmpty(), |
| "exposedCapsBundle was null or empty"); |
| for (Integer cap : getAllExposedCapabilities()) { |
| checkValidCapability(cap); |
| } |
| |
| validateNetworkTemplateList(mUnderlyingNetworkTemplates); |
| Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null"); |
| validateRetryInterval(mRetryIntervalsMs); |
| |
| Preconditions.checkArgument( |
| mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)"); |
| |
| Preconditions.checkArgument( |
| mMinUdpPort4500NatTimeoutSeconds == MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET |
| || mMinUdpPort4500NatTimeoutSeconds |
| >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS, |
| "minUdpPort4500NatTimeoutSeconds must be at least 120s"); |
| |
| for (int option : mGatewayOptions) { |
| validateGatewayOption(option); |
| } |
| } |
| |
| private static void checkValidCapability(int capability) { |
| Preconditions.checkArgument( |
| ALLOWED_CAPABILITIES.contains(capability), |
| "NetworkCapability " + capability + "out of range"); |
| } |
| |
| private static void validateRetryInterval(@Nullable long[] retryIntervalsMs) { |
| Preconditions.checkArgument( |
| retryIntervalsMs != null |
| && retryIntervalsMs.length > 0 |
| && retryIntervalsMs.length <= MAX_RETRY_INTERVAL_COUNT, |
| "retryIntervalsMs was null, empty or exceed max interval count"); |
| |
| final long repeatingInterval = retryIntervalsMs[retryIntervalsMs.length - 1]; |
| if (repeatingInterval < MINIMUM_REPEATING_RETRY_INTERVAL_MS) { |
| throw new IllegalArgumentException( |
| "Repeating retry interval was too short, must be a minimum of 15 minutes: " |
| + repeatingInterval); |
| } |
| } |
| |
| private static void validateNetworkTemplateList( |
| List<VcnUnderlyingNetworkTemplate> networkPriorityRules) { |
| Objects.requireNonNull(networkPriorityRules, "networkPriorityRules is null"); |
| |
| Set<VcnUnderlyingNetworkTemplate> existingRules = new ArraySet<>(); |
| for (VcnUnderlyingNetworkTemplate rule : networkPriorityRules) { |
| Objects.requireNonNull(rule, "Found null value VcnUnderlyingNetworkTemplate"); |
| if (!existingRules.add(rule)) { |
| throw new IllegalArgumentException("Found duplicate VcnUnderlyingNetworkTemplate"); |
| } |
| } |
| } |
| |
| private static void validateGatewayOption(int option) { |
| if (!ALLOWED_GATEWAY_OPTIONS.contains(option)) { |
| throw new IllegalArgumentException("Invalid vcn gateway option: " + option); |
| } |
| } |
| |
| /** |
| * Returns the configured Gateway Connection name. |
| * |
| * <p>This name is used by the configuring apps to distinguish between |
| * VcnGatewayConnectionConfigs configured on a single {@link VcnConfig}. This will be used as |
| * the identifier in VcnStatusCallback invocations. |
| * |
| * @see VcnManager.VcnStatusCallback#onGatewayConnectionError |
| */ |
| @NonNull |
| public String getGatewayConnectionName() { |
| return mGatewayConnectionName; |
| } |
| |
| /** |
| * Returns tunnel connection parameters. |
| * |
| * @hide |
| */ |
| @NonNull |
| public IkeTunnelConnectionParams getTunnelConnectionParams() { |
| return mTunnelConnectionParams; |
| } |
| |
| /** |
| * Returns all exposed capabilities. |
| * |
| * <p>The returned integer-value capabilities will not contain duplicates, and will be sorted in |
| * ascending numerical order. |
| * |
| * @see Builder#addExposedCapability(int) |
| * @see Builder#removeExposedCapability(int) |
| */ |
| @NonNull |
| public int[] getExposedCapabilities() { |
| // Sorted set guarantees ordering |
| return ArrayUtils.convertToIntArray(new ArrayList<>(mExposedCapabilities)); |
| } |
| |
| /** |
| * Returns all exposed capabilities. |
| * |
| * <p>Left to prevent the need to make major changes while changes are actively in flight. |
| * |
| * @deprecated use getExposedCapabilities() instead |
| * @hide |
| */ |
| @Deprecated |
| @NonNull |
| public Set<Integer> getAllExposedCapabilities() { |
| return Collections.unmodifiableSet(mExposedCapabilities); |
| } |
| |
| /** |
| * Retrieve the VcnUnderlyingNetworkTemplate list, or a default list if it is not configured. |
| * |
| * @see Builder#setVcnUnderlyingNetworkPriorities(List) |
| */ |
| @NonNull |
| public List<VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities() { |
| return new ArrayList<>(mUnderlyingNetworkTemplates); |
| } |
| |
| /** |
| * Retrieves the configured retry intervals. |
| * |
| * @see Builder#setRetryIntervalsMillis(long[]) |
| */ |
| @NonNull |
| public long[] getRetryIntervalsMillis() { |
| return Arrays.copyOf(mRetryIntervalsMs, mRetryIntervalsMs.length); |
| } |
| |
| /** |
| * Retrieves the maximum MTU allowed for this Gateway Connection. |
| * |
| * @see Builder#setMaxMtu(int) |
| */ |
| @IntRange(from = MIN_MTU_V6) |
| public int getMaxMtu() { |
| return mMaxMtu; |
| } |
| |
| /** |
| * Retrieves the maximum supported IKEv2/IPsec NATT keepalive timeout. |
| * |
| * @see Builder#setMinUdpPort4500NatTimeoutSeconds(int) |
| */ |
| public int getMinUdpPort4500NatTimeoutSeconds() { |
| return mMinUdpPort4500NatTimeoutSeconds; |
| } |
| |
| /** |
| * Checks if the given VCN gateway option is enabled. |
| * |
| * @param option the option to check. |
| * @throws IllegalArgumentException if the provided option is invalid. |
| * @see Builder#addGatewayOption(int) |
| * @see Builder#removeGatewayOption(int) |
| */ |
| public boolean hasGatewayOption(@VcnGatewayOption int option) { |
| validateGatewayOption(option); |
| return mGatewayOptions.contains(option); |
| } |
| |
| /** |
| * Converts this config to a PersistableBundle. |
| * |
| * @hide |
| */ |
| @NonNull |
| @VisibleForTesting(visibility = Visibility.PROTECTED) |
| public PersistableBundle toPersistableBundle() { |
| final PersistableBundle result = new PersistableBundle(); |
| |
| final PersistableBundle tunnelConnectionParamsBundle = |
| TunnelConnectionParamsUtils.toPersistableBundle(mTunnelConnectionParams); |
| final PersistableBundle exposedCapsBundle = |
| PersistableBundleUtils.fromList( |
| new ArrayList<>(mExposedCapabilities), |
| PersistableBundleUtils.INTEGER_SERIALIZER); |
| final PersistableBundle networkTemplatesBundle = |
| PersistableBundleUtils.fromList( |
| mUnderlyingNetworkTemplates, |
| VcnUnderlyingNetworkTemplate::toPersistableBundle); |
| final PersistableBundle gatewayOptionsBundle = |
| PersistableBundleUtils.fromList( |
| new ArrayList<>(mGatewayOptions), |
| PersistableBundleUtils.INTEGER_SERIALIZER); |
| |
| result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName); |
| result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle); |
| result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle); |
| result.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, networkTemplatesBundle); |
| result.putPersistableBundle(GATEWAY_OPTIONS_KEY, gatewayOptionsBundle); |
| result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs); |
| result.putInt(MAX_MTU_KEY, mMaxMtu); |
| result.putInt(MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY, mMinUdpPort4500NatTimeoutSeconds); |
| |
| return result; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash( |
| mGatewayConnectionName, |
| mTunnelConnectionParams, |
| mExposedCapabilities, |
| mUnderlyingNetworkTemplates, |
| Arrays.hashCode(mRetryIntervalsMs), |
| mMaxMtu, |
| mMinUdpPort4500NatTimeoutSeconds, |
| mGatewayOptions); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object other) { |
| if (!(other instanceof VcnGatewayConnectionConfig)) { |
| return false; |
| } |
| |
| final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other; |
| return mGatewayConnectionName.equals(rhs.mGatewayConnectionName) |
| && mTunnelConnectionParams.equals(rhs.mTunnelConnectionParams) |
| && mExposedCapabilities.equals(rhs.mExposedCapabilities) |
| && mUnderlyingNetworkTemplates.equals(rhs.mUnderlyingNetworkTemplates) |
| && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs) |
| && mMaxMtu == rhs.mMaxMtu |
| && mMinUdpPort4500NatTimeoutSeconds == rhs.mMinUdpPort4500NatTimeoutSeconds |
| && mGatewayOptions.equals(rhs.mGatewayOptions); |
| } |
| |
| /** |
| * This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects. |
| */ |
| public static final class Builder { |
| @NonNull private final String mGatewayConnectionName; |
| @NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams; |
| @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet(); |
| |
| @NonNull |
| private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates = |
| new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); |
| |
| @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS; |
| private int mMaxMtu = DEFAULT_MAX_MTU; |
| private int mMinUdpPort4500NatTimeoutSeconds = MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET; |
| |
| @NonNull private final Set<Integer> mGatewayOptions = new ArraySet<>(); |
| |
| // TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent. |
| // Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS |
| // when on Cell. |
| |
| /** |
| * Construct a Builder object. |
| * |
| * @param gatewayConnectionName the String GatewayConnection name for this |
| * VcnGatewayConnectionConfig. Each VcnGatewayConnectionConfig within a {@link |
| * VcnConfig} must be given a unique name. This name is used by the caller to |
| * distinguish between VcnGatewayConnectionConfigs configured on a single {@link |
| * VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations. |
| * @param tunnelConnectionParams the IKE tunnel connection configuration |
| * @throws IllegalArgumentException if the provided IkeTunnelConnectionParams is not |
| * configured to support MOBIKE |
| * @see IkeTunnelConnectionParams |
| * @see VcnManager.VcnStatusCallback#onGatewayConnectionError |
| */ |
| public Builder( |
| @NonNull String gatewayConnectionName, |
| @NonNull IkeTunnelConnectionParams tunnelConnectionParams) { |
| Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null"); |
| Objects.requireNonNull(tunnelConnectionParams, "tunnelConnectionParams was null"); |
| if (!tunnelConnectionParams.getIkeSessionParams().hasIkeOption(IKE_OPTION_MOBIKE)) { |
| throw new IllegalArgumentException( |
| "MOBIKE must be configured for the provided IkeSessionParams"); |
| } |
| |
| mGatewayConnectionName = gatewayConnectionName; |
| mTunnelConnectionParams = tunnelConnectionParams; |
| } |
| |
| /** |
| * Add a capability that this VCN Gateway Connection will support. |
| * |
| * @param exposedCapability the app-facing capability to be exposed by this VCN Gateway |
| * Connection (i.e., the capabilities that this VCN Gateway Connection will support). |
| * @return this {@link Builder} instance, for chaining |
| * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway |
| * Connection |
| */ |
| @NonNull |
| public Builder addExposedCapability(@VcnSupportedCapability int exposedCapability) { |
| checkValidCapability(exposedCapability); |
| |
| mExposedCapabilities.add(exposedCapability); |
| return this; |
| } |
| |
| /** |
| * Remove a capability that this VCN Gateway Connection will support. |
| * |
| * @param exposedCapability the app-facing capability to not be exposed by this VCN Gateway |
| * Connection (i.e., the capabilities that this VCN Gateway Connection will support) |
| * @return this {@link Builder} instance, for chaining |
| * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway |
| * Connection |
| */ |
| @NonNull |
| @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap |
| public Builder removeExposedCapability(@VcnSupportedCapability int exposedCapability) { |
| checkValidCapability(exposedCapability); |
| |
| mExposedCapabilities.remove(exposedCapability); |
| return this; |
| } |
| |
| /** |
| * Set the list of templates to match underlying networks against, in high-to-low priority |
| * order. |
| * |
| * <p>To select the VCN underlying network, the VCN connection will go through all the |
| * network candidates and return a network matching the highest priority rule. |
| * |
| * <p>If multiple networks match the same rule, the VCN will prefer an already-selected |
| * network as opposed to a new/unselected network. However, if both are new/unselected |
| * networks, a network will be chosen arbitrarily amongst the networks matching the highest |
| * priority rule. |
| * |
| * <p>If all networks fail to match the rules provided, a carrier-owned underlying network |
| * will still be selected (if available, at random if necessary). |
| * |
| * @param underlyingNetworkTemplates a list of unique VcnUnderlyingNetworkTemplates that are |
| * ordered from most to least preferred, or an empty list to use the default |
| * prioritization. The default network prioritization order is Opportunistic cellular, |
| * Carrier WiFi and then Macro cellular. |
| * @return this {@link Builder} instance, for chaining |
| */ |
| @NonNull |
| public Builder setVcnUnderlyingNetworkPriorities( |
| @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates) { |
| validateNetworkTemplateList(underlyingNetworkTemplates); |
| |
| mUnderlyingNetworkTemplates.clear(); |
| |
| if (underlyingNetworkTemplates.isEmpty()) { |
| mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); |
| } else { |
| mUnderlyingNetworkTemplates.addAll(underlyingNetworkTemplates); |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Set the retry interval between VCN establishment attempts upon successive failures. |
| * |
| * <p>The last retry interval will be repeated until safe mode is entered, or a connection |
| * is successfully established, at which point the retry timers will be reset. For power |
| * reasons, the last (repeated) retry interval MUST be at least 15 minutes. |
| * |
| * <p>Retry intervals MAY be subject to system power saving modes. That is to say that if |
| * the system enters a power saving mode, the retry may not occur until the device leaves |
| * the specified power saving mode. Intervals are sequential, and intervals will NOT be |
| * skipped if system power saving results in delaying retries (even if it exceed multiple |
| * retry intervals). |
| * |
| * <p>Each Gateway Connection will retry according to the retry intervals configured, but if |
| * safe mode is enabled, all Gateway Connection(s) will be disabled. |
| * |
| * @param retryIntervalsMs an array of between 1 and 10 millisecond intervals after which |
| * the VCN will attempt to retry a session initiation. The last (repeating) retry |
| * interval must be at least 15 minutes. Defaults to: {@code [1s, 2s, 5s, 30s, 1m, 5m, |
| * 15m]} |
| * @return this {@link Builder} instance, for chaining |
| * @see VcnManager for additional discussion on fail-safe mode |
| */ |
| @NonNull |
| public Builder setRetryIntervalsMillis(@NonNull long[] retryIntervalsMs) { |
| validateRetryInterval(retryIntervalsMs); |
| |
| mRetryIntervalsMs = retryIntervalsMs; |
| return this; |
| } |
| |
| /** |
| * Sets the maximum MTU allowed for this VCN Gateway Connection. |
| * |
| * <p>This MTU is applied to the VCN Gateway Connection exposed Networks, and represents the |
| * MTU of the virtualized network. |
| * |
| * <p>The system may reduce the MTU below the maximum specified based on signals such as the |
| * MTU of the underlying networks (and adjusted for Gateway Connection overhead). |
| * |
| * @param maxMtu the maximum MTU allowed for this Gateway Connection. Must be greater than |
| * the IPv6 minimum MTU of 1280. Defaults to 1500. |
| * @return this {@link Builder} instance, for chaining |
| */ |
| @NonNull |
| public Builder setMaxMtu(@IntRange(from = MIN_MTU_V6) int maxMtu) { |
| Preconditions.checkArgument( |
| maxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)"); |
| |
| mMaxMtu = maxMtu; |
| return this; |
| } |
| |
| /** |
| * Sets the maximum supported IKEv2/IPsec NATT keepalive timeout. |
| * |
| * <p>This is used as a power-optimization hint for other IKEv2/IPsec use cases (e.g. VPNs, |
| * or IWLAN) to reduce the necessary keepalive frequency, thus conserving power and data. |
| * |
| * @param minUdpPort4500NatTimeoutSeconds the maximum keepalive timeout supported by the VCN |
| * Gateway Connection, generally the minimum duration a NAT mapping is cached on the VCN |
| * Gateway. |
| * @return this {@link Builder} instance, for chaining |
| */ |
| @NonNull |
| public Builder setMinUdpPort4500NatTimeoutSeconds( |
| @IntRange(from = MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS) |
| int minUdpPort4500NatTimeoutSeconds) { |
| Preconditions.checkArgument( |
| minUdpPort4500NatTimeoutSeconds >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS, |
| "Timeout must be at least 120s"); |
| |
| mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds; |
| return this; |
| } |
| |
| /** |
| * Enables the specified VCN gateway option. |
| * |
| * @param option the option to be enabled |
| * @return this {@link Builder} instance, for chaining |
| * @throws IllegalArgumentException if the provided option is invalid |
| */ |
| @NonNull |
| public Builder addGatewayOption(@VcnGatewayOption int option) { |
| validateGatewayOption(option); |
| mGatewayOptions.add(option); |
| return this; |
| } |
| |
| /** |
| * Resets (disables) the specified VCN gateway option. |
| * |
| * @param option the option to be disabled |
| * @return this {@link Builder} instance, for chaining |
| * @throws IllegalArgumentException if the provided option is invalid |
| */ |
| @NonNull |
| public Builder removeGatewayOption(@VcnGatewayOption int option) { |
| validateGatewayOption(option); |
| mGatewayOptions.remove(option); |
| return this; |
| } |
| |
| /** |
| * Builds and validates the VcnGatewayConnectionConfig. |
| * |
| * @return an immutable VcnGatewayConnectionConfig instance |
| */ |
| @NonNull |
| public VcnGatewayConnectionConfig build() { |
| return new VcnGatewayConnectionConfig( |
| mGatewayConnectionName, |
| mTunnelConnectionParams, |
| mExposedCapabilities, |
| mUnderlyingNetworkTemplates, |
| mRetryIntervalsMs, |
| mMaxMtu, |
| mMinUdpPort4500NatTimeoutSeconds, |
| mGatewayOptions); |
| } |
| } |
| } |