1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.net.vcn; 17 18 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE; 19 import static android.net.vcn.Flags.FLAG_SAFE_MODE_CONFIG; 20 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED; 21 22 import static com.android.internal.annotations.VisibleForTesting.Visibility; 23 24 import android.annotation.FlaggedApi; 25 import android.annotation.IntDef; 26 import android.annotation.IntRange; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.SuppressLint; 30 import android.net.Network; 31 import android.net.NetworkCapabilities; 32 import android.net.ipsec.ike.IkeTunnelConnectionParams; 33 import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtils; 34 import android.os.PersistableBundle; 35 import android.util.ArraySet; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.internal.util.ArrayUtils; 39 import com.android.internal.util.Preconditions; 40 import com.android.server.vcn.util.PersistableBundleUtils; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.Collections; 47 import java.util.List; 48 import java.util.Objects; 49 import java.util.Set; 50 import java.util.SortedSet; 51 import java.util.TreeSet; 52 import java.util.concurrent.TimeUnit; 53 54 /** 55 * This class represents a configuration for a connection to a Virtual Carrier Network gateway. 56 * 57 * <p>Each VcnGatewayConnectionConfig represents a single logical connection to a carrier gateway, 58 * and may provide one or more telephony services (as represented by network capabilities). Each 59 * gateway is expected to provide mobility for a given session as the device roams across {@link 60 * Network}s. 61 * 62 * <p>A VCN connection based on this configuration will be brought up dynamically based on device 63 * settings, and filed NetworkRequests. Underlying Networks must provide INTERNET connectivity, and 64 * must be part of the subscription group under which this configuration is registered (see {@link 65 * VcnManager#setVcnConfig}). 66 * 67 * <p>As an abstraction of a cellular network, services that can be provided by a VCN network are 68 * limited to services provided by cellular networks: 69 * 70 * <ul> 71 * <li>{@link NetworkCapabilities#NET_CAPABILITY_MMS} 72 * <li>{@link NetworkCapabilities#NET_CAPABILITY_SUPL} 73 * <li>{@link NetworkCapabilities#NET_CAPABILITY_DUN} 74 * <li>{@link NetworkCapabilities#NET_CAPABILITY_FOTA} 75 * <li>{@link NetworkCapabilities#NET_CAPABILITY_IMS} 76 * <li>{@link NetworkCapabilities#NET_CAPABILITY_CBS} 77 * <li>{@link NetworkCapabilities#NET_CAPABILITY_IA} 78 * <li>{@link NetworkCapabilities#NET_CAPABILITY_RCS} 79 * <li>{@link NetworkCapabilities#NET_CAPABILITY_XCAP} 80 * <li>{@link NetworkCapabilities#NET_CAPABILITY_EIMS} 81 * <li>{@link NetworkCapabilities#NET_CAPABILITY_INTERNET} 82 * <li>{@link NetworkCapabilities#NET_CAPABILITY_MCX} 83 * </ul> 84 */ 85 public final class VcnGatewayConnectionConfig { 86 /** @hide */ 87 public static final int MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET = -1; 88 89 /** @hide */ 90 public static final int MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS = 120; 91 92 // TODO: Use MIN_MTU_V6 once it is public, @hide 93 @VisibleForTesting(visibility = Visibility.PRIVATE) 94 static final int MIN_MTU_V6 = 1280; 95 96 /** 97 * The set of allowed capabilities for exposed capabilities. 98 * 99 * @hide 100 */ 101 public static final Set<Integer> ALLOWED_CAPABILITIES; 102 103 static { 104 Set<Integer> allowedCaps = new ArraySet<>(); 105 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MMS); 106 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_SUPL); 107 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_DUN); 108 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_FOTA); 109 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IMS); 110 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_CBS); 111 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IA); 112 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_RCS); 113 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_XCAP); 114 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_EIMS); 115 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_INTERNET); 116 allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MCX); 117 118 ALLOWED_CAPABILITIES = Collections.unmodifiableSet(allowedCaps); 119 } 120 121 /** @hide */ 122 @Retention(RetentionPolicy.SOURCE) 123 @IntDef( 124 prefix = {"NET_CAPABILITY_"}, 125 value = { 126 NetworkCapabilities.NET_CAPABILITY_MMS, 127 NetworkCapabilities.NET_CAPABILITY_SUPL, 128 NetworkCapabilities.NET_CAPABILITY_DUN, 129 NetworkCapabilities.NET_CAPABILITY_FOTA, 130 NetworkCapabilities.NET_CAPABILITY_IMS, 131 NetworkCapabilities.NET_CAPABILITY_CBS, 132 NetworkCapabilities.NET_CAPABILITY_IA, 133 NetworkCapabilities.NET_CAPABILITY_RCS, 134 NetworkCapabilities.NET_CAPABILITY_XCAP, 135 NetworkCapabilities.NET_CAPABILITY_EIMS, 136 NetworkCapabilities.NET_CAPABILITY_INTERNET, 137 NetworkCapabilities.NET_CAPABILITY_MCX, 138 }) 139 public @interface VcnSupportedCapability {} 140 141 /** 142 * Perform mobility update to attempt recovery from suspected data stalls. 143 * 144 * <p>If set, the gateway connection will monitor the data stall detection of the VCN network. 145 * When there is a suspected data stall, the gateway connection will attempt recovery by 146 * performing a mobility update on the underlying IKE session. 147 */ 148 public static final int VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY = 0; 149 150 /** @hide */ 151 @Retention(RetentionPolicy.SOURCE) 152 @IntDef( 153 prefix = {"VCN_GATEWAY_OPTION_"}, 154 value = { 155 VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY, 156 }) 157 public @interface VcnGatewayOption {} 158 159 private static final Set<Integer> ALLOWED_GATEWAY_OPTIONS = new ArraySet<>(); 160 161 static { 162 ALLOWED_GATEWAY_OPTIONS.add(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY); 163 } 164 165 private static final int DEFAULT_MAX_MTU = 1500; 166 167 /** 168 * The maximum number of retry intervals that may be specified. 169 * 170 * <p>Limited to ensure an upper bound on config sizes. 171 */ 172 private static final int MAX_RETRY_INTERVAL_COUNT = 10; 173 174 /** 175 * The minimum allowable repeating retry interval 176 * 177 * <p>To ensure the device is not constantly being woken up, this retry interval MUST be greater 178 * than this value. 179 * 180 * @see {@link Builder#setRetryIntervalsMillis()} 181 */ 182 private static final long MINIMUM_REPEATING_RETRY_INTERVAL_MS = TimeUnit.MINUTES.toMillis(15); 183 184 private static final long[] DEFAULT_RETRY_INTERVALS_MS = 185 new long[] { 186 TimeUnit.SECONDS.toMillis(1), 187 TimeUnit.SECONDS.toMillis(2), 188 TimeUnit.SECONDS.toMillis(5), 189 TimeUnit.SECONDS.toMillis(30), 190 TimeUnit.MINUTES.toMillis(1), 191 TimeUnit.MINUTES.toMillis(5), 192 TimeUnit.MINUTES.toMillis(15) 193 }; 194 195 /** @hide */ 196 @VisibleForTesting(visibility = Visibility.PRIVATE) 197 public static final List<VcnUnderlyingNetworkTemplate> DEFAULT_UNDERLYING_NETWORK_TEMPLATES = 198 new ArrayList<>(); 199 200 static { DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( new VcnCellUnderlyingNetworkTemplate.Builder() .setOpportunistic(MATCH_REQUIRED) .build())201 DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( 202 new VcnCellUnderlyingNetworkTemplate.Builder() 203 .setOpportunistic(MATCH_REQUIRED) 204 .build()); 205 DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( new VcnWifiUnderlyingNetworkTemplate.Builder() .build())206 DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( 207 new VcnWifiUnderlyingNetworkTemplate.Builder() 208 .build()); 209 DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( new VcnCellUnderlyingNetworkTemplate.Builder() .build())210 DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( 211 new VcnCellUnderlyingNetworkTemplate.Builder() 212 .build()); 213 } 214 215 private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName"; 216 @NonNull private final String mGatewayConnectionName; 217 218 private static final String TUNNEL_CONNECTION_PARAMS_KEY = "mTunnelConnectionParams"; 219 @NonNull private IkeTunnelConnectionParams mTunnelConnectionParams; 220 221 private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities"; 222 @NonNull private final SortedSet<Integer> mExposedCapabilities; 223 224 /** @hide */ 225 @VisibleForTesting(visibility = Visibility.PRIVATE) 226 public static final String UNDERLYING_NETWORK_TEMPLATES_KEY = "mUnderlyingNetworkTemplates"; 227 228 @NonNull private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates; 229 230 private static final String MAX_MTU_KEY = "mMaxMtu"; 231 private final int mMaxMtu; 232 233 private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs"; 234 @NonNull private final long[] mRetryIntervalsMs; 235 236 private static final String MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY = 237 "mMinUdpPort4500NatTimeoutSeconds"; 238 private final int mMinUdpPort4500NatTimeoutSeconds; 239 240 private static final String IS_SAFE_MODE_DISABLED_KEY = "mIsSafeModeDisabled"; 241 private final boolean mIsSafeModeDisabled; 242 243 private static final String GATEWAY_OPTIONS_KEY = "mGatewayOptions"; 244 @NonNull private final Set<Integer> mGatewayOptions; 245 246 /** Builds a VcnGatewayConnectionConfig with the specified parameters. */ VcnGatewayConnectionConfig( @onNull 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, boolean isSafeModeDisabled, @NonNull Set<Integer> gatewayOptions)247 private VcnGatewayConnectionConfig( 248 @NonNull String gatewayConnectionName, 249 @NonNull IkeTunnelConnectionParams tunnelConnectionParams, 250 @NonNull Set<Integer> exposedCapabilities, 251 @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, 252 @NonNull long[] retryIntervalsMs, 253 @IntRange(from = MIN_MTU_V6) int maxMtu, 254 @NonNull int minUdpPort4500NatTimeoutSeconds, 255 boolean isSafeModeDisabled, 256 @NonNull Set<Integer> gatewayOptions) { 257 mGatewayConnectionName = gatewayConnectionName; 258 mTunnelConnectionParams = tunnelConnectionParams; 259 mExposedCapabilities = new TreeSet(exposedCapabilities); 260 mRetryIntervalsMs = retryIntervalsMs; 261 mMaxMtu = maxMtu; 262 mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds; 263 mGatewayOptions = Collections.unmodifiableSet(new ArraySet(gatewayOptions)); 264 mIsSafeModeDisabled = isSafeModeDisabled; 265 266 mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates); 267 if (mUnderlyingNetworkTemplates.isEmpty()) { 268 mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); 269 } 270 271 validate(); 272 } 273 274 // Null check MUST be done for all new fields added to VcnGatewayConnectionConfig, to avoid 275 // crashes when parsing PersistableBundle built on old platforms. 276 /** @hide */ 277 @VisibleForTesting(visibility = Visibility.PRIVATE) VcnGatewayConnectionConfig(@onNull PersistableBundle in)278 public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) { 279 final PersistableBundle tunnelConnectionParamsBundle = 280 in.getPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY); 281 Objects.requireNonNull( 282 tunnelConnectionParamsBundle, "tunnelConnectionParamsBundle was null"); 283 284 final PersistableBundle exposedCapsBundle = 285 in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY); 286 mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY); 287 mTunnelConnectionParams = 288 TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle); 289 mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList( 290 exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER)); 291 292 final PersistableBundle networkTemplatesBundle = 293 in.getPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY); 294 295 if (networkTemplatesBundle == null) { 296 // UNDERLYING_NETWORK_TEMPLATES_KEY was added in Android T. Thus 297 // VcnGatewayConnectionConfig created on old platforms will not have this data and will 298 // be assigned with the default value 299 mUnderlyingNetworkTemplates = new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); 300 } else { 301 mUnderlyingNetworkTemplates = 302 PersistableBundleUtils.toList( 303 networkTemplatesBundle, 304 VcnUnderlyingNetworkTemplate::fromPersistableBundle); 305 } 306 307 final PersistableBundle gatewayOptionsBundle = in.getPersistableBundle(GATEWAY_OPTIONS_KEY); 308 309 if (gatewayOptionsBundle == null) { 310 // GATEWAY_OPTIONS_KEY was added in Android U. Thus VcnGatewayConnectionConfig created 311 // on old platforms will not have this data and will be assigned with the default value 312 mGatewayOptions = Collections.emptySet(); 313 } else { 314 mGatewayOptions = 315 new ArraySet<>( 316 PersistableBundleUtils.toList( 317 gatewayOptionsBundle, 318 PersistableBundleUtils.INTEGER_DESERIALIZER)); 319 } 320 321 mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY); 322 mMaxMtu = in.getInt(MAX_MTU_KEY); 323 mMinUdpPort4500NatTimeoutSeconds = 324 in.getInt( 325 MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY, 326 MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET); 327 mIsSafeModeDisabled = in.getBoolean(IS_SAFE_MODE_DISABLED_KEY); 328 329 validate(); 330 } 331 validate()332 private void validate() { 333 Objects.requireNonNull(mGatewayConnectionName, "gatewayConnectionName was null"); 334 Objects.requireNonNull(mTunnelConnectionParams, "tunnel connection parameter was null"); 335 336 Preconditions.checkArgument( 337 mExposedCapabilities != null && !mExposedCapabilities.isEmpty(), 338 "exposedCapsBundle was null or empty"); 339 for (Integer cap : getAllExposedCapabilities()) { 340 checkValidCapability(cap); 341 } 342 343 validateNetworkTemplateList(mUnderlyingNetworkTemplates); 344 Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null"); 345 validateRetryInterval(mRetryIntervalsMs); 346 347 Preconditions.checkArgument( 348 mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)"); 349 350 Preconditions.checkArgument( 351 mMinUdpPort4500NatTimeoutSeconds == MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET 352 || mMinUdpPort4500NatTimeoutSeconds 353 >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS, 354 "minUdpPort4500NatTimeoutSeconds must be at least 120s"); 355 356 for (int option : mGatewayOptions) { 357 validateGatewayOption(option); 358 } 359 } 360 checkValidCapability(int capability)361 private static void checkValidCapability(int capability) { 362 Preconditions.checkArgument( 363 ALLOWED_CAPABILITIES.contains(capability), 364 "NetworkCapability " + capability + "out of range"); 365 } 366 validateRetryInterval(@ullable long[] retryIntervalsMs)367 private static void validateRetryInterval(@Nullable long[] retryIntervalsMs) { 368 Preconditions.checkArgument( 369 retryIntervalsMs != null 370 && retryIntervalsMs.length > 0 371 && retryIntervalsMs.length <= MAX_RETRY_INTERVAL_COUNT, 372 "retryIntervalsMs was null, empty or exceed max interval count"); 373 374 final long repeatingInterval = retryIntervalsMs[retryIntervalsMs.length - 1]; 375 if (repeatingInterval < MINIMUM_REPEATING_RETRY_INTERVAL_MS) { 376 throw new IllegalArgumentException( 377 "Repeating retry interval was too short, must be a minimum of 15 minutes: " 378 + repeatingInterval); 379 } 380 } 381 validateNetworkTemplateList( List<VcnUnderlyingNetworkTemplate> networkPriorityRules)382 private static void validateNetworkTemplateList( 383 List<VcnUnderlyingNetworkTemplate> networkPriorityRules) { 384 Objects.requireNonNull(networkPriorityRules, "networkPriorityRules is null"); 385 386 Set<VcnUnderlyingNetworkTemplate> existingRules = new ArraySet<>(); 387 for (VcnUnderlyingNetworkTemplate rule : networkPriorityRules) { 388 Objects.requireNonNull(rule, "Found null value VcnUnderlyingNetworkTemplate"); 389 if (!existingRules.add(rule)) { 390 throw new IllegalArgumentException("Found duplicate VcnUnderlyingNetworkTemplate"); 391 } 392 } 393 } 394 validateGatewayOption(int option)395 private static void validateGatewayOption(int option) { 396 if (!ALLOWED_GATEWAY_OPTIONS.contains(option)) { 397 throw new IllegalArgumentException("Invalid vcn gateway option: " + option); 398 } 399 } 400 401 /** 402 * Returns the configured Gateway Connection name. 403 * 404 * <p>This name is used by the configuring apps to distinguish between 405 * VcnGatewayConnectionConfigs configured on a single {@link VcnConfig}. This will be used as 406 * the identifier in VcnStatusCallback invocations. 407 * 408 * @see VcnManager.VcnStatusCallback#onGatewayConnectionError 409 */ 410 @NonNull getGatewayConnectionName()411 public String getGatewayConnectionName() { 412 return mGatewayConnectionName; 413 } 414 415 /** 416 * Returns tunnel connection parameters. 417 * 418 * @hide 419 */ 420 @NonNull getTunnelConnectionParams()421 public IkeTunnelConnectionParams getTunnelConnectionParams() { 422 return mTunnelConnectionParams; 423 } 424 425 /** 426 * Returns all exposed capabilities. 427 * 428 * <p>The returned integer-value capabilities will not contain duplicates, and will be sorted in 429 * ascending numerical order. 430 * 431 * @see Builder#addExposedCapability(int) 432 * @see Builder#removeExposedCapability(int) 433 */ 434 @NonNull getExposedCapabilities()435 public int[] getExposedCapabilities() { 436 // Sorted set guarantees ordering 437 return ArrayUtils.convertToIntArray(new ArrayList<>(mExposedCapabilities)); 438 } 439 440 /** 441 * Returns all exposed capabilities. 442 * 443 * <p>Left to prevent the need to make major changes while changes are actively in flight. 444 * 445 * @deprecated use getExposedCapabilities() instead 446 * @hide 447 */ 448 @Deprecated 449 @NonNull getAllExposedCapabilities()450 public Set<Integer> getAllExposedCapabilities() { 451 return Collections.unmodifiableSet(mExposedCapabilities); 452 } 453 454 /** 455 * Retrieve the VcnUnderlyingNetworkTemplate list, or a default list if it is not configured. 456 * 457 * @see Builder#setVcnUnderlyingNetworkPriorities(List) 458 */ 459 @NonNull getVcnUnderlyingNetworkPriorities()460 public List<VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities() { 461 return new ArrayList<>(mUnderlyingNetworkTemplates); 462 } 463 464 /** 465 * Retrieves the configured retry intervals. 466 * 467 * @see Builder#setRetryIntervalsMillis(long[]) 468 */ 469 @NonNull getRetryIntervalsMillis()470 public long[] getRetryIntervalsMillis() { 471 return Arrays.copyOf(mRetryIntervalsMs, mRetryIntervalsMs.length); 472 } 473 474 /** 475 * Retrieves the maximum MTU allowed for this Gateway Connection. 476 * 477 * @see Builder#setMaxMtu(int) 478 */ 479 @IntRange(from = MIN_MTU_V6) getMaxMtu()480 public int getMaxMtu() { 481 return mMaxMtu; 482 } 483 484 /** 485 * Retrieves the maximum supported IKEv2/IPsec NATT keepalive timeout. 486 * 487 * @see Builder#setMinUdpPort4500NatTimeoutSeconds(int) 488 */ getMinUdpPort4500NatTimeoutSeconds()489 public int getMinUdpPort4500NatTimeoutSeconds() { 490 return mMinUdpPort4500NatTimeoutSeconds; 491 } 492 493 /** 494 * Check whether safe mode is enabled 495 * 496 * @see Builder#setSafeModeEnabled(boolean) 497 */ 498 @FlaggedApi(FLAG_SAFE_MODE_CONFIG) isSafeModeEnabled()499 public boolean isSafeModeEnabled() { 500 return !mIsSafeModeDisabled; 501 } 502 503 /** 504 * Checks if the given VCN gateway option is enabled. 505 * 506 * @param option the option to check. 507 * @throws IllegalArgumentException if the provided option is invalid. 508 * @see Builder#addGatewayOption(int) 509 * @see Builder#removeGatewayOption(int) 510 */ hasGatewayOption(@cnGatewayOption int option)511 public boolean hasGatewayOption(@VcnGatewayOption int option) { 512 validateGatewayOption(option); 513 return mGatewayOptions.contains(option); 514 } 515 516 /** 517 * Converts this config to a PersistableBundle. 518 * 519 * @hide 520 */ 521 @NonNull 522 @VisibleForTesting(visibility = Visibility.PROTECTED) toPersistableBundle()523 public PersistableBundle toPersistableBundle() { 524 final PersistableBundle result = new PersistableBundle(); 525 526 final PersistableBundle tunnelConnectionParamsBundle = 527 TunnelConnectionParamsUtils.toPersistableBundle(mTunnelConnectionParams); 528 final PersistableBundle exposedCapsBundle = 529 PersistableBundleUtils.fromList( 530 new ArrayList<>(mExposedCapabilities), 531 PersistableBundleUtils.INTEGER_SERIALIZER); 532 final PersistableBundle networkTemplatesBundle = 533 PersistableBundleUtils.fromList( 534 mUnderlyingNetworkTemplates, 535 VcnUnderlyingNetworkTemplate::toPersistableBundle); 536 final PersistableBundle gatewayOptionsBundle = 537 PersistableBundleUtils.fromList( 538 new ArrayList<>(mGatewayOptions), 539 PersistableBundleUtils.INTEGER_SERIALIZER); 540 541 result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName); 542 result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle); 543 result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle); 544 result.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, networkTemplatesBundle); 545 result.putPersistableBundle(GATEWAY_OPTIONS_KEY, gatewayOptionsBundle); 546 result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs); 547 result.putInt(MAX_MTU_KEY, mMaxMtu); 548 result.putInt(MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY, mMinUdpPort4500NatTimeoutSeconds); 549 result.putBoolean(IS_SAFE_MODE_DISABLED_KEY, mIsSafeModeDisabled); 550 551 return result; 552 } 553 554 @Override hashCode()555 public int hashCode() { 556 return Objects.hash( 557 mGatewayConnectionName, 558 mTunnelConnectionParams, 559 mExposedCapabilities, 560 mUnderlyingNetworkTemplates, 561 Arrays.hashCode(mRetryIntervalsMs), 562 mMaxMtu, 563 mMinUdpPort4500NatTimeoutSeconds, 564 mIsSafeModeDisabled, 565 mGatewayOptions); 566 } 567 568 @Override equals(@ullable Object other)569 public boolean equals(@Nullable Object other) { 570 if (!(other instanceof VcnGatewayConnectionConfig)) { 571 return false; 572 } 573 574 final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other; 575 return mGatewayConnectionName.equals(rhs.mGatewayConnectionName) 576 && mTunnelConnectionParams.equals(rhs.mTunnelConnectionParams) 577 && mExposedCapabilities.equals(rhs.mExposedCapabilities) 578 && mUnderlyingNetworkTemplates.equals(rhs.mUnderlyingNetworkTemplates) 579 && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs) 580 && mMaxMtu == rhs.mMaxMtu 581 && mMinUdpPort4500NatTimeoutSeconds == rhs.mMinUdpPort4500NatTimeoutSeconds 582 && mIsSafeModeDisabled == rhs.mIsSafeModeDisabled 583 && mGatewayOptions.equals(rhs.mGatewayOptions); 584 } 585 586 /** 587 * This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects. 588 */ 589 public static final class Builder { 590 @NonNull private final String mGatewayConnectionName; 591 @NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams; 592 @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet(); 593 594 @NonNull 595 private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates = 596 new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); 597 598 @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS; 599 private int mMaxMtu = DEFAULT_MAX_MTU; 600 private int mMinUdpPort4500NatTimeoutSeconds = MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET; 601 private boolean mIsSafeModeDisabled = false; 602 603 @NonNull private final Set<Integer> mGatewayOptions = new ArraySet<>(); 604 605 // TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent. 606 // Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS 607 // when on Cell. 608 609 /** 610 * Construct a Builder object. 611 * 612 * @param gatewayConnectionName the String GatewayConnection name for this 613 * VcnGatewayConnectionConfig. Each VcnGatewayConnectionConfig within a {@link 614 * VcnConfig} must be given a unique name. This name is used by the caller to 615 * distinguish between VcnGatewayConnectionConfigs configured on a single {@link 616 * VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations. 617 * @param tunnelConnectionParams the IKE tunnel connection configuration 618 * @throws IllegalArgumentException if the provided IkeTunnelConnectionParams is not 619 * configured to support MOBIKE 620 * @see IkeTunnelConnectionParams 621 * @see VcnManager.VcnStatusCallback#onGatewayConnectionError 622 */ Builder( @onNull String gatewayConnectionName, @NonNull IkeTunnelConnectionParams tunnelConnectionParams)623 public Builder( 624 @NonNull String gatewayConnectionName, 625 @NonNull IkeTunnelConnectionParams tunnelConnectionParams) { 626 Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null"); 627 Objects.requireNonNull(tunnelConnectionParams, "tunnelConnectionParams was null"); 628 if (!tunnelConnectionParams.getIkeSessionParams().hasIkeOption(IKE_OPTION_MOBIKE)) { 629 throw new IllegalArgumentException( 630 "MOBIKE must be configured for the provided IkeSessionParams"); 631 } 632 633 mGatewayConnectionName = gatewayConnectionName; 634 mTunnelConnectionParams = tunnelConnectionParams; 635 } 636 637 /** 638 * Add a capability that this VCN Gateway Connection will support. 639 * 640 * @param exposedCapability the app-facing capability to be exposed by this VCN Gateway 641 * Connection (i.e., the capabilities that this VCN Gateway Connection will support). 642 * @return this {@link Builder} instance, for chaining 643 * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway 644 * Connection 645 */ 646 @NonNull addExposedCapability(@cnSupportedCapability int exposedCapability)647 public Builder addExposedCapability(@VcnSupportedCapability int exposedCapability) { 648 checkValidCapability(exposedCapability); 649 650 mExposedCapabilities.add(exposedCapability); 651 return this; 652 } 653 654 /** 655 * Remove a capability that this VCN Gateway Connection will support. 656 * 657 * @param exposedCapability the app-facing capability to not be exposed by this VCN Gateway 658 * Connection (i.e., the capabilities that this VCN Gateway Connection will support) 659 * @return this {@link Builder} instance, for chaining 660 * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway 661 * Connection 662 */ 663 @NonNull 664 @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap removeExposedCapability(@cnSupportedCapability int exposedCapability)665 public Builder removeExposedCapability(@VcnSupportedCapability int exposedCapability) { 666 checkValidCapability(exposedCapability); 667 668 mExposedCapabilities.remove(exposedCapability); 669 return this; 670 } 671 672 /** 673 * Set the list of templates to match underlying networks against, in high-to-low priority 674 * order. 675 * 676 * <p>To select the VCN underlying network, the VCN connection will go through all the 677 * network candidates and return a network matching the highest priority rule. 678 * 679 * <p>If multiple networks match the same rule, the VCN will prefer an already-selected 680 * network as opposed to a new/unselected network. However, if both are new/unselected 681 * networks, a network will be chosen arbitrarily amongst the networks matching the highest 682 * priority rule. 683 * 684 * <p>If all networks fail to match the rules provided, a carrier-owned underlying network 685 * will still be selected (if available, at random if necessary). 686 * 687 * @param underlyingNetworkTemplates a list of unique VcnUnderlyingNetworkTemplates that are 688 * ordered from most to least preferred, or an empty list to use the default 689 * prioritization. The default network prioritization order is Opportunistic cellular, 690 * Carrier WiFi and then Macro cellular. 691 * @return this {@link Builder} instance, for chaining 692 */ 693 @NonNull setVcnUnderlyingNetworkPriorities( @onNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates)694 public Builder setVcnUnderlyingNetworkPriorities( 695 @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates) { 696 validateNetworkTemplateList(underlyingNetworkTemplates); 697 698 mUnderlyingNetworkTemplates.clear(); 699 700 if (underlyingNetworkTemplates.isEmpty()) { 701 mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES); 702 } else { 703 mUnderlyingNetworkTemplates.addAll(underlyingNetworkTemplates); 704 } 705 706 return this; 707 } 708 709 /** 710 * Set the retry interval between VCN establishment attempts upon successive failures. 711 * 712 * <p>The last retry interval will be repeated until safe mode is entered, or a connection 713 * is successfully established, at which point the retry timers will be reset. For power 714 * reasons, the last (repeated) retry interval MUST be at least 15 minutes. 715 * 716 * <p>Retry intervals MAY be subject to system power saving modes. That is to say that if 717 * the system enters a power saving mode, the retry may not occur until the device leaves 718 * the specified power saving mode. Intervals are sequential, and intervals will NOT be 719 * skipped if system power saving results in delaying retries (even if it exceed multiple 720 * retry intervals). 721 * 722 * <p>Each Gateway Connection will retry according to the retry intervals configured, but if 723 * safe mode is enabled, all Gateway Connection(s) will be disabled. 724 * 725 * @param retryIntervalsMs an array of between 1 and 10 millisecond intervals after which 726 * the VCN will attempt to retry a session initiation. The last (repeating) retry 727 * interval must be at least 15 minutes. Defaults to: {@code [1s, 2s, 5s, 30s, 1m, 5m, 728 * 15m]} 729 * @return this {@link Builder} instance, for chaining 730 * @see VcnManager for additional discussion on fail-safe mode 731 */ 732 @NonNull setRetryIntervalsMillis(@onNull long[] retryIntervalsMs)733 public Builder setRetryIntervalsMillis(@NonNull long[] retryIntervalsMs) { 734 validateRetryInterval(retryIntervalsMs); 735 736 mRetryIntervalsMs = retryIntervalsMs; 737 return this; 738 } 739 740 /** 741 * Sets the maximum MTU allowed for this VCN Gateway Connection. 742 * 743 * <p>This MTU is applied to the VCN Gateway Connection exposed Networks, and represents the 744 * MTU of the virtualized network. 745 * 746 * <p>The system may reduce the MTU below the maximum specified based on signals such as the 747 * MTU of the underlying networks (and adjusted for Gateway Connection overhead). 748 * 749 * @param maxMtu the maximum MTU allowed for this Gateway Connection. Must be greater than 750 * the IPv6 minimum MTU of 1280. Defaults to 1500. 751 * @return this {@link Builder} instance, for chaining 752 */ 753 @NonNull setMaxMtu(@ntRangefrom = MIN_MTU_V6) int maxMtu)754 public Builder setMaxMtu(@IntRange(from = MIN_MTU_V6) int maxMtu) { 755 Preconditions.checkArgument( 756 maxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)"); 757 758 mMaxMtu = maxMtu; 759 return this; 760 } 761 762 /** 763 * Sets the maximum supported IKEv2/IPsec NATT keepalive timeout. 764 * 765 * <p>This is used as a power-optimization hint for other IKEv2/IPsec use cases (e.g. VPNs, 766 * or IWLAN) to reduce the necessary keepalive frequency, thus conserving power and data. 767 * 768 * @param minUdpPort4500NatTimeoutSeconds the maximum keepalive timeout supported by the VCN 769 * Gateway Connection, generally the minimum duration a NAT mapping is cached on the VCN 770 * Gateway. 771 * @return this {@link Builder} instance, for chaining 772 */ 773 @NonNull setMinUdpPort4500NatTimeoutSeconds( @ntRangefrom = MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS) int minUdpPort4500NatTimeoutSeconds)774 public Builder setMinUdpPort4500NatTimeoutSeconds( 775 @IntRange(from = MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS) 776 int minUdpPort4500NatTimeoutSeconds) { 777 Preconditions.checkArgument( 778 minUdpPort4500NatTimeoutSeconds >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS, 779 "Timeout must be at least 120s"); 780 781 mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds; 782 return this; 783 } 784 785 /** 786 * Enables the specified VCN gateway option. 787 * 788 * @param option the option to be enabled 789 * @return this {@link Builder} instance, for chaining 790 * @throws IllegalArgumentException if the provided option is invalid 791 */ 792 @NonNull addGatewayOption(@cnGatewayOption int option)793 public Builder addGatewayOption(@VcnGatewayOption int option) { 794 validateGatewayOption(option); 795 mGatewayOptions.add(option); 796 return this; 797 } 798 799 /** 800 * Resets (disables) the specified VCN gateway option. 801 * 802 * @param option the option to be disabled 803 * @return this {@link Builder} instance, for chaining 804 * @throws IllegalArgumentException if the provided option is invalid 805 */ 806 @NonNull removeGatewayOption(@cnGatewayOption int option)807 public Builder removeGatewayOption(@VcnGatewayOption int option) { 808 validateGatewayOption(option); 809 mGatewayOptions.remove(option); 810 return this; 811 } 812 813 /** 814 * Enable/disable safe mode 815 * 816 * <p>If a VCN fails to provide connectivity within a system-provided timeout, it will enter 817 * safe mode. In safe mode, the VCN Network will be torn down and the system will restore 818 * connectivity by allowing underlying cellular or WiFi networks to be used as default. At 819 * the same time, VCN will continue to retry until it succeeds. 820 * 821 * <p>When safe mode is disabled and VCN connection fails to provide connectivity, end users 822 * might not have connectivity, and may not have access to carrier-owned underlying 823 * networks. 824 * 825 * @param enabled whether safe mode should be enabled. Defaults to {@code true} 826 */ 827 @FlaggedApi(FLAG_SAFE_MODE_CONFIG) 828 @NonNull setSafeModeEnabled(boolean enabled)829 public Builder setSafeModeEnabled(boolean enabled) { 830 mIsSafeModeDisabled = !enabled; 831 return this; 832 } 833 834 /** 835 * Builds and validates the VcnGatewayConnectionConfig. 836 * 837 * @return an immutable VcnGatewayConnectionConfig instance 838 */ 839 @NonNull build()840 public VcnGatewayConnectionConfig build() { 841 return new VcnGatewayConnectionConfig( 842 mGatewayConnectionName, 843 mTunnelConnectionParams, 844 mExposedCapabilities, 845 mUnderlyingNetworkTemplates, 846 mRetryIntervalsMs, 847 mMaxMtu, 848 mMinUdpPort4500NatTimeoutSeconds, 849 mIsSafeModeDisabled, 850 mGatewayOptions); 851 } 852 } 853 } 854