• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
20 
21 import static com.android.internal.annotations.VisibleForTesting.Visibility;
22 
23 import android.annotation.IntDef;
24 import android.annotation.IntRange;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.SuppressLint;
28 import android.net.Network;
29 import android.net.NetworkCapabilities;
30 import android.net.ipsec.ike.IkeTunnelConnectionParams;
31 import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtils;
32 import android.os.PersistableBundle;
33 import android.util.ArraySet;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 import com.android.internal.util.ArrayUtils;
37 import com.android.internal.util.Preconditions;
38 import com.android.server.vcn.util.PersistableBundleUtils;
39 
40 import java.lang.annotation.Retention;
41 import java.lang.annotation.RetentionPolicy;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collections;
45 import java.util.List;
46 import java.util.Objects;
47 import java.util.Set;
48 import java.util.SortedSet;
49 import java.util.TreeSet;
50 import java.util.concurrent.TimeUnit;
51 
52 /**
53  * This class represents a configuration for a connection to a Virtual Carrier Network gateway.
54  *
55  * <p>Each VcnGatewayConnectionConfig represents a single logical connection to a carrier gateway,
56  * and may provide one or more telephony services (as represented by network capabilities). Each
57  * gateway is expected to provide mobility for a given session as the device roams across {@link
58  * Network}s.
59  *
60  * <p>A VCN connection based on this configuration will be brought up dynamically based on device
61  * settings, and filed NetworkRequests. Underlying Networks must provide INTERNET connectivity, and
62  * must be part of the subscription group under which this configuration is registered (see {@link
63  * VcnManager#setVcnConfig}).
64  *
65  * <p>As an abstraction of a cellular network, services that can be provided by a VCN network are
66  * limited to services provided by cellular networks:
67  *
68  * <ul>
69  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_MMS}
70  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_SUPL}
71  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_DUN}
72  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_FOTA}
73  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_IMS}
74  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_CBS}
75  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_IA}
76  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_RCS}
77  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_XCAP}
78  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_EIMS}
79  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_INTERNET}
80  *   <li>{@link NetworkCapabilities#NET_CAPABILITY_MCX}
81  * </ul>
82  */
83 public final class VcnGatewayConnectionConfig {
84     // TODO: Use MIN_MTU_V6 once it is public, @hide
85     @VisibleForTesting(visibility = Visibility.PRIVATE)
86     static final int MIN_MTU_V6 = 1280;
87 
88     /**
89      * The set of allowed capabilities for exposed capabilities.
90      *
91      * @hide
92      */
93     public static final Set<Integer> ALLOWED_CAPABILITIES;
94 
95     static {
96         Set<Integer> allowedCaps = new ArraySet<>();
97         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MMS);
98         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_SUPL);
99         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_DUN);
100         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_FOTA);
101         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IMS);
102         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_CBS);
103         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IA);
104         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_RCS);
105         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_XCAP);
106         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_EIMS);
107         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_INTERNET);
108         allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MCX);
109 
110         ALLOWED_CAPABILITIES = Collections.unmodifiableSet(allowedCaps);
111     }
112 
113     /** @hide */
114     @Retention(RetentionPolicy.SOURCE)
115     @IntDef(
116             prefix = {"NET_CAPABILITY_"},
117             value = {
118                 NetworkCapabilities.NET_CAPABILITY_MMS,
119                 NetworkCapabilities.NET_CAPABILITY_SUPL,
120                 NetworkCapabilities.NET_CAPABILITY_DUN,
121                 NetworkCapabilities.NET_CAPABILITY_FOTA,
122                 NetworkCapabilities.NET_CAPABILITY_IMS,
123                 NetworkCapabilities.NET_CAPABILITY_CBS,
124                 NetworkCapabilities.NET_CAPABILITY_IA,
125                 NetworkCapabilities.NET_CAPABILITY_RCS,
126                 NetworkCapabilities.NET_CAPABILITY_XCAP,
127                 NetworkCapabilities.NET_CAPABILITY_EIMS,
128                 NetworkCapabilities.NET_CAPABILITY_INTERNET,
129                 NetworkCapabilities.NET_CAPABILITY_MCX,
130             })
131     public @interface VcnSupportedCapability {}
132 
133     private static final int DEFAULT_MAX_MTU = 1500;
134 
135     /**
136      * The maximum number of retry intervals that may be specified.
137      *
138      * <p>Limited to ensure an upper bound on config sizes.
139      */
140     private static final int MAX_RETRY_INTERVAL_COUNT = 10;
141 
142     /**
143      * The minimum allowable repeating retry interval
144      *
145      * <p>To ensure the device is not constantly being woken up, this retry interval MUST be greater
146      * than this value.
147      *
148      * @see {@link Builder#setRetryIntervalsMillis()}
149      */
150     private static final long MINIMUM_REPEATING_RETRY_INTERVAL_MS = TimeUnit.MINUTES.toMillis(15);
151 
152     private static final long[] DEFAULT_RETRY_INTERVALS_MS =
153             new long[] {
154                 TimeUnit.SECONDS.toMillis(1),
155                 TimeUnit.SECONDS.toMillis(2),
156                 TimeUnit.SECONDS.toMillis(5),
157                 TimeUnit.SECONDS.toMillis(30),
158                 TimeUnit.MINUTES.toMillis(1),
159                 TimeUnit.MINUTES.toMillis(5),
160                 TimeUnit.MINUTES.toMillis(15)
161             };
162 
163     /** @hide */
164     @VisibleForTesting(visibility = Visibility.PRIVATE)
165     public static final List<VcnUnderlyingNetworkTemplate> DEFAULT_UNDERLYING_NETWORK_TEMPLATES =
166             new ArrayList<>();
167 
168     static {
DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( new VcnCellUnderlyingNetworkTemplate.Builder() .setOpportunistic(MATCH_REQUIRED) .build())169         DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
170                 new VcnCellUnderlyingNetworkTemplate.Builder()
171                         .setOpportunistic(MATCH_REQUIRED)
172                         .build());
173 
DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( new VcnWifiUnderlyingNetworkTemplate.Builder() .build())174         DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
175                 new VcnWifiUnderlyingNetworkTemplate.Builder()
176                         .build());
177 
DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add( new VcnCellUnderlyingNetworkTemplate.Builder() .build())178         DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
179                 new VcnCellUnderlyingNetworkTemplate.Builder()
180                         .build());
181     }
182 
183     private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName";
184     @NonNull private final String mGatewayConnectionName;
185 
186     private static final String TUNNEL_CONNECTION_PARAMS_KEY = "mTunnelConnectionParams";
187     @NonNull private IkeTunnelConnectionParams mTunnelConnectionParams;
188 
189     private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
190     @NonNull private final SortedSet<Integer> mExposedCapabilities;
191 
192     /** @hide */
193     @VisibleForTesting(visibility = Visibility.PRIVATE)
194     public static final String UNDERLYING_NETWORK_TEMPLATES_KEY = "mUnderlyingNetworkTemplates";
195 
196     @NonNull private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates;
197 
198     private static final String MAX_MTU_KEY = "mMaxMtu";
199     private final int mMaxMtu;
200 
201     private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs";
202     @NonNull private final long[] mRetryIntervalsMs;
203 
204     /** 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)205     private VcnGatewayConnectionConfig(
206             @NonNull String gatewayConnectionName,
207             @NonNull IkeTunnelConnectionParams tunnelConnectionParams,
208             @NonNull Set<Integer> exposedCapabilities,
209             @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
210             @NonNull long[] retryIntervalsMs,
211             @IntRange(from = MIN_MTU_V6) int maxMtu) {
212         mGatewayConnectionName = gatewayConnectionName;
213         mTunnelConnectionParams = tunnelConnectionParams;
214         mExposedCapabilities = new TreeSet(exposedCapabilities);
215         mRetryIntervalsMs = retryIntervalsMs;
216         mMaxMtu = maxMtu;
217 
218         mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates);
219         if (mUnderlyingNetworkTemplates.isEmpty()) {
220             mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
221         }
222 
223         validate();
224     }
225 
226     // Null check MUST be done for all new fields added to VcnGatewayConnectionConfig, to avoid
227     // crashes when parsing PersistableBundle built on old platforms.
228     /** @hide */
229     @VisibleForTesting(visibility = Visibility.PRIVATE)
VcnGatewayConnectionConfig(@onNull PersistableBundle in)230     public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) {
231         final PersistableBundle tunnelConnectionParamsBundle =
232                 in.getPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY);
233         Objects.requireNonNull(
234                 tunnelConnectionParamsBundle, "tunnelConnectionParamsBundle was null");
235 
236         final PersistableBundle exposedCapsBundle =
237                 in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
238         mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
239         mTunnelConnectionParams =
240                 TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle);
241         mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
242                 exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
243 
244         final PersistableBundle networkTemplatesBundle =
245                 in.getPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY);
246 
247         if (networkTemplatesBundle == null) {
248             // UNDERLYING_NETWORK_TEMPLATES_KEY was added in Android T. Thus
249             // VcnGatewayConnectionConfig created on old platforms will not have this data and will
250             // be assigned with the default value
251             mUnderlyingNetworkTemplates = new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
252         } else {
253             mUnderlyingNetworkTemplates =
254                     PersistableBundleUtils.toList(
255                             networkTemplatesBundle,
256                             VcnUnderlyingNetworkTemplate::fromPersistableBundle);
257         }
258 
259         mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
260         mMaxMtu = in.getInt(MAX_MTU_KEY);
261 
262         validate();
263     }
264 
validate()265     private void validate() {
266         Objects.requireNonNull(mGatewayConnectionName, "gatewayConnectionName was null");
267         Objects.requireNonNull(mTunnelConnectionParams, "tunnel connection parameter was null");
268 
269         Preconditions.checkArgument(
270                 mExposedCapabilities != null && !mExposedCapabilities.isEmpty(),
271                 "exposedCapsBundle was null or empty");
272         for (Integer cap : getAllExposedCapabilities()) {
273             checkValidCapability(cap);
274         }
275 
276         validateNetworkTemplateList(mUnderlyingNetworkTemplates);
277         Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null");
278         validateRetryInterval(mRetryIntervalsMs);
279 
280         Preconditions.checkArgument(
281                 mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
282     }
283 
checkValidCapability(int capability)284     private static void checkValidCapability(int capability) {
285         Preconditions.checkArgument(
286                 ALLOWED_CAPABILITIES.contains(capability),
287                 "NetworkCapability " + capability + "out of range");
288     }
289 
validateRetryInterval(@ullable long[] retryIntervalsMs)290     private static void validateRetryInterval(@Nullable long[] retryIntervalsMs) {
291         Preconditions.checkArgument(
292                 retryIntervalsMs != null
293                         && retryIntervalsMs.length > 0
294                         && retryIntervalsMs.length <= MAX_RETRY_INTERVAL_COUNT,
295                 "retryIntervalsMs was null, empty or exceed max interval count");
296 
297         final long repeatingInterval = retryIntervalsMs[retryIntervalsMs.length - 1];
298         if (repeatingInterval < MINIMUM_REPEATING_RETRY_INTERVAL_MS) {
299             throw new IllegalArgumentException(
300                     "Repeating retry interval was too short, must be a minimum of 15 minutes: "
301                             + repeatingInterval);
302         }
303     }
304 
validateNetworkTemplateList( List<VcnUnderlyingNetworkTemplate> networkPriorityRules)305     private static void validateNetworkTemplateList(
306             List<VcnUnderlyingNetworkTemplate> networkPriorityRules) {
307         Objects.requireNonNull(networkPriorityRules, "networkPriorityRules is null");
308 
309         Set<VcnUnderlyingNetworkTemplate> existingRules = new ArraySet<>();
310         for (VcnUnderlyingNetworkTemplate rule : networkPriorityRules) {
311             Objects.requireNonNull(rule, "Found null value VcnUnderlyingNetworkTemplate");
312             if (!existingRules.add(rule)) {
313                 throw new IllegalArgumentException("Found duplicate VcnUnderlyingNetworkTemplate");
314             }
315         }
316     }
317 
318     /**
319      * Returns the configured Gateway Connection name.
320      *
321      * <p>This name is used by the configuring apps to distinguish between
322      * VcnGatewayConnectionConfigs configured on a single {@link VcnConfig}. This will be used as
323      * the identifier in VcnStatusCallback invocations.
324      *
325      * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
326      */
327     @NonNull
getGatewayConnectionName()328     public String getGatewayConnectionName() {
329         return mGatewayConnectionName;
330     }
331 
332     /**
333      * Returns tunnel connection parameters.
334      *
335      * @hide
336      */
337     @NonNull
getTunnelConnectionParams()338     public IkeTunnelConnectionParams getTunnelConnectionParams() {
339         return mTunnelConnectionParams;
340     }
341 
342     /**
343      * Returns all exposed capabilities.
344      *
345      * <p>The returned integer-value capabilities will not contain duplicates, and will be sorted in
346      * ascending numerical order.
347      *
348      * @see Builder#addExposedCapability(int)
349      * @see Builder#removeExposedCapability(int)
350      */
351     @NonNull
getExposedCapabilities()352     public int[] getExposedCapabilities() {
353         // Sorted set guarantees ordering
354         return ArrayUtils.convertToIntArray(new ArrayList<>(mExposedCapabilities));
355     }
356 
357     /**
358      * Returns all exposed capabilities.
359      *
360      * <p>Left to prevent the need to make major changes while changes are actively in flight.
361      *
362      * @deprecated use getExposedCapabilities() instead
363      * @hide
364      */
365     @Deprecated
366     @NonNull
getAllExposedCapabilities()367     public Set<Integer> getAllExposedCapabilities() {
368         return Collections.unmodifiableSet(mExposedCapabilities);
369     }
370 
371     /**
372      * Retrieve the VcnUnderlyingNetworkTemplate list, or a default list if it is not configured.
373      *
374      * @see Builder#setVcnUnderlyingNetworkPriorities(List)
375      */
376     @NonNull
getVcnUnderlyingNetworkPriorities()377     public List<VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities() {
378         return new ArrayList<>(mUnderlyingNetworkTemplates);
379     }
380 
381     /**
382      * Retrieves the configured retry intervals.
383      *
384      * @see Builder#setRetryIntervalsMillis(long[])
385      */
386     @NonNull
getRetryIntervalsMillis()387     public long[] getRetryIntervalsMillis() {
388         return Arrays.copyOf(mRetryIntervalsMs, mRetryIntervalsMs.length);
389     }
390 
391     /**
392      * Retrieves the maximum MTU allowed for this Gateway Connection.
393      *
394      * @see Builder#setMaxMtu(int)
395      */
396     @IntRange(from = MIN_MTU_V6)
getMaxMtu()397     public int getMaxMtu() {
398         return mMaxMtu;
399     }
400 
401     /**
402      * Converts this config to a PersistableBundle.
403      *
404      * @hide
405      */
406     @NonNull
407     @VisibleForTesting(visibility = Visibility.PROTECTED)
toPersistableBundle()408     public PersistableBundle toPersistableBundle() {
409         final PersistableBundle result = new PersistableBundle();
410 
411         final PersistableBundle tunnelConnectionParamsBundle =
412                 TunnelConnectionParamsUtils.toPersistableBundle(mTunnelConnectionParams);
413         final PersistableBundle exposedCapsBundle =
414                 PersistableBundleUtils.fromList(
415                         new ArrayList<>(mExposedCapabilities),
416                         PersistableBundleUtils.INTEGER_SERIALIZER);
417         final PersistableBundle networkTemplatesBundle =
418                 PersistableBundleUtils.fromList(
419                         mUnderlyingNetworkTemplates,
420                         VcnUnderlyingNetworkTemplate::toPersistableBundle);
421 
422         result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
423         result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
424         result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
425         result.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, networkTemplatesBundle);
426         result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
427         result.putInt(MAX_MTU_KEY, mMaxMtu);
428 
429         return result;
430     }
431 
432     @Override
hashCode()433     public int hashCode() {
434         return Objects.hash(
435                 mGatewayConnectionName,
436                 mTunnelConnectionParams,
437                 mExposedCapabilities,
438                 mUnderlyingNetworkTemplates,
439                 Arrays.hashCode(mRetryIntervalsMs),
440                 mMaxMtu);
441     }
442 
443     @Override
equals(@ullable Object other)444     public boolean equals(@Nullable Object other) {
445         if (!(other instanceof VcnGatewayConnectionConfig)) {
446             return false;
447         }
448 
449         final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
450         return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
451                 && mTunnelConnectionParams.equals(rhs.mTunnelConnectionParams)
452                 && mExposedCapabilities.equals(rhs.mExposedCapabilities)
453                 && mUnderlyingNetworkTemplates.equals(rhs.mUnderlyingNetworkTemplates)
454                 && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
455                 && mMaxMtu == rhs.mMaxMtu;
456     }
457 
458     /**
459      * This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects.
460      */
461     public static final class Builder {
462         @NonNull private final String mGatewayConnectionName;
463         @NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams;
464         @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
465 
466         @NonNull
467         private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates =
468                 new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
469 
470         @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
471         private int mMaxMtu = DEFAULT_MAX_MTU;
472 
473         // TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent.
474         //       Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS
475         //       when on Cell.
476 
477         /**
478          * Construct a Builder object.
479          *
480          * @param gatewayConnectionName the String GatewayConnection name for this
481          *     VcnGatewayConnectionConfig. Each VcnGatewayConnectionConfig within a {@link
482          *     VcnConfig} must be given a unique name. This name is used by the caller to
483          *     distinguish between VcnGatewayConnectionConfigs configured on a single {@link
484          *     VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations.
485          * @param tunnelConnectionParams the IKE tunnel connection configuration
486          * @throws IllegalArgumentException if the provided IkeTunnelConnectionParams is not
487          *     configured to support MOBIKE
488          * @see IkeTunnelConnectionParams
489          * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
490          */
Builder( @onNull String gatewayConnectionName, @NonNull IkeTunnelConnectionParams tunnelConnectionParams)491         public Builder(
492                 @NonNull String gatewayConnectionName,
493                 @NonNull IkeTunnelConnectionParams tunnelConnectionParams) {
494             Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null");
495             Objects.requireNonNull(tunnelConnectionParams, "tunnelConnectionParams was null");
496             if (!tunnelConnectionParams.getIkeSessionParams().hasIkeOption(IKE_OPTION_MOBIKE)) {
497                 throw new IllegalArgumentException(
498                         "MOBIKE must be configured for the provided IkeSessionParams");
499             }
500 
501             mGatewayConnectionName = gatewayConnectionName;
502             mTunnelConnectionParams = tunnelConnectionParams;
503         }
504 
505         /**
506          * Add a capability that this VCN Gateway Connection will support.
507          *
508          * @param exposedCapability the app-facing capability to be exposed by this VCN Gateway
509          *     Connection (i.e., the capabilities that this VCN Gateway Connection will support).
510          * @return this {@link Builder} instance, for chaining
511          * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
512          *     Connection
513          */
514         @NonNull
addExposedCapability(@cnSupportedCapability int exposedCapability)515         public Builder addExposedCapability(@VcnSupportedCapability int exposedCapability) {
516             checkValidCapability(exposedCapability);
517 
518             mExposedCapabilities.add(exposedCapability);
519             return this;
520         }
521 
522         /**
523          * Remove a capability that this VCN Gateway Connection will support.
524          *
525          * @param exposedCapability the app-facing capability to not be exposed by this VCN Gateway
526          *     Connection (i.e., the capabilities that this VCN Gateway Connection will support)
527          * @return this {@link Builder} instance, for chaining
528          * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
529          *     Connection
530          */
531         @NonNull
532         @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap
removeExposedCapability(@cnSupportedCapability int exposedCapability)533         public Builder removeExposedCapability(@VcnSupportedCapability int exposedCapability) {
534             checkValidCapability(exposedCapability);
535 
536             mExposedCapabilities.remove(exposedCapability);
537             return this;
538         }
539 
540         /**
541          * Set the list of templates to match underlying networks against, in high-to-low priority
542          * order.
543          *
544          * <p>To select the VCN underlying network, the VCN connection will go through all the
545          * network candidates and return a network matching the highest priority rule.
546          *
547          * <p>If multiple networks match the same rule, the VCN will prefer an already-selected
548          * network as opposed to a new/unselected network. However, if both are new/unselected
549          * networks, a network will be chosen arbitrarily amongst the networks matching the highest
550          * priority rule.
551          *
552          * <p>If all networks fail to match the rules provided, a carrier-owned underlying network
553          * will still be selected (if available, at random if necessary).
554          *
555          * @param underlyingNetworkTemplates a list of unique VcnUnderlyingNetworkTemplates that are
556          *     ordered from most to least preferred, or an empty list to use the default
557          *     prioritization. The default network prioritization order is Opportunistic cellular,
558          *     Carrier WiFi and then Macro cellular.
559          * @return this {@link Builder} instance, for chaining
560          */
561         @NonNull
setVcnUnderlyingNetworkPriorities( @onNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates)562         public Builder setVcnUnderlyingNetworkPriorities(
563                 @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates) {
564             validateNetworkTemplateList(underlyingNetworkTemplates);
565 
566             mUnderlyingNetworkTemplates.clear();
567 
568             if (underlyingNetworkTemplates.isEmpty()) {
569                 mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
570             } else {
571                 mUnderlyingNetworkTemplates.addAll(underlyingNetworkTemplates);
572             }
573 
574             return this;
575         }
576 
577         /**
578          * Set the retry interval between VCN establishment attempts upon successive failures.
579          *
580          * <p>The last retry interval will be repeated until safe mode is entered, or a connection
581          * is successfully established, at which point the retry timers will be reset. For power
582          * reasons, the last (repeated) retry interval MUST be at least 15 minutes.
583          *
584          * <p>Retry intervals MAY be subject to system power saving modes. That is to say that if
585          * the system enters a power saving mode, the retry may not occur until the device leaves
586          * the specified power saving mode. Intervals are sequential, and intervals will NOT be
587          * skipped if system power saving results in delaying retries (even if it exceed multiple
588          * retry intervals).
589          *
590          * <p>Each Gateway Connection will retry according to the retry intervals configured, but if
591          * safe mode is enabled, all Gateway Connection(s) will be disabled.
592          *
593          * @param retryIntervalsMs an array of between 1 and 10 millisecond intervals after which
594          *     the VCN will attempt to retry a session initiation. The last (repeating) retry
595          *     interval must be at least 15 minutes. Defaults to: {@code [1s, 2s, 5s, 30s, 1m, 5m,
596          *     15m]}
597          * @return this {@link Builder} instance, for chaining
598          * @see VcnManager for additional discussion on fail-safe mode
599          */
600         @NonNull
setRetryIntervalsMillis(@onNull long[] retryIntervalsMs)601         public Builder setRetryIntervalsMillis(@NonNull long[] retryIntervalsMs) {
602             validateRetryInterval(retryIntervalsMs);
603 
604             mRetryIntervalsMs = retryIntervalsMs;
605             return this;
606         }
607 
608         /**
609          * Sets the maximum MTU allowed for this VCN Gateway Connection.
610          *
611          * <p>This MTU is applied to the VCN Gateway Connection exposed Networks, and represents the
612          * MTU of the virtualized network.
613          *
614          * <p>The system may reduce the MTU below the maximum specified based on signals such as the
615          * MTU of the underlying networks (and adjusted for Gateway Connection overhead).
616          *
617          * @param maxMtu the maximum MTU allowed for this Gateway Connection. Must be greater than
618          *     the IPv6 minimum MTU of 1280. Defaults to 1500.
619          * @return this {@link Builder} instance, for chaining
620          */
621         @NonNull
setMaxMtu(@ntRangefrom = MIN_MTU_V6) int maxMtu)622         public Builder setMaxMtu(@IntRange(from = MIN_MTU_V6) int maxMtu) {
623             Preconditions.checkArgument(
624                     maxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
625 
626             mMaxMtu = maxMtu;
627             return this;
628         }
629 
630         /**
631          * Builds and validates the VcnGatewayConnectionConfig.
632          *
633          * @return an immutable VcnGatewayConnectionConfig instance
634          */
635         @NonNull
build()636         public VcnGatewayConnectionConfig build() {
637             return new VcnGatewayConnectionConfig(
638                     mGatewayConnectionName,
639                     mTunnelConnectionParams,
640                     mExposedCapabilities,
641                     mUnderlyingNetworkTemplates,
642                     mRetryIntervalsMs,
643                     mMaxMtu);
644         }
645     }
646 }
647