1 /*
2  * Copyright (C) 2021 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.NetworkCapabilities.NET_CAPABILITY_CBS;
19 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
20 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
21 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
22 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
23 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
24 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
25 import static android.net.vcn.VcnUnderlyingNetworkTemplate.getMatchCriteriaString;
26 
27 import static com.android.internal.annotations.VisibleForTesting.Visibility;
28 import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER;
29 import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER;
30 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
31 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER;
32 
33 import android.annotation.NonNull;
34 import android.annotation.Nullable;
35 import android.annotation.SuppressLint;
36 import android.net.NetworkCapabilities;
37 import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria;
38 import android.os.PersistableBundle;
39 import android.telephony.SubscriptionInfo;
40 import android.telephony.SubscriptionManager;
41 import android.telephony.TelephonyManager;
42 import android.util.ArraySet;
43 
44 import com.android.internal.annotations.VisibleForTesting;
45 import com.android.internal.util.IndentingPrintWriter;
46 import com.android.internal.util.Preconditions;
47 import com.android.server.vcn.util.PersistableBundleUtils;
48 
49 import java.util.ArrayList;
50 import java.util.Collections;
51 import java.util.HashMap;
52 import java.util.Map;
53 import java.util.Objects;
54 import java.util.Set;
55 
56 /**
57  * This class represents a configuration for a network template class of underlying cellular
58  * networks.
59  *
60  * <p>See {@link VcnUnderlyingNetworkTemplate}
61  */
62 public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetworkTemplate {
63     private static final String ALLOWED_NETWORK_PLMN_IDS_KEY = "mAllowedNetworkPlmnIds";
64     @NonNull private final Set<String> mAllowedNetworkPlmnIds;
65     private static final String ALLOWED_SPECIFIC_CARRIER_IDS_KEY = "mAllowedSpecificCarrierIds";
66     @NonNull private final Set<Integer> mAllowedSpecificCarrierIds;
67 
68     private static final String ROAMING_MATCH_KEY = "mRoamingMatchCriteria";
69     private static final int DEFAULT_ROAMING_MATCH_CRITERIA = MATCH_ANY;
70     private final int mRoamingMatchCriteria;
71 
72     private static final String OPPORTUNISTIC_MATCH_KEY = "mOpportunisticMatchCriteria";
73     private static final int DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA = MATCH_ANY;
74     private final int mOpportunisticMatchCriteria;
75 
76     private static final String CAPABILITIES_MATCH_CRITERIA_KEY = "mCapabilitiesMatchCriteria";
77     @NonNull private final Map<Integer, Integer> mCapabilitiesMatchCriteria;
78 
79     private static final Map<Integer, Integer> CAPABILITIES_MATCH_CRITERIA_DEFAULT;
80 
81     static {
82         Map<Integer, Integer> capsMatchCriteria = new HashMap<>();
capsMatchCriteria.put(NET_CAPABILITY_CBS, MATCH_ANY)83         capsMatchCriteria.put(NET_CAPABILITY_CBS, MATCH_ANY);
capsMatchCriteria.put(NET_CAPABILITY_DUN, MATCH_ANY)84         capsMatchCriteria.put(NET_CAPABILITY_DUN, MATCH_ANY);
capsMatchCriteria.put(NET_CAPABILITY_IMS, MATCH_ANY)85         capsMatchCriteria.put(NET_CAPABILITY_IMS, MATCH_ANY);
capsMatchCriteria.put(NET_CAPABILITY_INTERNET, MATCH_REQUIRED)86         capsMatchCriteria.put(NET_CAPABILITY_INTERNET, MATCH_REQUIRED);
capsMatchCriteria.put(NET_CAPABILITY_MMS, MATCH_ANY)87         capsMatchCriteria.put(NET_CAPABILITY_MMS, MATCH_ANY);
capsMatchCriteria.put(NET_CAPABILITY_RCS, MATCH_ANY)88         capsMatchCriteria.put(NET_CAPABILITY_RCS, MATCH_ANY);
89 
90         CAPABILITIES_MATCH_CRITERIA_DEFAULT = Collections.unmodifiableMap(capsMatchCriteria);
91     }
92 
VcnCellUnderlyingNetworkTemplate( int meteredMatchCriteria, int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps, int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps, Set<String> allowedNetworkPlmnIds, Set<Integer> allowedSpecificCarrierIds, int roamingMatchCriteria, int opportunisticMatchCriteria, Map<Integer, Integer> capabilitiesMatchCriteria)93     private VcnCellUnderlyingNetworkTemplate(
94             int meteredMatchCriteria,
95             int minEntryUpstreamBandwidthKbps,
96             int minExitUpstreamBandwidthKbps,
97             int minEntryDownstreamBandwidthKbps,
98             int minExitDownstreamBandwidthKbps,
99             Set<String> allowedNetworkPlmnIds,
100             Set<Integer> allowedSpecificCarrierIds,
101             int roamingMatchCriteria,
102             int opportunisticMatchCriteria,
103             Map<Integer, Integer> capabilitiesMatchCriteria) {
104         super(
105                 NETWORK_PRIORITY_TYPE_CELL,
106                 meteredMatchCriteria,
107                 minEntryUpstreamBandwidthKbps,
108                 minExitUpstreamBandwidthKbps,
109                 minEntryDownstreamBandwidthKbps,
110                 minExitDownstreamBandwidthKbps);
111         mAllowedNetworkPlmnIds = new ArraySet<>(allowedNetworkPlmnIds);
112         mAllowedSpecificCarrierIds = new ArraySet<>(allowedSpecificCarrierIds);
113         mRoamingMatchCriteria = roamingMatchCriteria;
114         mOpportunisticMatchCriteria = opportunisticMatchCriteria;
115         mCapabilitiesMatchCriteria = new HashMap<>(capabilitiesMatchCriteria);
116 
117         validate();
118     }
119 
120     /** @hide */
121     @Override
validate()122     protected void validate() {
123         super.validate();
124         validatePlmnIds(mAllowedNetworkPlmnIds);
125         validateCapabilitiesMatchCriteria(mCapabilitiesMatchCriteria);
126         Objects.requireNonNull(mAllowedSpecificCarrierIds, "matchingCarrierIds is null");
127         validateMatchCriteria(mRoamingMatchCriteria, "mRoamingMatchCriteria");
128         validateMatchCriteria(mOpportunisticMatchCriteria, "mOpportunisticMatchCriteria");
129     }
130 
validatePlmnIds(Set<String> matchingOperatorPlmnIds)131     private static void validatePlmnIds(Set<String> matchingOperatorPlmnIds) {
132         Objects.requireNonNull(matchingOperatorPlmnIds, "matchingOperatorPlmnIds is null");
133 
134         // A valid PLMN is a concatenation of MNC and MCC, and thus consists of 5 or 6 decimal
135         // digits.
136         for (String id : matchingOperatorPlmnIds) {
137             if ((id.length() == 5 || id.length() == 6) && id.matches("[0-9]+")) {
138                 continue;
139             } else {
140                 throw new IllegalArgumentException("Found invalid PLMN ID: " + id);
141             }
142         }
143     }
144 
validateCapabilitiesMatchCriteria( Map<Integer, Integer> capabilitiesMatchCriteria)145     private static void validateCapabilitiesMatchCriteria(
146             Map<Integer, Integer> capabilitiesMatchCriteria) {
147         Objects.requireNonNull(capabilitiesMatchCriteria, "capabilitiesMatchCriteria is null");
148 
149         boolean requiredCapabilityFound = false;
150         for (Map.Entry<Integer, Integer> entry : capabilitiesMatchCriteria.entrySet()) {
151             final int capability = entry.getKey();
152             final int matchCriteria = entry.getValue();
153 
154             Preconditions.checkArgument(
155                     CAPABILITIES_MATCH_CRITERIA_DEFAULT.containsKey(capability),
156                     "NetworkCapability " + capability + "out of range");
157             validateMatchCriteria(matchCriteria, "capability " + capability);
158 
159             requiredCapabilityFound |= (matchCriteria == MATCH_REQUIRED);
160         }
161 
162         if (!requiredCapabilityFound) {
163             throw new IllegalArgumentException("No required capabilities found");
164         }
165     }
166 
167     /** @hide */
168     @NonNull
169     @VisibleForTesting(visibility = Visibility.PROTECTED)
fromPersistableBundle( @onNull PersistableBundle in)170     public static VcnCellUnderlyingNetworkTemplate fromPersistableBundle(
171             @NonNull PersistableBundle in) {
172         Objects.requireNonNull(in, "PersistableBundle is null");
173 
174         final int meteredMatchCriteria = in.getInt(METERED_MATCH_KEY);
175 
176         final int minEntryUpstreamBandwidthKbps =
177                 in.getInt(MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
178         final int minExitUpstreamBandwidthKbps =
179                 in.getInt(MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
180         final int minEntryDownstreamBandwidthKbps =
181                 in.getInt(MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
182         final int minExitDownstreamBandwidthKbps =
183                 in.getInt(MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
184 
185         final PersistableBundle plmnIdsBundle =
186                 in.getPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY);
187         Objects.requireNonNull(plmnIdsBundle, "plmnIdsBundle is null");
188         final Set<String> allowedNetworkPlmnIds =
189                 new ArraySet<String>(
190                         PersistableBundleUtils.toList(plmnIdsBundle, STRING_DESERIALIZER));
191 
192         final PersistableBundle specificCarrierIdsBundle =
193                 in.getPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY);
194         Objects.requireNonNull(specificCarrierIdsBundle, "specificCarrierIdsBundle is null");
195         final Set<Integer> allowedSpecificCarrierIds =
196                 new ArraySet<Integer>(
197                         PersistableBundleUtils.toList(
198                                 specificCarrierIdsBundle, INTEGER_DESERIALIZER));
199 
200         final PersistableBundle capabilitiesMatchCriteriaBundle =
201                 in.getPersistableBundle(CAPABILITIES_MATCH_CRITERIA_KEY);
202         final Map<Integer, Integer> capabilitiesMatchCriteria;
203         if (capabilitiesMatchCriteriaBundle == null) {
204             capabilitiesMatchCriteria = CAPABILITIES_MATCH_CRITERIA_DEFAULT;
205         } else {
206             capabilitiesMatchCriteria =
207                     PersistableBundleUtils.toMap(
208                             capabilitiesMatchCriteriaBundle,
209                             INTEGER_DESERIALIZER,
210                             INTEGER_DESERIALIZER);
211         }
212 
213         final int roamingMatchCriteria = in.getInt(ROAMING_MATCH_KEY);
214         final int opportunisticMatchCriteria = in.getInt(OPPORTUNISTIC_MATCH_KEY);
215 
216         return new VcnCellUnderlyingNetworkTemplate(
217                 meteredMatchCriteria,
218                 minEntryUpstreamBandwidthKbps,
219                 minExitUpstreamBandwidthKbps,
220                 minEntryDownstreamBandwidthKbps,
221                 minExitDownstreamBandwidthKbps,
222                 allowedNetworkPlmnIds,
223                 allowedSpecificCarrierIds,
224                 roamingMatchCriteria,
225                 opportunisticMatchCriteria,
226                 capabilitiesMatchCriteria);
227     }
228 
229     /** @hide */
230     @Override
231     @NonNull
232     @VisibleForTesting(visibility = Visibility.PROTECTED)
toPersistableBundle()233     public PersistableBundle toPersistableBundle() {
234         final PersistableBundle result = super.toPersistableBundle();
235 
236         final PersistableBundle plmnIdsBundle =
237                 PersistableBundleUtils.fromList(
238                         new ArrayList<>(mAllowedNetworkPlmnIds), STRING_SERIALIZER);
239         result.putPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY, plmnIdsBundle);
240 
241         final PersistableBundle specificCarrierIdsBundle =
242                 PersistableBundleUtils.fromList(
243                         new ArrayList<>(mAllowedSpecificCarrierIds), INTEGER_SERIALIZER);
244         result.putPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY, specificCarrierIdsBundle);
245 
246         final PersistableBundle capabilitiesMatchCriteriaBundle =
247                 PersistableBundleUtils.fromMap(
248                         mCapabilitiesMatchCriteria, INTEGER_SERIALIZER, INTEGER_SERIALIZER);
249         result.putPersistableBundle(
250                 CAPABILITIES_MATCH_CRITERIA_KEY, capabilitiesMatchCriteriaBundle);
251 
252         result.putInt(ROAMING_MATCH_KEY, mRoamingMatchCriteria);
253         result.putInt(OPPORTUNISTIC_MATCH_KEY, mOpportunisticMatchCriteria);
254 
255         return result;
256     }
257 
258     /**
259      * Retrieve the matching operator PLMN IDs, or an empty set if any PLMN ID is acceptable.
260      *
261      * @see Builder#setOperatorPlmnIds(Set)
262      */
263     @NonNull
getOperatorPlmnIds()264     public Set<String> getOperatorPlmnIds() {
265         return Collections.unmodifiableSet(mAllowedNetworkPlmnIds);
266     }
267 
268     /**
269      * Retrieve the matching sim specific carrier IDs, or an empty set if any sim specific carrier
270      * ID is acceptable.
271      *
272      * @see Builder#setSimSpecificCarrierIds(Set)
273      */
274     @NonNull
getSimSpecificCarrierIds()275     public Set<Integer> getSimSpecificCarrierIds() {
276         return Collections.unmodifiableSet(mAllowedSpecificCarrierIds);
277     }
278 
279     /**
280      * Return the matching criteria for roaming networks.
281      *
282      * @see Builder#setRoaming(int)
283      */
284     @MatchCriteria
getRoaming()285     public int getRoaming() {
286         return mRoamingMatchCriteria;
287     }
288 
289     /**
290      * Return the matching criteria for opportunistic cellular subscriptions.
291      *
292      * @see Builder#setOpportunistic(int)
293      */
294     @MatchCriteria
getOpportunistic()295     public int getOpportunistic() {
296         return mOpportunisticMatchCriteria;
297     }
298 
299     /**
300      * Returns the matching criteria for CBS networks.
301      *
302      * @see Builder#setCbs(int)
303      */
304     @MatchCriteria
getCbs()305     public int getCbs() {
306         return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_CBS);
307     }
308 
309     /**
310      * Returns the matching criteria for DUN networks.
311      *
312      * @see Builder#setDun(int)
313      */
314     @MatchCriteria
getDun()315     public int getDun() {
316         return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_DUN);
317     }
318     /**
319      * Returns the matching criteria for IMS networks.
320      *
321      * @see Builder#setIms(int)
322      */
323     @MatchCriteria
getIms()324     public int getIms() {
325         return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_IMS);
326     }
327     /**
328      * Returns the matching criteria for INTERNET networks.
329      *
330      * @see Builder#setInternet(int)
331      */
332     @MatchCriteria
getInternet()333     public int getInternet() {
334         return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_INTERNET);
335     }
336     /**
337      * Returns the matching criteria for MMS networks.
338      *
339      * @see Builder#setMms(int)
340      */
341     @MatchCriteria
getMms()342     public int getMms() {
343         return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_MMS);
344     }
345 
346     /**
347      * Returns the matching criteria for RCS networks.
348      *
349      * @see Builder#setRcs(int)
350      */
351     @MatchCriteria
getRcs()352     public int getRcs() {
353         return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_RCS);
354     }
355 
356     /** @hide */
357     @Override
getCapabilitiesMatchCriteria()358     public Map<Integer, Integer> getCapabilitiesMatchCriteria() {
359         return Collections.unmodifiableMap(new HashMap<>(mCapabilitiesMatchCriteria));
360     }
361 
362     @Override
hashCode()363     public int hashCode() {
364         return Objects.hash(
365                 super.hashCode(),
366                 mAllowedNetworkPlmnIds,
367                 mAllowedSpecificCarrierIds,
368                 mCapabilitiesMatchCriteria,
369                 mRoamingMatchCriteria,
370                 mOpportunisticMatchCriteria);
371     }
372 
373     @Override
equals(@ullable Object other)374     public boolean equals(@Nullable Object other) {
375         if (!super.equals(other)) {
376             return false;
377         }
378 
379         if (!(other instanceof VcnCellUnderlyingNetworkTemplate)) {
380             return false;
381         }
382 
383         final VcnCellUnderlyingNetworkTemplate rhs = (VcnCellUnderlyingNetworkTemplate) other;
384         return Objects.equals(mAllowedNetworkPlmnIds, rhs.mAllowedNetworkPlmnIds)
385                 && Objects.equals(mAllowedSpecificCarrierIds, rhs.mAllowedSpecificCarrierIds)
386                 && Objects.equals(mCapabilitiesMatchCriteria, rhs.mCapabilitiesMatchCriteria)
387                 && mRoamingMatchCriteria == rhs.mRoamingMatchCriteria
388                 && mOpportunisticMatchCriteria == rhs.mOpportunisticMatchCriteria;
389     }
390 
391     /** @hide */
392     @Override
dumpTransportSpecificFields(IndentingPrintWriter pw)393     void dumpTransportSpecificFields(IndentingPrintWriter pw) {
394         if (!mAllowedNetworkPlmnIds.isEmpty()) {
395             pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds);
396         }
397         if (!mAllowedNetworkPlmnIds.isEmpty()) {
398             pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds);
399         }
400         pw.println("mCapabilitiesMatchCriteria: " + mCapabilitiesMatchCriteria);
401         if (mRoamingMatchCriteria != DEFAULT_ROAMING_MATCH_CRITERIA) {
402             pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria));
403         }
404         if (mOpportunisticMatchCriteria != DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA) {
405             pw.println(
406                     "mOpportunisticMatchCriteria: "
407                             + getMatchCriteriaString(mOpportunisticMatchCriteria));
408         }
409     }
410 
411     /** This class is used to incrementally build VcnCellUnderlyingNetworkTemplate objects. */
412     public static final class Builder {
413         private int mMeteredMatchCriteria = DEFAULT_METERED_MATCH_CRITERIA;
414 
415         @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
416         @NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>();
417         @NonNull private final Map<Integer, Integer> mCapabilitiesMatchCriteria = new HashMap<>();
418 
419         private int mRoamingMatchCriteria = DEFAULT_ROAMING_MATCH_CRITERIA;
420         private int mOpportunisticMatchCriteria = DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA;
421 
422         private int mMinEntryUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
423         private int mMinExitUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
424         private int mMinEntryDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
425         private int mMinExitDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
426 
427         /** Construct a Builder object. */
Builder()428         public Builder() {
429             mCapabilitiesMatchCriteria.putAll(CAPABILITIES_MATCH_CRITERIA_DEFAULT);
430         }
431 
432         /**
433          * Set the matching criteria for metered networks.
434          *
435          * <p>A template where setMetered(MATCH_REQUIRED) will only match metered networks (one
436          * without NET_CAPABILITY_NOT_METERED). A template where setMetered(MATCH_FORBIDDEN) will
437          * only match a network that is not metered (one with NET_CAPABILITY_NOT_METERED).
438          *
439          * @param matchCriteria the matching criteria for metered networks. Defaults to {@link
440          *     #MATCH_ANY}.
441          * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED
442          */
443         // The matching getter is defined in the super class. Please see {@link
444         // VcnUnderlyingNetworkTemplate#getMetered()}
445         @SuppressLint("MissingGetterMatchingBuilder")
446         @NonNull
setMetered(@atchCriteria int matchCriteria)447         public Builder setMetered(@MatchCriteria int matchCriteria) {
448             validateMatchCriteria(matchCriteria, "setMetered");
449 
450             mMeteredMatchCriteria = matchCriteria;
451             return this;
452         }
453 
454         /**
455          * Set operator PLMN IDs with which a network can match this template.
456          *
457          * <p>This is used to distinguish cases where roaming agreements may dictate a different
458          * priority from a partner's networks.
459          *
460          * @param operatorPlmnIds the matching operator PLMN IDs in String. Network with one of the
461          *     matching PLMN IDs can match this template. If the set is empty, any PLMN ID will
462          *     match. The default is an empty set. A valid PLMN is a concatenation of MNC and MCC,
463          *     and thus consists of 5 or 6 decimal digits.
464          * @see SubscriptionInfo#getMccString()
465          * @see SubscriptionInfo#getMncString()
466          */
467         @NonNull
setOperatorPlmnIds(@onNull Set<String> operatorPlmnIds)468         public Builder setOperatorPlmnIds(@NonNull Set<String> operatorPlmnIds) {
469             validatePlmnIds(operatorPlmnIds);
470 
471             mAllowedNetworkPlmnIds.clear();
472             mAllowedNetworkPlmnIds.addAll(operatorPlmnIds);
473             return this;
474         }
475 
476         /**
477          * Set sim specific carrier IDs with which a network can match this template.
478          *
479          * @param simSpecificCarrierIds the matching sim specific carrier IDs. Network with one of
480          *     the sim specific carrier IDs can match this template. If the set is empty, any
481          *     carrier ID will match. The default is an empty set.
482          * @see TelephonyManager#getSimSpecificCarrierId()
483          */
484         @NonNull
setSimSpecificCarrierIds(@onNull Set<Integer> simSpecificCarrierIds)485         public Builder setSimSpecificCarrierIds(@NonNull Set<Integer> simSpecificCarrierIds) {
486             Objects.requireNonNull(simSpecificCarrierIds, "simSpecificCarrierIds is null");
487 
488             mAllowedSpecificCarrierIds.clear();
489             mAllowedSpecificCarrierIds.addAll(simSpecificCarrierIds);
490             return this;
491         }
492 
493         /**
494          * Set the matching criteria for roaming networks.
495          *
496          * <p>A template where setRoaming(MATCH_REQUIRED) will only match roaming networks (one
497          * without NET_CAPABILITY_NOT_ROAMING). A template where setRoaming(MATCH_FORBIDDEN) will
498          * only match a network that is not roaming (one with NET_CAPABILITY_NOT_ROAMING).
499          *
500          * @param matchCriteria the matching criteria for roaming networks. Defaults to {@link
501          *     #MATCH_ANY}.
502          * @see NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING
503          */
504         @NonNull
setRoaming(@atchCriteria int matchCriteria)505         public Builder setRoaming(@MatchCriteria int matchCriteria) {
506             validateMatchCriteria(matchCriteria, "setRoaming");
507 
508             mRoamingMatchCriteria = matchCriteria;
509             return this;
510         }
511 
512         /**
513          * Set the matching criteria for opportunistic cellular subscriptions.
514          *
515          * @param matchCriteria the matching criteria for opportunistic cellular subscriptions.
516          *     Defaults to {@link #MATCH_ANY}.
517          * @see SubscriptionManager#setOpportunistic(boolean, int)
518          */
519         @NonNull
setOpportunistic(@atchCriteria int matchCriteria)520         public Builder setOpportunistic(@MatchCriteria int matchCriteria) {
521             validateMatchCriteria(matchCriteria, "setOpportunistic");
522 
523             mOpportunisticMatchCriteria = matchCriteria;
524             return this;
525         }
526 
527         /**
528          * Set the minimum upstream bandwidths that this template will match.
529          *
530          * <p>This template will not match a network that does not provide at least the bandwidth
531          * passed as the entry bandwidth, except in the case that the network is selected as the VCN
532          * Gateway Connection's underlying network, where it will continue to match until the
533          * bandwidth drops under the exit bandwidth.
534          *
535          * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
536          * invalid case where a network fulfills the entry criteria, but at the same time fails the
537          * exit criteria.
538          *
539          * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
540          * {@link NetworkCapabilities}. The provided estimates will be used without modification.
541          *
542          * @param minEntryUpstreamBandwidthKbps the minimum accepted upstream bandwidth for networks
543          *     that ARE NOT the already-selected underlying network, or {@code 0} to disable this
544          *     requirement. Disabled by default.
545          * @param minExitUpstreamBandwidthKbps the minimum accepted upstream bandwidth for a network
546          *     that IS the already-selected underlying network, or {@code 0} to disable this
547          *     requirement. Disabled by default.
548          * @return this {@link Builder} instance, for chaining
549          */
550         @NonNull
551         // The getter for the two integers are separated, and in the superclass. Please see {@link
552         // VcnUnderlyingNetworkTemplate#getMinEntryUpstreamBandwidthKbps()} and {@link
553         // VcnUnderlyingNetworkTemplate#getMinExitUpstreamBandwidthKbps()}
554         @SuppressLint("MissingGetterMatchingBuilder")
setMinUpstreamBandwidthKbps( int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps)555         public Builder setMinUpstreamBandwidthKbps(
556                 int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps) {
557             validateMinBandwidthKbps(minEntryUpstreamBandwidthKbps, minExitUpstreamBandwidthKbps);
558 
559             mMinEntryUpstreamBandwidthKbps = minEntryUpstreamBandwidthKbps;
560             mMinExitUpstreamBandwidthKbps = minExitUpstreamBandwidthKbps;
561 
562             return this;
563         }
564 
565         /**
566          * Set the minimum upstream bandwidths that this template will match.
567          *
568          * <p>This template will not match a network that does not provide at least the bandwidth
569          * passed as the entry bandwidth, except in the case that the network is selected as the VCN
570          * Gateway Connection's underlying network, where it will continue to match until the
571          * bandwidth drops under the exit bandwidth.
572          *
573          * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
574          * invalid case where a network fulfills the entry criteria, but at the same time fails the
575          * exit criteria.
576          *
577          * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
578          * {@link NetworkCapabilities}. The provided estimates will be used without modification.
579          *
580          * @param minEntryDownstreamBandwidthKbps the minimum accepted downstream bandwidth for
581          *     networks that ARE NOT the already-selected underlying network, or {@code 0} to
582          *     disable this requirement. Disabled by default.
583          * @param minExitDownstreamBandwidthKbps the minimum accepted downstream bandwidth for a
584          *     network that IS the already-selected underlying network, or {@code 0} to disable this
585          *     requirement. Disabled by default.
586          * @return this {@link Builder} instance, for chaining
587          */
588         @NonNull
589         // The getter for the two integers are separated, and in the superclass. Please see {@link
590         // VcnUnderlyingNetworkTemplate#getMinEntryDownstreamBandwidthKbps()} and {@link
591         // VcnUnderlyingNetworkTemplate#getMinExitDownstreamBandwidthKbps()}
592         @SuppressLint("MissingGetterMatchingBuilder")
setMinDownstreamBandwidthKbps( int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps)593         public Builder setMinDownstreamBandwidthKbps(
594                 int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps) {
595             validateMinBandwidthKbps(
596                     minEntryDownstreamBandwidthKbps, minExitDownstreamBandwidthKbps);
597 
598             mMinEntryDownstreamBandwidthKbps = minEntryDownstreamBandwidthKbps;
599             mMinExitDownstreamBandwidthKbps = minExitDownstreamBandwidthKbps;
600 
601             return this;
602         }
603 
604         /**
605          * Sets the matching criteria for CBS networks.
606          *
607          * <p>A template where {@code setCbs(MATCH_REQUIRED)} is called will only match CBS networks
608          * (ones with NET_CAPABILITY_CBS). A template where {@code setCbs(MATCH_FORBIDDEN)} is
609          * called will only match networks that do not support CBS (ones without
610          * NET_CAPABILITY_CBS).
611          *
612          * @param matchCriteria the matching criteria for CBS networks. Defaults to {@link
613          *     #MATCH_ANY}.
614          * @see NetworkCapabilities#NET_CAPABILITY_CBS
615          */
616         @NonNull
setCbs(@atchCriteria int matchCriteria)617         public Builder setCbs(@MatchCriteria int matchCriteria) {
618             validateMatchCriteria(matchCriteria, "setCbs");
619 
620             mCapabilitiesMatchCriteria.put(NET_CAPABILITY_CBS, matchCriteria);
621             return this;
622         }
623 
624         /**
625          * Sets the matching criteria for DUN networks.
626          *
627          * <p>A template where {@code setDun(MATCH_REQUIRED)} is called will only match DUN networks
628          * (ones with NET_CAPABILITY_DUN). A template where {@code setDun(MATCH_FORBIDDEN)} is
629          * called will only match networks that do not support DUN (ones without
630          * NET_CAPABILITY_DUN).
631          *
632          * @param matchCriteria the matching criteria for DUN networks. Defaults to {@link
633          *     #MATCH_ANY}.
634          * @see NetworkCapabilities#NET_CAPABILITY_DUN
635          */
636         @NonNull
setDun(@atchCriteria int matchCriteria)637         public Builder setDun(@MatchCriteria int matchCriteria) {
638             validateMatchCriteria(matchCriteria, "setDun");
639 
640             mCapabilitiesMatchCriteria.put(NET_CAPABILITY_DUN, matchCriteria);
641             return this;
642         }
643 
644         /**
645          * Sets the matching criteria for IMS networks.
646          *
647          * <p>A template where {@code setIms(MATCH_REQUIRED)} is called will only match IMS networks
648          * (ones with NET_CAPABILITY_IMS). A template where {@code setIms(MATCH_FORBIDDEN)} is
649          * called will only match networks that do not support IMS (ones without
650          * NET_CAPABILITY_IMS).
651          *
652          * @param matchCriteria the matching criteria for IMS networks. Defaults to {@link
653          *     #MATCH_ANY}.
654          * @see NetworkCapabilities#NET_CAPABILITY_IMS
655          */
656         @NonNull
setIms(@atchCriteria int matchCriteria)657         public Builder setIms(@MatchCriteria int matchCriteria) {
658             validateMatchCriteria(matchCriteria, "setIms");
659 
660             mCapabilitiesMatchCriteria.put(NET_CAPABILITY_IMS, matchCriteria);
661             return this;
662         }
663 
664         /**
665          * Sets the matching criteria for INTERNET networks.
666          *
667          * <p>A template where {@code setInternet(MATCH_REQUIRED)} is called will only match
668          * INTERNET networks (ones with NET_CAPABILITY_INTERNET). A template where {@code
669          * setInternet(MATCH_FORBIDDEN)} is called will only match networks that do not support
670          * INTERNET (ones without NET_CAPABILITY_INTERNET).
671          *
672          * @param matchCriteria the matching criteria for INTERNET networks. Defaults to {@link
673          *     #MATCH_REQUIRED}.
674          * @see NetworkCapabilities#NET_CAPABILITY_INTERNET
675          */
676         @NonNull
setInternet(@atchCriteria int matchCriteria)677         public Builder setInternet(@MatchCriteria int matchCriteria) {
678             validateMatchCriteria(matchCriteria, "setInternet");
679 
680             mCapabilitiesMatchCriteria.put(NET_CAPABILITY_INTERNET, matchCriteria);
681             return this;
682         }
683 
684         /**
685          * Sets the matching criteria for MMS networks.
686          *
687          * <p>A template where {@code setMms(MATCH_REQUIRED)} is called will only match MMS networks
688          * (ones with NET_CAPABILITY_MMS). A template where {@code setMms(MATCH_FORBIDDEN)} is
689          * called will only match networks that do not support MMS (ones without
690          * NET_CAPABILITY_MMS).
691          *
692          * @param matchCriteria the matching criteria for MMS networks. Defaults to {@link
693          *     #MATCH_ANY}.
694          * @see NetworkCapabilities#NET_CAPABILITY_MMS
695          */
696         @NonNull
setMms(@atchCriteria int matchCriteria)697         public Builder setMms(@MatchCriteria int matchCriteria) {
698             validateMatchCriteria(matchCriteria, "setMms");
699 
700             mCapabilitiesMatchCriteria.put(NET_CAPABILITY_MMS, matchCriteria);
701             return this;
702         }
703 
704         /**
705          * Sets the matching criteria for RCS networks.
706          *
707          * <p>A template where {@code setRcs(MATCH_REQUIRED)} is called will only match RCS networks
708          * (ones with NET_CAPABILITY_RCS). A template where {@code setRcs(MATCH_FORBIDDEN)} is
709          * called will only match networks that do not support RCS (ones without
710          * NET_CAPABILITY_RCS).
711          *
712          * @param matchCriteria the matching criteria for RCS networks. Defaults to {@link
713          *     #MATCH_ANY}.
714          * @see NetworkCapabilities#NET_CAPABILITY_RCS
715          */
716         @NonNull
setRcs(@atchCriteria int matchCriteria)717         public Builder setRcs(@MatchCriteria int matchCriteria) {
718             validateMatchCriteria(matchCriteria, "setRcs");
719 
720             mCapabilitiesMatchCriteria.put(NET_CAPABILITY_RCS, matchCriteria);
721             return this;
722         }
723 
724         /** Build the VcnCellUnderlyingNetworkTemplate. */
725         @NonNull
build()726         public VcnCellUnderlyingNetworkTemplate build() {
727             return new VcnCellUnderlyingNetworkTemplate(
728                     mMeteredMatchCriteria,
729                     mMinEntryUpstreamBandwidthKbps,
730                     mMinExitUpstreamBandwidthKbps,
731                     mMinEntryDownstreamBandwidthKbps,
732                     mMinExitDownstreamBandwidthKbps,
733                     mAllowedNetworkPlmnIds,
734                     mAllowedSpecificCarrierIds,
735                     mRoamingMatchCriteria,
736                     mOpportunisticMatchCriteria,
737                     mCapabilitiesMatchCriteria);
738         }
739     }
740 }
741