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 com.android.internal.annotations.VisibleForTesting.Visibility;
19 
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.os.PersistableBundle;
24 import android.util.SparseArray;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.internal.util.IndentingPrintWriter;
28 import com.android.internal.util.Preconditions;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.Map;
33 import java.util.Objects;
34 
35 /**
36  * This class represents a template containing set of underlying network requirements for doing
37  * route selection.
38  *
39  * <p>Apps provisioning a VCN can configure the underlying network priority for each Gateway
40  * Connection by setting a list (in priority order, most to least preferred) of the appropriate
41  * subclasses in the VcnGatewayConnectionConfig. See {@link
42  * VcnGatewayConnectionConfig.Builder#setVcnUnderlyingNetworkPriorities}
43  */
44 public abstract class VcnUnderlyingNetworkTemplate {
45     /** @hide */
46     static final int NETWORK_PRIORITY_TYPE_WIFI = 1;
47     /** @hide */
48     static final int NETWORK_PRIORITY_TYPE_CELL = 2;
49 
50     /**
51      * Used to configure the matching criteria of a network characteristic. This may include network
52      * capabilities, or cellular subscription information. Denotes that networks with or without the
53      * characteristic are both acceptable to match this template.
54      */
55     public static final int MATCH_ANY = 0;
56 
57     /**
58      * Used to configure the matching criteria of a network characteristic. This may include network
59      * capabilities, or cellular subscription information. Denotes that a network MUST have the
60      * capability in order to match this template.
61      */
62     public static final int MATCH_REQUIRED = 1;
63 
64     /**
65      * Used to configure the matching criteria of a network characteristic. This may include network
66      * capabilities, or cellular subscription information. Denotes that a network MUST NOT have the
67      * capability in order to match this template.
68      */
69     public static final int MATCH_FORBIDDEN = 2;
70 
71     /** @hide */
72     @Retention(RetentionPolicy.SOURCE)
73     @IntDef({MATCH_ANY, MATCH_REQUIRED, MATCH_FORBIDDEN})
74     public @interface MatchCriteria {}
75 
76     private static final SparseArray<String> MATCH_CRITERIA_TO_STRING_MAP = new SparseArray<>();
77 
78     static {
MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_ANY, "MATCH_ANY")79         MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_ANY, "MATCH_ANY");
MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_REQUIRED, "MATCH_REQUIRED")80         MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_REQUIRED, "MATCH_REQUIRED");
MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_FORBIDDEN, "MATCH_FORBIDDEN")81         MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_FORBIDDEN, "MATCH_FORBIDDEN");
82     }
83 
84     private static final String NETWORK_PRIORITY_TYPE_KEY = "mNetworkPriorityType";
85     private final int mNetworkPriorityType;
86 
87     /** @hide */
88     static final String METERED_MATCH_KEY = "mMeteredMatchCriteria";
89 
90     /** @hide */
91     static final int DEFAULT_METERED_MATCH_CRITERIA = MATCH_ANY;
92 
93     private final int mMeteredMatchCriteria;
94 
95     /** @hide */
96     public static final int DEFAULT_MIN_BANDWIDTH_KBPS = 0;
97 
98     /** @hide */
99     static final String MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY = "mMinEntryUpstreamBandwidthKbps";
100 
101     private final int mMinEntryUpstreamBandwidthKbps;
102 
103     /** @hide */
104     static final String MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY = "mMinExitUpstreamBandwidthKbps";
105 
106     private final int mMinExitUpstreamBandwidthKbps;
107 
108     /** @hide */
109     static final String MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY =
110             "mMinEntryDownstreamBandwidthKbps";
111 
112     private final int mMinEntryDownstreamBandwidthKbps;
113 
114     /** @hide */
115     static final String MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY = "mMinExitDownstreamBandwidthKbps";
116 
117     private final int mMinExitDownstreamBandwidthKbps;
118 
119     /** @hide */
VcnUnderlyingNetworkTemplate( int networkPriorityType, int meteredMatchCriteria, int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps, int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps)120     VcnUnderlyingNetworkTemplate(
121             int networkPriorityType,
122             int meteredMatchCriteria,
123             int minEntryUpstreamBandwidthKbps,
124             int minExitUpstreamBandwidthKbps,
125             int minEntryDownstreamBandwidthKbps,
126             int minExitDownstreamBandwidthKbps) {
127         mNetworkPriorityType = networkPriorityType;
128         mMeteredMatchCriteria = meteredMatchCriteria;
129         mMinEntryUpstreamBandwidthKbps = minEntryUpstreamBandwidthKbps;
130         mMinExitUpstreamBandwidthKbps = minExitUpstreamBandwidthKbps;
131         mMinEntryDownstreamBandwidthKbps = minEntryDownstreamBandwidthKbps;
132         mMinExitDownstreamBandwidthKbps = minExitDownstreamBandwidthKbps;
133     }
134 
135     /** @hide */
validateMatchCriteria(int matchCriteria, String matchingCapability)136     static void validateMatchCriteria(int matchCriteria, String matchingCapability) {
137         Preconditions.checkArgument(
138                 MATCH_CRITERIA_TO_STRING_MAP.contains(matchCriteria),
139                 "Invalid matching criteria: " + matchCriteria + " for " + matchingCapability);
140     }
141 
142     /** @hide */
validateMinBandwidthKbps(int minEntryBandwidth, int minExitBandwidth)143     static void validateMinBandwidthKbps(int minEntryBandwidth, int minExitBandwidth) {
144         Preconditions.checkArgument(
145                 minEntryBandwidth >= 0, "Invalid minEntryBandwidth, must be >= 0");
146         Preconditions.checkArgument(
147                 minExitBandwidth >= 0, "Invalid minExitBandwidth, must be >= 0");
148         Preconditions.checkArgument(
149                 minEntryBandwidth >= minExitBandwidth,
150                 "Minimum entry bandwidth must be >= exit bandwidth");
151     }
152 
153     /** @hide */
validate()154     protected void validate() {
155         validateMatchCriteria(mMeteredMatchCriteria, "mMeteredMatchCriteria");
156         validateMinBandwidthKbps(mMinEntryUpstreamBandwidthKbps, mMinExitUpstreamBandwidthKbps);
157         validateMinBandwidthKbps(mMinEntryDownstreamBandwidthKbps, mMinExitDownstreamBandwidthKbps);
158     }
159 
160     /** @hide */
161     @NonNull
162     @VisibleForTesting(visibility = Visibility.PROTECTED)
fromPersistableBundle( @onNull PersistableBundle in)163     public static VcnUnderlyingNetworkTemplate fromPersistableBundle(
164             @NonNull PersistableBundle in) {
165         Objects.requireNonNull(in, "PersistableBundle is null");
166 
167         final int networkPriorityType = in.getInt(NETWORK_PRIORITY_TYPE_KEY);
168         switch (networkPriorityType) {
169             case NETWORK_PRIORITY_TYPE_WIFI:
170                 return VcnWifiUnderlyingNetworkTemplate.fromPersistableBundle(in);
171             case NETWORK_PRIORITY_TYPE_CELL:
172                 return VcnCellUnderlyingNetworkTemplate.fromPersistableBundle(in);
173             default:
174                 throw new IllegalArgumentException(
175                         "Invalid networkPriorityType:" + networkPriorityType);
176         }
177     }
178 
179     /** @hide */
180     @NonNull
toPersistableBundle()181     PersistableBundle toPersistableBundle() {
182         final PersistableBundle result = new PersistableBundle();
183 
184         result.putInt(NETWORK_PRIORITY_TYPE_KEY, mNetworkPriorityType);
185         result.putInt(METERED_MATCH_KEY, mMeteredMatchCriteria);
186         result.putInt(MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY, mMinEntryUpstreamBandwidthKbps);
187         result.putInt(MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY, mMinExitUpstreamBandwidthKbps);
188         result.putInt(MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY, mMinEntryDownstreamBandwidthKbps);
189         result.putInt(MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY, mMinExitDownstreamBandwidthKbps);
190 
191         return result;
192     }
193 
194     @Override
hashCode()195     public int hashCode() {
196         return Objects.hash(
197                 mNetworkPriorityType,
198                 mMeteredMatchCriteria,
199                 mMinEntryUpstreamBandwidthKbps,
200                 mMinExitUpstreamBandwidthKbps,
201                 mMinEntryDownstreamBandwidthKbps,
202                 mMinExitDownstreamBandwidthKbps);
203     }
204 
205     @Override
equals(@ullable Object other)206     public boolean equals(@Nullable Object other) {
207         if (!(other instanceof VcnUnderlyingNetworkTemplate)) {
208             return false;
209         }
210 
211         final VcnUnderlyingNetworkTemplate rhs = (VcnUnderlyingNetworkTemplate) other;
212         return mNetworkPriorityType == rhs.mNetworkPriorityType
213                 && mMeteredMatchCriteria == rhs.mMeteredMatchCriteria
214                 && mMinEntryUpstreamBandwidthKbps == rhs.mMinEntryUpstreamBandwidthKbps
215                 && mMinExitUpstreamBandwidthKbps == rhs.mMinExitUpstreamBandwidthKbps
216                 && mMinEntryDownstreamBandwidthKbps == rhs.mMinEntryDownstreamBandwidthKbps
217                 && mMinExitDownstreamBandwidthKbps == rhs.mMinExitDownstreamBandwidthKbps;
218     }
219 
220     /** @hide */
getNameString(SparseArray<String> toStringMap, int key)221     static String getNameString(SparseArray<String> toStringMap, int key) {
222         return toStringMap.get(key, "Invalid value " + key);
223     }
224 
225     /** @hide */
getMatchCriteriaString(int matchCriteria)226     static String getMatchCriteriaString(int matchCriteria) {
227         return getNameString(MATCH_CRITERIA_TO_STRING_MAP, matchCriteria);
228     }
229 
230     /** @hide */
dumpTransportSpecificFields(IndentingPrintWriter pw)231     abstract void dumpTransportSpecificFields(IndentingPrintWriter pw);
232 
233     /**
234      * Dumps the state of this record for logging and debugging purposes.
235      *
236      * @hide
237      */
dump(IndentingPrintWriter pw)238     public void dump(IndentingPrintWriter pw) {
239         pw.println(this.getClass().getSimpleName() + ":");
240         pw.increaseIndent();
241 
242         if (mMeteredMatchCriteria != DEFAULT_METERED_MATCH_CRITERIA) {
243             pw.println("mMeteredMatchCriteria: " + getMatchCriteriaString(mMeteredMatchCriteria));
244         }
245         if (mMinEntryUpstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
246             pw.println("mMinEntryUpstreamBandwidthKbps: " + mMinEntryUpstreamBandwidthKbps);
247         }
248         if (mMinExitUpstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
249             pw.println("mMinExitUpstreamBandwidthKbps: " + mMinExitUpstreamBandwidthKbps);
250         }
251         if (mMinEntryDownstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
252             pw.println("mMinEntryDownstreamBandwidthKbps: " + mMinEntryDownstreamBandwidthKbps);
253         }
254         if (mMinExitDownstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) {
255             pw.println("mMinExitDownstreamBandwidthKbps: " + mMinExitDownstreamBandwidthKbps);
256         }
257         dumpTransportSpecificFields(pw);
258 
259         pw.decreaseIndent();
260     }
261 
262     /**
263      * Return the matching criteria for metered networks.
264      *
265      * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMetered(int)
266      * @see VcnCellUnderlyingNetworkTemplate.Builder#setMetered(int)
267      */
getMetered()268     public int getMetered() {
269         return mMeteredMatchCriteria;
270     }
271 
272     /**
273      * Returns the minimum entry upstream bandwidth allowed by this template.
274      *
275      * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
276      * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
277      */
getMinEntryUpstreamBandwidthKbps()278     public int getMinEntryUpstreamBandwidthKbps() {
279         return mMinEntryUpstreamBandwidthKbps;
280     }
281 
282     /**
283      * Returns the minimum exit upstream bandwidth allowed by this template.
284      *
285      * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
286      * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
287      */
getMinExitUpstreamBandwidthKbps()288     public int getMinExitUpstreamBandwidthKbps() {
289         return mMinExitUpstreamBandwidthKbps;
290     }
291 
292     /**
293      * Returns the minimum entry downstream bandwidth allowed by this template.
294      *
295      * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
296      * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
297      */
getMinEntryDownstreamBandwidthKbps()298     public int getMinEntryDownstreamBandwidthKbps() {
299         return mMinEntryDownstreamBandwidthKbps;
300     }
301 
302     /**
303      * Returns the minimum exit downstream bandwidth allowed by this template.
304      *
305      * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
306      * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
307      */
getMinExitDownstreamBandwidthKbps()308     public int getMinExitDownstreamBandwidthKbps() {
309         return mMinExitDownstreamBandwidthKbps;
310     }
311 
312     /** @hide */
getCapabilitiesMatchCriteria()313     public abstract Map<Integer, Integer> getCapabilitiesMatchCriteria();
314 }
315