• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
19 import static android.net.vcn.VcnUnderlyingNetworkTemplate.getMatchCriteriaString;
20 
21 import static com.android.internal.annotations.VisibleForTesting.Visibility;
22 import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER;
23 import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER;
24 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
25 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER;
26 
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.annotation.SuppressLint;
30 import android.net.NetworkCapabilities;
31 import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria;
32 import android.os.PersistableBundle;
33 import android.telephony.SubscriptionInfo;
34 import android.telephony.SubscriptionManager;
35 import android.telephony.TelephonyManager;
36 import android.util.ArraySet;
37 
38 import com.android.internal.annotations.VisibleForTesting;
39 import com.android.internal.util.IndentingPrintWriter;
40 import com.android.server.vcn.util.PersistableBundleUtils;
41 
42 import java.util.ArrayList;
43 import java.util.Collections;
44 import java.util.Objects;
45 import java.util.Set;
46 
47 /**
48  * This class represents a configuration for a network template class of underlying cellular
49  * networks.
50  *
51  * <p>See {@link VcnUnderlyingNetworkTemplate}
52  */
53 public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetworkTemplate {
54     private static final String ALLOWED_NETWORK_PLMN_IDS_KEY = "mAllowedNetworkPlmnIds";
55     @NonNull private final Set<String> mAllowedNetworkPlmnIds;
56     private static final String ALLOWED_SPECIFIC_CARRIER_IDS_KEY = "mAllowedSpecificCarrierIds";
57     @NonNull private final Set<Integer> mAllowedSpecificCarrierIds;
58 
59     private static final String ROAMING_MATCH_KEY = "mRoamingMatchCriteria";
60     private static final int DEFAULT_ROAMING_MATCH_CRITERIA = MATCH_ANY;
61     private final int mRoamingMatchCriteria;
62 
63     private static final String OPPORTUNISTIC_MATCH_KEY = "mOpportunisticMatchCriteria";
64     private static final int DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA = MATCH_ANY;
65     private final int mOpportunisticMatchCriteria;
66 
VcnCellUnderlyingNetworkTemplate( int meteredMatchCriteria, int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps, int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps, Set<String> allowedNetworkPlmnIds, Set<Integer> allowedSpecificCarrierIds, int roamingMatchCriteria, int opportunisticMatchCriteria)67     private VcnCellUnderlyingNetworkTemplate(
68             int meteredMatchCriteria,
69             int minEntryUpstreamBandwidthKbps,
70             int minExitUpstreamBandwidthKbps,
71             int minEntryDownstreamBandwidthKbps,
72             int minExitDownstreamBandwidthKbps,
73             Set<String> allowedNetworkPlmnIds,
74             Set<Integer> allowedSpecificCarrierIds,
75             int roamingMatchCriteria,
76             int opportunisticMatchCriteria) {
77         super(
78                 NETWORK_PRIORITY_TYPE_CELL,
79                 meteredMatchCriteria,
80                 minEntryUpstreamBandwidthKbps,
81                 minExitUpstreamBandwidthKbps,
82                 minEntryDownstreamBandwidthKbps,
83                 minExitDownstreamBandwidthKbps);
84         mAllowedNetworkPlmnIds = new ArraySet<>(allowedNetworkPlmnIds);
85         mAllowedSpecificCarrierIds = new ArraySet<>(allowedSpecificCarrierIds);
86         mRoamingMatchCriteria = roamingMatchCriteria;
87         mOpportunisticMatchCriteria = opportunisticMatchCriteria;
88 
89         validate();
90     }
91 
92     /** @hide */
93     @Override
validate()94     protected void validate() {
95         super.validate();
96         validatePlmnIds(mAllowedNetworkPlmnIds);
97         Objects.requireNonNull(mAllowedSpecificCarrierIds, "matchingCarrierIds is null");
98         validateMatchCriteria(mRoamingMatchCriteria, "mRoamingMatchCriteria");
99         validateMatchCriteria(mOpportunisticMatchCriteria, "mOpportunisticMatchCriteria");
100     }
101 
validatePlmnIds(Set<String> matchingOperatorPlmnIds)102     private static void validatePlmnIds(Set<String> matchingOperatorPlmnIds) {
103         Objects.requireNonNull(matchingOperatorPlmnIds, "matchingOperatorPlmnIds is null");
104 
105         // A valid PLMN is a concatenation of MNC and MCC, and thus consists of 5 or 6 decimal
106         // digits.
107         for (String id : matchingOperatorPlmnIds) {
108             if ((id.length() == 5 || id.length() == 6) && id.matches("[0-9]+")) {
109                 continue;
110             } else {
111                 throw new IllegalArgumentException("Found invalid PLMN ID: " + id);
112             }
113         }
114     }
115 
116     /** @hide */
117     @NonNull
118     @VisibleForTesting(visibility = Visibility.PROTECTED)
fromPersistableBundle( @onNull PersistableBundle in)119     public static VcnCellUnderlyingNetworkTemplate fromPersistableBundle(
120             @NonNull PersistableBundle in) {
121         Objects.requireNonNull(in, "PersistableBundle is null");
122 
123         final int meteredMatchCriteria = in.getInt(METERED_MATCH_KEY);
124 
125         final int minEntryUpstreamBandwidthKbps =
126                 in.getInt(MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
127         final int minExitUpstreamBandwidthKbps =
128                 in.getInt(MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
129         final int minEntryDownstreamBandwidthKbps =
130                 in.getInt(MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
131         final int minExitDownstreamBandwidthKbps =
132                 in.getInt(MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
133 
134         final PersistableBundle plmnIdsBundle =
135                 in.getPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY);
136         Objects.requireNonNull(plmnIdsBundle, "plmnIdsBundle is null");
137         final Set<String> allowedNetworkPlmnIds =
138                 new ArraySet<String>(
139                         PersistableBundleUtils.toList(plmnIdsBundle, STRING_DESERIALIZER));
140 
141         final PersistableBundle specificCarrierIdsBundle =
142                 in.getPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY);
143         Objects.requireNonNull(specificCarrierIdsBundle, "specificCarrierIdsBundle is null");
144         final Set<Integer> allowedSpecificCarrierIds =
145                 new ArraySet<Integer>(
146                         PersistableBundleUtils.toList(
147                                 specificCarrierIdsBundle, INTEGER_DESERIALIZER));
148 
149         final int roamingMatchCriteria = in.getInt(ROAMING_MATCH_KEY);
150         final int opportunisticMatchCriteria = in.getInt(OPPORTUNISTIC_MATCH_KEY);
151 
152         return new VcnCellUnderlyingNetworkTemplate(
153                 meteredMatchCriteria,
154                 minEntryUpstreamBandwidthKbps,
155                 minExitUpstreamBandwidthKbps,
156                 minEntryDownstreamBandwidthKbps,
157                 minExitDownstreamBandwidthKbps,
158                 allowedNetworkPlmnIds,
159                 allowedSpecificCarrierIds,
160                 roamingMatchCriteria,
161                 opportunisticMatchCriteria);
162     }
163 
164     /** @hide */
165     @Override
166     @NonNull
167     @VisibleForTesting(visibility = Visibility.PROTECTED)
toPersistableBundle()168     public PersistableBundle toPersistableBundle() {
169         final PersistableBundle result = super.toPersistableBundle();
170 
171         final PersistableBundle plmnIdsBundle =
172                 PersistableBundleUtils.fromList(
173                         new ArrayList<>(mAllowedNetworkPlmnIds), STRING_SERIALIZER);
174         result.putPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY, plmnIdsBundle);
175 
176         final PersistableBundle specificCarrierIdsBundle =
177                 PersistableBundleUtils.fromList(
178                         new ArrayList<>(mAllowedSpecificCarrierIds), INTEGER_SERIALIZER);
179         result.putPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY, specificCarrierIdsBundle);
180 
181         result.putInt(ROAMING_MATCH_KEY, mRoamingMatchCriteria);
182         result.putInt(OPPORTUNISTIC_MATCH_KEY, mOpportunisticMatchCriteria);
183 
184         return result;
185     }
186 
187     /**
188      * Retrieve the matching operator PLMN IDs, or an empty set if any PLMN ID is acceptable.
189      *
190      * @see Builder#setOperatorPlmnIds(Set)
191      */
192     @NonNull
getOperatorPlmnIds()193     public Set<String> getOperatorPlmnIds() {
194         return Collections.unmodifiableSet(mAllowedNetworkPlmnIds);
195     }
196 
197     /**
198      * Retrieve the matching sim specific carrier IDs, or an empty set if any sim specific carrier
199      * ID is acceptable.
200      *
201      * @see Builder#setSimSpecificCarrierIds(Set)
202      */
203     @NonNull
getSimSpecificCarrierIds()204     public Set<Integer> getSimSpecificCarrierIds() {
205         return Collections.unmodifiableSet(mAllowedSpecificCarrierIds);
206     }
207 
208     /**
209      * Return the matching criteria for roaming networks.
210      *
211      * @see Builder#setRoaming(int)
212      */
213     @MatchCriteria
getRoaming()214     public int getRoaming() {
215         return mRoamingMatchCriteria;
216     }
217 
218     /**
219      * Return the matching criteria for opportunistic cellular subscriptions.
220      *
221      * @see Builder#setOpportunistic(int)
222      */
223     @MatchCriteria
getOpportunistic()224     public int getOpportunistic() {
225         return mOpportunisticMatchCriteria;
226     }
227 
228     @Override
hashCode()229     public int hashCode() {
230         return Objects.hash(
231                 super.hashCode(),
232                 mAllowedNetworkPlmnIds,
233                 mAllowedSpecificCarrierIds,
234                 mRoamingMatchCriteria,
235                 mOpportunisticMatchCriteria);
236     }
237 
238     @Override
equals(@ullable Object other)239     public boolean equals(@Nullable Object other) {
240         if (!super.equals(other)) {
241             return false;
242         }
243 
244         if (!(other instanceof VcnCellUnderlyingNetworkTemplate)) {
245             return false;
246         }
247 
248         final VcnCellUnderlyingNetworkTemplate rhs = (VcnCellUnderlyingNetworkTemplate) other;
249         return Objects.equals(mAllowedNetworkPlmnIds, rhs.mAllowedNetworkPlmnIds)
250                 && Objects.equals(mAllowedSpecificCarrierIds, rhs.mAllowedSpecificCarrierIds)
251                 && mRoamingMatchCriteria == rhs.mRoamingMatchCriteria
252                 && mOpportunisticMatchCriteria == rhs.mOpportunisticMatchCriteria;
253     }
254 
255     /** @hide */
256     @Override
dumpTransportSpecificFields(IndentingPrintWriter pw)257     void dumpTransportSpecificFields(IndentingPrintWriter pw) {
258         if (!mAllowedNetworkPlmnIds.isEmpty()) {
259             pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds);
260         }
261         if (!mAllowedNetworkPlmnIds.isEmpty()) {
262             pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds);
263         }
264         if (mRoamingMatchCriteria != DEFAULT_ROAMING_MATCH_CRITERIA) {
265             pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria));
266         }
267         if (mOpportunisticMatchCriteria != DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA) {
268             pw.println(
269                     "mOpportunisticMatchCriteria: "
270                             + getMatchCriteriaString(mOpportunisticMatchCriteria));
271         }
272     }
273 
274     /** This class is used to incrementally build VcnCellUnderlyingNetworkTemplate objects. */
275     public static final class Builder {
276         private int mMeteredMatchCriteria = DEFAULT_METERED_MATCH_CRITERIA;
277 
278         @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
279         @NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>();
280 
281         private int mRoamingMatchCriteria = DEFAULT_ROAMING_MATCH_CRITERIA;
282         private int mOpportunisticMatchCriteria = DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA;
283 
284         private int mMinEntryUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
285         private int mMinExitUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
286         private int mMinEntryDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
287         private int mMinExitDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
288 
289         /** Construct a Builder object. */
Builder()290         public Builder() {}
291 
292         /**
293          * Set the matching criteria for metered networks.
294          *
295          * <p>A template where setMetered(MATCH_REQUIRED) will only match metered networks (one
296          * without NET_CAPABILITY_NOT_METERED). A template where setMetered(MATCH_FORBIDDEN) will
297          * only match a network that is not metered (one with NET_CAPABILITY_NOT_METERED).
298          *
299          * @param matchCriteria the matching criteria for metered networks. Defaults to {@link
300          *     #MATCH_ANY}.
301          * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED
302          */
303         // The matching getter is defined in the super class. Please see {@link
304         // VcnUnderlyingNetworkTemplate#getMetered()}
305         @SuppressLint("MissingGetterMatchingBuilder")
306         @NonNull
setMetered(@atchCriteria int matchCriteria)307         public Builder setMetered(@MatchCriteria int matchCriteria) {
308             validateMatchCriteria(matchCriteria, "setMetered");
309 
310             mMeteredMatchCriteria = matchCriteria;
311             return this;
312         }
313 
314         /**
315          * Set operator PLMN IDs with which a network can match this template.
316          *
317          * <p>This is used to distinguish cases where roaming agreements may dictate a different
318          * priority from a partner's networks.
319          *
320          * @param operatorPlmnIds the matching operator PLMN IDs in String. Network with one of the
321          *     matching PLMN IDs can match this template. If the set is empty, any PLMN ID will
322          *     match. The default is an empty set. A valid PLMN is a concatenation of MNC and MCC,
323          *     and thus consists of 5 or 6 decimal digits.
324          * @see SubscriptionInfo#getMccString()
325          * @see SubscriptionInfo#getMncString()
326          */
327         @NonNull
setOperatorPlmnIds(@onNull Set<String> operatorPlmnIds)328         public Builder setOperatorPlmnIds(@NonNull Set<String> operatorPlmnIds) {
329             validatePlmnIds(operatorPlmnIds);
330 
331             mAllowedNetworkPlmnIds.clear();
332             mAllowedNetworkPlmnIds.addAll(operatorPlmnIds);
333             return this;
334         }
335 
336         /**
337          * Set sim specific carrier IDs with which a network can match this template.
338          *
339          * @param simSpecificCarrierIds the matching sim specific carrier IDs. Network with one of
340          *     the sim specific carrier IDs can match this template. If the set is empty, any
341          *     carrier ID will match. The default is an empty set.
342          * @see TelephonyManager#getSimSpecificCarrierId()
343          */
344         @NonNull
setSimSpecificCarrierIds(@onNull Set<Integer> simSpecificCarrierIds)345         public Builder setSimSpecificCarrierIds(@NonNull Set<Integer> simSpecificCarrierIds) {
346             Objects.requireNonNull(simSpecificCarrierIds, "simSpecificCarrierIds is null");
347 
348             mAllowedSpecificCarrierIds.clear();
349             mAllowedSpecificCarrierIds.addAll(simSpecificCarrierIds);
350             return this;
351         }
352 
353         /**
354          * Set the matching criteria for roaming networks.
355          *
356          * <p>A template where setRoaming(MATCH_REQUIRED) will only match roaming networks (one
357          * without NET_CAPABILITY_NOT_ROAMING). A template where setRoaming(MATCH_FORBIDDEN) will
358          * only match a network that is not roaming (one with NET_CAPABILITY_NOT_ROAMING).
359          *
360          * @param matchCriteria the matching criteria for roaming networks. Defaults to {@link
361          *     #MATCH_ANY}.
362          * @see NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING
363          */
364         @NonNull
setRoaming(@atchCriteria int matchCriteria)365         public Builder setRoaming(@MatchCriteria int matchCriteria) {
366             validateMatchCriteria(matchCriteria, "setRoaming");
367 
368             mRoamingMatchCriteria = matchCriteria;
369             return this;
370         }
371 
372         /**
373          * Set the matching criteria for opportunistic cellular subscriptions.
374          *
375          * @param matchCriteria the matching criteria for opportunistic cellular subscriptions.
376          *     Defaults to {@link #MATCH_ANY}.
377          * @see SubscriptionManager#setOpportunistic(boolean, int)
378          */
379         @NonNull
setOpportunistic(@atchCriteria int matchCriteria)380         public Builder setOpportunistic(@MatchCriteria int matchCriteria) {
381             validateMatchCriteria(matchCriteria, "setOpportunistic");
382 
383             mOpportunisticMatchCriteria = matchCriteria;
384             return this;
385         }
386 
387         /**
388          * Set the minimum upstream bandwidths that this template will match.
389          *
390          * <p>This template will not match a network that does not provide at least the bandwidth
391          * passed as the entry bandwidth, except in the case that the network is selected as the VCN
392          * Gateway Connection's underlying network, where it will continue to match until the
393          * bandwidth drops under the exit bandwidth.
394          *
395          * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
396          * invalid case where a network fulfills the entry criteria, but at the same time fails the
397          * exit criteria.
398          *
399          * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
400          * {@link NetworkCapabilities}. The provided estimates will be used without modification.
401          *
402          * @param minEntryUpstreamBandwidthKbps the minimum accepted upstream bandwidth for networks
403          *     that ARE NOT the already-selected underlying network, or {@code 0} to disable this
404          *     requirement. Disabled by default.
405          * @param minExitUpstreamBandwidthKbps the minimum accepted upstream bandwidth for a network
406          *     that IS the already-selected underlying network, or {@code 0} to disable this
407          *     requirement. Disabled by default.
408          * @return this {@link Builder} instance, for chaining
409          */
410         @NonNull
411         // The getter for the two integers are separated, and in the superclass. Please see {@link
412         // VcnUnderlyingNetworkTemplate#getMinEntryUpstreamBandwidthKbps()} and {@link
413         // VcnUnderlyingNetworkTemplate#getMinExitUpstreamBandwidthKbps()}
414         @SuppressLint("MissingGetterMatchingBuilder")
setMinUpstreamBandwidthKbps( int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps)415         public Builder setMinUpstreamBandwidthKbps(
416                 int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps) {
417             validateMinBandwidthKbps(minEntryUpstreamBandwidthKbps, minExitUpstreamBandwidthKbps);
418 
419             mMinEntryUpstreamBandwidthKbps = minEntryUpstreamBandwidthKbps;
420             mMinExitUpstreamBandwidthKbps = minExitUpstreamBandwidthKbps;
421 
422             return this;
423         }
424 
425         /**
426          * Set the minimum upstream bandwidths that this template will match.
427          *
428          * <p>This template will not match a network that does not provide at least the bandwidth
429          * passed as the entry bandwidth, except in the case that the network is selected as the VCN
430          * Gateway Connection's underlying network, where it will continue to match until the
431          * bandwidth drops under the exit bandwidth.
432          *
433          * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
434          * invalid case where a network fulfills the entry criteria, but at the same time fails the
435          * exit criteria.
436          *
437          * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
438          * {@link NetworkCapabilities}. The provided estimates will be used without modification.
439          *
440          * @param minEntryDownstreamBandwidthKbps the minimum accepted downstream bandwidth for
441          *     networks that ARE NOT the already-selected underlying network, or {@code 0} to
442          *     disable this requirement. Disabled by default.
443          * @param minExitDownstreamBandwidthKbps the minimum accepted downstream bandwidth for a
444          *     network that IS the already-selected underlying network, or {@code 0} to disable this
445          *     requirement. Disabled by default.
446          * @return this {@link Builder} instance, for chaining
447          */
448         @NonNull
449         // The getter for the two integers are separated, and in the superclass. Please see {@link
450         // VcnUnderlyingNetworkTemplate#getMinEntryDownstreamBandwidthKbps()} and {@link
451         // VcnUnderlyingNetworkTemplate#getMinExitDownstreamBandwidthKbps()}
452         @SuppressLint("MissingGetterMatchingBuilder")
setMinDownstreamBandwidthKbps( int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps)453         public Builder setMinDownstreamBandwidthKbps(
454                 int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps) {
455             validateMinBandwidthKbps(
456                     minEntryDownstreamBandwidthKbps, minExitDownstreamBandwidthKbps);
457 
458             mMinEntryDownstreamBandwidthKbps = minEntryDownstreamBandwidthKbps;
459             mMinExitDownstreamBandwidthKbps = minExitDownstreamBandwidthKbps;
460 
461             return this;
462         }
463 
464         /** Build the VcnCellUnderlyingNetworkTemplate. */
465         @NonNull
build()466         public VcnCellUnderlyingNetworkTemplate build() {
467             return new VcnCellUnderlyingNetworkTemplate(
468                     mMeteredMatchCriteria,
469                     mMinEntryUpstreamBandwidthKbps,
470                     mMinExitUpstreamBandwidthKbps,
471                     mMinEntryDownstreamBandwidthKbps,
472                     mMinExitDownstreamBandwidthKbps,
473                     mAllowedNetworkPlmnIds,
474                     mAllowedSpecificCarrierIds,
475                     mRoamingMatchCriteria,
476                     mOpportunisticMatchCriteria);
477         }
478     }
479 }
480