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_INTERNET; 19 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY; 20 21 import static com.android.internal.annotations.VisibleForTesting.Visibility; 22 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; 23 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.SuppressLint; 28 import android.net.NetworkCapabilities; 29 import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria; 30 import android.os.PersistableBundle; 31 import android.util.ArraySet; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.internal.util.IndentingPrintWriter; 35 import com.android.server.vcn.util.PersistableBundleUtils; 36 37 import java.util.ArrayList; 38 import java.util.Collections; 39 import java.util.Map; 40 import java.util.Objects; 41 import java.util.Set; 42 43 /** 44 * This class represents a configuration for a network template class of underlying Carrier WiFi 45 * networks. 46 * 47 * <p>See {@link VcnUnderlyingNetworkTemplate} 48 */ 49 public final class VcnWifiUnderlyingNetworkTemplate extends VcnUnderlyingNetworkTemplate { 50 private static final String SSIDS_KEY = "mSsids"; 51 @Nullable private final Set<String> mSsids; 52 VcnWifiUnderlyingNetworkTemplate( int meteredMatchCriteria, int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps, int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps, Set<String> ssids)53 private VcnWifiUnderlyingNetworkTemplate( 54 int meteredMatchCriteria, 55 int minEntryUpstreamBandwidthKbps, 56 int minExitUpstreamBandwidthKbps, 57 int minEntryDownstreamBandwidthKbps, 58 int minExitDownstreamBandwidthKbps, 59 Set<String> ssids) { 60 super( 61 NETWORK_PRIORITY_TYPE_WIFI, 62 meteredMatchCriteria, 63 minEntryUpstreamBandwidthKbps, 64 minExitUpstreamBandwidthKbps, 65 minEntryDownstreamBandwidthKbps, 66 minExitDownstreamBandwidthKbps); 67 mSsids = new ArraySet<>(ssids); 68 69 validate(); 70 } 71 72 /** @hide */ 73 @Override validate()74 protected void validate() { 75 super.validate(); 76 validateSsids(mSsids); 77 } 78 validateSsids(Set<String> ssids)79 private static void validateSsids(Set<String> ssids) { 80 Objects.requireNonNull(ssids, "ssids is null"); 81 82 for (String ssid : ssids) { 83 Objects.requireNonNull(ssid, "found null value ssid"); 84 } 85 } 86 87 /** @hide */ 88 @NonNull 89 @VisibleForTesting(visibility = Visibility.PROTECTED) fromPersistableBundle( @onNull PersistableBundle in)90 public static VcnWifiUnderlyingNetworkTemplate fromPersistableBundle( 91 @NonNull PersistableBundle in) { 92 Objects.requireNonNull(in, "PersistableBundle is null"); 93 94 final int meteredMatchCriteria = in.getInt(METERED_MATCH_KEY); 95 96 final int minEntryUpstreamBandwidthKbps = 97 in.getInt(MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS); 98 final int minExitUpstreamBandwidthKbps = 99 in.getInt(MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS); 100 final int minEntryDownstreamBandwidthKbps = 101 in.getInt(MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS); 102 final int minExitDownstreamBandwidthKbps = 103 in.getInt(MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS); 104 105 final PersistableBundle ssidsBundle = in.getPersistableBundle(SSIDS_KEY); 106 Objects.requireNonNull(ssidsBundle, "ssidsBundle is null"); 107 final Set<String> ssids = 108 new ArraySet<String>( 109 PersistableBundleUtils.toList(ssidsBundle, STRING_DESERIALIZER)); 110 return new VcnWifiUnderlyingNetworkTemplate( 111 meteredMatchCriteria, 112 minEntryUpstreamBandwidthKbps, 113 minExitUpstreamBandwidthKbps, 114 minEntryDownstreamBandwidthKbps, 115 minExitDownstreamBandwidthKbps, 116 ssids); 117 } 118 119 /** @hide */ 120 @Override 121 @NonNull 122 @VisibleForTesting(visibility = Visibility.PROTECTED) toPersistableBundle()123 public PersistableBundle toPersistableBundle() { 124 final PersistableBundle result = super.toPersistableBundle(); 125 126 final PersistableBundle ssidsBundle = 127 PersistableBundleUtils.fromList(new ArrayList<>(mSsids), STRING_SERIALIZER); 128 result.putPersistableBundle(SSIDS_KEY, ssidsBundle); 129 130 return result; 131 } 132 133 @Override hashCode()134 public int hashCode() { 135 return Objects.hash(super.hashCode(), mSsids); 136 } 137 138 @Override equals(@ullable Object other)139 public boolean equals(@Nullable Object other) { 140 if (!super.equals(other)) { 141 return false; 142 } 143 144 if (!(other instanceof VcnWifiUnderlyingNetworkTemplate)) { 145 return false; 146 } 147 148 final VcnWifiUnderlyingNetworkTemplate rhs = (VcnWifiUnderlyingNetworkTemplate) other; 149 return mSsids.equals(rhs.mSsids); 150 } 151 152 /** @hide */ 153 @Override dumpTransportSpecificFields(IndentingPrintWriter pw)154 void dumpTransportSpecificFields(IndentingPrintWriter pw) { 155 if (!mSsids.isEmpty()) { 156 pw.println("mSsids: " + mSsids); 157 } 158 } 159 160 /** 161 * Retrieve the matching SSIDs, or an empty set if any SSID is acceptable. 162 * 163 * @see Builder#setSsids(Set) 164 */ 165 @NonNull getSsids()166 public Set<String> getSsids() { 167 return Collections.unmodifiableSet(mSsids); 168 } 169 170 /** @hide */ 171 @Override getCapabilitiesMatchCriteria()172 public Map<Integer, Integer> getCapabilitiesMatchCriteria() { 173 return Collections.singletonMap(NET_CAPABILITY_INTERNET, MATCH_REQUIRED); 174 } 175 176 /** This class is used to incrementally build VcnWifiUnderlyingNetworkTemplate objects. */ 177 public static final class Builder { 178 private int mMeteredMatchCriteria = MATCH_ANY; 179 @NonNull private final Set<String> mSsids = new ArraySet<>(); 180 181 private int mMinEntryUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS; 182 private int mMinExitUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS; 183 private int mMinEntryDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS; 184 private int mMinExitDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS; 185 186 /** Construct a Builder object. */ Builder()187 public Builder() {} 188 189 /** 190 * Set the matching criteria for metered networks. 191 * 192 * <p>A template where setMetered(MATCH_REQUIRED) will only match metered networks (one 193 * without NET_CAPABILITY_NOT_METERED). A template where setMetered(MATCH_FORBIDDEN) will 194 * only match a network that is not metered (one with NET_CAPABILITY_NOT_METERED). 195 * 196 * @param matchCriteria the matching criteria for metered networks. Defaults to {@link 197 * #MATCH_ANY}. 198 * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED 199 */ 200 // The matching getter is defined in the super class. Please see {@link 201 // VcnUnderlyingNetworkTemplate#getMetered()} 202 @SuppressLint("MissingGetterMatchingBuilder") 203 @NonNull setMetered(@atchCriteria int matchCriteria)204 public Builder setMetered(@MatchCriteria int matchCriteria) { 205 validateMatchCriteria(matchCriteria, "setMetered"); 206 207 mMeteredMatchCriteria = matchCriteria; 208 return this; 209 } 210 211 /** 212 * Set the SSIDs with which a network can match this priority rule. 213 * 214 * @param ssids the matching SSIDs. Network with one of the matching SSIDs can match this 215 * priority rule. If the set is empty, any SSID will match. The default is an empty set. 216 */ 217 @NonNull setSsids(@onNull Set<String> ssids)218 public Builder setSsids(@NonNull Set<String> ssids) { 219 validateSsids(ssids); 220 221 mSsids.clear(); 222 mSsids.addAll(ssids); 223 return this; 224 } 225 226 /** 227 * Set the minimum upstream bandwidths that this template will match. 228 * 229 * <p>This template will not match a network that does not provide at least the bandwidth 230 * passed as the entry bandwidth, except in the case that the network is selected as the VCN 231 * Gateway Connection's underlying network, where it will continue to match until the 232 * bandwidth drops under the exit bandwidth. 233 * 234 * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the 235 * invalid case where a network fulfills the entry criteria, but at the same time fails the 236 * exit criteria. 237 * 238 * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in 239 * {@link NetworkCapabilities}. The provided estimates will be used without modification. 240 * 241 * @param minEntryUpstreamBandwidthKbps the minimum accepted upstream bandwidth for networks 242 * that ARE NOT the already-selected underlying network, or {@code 0} to disable this 243 * requirement. Disabled by default. 244 * @param minExitUpstreamBandwidthKbps the minimum accepted upstream bandwidth for a network 245 * that IS the already-selected underlying network, or {@code 0} to disable this 246 * requirement. Disabled by default. 247 * @return this {@link Builder} instance, for chaining 248 */ 249 @NonNull 250 // The getter for the two integers are separated, and in the superclass. Please see {@link 251 // VcnUnderlyingNetworkTemplate#getMinEntryUpstreamBandwidthKbps()} and {@link 252 // VcnUnderlyingNetworkTemplate#getMinExitUpstreamBandwidthKbps()} 253 @SuppressLint("MissingGetterMatchingBuilder") setMinUpstreamBandwidthKbps( int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps)254 public Builder setMinUpstreamBandwidthKbps( 255 int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps) { 256 validateMinBandwidthKbps(minEntryUpstreamBandwidthKbps, minExitUpstreamBandwidthKbps); 257 258 mMinEntryUpstreamBandwidthKbps = minEntryUpstreamBandwidthKbps; 259 mMinExitUpstreamBandwidthKbps = minExitUpstreamBandwidthKbps; 260 261 return this; 262 } 263 264 /** 265 * Set the minimum upstream bandwidths that this template will match. 266 * 267 * <p>This template will not match a network that does not provide at least the bandwidth 268 * passed as the entry bandwidth, except in the case that the network is selected as the VCN 269 * Gateway Connection's underlying network, where it will continue to match until the 270 * bandwidth drops under the exit bandwidth. 271 * 272 * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the 273 * invalid case where a network fulfills the entry criteria, but at the same time fails the 274 * exit criteria. 275 * 276 * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in 277 * {@link NetworkCapabilities}. The provided estimates will be used without modification. 278 * 279 * @param minEntryDownstreamBandwidthKbps the minimum accepted downstream bandwidth for 280 * networks that ARE NOT the already-selected underlying network, or {@code 0} to 281 * disable this requirement. Disabled by default. 282 * @param minExitDownstreamBandwidthKbps the minimum accepted downstream bandwidth for a 283 * network that IS the already-selected underlying network, or {@code 0} to disable this 284 * requirement. Disabled by default. 285 * @return this {@link Builder} instance, for chaining 286 */ 287 @NonNull 288 // The getter for the two integers are separated, and in the superclass. Please see {@link 289 // VcnUnderlyingNetworkTemplate#getMinEntryDownstreamBandwidthKbps()} and {@link 290 // VcnUnderlyingNetworkTemplate#getMinExitDownstreamBandwidthKbps()} 291 @SuppressLint("MissingGetterMatchingBuilder") setMinDownstreamBandwidthKbps( int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps)292 public Builder setMinDownstreamBandwidthKbps( 293 int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps) { 294 validateMinBandwidthKbps( 295 minEntryDownstreamBandwidthKbps, minExitDownstreamBandwidthKbps); 296 297 mMinEntryDownstreamBandwidthKbps = minEntryDownstreamBandwidthKbps; 298 mMinExitDownstreamBandwidthKbps = minExitDownstreamBandwidthKbps; 299 300 return this; 301 } 302 303 /** Build the VcnWifiUnderlyingNetworkTemplate. */ 304 @NonNull build()305 public VcnWifiUnderlyingNetworkTemplate build() { 306 return new VcnWifiUnderlyingNetworkTemplate( 307 mMeteredMatchCriteria, 308 mMinEntryUpstreamBandwidthKbps, 309 mMinExitUpstreamBandwidthKbps, 310 mMinEntryDownstreamBandwidthKbps, 311 mMinExitDownstreamBandwidthKbps, 312 mSsids); 313 } 314 } 315 } 316