2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 import android.text.TextUtils;
22 import java.lang.IllegalArgumentException;
25 * This class represents the capabilities of a network. This is used both to specify
26 * needs to {@link ConnectivityManager} and when inspecting a network.
28 * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method
29 * of network selection. Rather than indicate a need for Wi-Fi because an application
30 * needs high bandwidth and risk obsolescence when a new, fast network appears (like LTE),
31 * the application should specify it needs high bandwidth. Similarly if an application
32 * needs an unmetered network for a bulk transfer it can specify that rather than assuming
33 * all cellular based connections are metered and all Wi-Fi based connections are not.
35 public final class NetworkCapabilities implements Parcelable {
39 public NetworkCapabilities() {
40 mNetworkCapabilities = DEFAULT_CAPABILITIES;
43 public NetworkCapabilities(NetworkCapabilities nc) {
45 mNetworkCapabilities = nc.mNetworkCapabilities;
46 mTransportTypes = nc.mTransportTypes;
47 mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
48 mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
49 mNetworkSpecifier = nc.mNetworkSpecifier;
54 * Represents the network's capabilities. If any are specified they will be satisfied
55 * by any Network that matches all of them.
57 private long mNetworkCapabilities;
60 * Indicates this is a network that has the ability to reach the
61 * carrier's MMSC for sending and receiving MMS messages.
63 public static final int NET_CAPABILITY_MMS = 0;
66 * Indicates this is a network that has the ability to reach the carrier's
67 * SUPL server, used to retrieve GPS information.
69 public static final int NET_CAPABILITY_SUPL = 1;
72 * Indicates this is a network that has the ability to reach the carrier's
73 * DUN or tethering gateway.
75 public static final int NET_CAPABILITY_DUN = 2;
78 * Indicates this is a network that has the ability to reach the carrier's
79 * FOTA portal, used for over the air updates.
81 public static final int NET_CAPABILITY_FOTA = 3;
84 * Indicates this is a network that has the ability to reach the carrier's
85 * IMS servers, used for network registration and signaling.
87 public static final int NET_CAPABILITY_IMS = 4;
90 * Indicates this is a network that has the ability to reach the carrier's
91 * CBS servers, used for carrier specific services.
93 public static final int NET_CAPABILITY_CBS = 5;
96 * Indicates this is a network that has the ability to reach a Wi-Fi direct
99 public static final int NET_CAPABILITY_WIFI_P2P = 6;
102 * Indicates this is a network that has the ability to reach a carrier's
103 * Initial Attach servers.
105 public static final int NET_CAPABILITY_IA = 7;
108 * Indicates this is a network that has the ability to reach a carrier's
109 * RCS servers, used for Rich Communication Services.
111 public static final int NET_CAPABILITY_RCS = 8;
114 * Indicates this is a network that has the ability to reach a carrier's
115 * XCAP servers, used for configuration and control.
117 public static final int NET_CAPABILITY_XCAP = 9;
120 * Indicates this is a network that has the ability to reach a carrier's
121 * Emergency IMS servers, used for network signaling during emergency calls.
123 public static final int NET_CAPABILITY_EIMS = 10;
126 * Indicates that this network is unmetered.
128 public static final int NET_CAPABILITY_NOT_METERED = 11;
131 * Indicates that this network should be able to reach the internet.
133 public static final int NET_CAPABILITY_INTERNET = 12;
136 * Indicates that this network is available for general use. If this is not set
137 * applications should not attempt to communicate on this network. Note that this
138 * is simply informative and not enforcement - enforcement is handled via other means.
141 public static final int NET_CAPABILITY_NOT_RESTRICTED = 13;
144 * Indicates that the user has indicated implicit trust of this network. This
145 * generally means it's a sim-selected carrier, a plugged in ethernet, a paired
146 * BT device or a wifi the user asked to connect to. Untrusted networks
147 * are probably limited to unknown wifi AP. Set by default.
149 public static final int NET_CAPABILITY_TRUSTED = 14;
152 * Indicates that this network is not a VPN. This capability is set by default and should be
153 * explicitly cleared when creating VPN networks.
155 public static final int NET_CAPABILITY_NOT_VPN = 15;
158 * Indicates that connectivity on this network was successfully validated. For example, for a
159 * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully
163 public static final int NET_CAPABILITY_VALIDATED = 16;
165 private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
166 private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_VALIDATED;
169 * Capabilities that are set by default when the object is constructed.
171 private static final long DEFAULT_CAPABILITIES =
172 (1 << NET_CAPABILITY_NOT_RESTRICTED) |
173 (1 << NET_CAPABILITY_TRUSTED) |
174 (1 << NET_CAPABILITY_NOT_VPN);
177 * Capabilities that suggest that a network is restricted.
178 * {@see #maybeMarkCapabilitiesRestricted}.
180 private static final long RESTRICTED_CAPABILITIES =
181 (1 << NET_CAPABILITY_CBS) |
182 (1 << NET_CAPABILITY_DUN) |
183 (1 << NET_CAPABILITY_EIMS) |
184 (1 << NET_CAPABILITY_FOTA) |
185 (1 << NET_CAPABILITY_IA) |
186 (1 << NET_CAPABILITY_IMS) |
187 (1 << NET_CAPABILITY_RCS) |
188 (1 << NET_CAPABILITY_XCAP);
191 * Adds the given capability to this {@code NetworkCapability} instance.
192 * Multiple capabilities may be applied sequentially. Note that when searching
193 * for a network to satisfy a request, all capabilities requested must be satisfied.
195 * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
196 * @return This NetworkCapability to facilitate chaining.
199 public NetworkCapabilities addCapability(int capability) {
200 if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
201 throw new IllegalArgumentException("NetworkCapability out of range");
203 mNetworkCapabilities |= 1 << capability;
208 * Removes (if found) the given capability from this {@code NetworkCapability} instance.
210 * @param capability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
211 * @return This NetworkCapability to facilitate chaining.
214 public NetworkCapabilities removeCapability(int capability) {
215 if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
216 throw new IllegalArgumentException("NetworkCapability out of range");
218 mNetworkCapabilities &= ~(1 << capability);
223 * Gets all the capabilities set on this {@code NetworkCapability} instance.
225 * @return an array of {@code NetworkCapabilities.NET_CAPABILITY_*} values
229 public int[] getCapabilities() {
230 return enumerateBits(mNetworkCapabilities);
234 * Tests for the presence of a capabilitity on this instance.
236 * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
237 * @return {@code true} if set on this instance.
239 public boolean hasCapability(int capability) {
240 if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
243 return ((mNetworkCapabilities & (1 << capability)) != 0);
246 private int[] enumerateBits(long val) {
247 int size = Long.bitCount(val);
248 int[] result = new int[size];
252 if ((val & 1) == 1) result[index++] = resource;
259 private void combineNetCapabilities(NetworkCapabilities nc) {
260 this.mNetworkCapabilities |= nc.mNetworkCapabilities;
263 private boolean satisfiedByNetCapabilities(NetworkCapabilities nc) {
264 return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities);
268 public boolean equalsNetCapabilities(NetworkCapabilities nc) {
269 return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
273 * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
274 * typically provided by restricted networks.
277 * - Renaming it to guessRestrictedCapability and make it set the
278 * restricted capability bit in addition to clearing it.
281 public void maybeMarkCapabilitiesRestricted() {
282 // If all the capabilities are typically provided by restricted networks, conclude that this
283 // network is restricted.
284 if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0 &&
285 // Must have at least some restricted capabilities, otherwise a request for an
286 // internet-less network will get marked restricted.
287 (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0) {
288 removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
293 * Representing the transport type. Apps should generally not care about transport. A
294 * request for a fast internet connection could be satisfied by a number of different
295 * transports. If any are specified here it will be satisfied a Network that matches
296 * any of them. If a caller doesn't care about the transport it should not specify any.
298 private long mTransportTypes;
301 * Indicates this network uses a Cellular transport.
303 public static final int TRANSPORT_CELLULAR = 0;
306 * Indicates this network uses a Wi-Fi transport.
308 public static final int TRANSPORT_WIFI = 1;
311 * Indicates this network uses a Bluetooth transport.
313 public static final int TRANSPORT_BLUETOOTH = 2;
316 * Indicates this network uses an Ethernet transport.
318 public static final int TRANSPORT_ETHERNET = 3;
321 * Indicates this network uses a VPN transport.
323 public static final int TRANSPORT_VPN = 4;
325 private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
326 private static final int MAX_TRANSPORT = TRANSPORT_VPN;
329 * Adds the given transport type to this {@code NetworkCapability} instance.
330 * Multiple transports may be applied sequentially. Note that when searching
331 * for a network to satisfy a request, any listed in the request will satisfy the request.
332 * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a
333 * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network
334 * to be selected. This is logically different than
335 * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
337 * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
338 * @return This NetworkCapability to facilitate chaining.
341 public NetworkCapabilities addTransportType(int transportType) {
342 if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
343 throw new IllegalArgumentException("TransportType out of range");
345 mTransportTypes |= 1 << transportType;
346 setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
351 * Removes (if found) the given transport from this {@code NetworkCapability} instance.
353 * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
354 * @return This NetworkCapability to facilitate chaining.
357 public NetworkCapabilities removeTransportType(int transportType) {
358 if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
359 throw new IllegalArgumentException("TransportType out of range");
361 mTransportTypes &= ~(1 << transportType);
362 setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
367 * Gets all the transports set on this {@code NetworkCapability} instance.
369 * @return an array of {@code NetworkCapabilities.TRANSPORT_*} values
373 public int[] getTransportTypes() {
374 return enumerateBits(mTransportTypes);
378 * Tests for the presence of a transport on this instance.
380 * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be tested for.
381 * @return {@code true} if set on this instance.
383 public boolean hasTransport(int transportType) {
384 if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
387 return ((mTransportTypes & (1 << transportType)) != 0);
390 private void combineTransportTypes(NetworkCapabilities nc) {
391 this.mTransportTypes |= nc.mTransportTypes;
393 private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
394 return ((this.mTransportTypes == 0) ||
395 ((this.mTransportTypes & nc.mTransportTypes) != 0));
398 public boolean equalsTransportTypes(NetworkCapabilities nc) {
399 return (nc.mTransportTypes == this.mTransportTypes);
403 * Passive link bandwidth. This is a rough guide of the expected peak bandwidth
404 * for the first hop on the given transport. It is not measured, but may take into account
405 * link parameters (Radio technology, allocated channels, etc).
407 private int mLinkUpBandwidthKbps;
408 private int mLinkDownBandwidthKbps;
411 * Sets the upstream bandwidth for this network in Kbps. This always only refers to
412 * the estimated first hop transport bandwidth.
414 * Note that when used to request a network, this specifies the minimum acceptable.
415 * When received as the state of an existing network this specifies the typical
416 * first hop bandwidth expected. This is never measured, but rather is inferred
417 * from technology type and other link parameters. It could be used to differentiate
418 * between very slow 1xRTT cellular links and other faster networks or even between
419 * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between
420 * fast backhauls and slow backhauls.
422 * @param upKbps the estimated first hop upstream (device to network) bandwidth.
425 public void setLinkUpstreamBandwidthKbps(int upKbps) {
426 mLinkUpBandwidthKbps = upKbps;
430 * Retrieves the upstream bandwidth for this network in Kbps. This always only refers to
431 * the estimated first hop transport bandwidth.
433 * @return The estimated first hop upstream (device to network) bandwidth.
435 public int getLinkUpstreamBandwidthKbps() {
436 return mLinkUpBandwidthKbps;
440 * Sets the downstream bandwidth for this network in Kbps. This always only refers to
441 * the estimated first hop transport bandwidth.
443 * Note that when used to request a network, this specifies the minimum acceptable.
444 * When received as the state of an existing network this specifies the typical
445 * first hop bandwidth expected. This is never measured, but rather is inferred
446 * from technology type and other link parameters. It could be used to differentiate
447 * between very slow 1xRTT cellular links and other faster networks or even between
448 * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between
449 * fast backhauls and slow backhauls.
451 * @param downKbps the estimated first hop downstream (network to device) bandwidth.
454 public void setLinkDownstreamBandwidthKbps(int downKbps) {
455 mLinkDownBandwidthKbps = downKbps;
459 * Retrieves the downstream bandwidth for this network in Kbps. This always only refers to
460 * the estimated first hop transport bandwidth.
462 * @return The estimated first hop downstream (network to device) bandwidth.
464 public int getLinkDownstreamBandwidthKbps() {
465 return mLinkDownBandwidthKbps;
468 private void combineLinkBandwidths(NetworkCapabilities nc) {
469 this.mLinkUpBandwidthKbps =
470 Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps);
471 this.mLinkDownBandwidthKbps =
472 Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps);
474 private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) {
475 return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps ||
476 this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
478 private boolean equalsLinkBandwidths(NetworkCapabilities nc) {
479 return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
480 this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
483 private String mNetworkSpecifier;
485 * Sets the optional bearer specific network specifier.
486 * This has no meaning if a single transport is also not specified, so calling
487 * this without a single transport set will generate an exception, as will
488 * subsequently adding or removing transports after this is set.
490 * The interpretation of this {@code String} is bearer specific and bearers that use
491 * it should document their particulars. For example, Bluetooth may use some sort of
492 * device id while WiFi could used SSID and/or BSSID. Cellular may use carrier SPN (name)
493 * or Subscription ID.
495 * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
496 * specific network specifier where the bearer has a choice of
500 public void setNetworkSpecifier(String networkSpecifier) {
501 if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) {
502 throw new IllegalStateException("Must have a single transport specified to use " +
503 "setNetworkSpecifier");
505 mNetworkSpecifier = networkSpecifier;
509 * Gets the optional bearer specific network specifier.
511 * @return The optional {@code String} specifying the bearer specific network specifier.
512 * See {@link #setNetworkSpecifier}.
515 public String getNetworkSpecifier() {
516 return mNetworkSpecifier;
519 private void combineSpecifiers(NetworkCapabilities nc) {
520 String otherSpecifier = nc.getNetworkSpecifier();
521 if (TextUtils.isEmpty(otherSpecifier)) return;
522 if (TextUtils.isEmpty(mNetworkSpecifier) == false) {
523 throw new IllegalStateException("Can't combine two networkSpecifiers");
525 setNetworkSpecifier(otherSpecifier);
527 private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
528 return (TextUtils.isEmpty(mNetworkSpecifier) ||
529 mNetworkSpecifier.equals(nc.mNetworkSpecifier));
531 private boolean equalsSpecifier(NetworkCapabilities nc) {
532 if (TextUtils.isEmpty(mNetworkSpecifier)) {
533 return TextUtils.isEmpty(nc.mNetworkSpecifier);
535 return mNetworkSpecifier.equals(nc.mNetworkSpecifier);
540 * Combine a set of Capabilities to this one. Useful for coming up with the complete set
543 public void combineCapabilities(NetworkCapabilities nc) {
544 combineNetCapabilities(nc);
545 combineTransportTypes(nc);
546 combineLinkBandwidths(nc);
547 combineSpecifiers(nc);
551 * Check if our requirements are satisfied by the given Capabilities.
554 public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
555 return (nc != null &&
556 satisfiedByNetCapabilities(nc) &&
557 satisfiedByTransportTypes(nc) &&
558 satisfiedByLinkBandwidths(nc) &&
559 satisfiedBySpecifier(nc));
563 public boolean equals(Object obj) {
564 if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
565 NetworkCapabilities that = (NetworkCapabilities)obj;
566 return (equalsNetCapabilities(that) &&
567 equalsTransportTypes(that) &&
568 equalsLinkBandwidths(that) &&
569 equalsSpecifier(that));
573 public int hashCode() {
574 return ((int)(mNetworkCapabilities & 0xFFFFFFFF) +
575 ((int)(mNetworkCapabilities >> 32) * 3) +
576 ((int)(mTransportTypes & 0xFFFFFFFF) * 5) +
577 ((int)(mTransportTypes >> 32) * 7) +
578 (mLinkUpBandwidthKbps * 11) +
579 (mLinkDownBandwidthKbps * 13) +
580 (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17));
584 public int describeContents() {
588 public void writeToParcel(Parcel dest, int flags) {
589 dest.writeLong(mNetworkCapabilities);
590 dest.writeLong(mTransportTypes);
591 dest.writeInt(mLinkUpBandwidthKbps);
592 dest.writeInt(mLinkDownBandwidthKbps);
593 dest.writeString(mNetworkSpecifier);
595 public static final Creator<NetworkCapabilities> CREATOR =
596 new Creator<NetworkCapabilities>() {
598 public NetworkCapabilities createFromParcel(Parcel in) {
599 NetworkCapabilities netCap = new NetworkCapabilities();
601 netCap.mNetworkCapabilities = in.readLong();
602 netCap.mTransportTypes = in.readLong();
603 netCap.mLinkUpBandwidthKbps = in.readInt();
604 netCap.mLinkDownBandwidthKbps = in.readInt();
605 netCap.mNetworkSpecifier = in.readString();
609 public NetworkCapabilities[] newArray(int size) {
610 return new NetworkCapabilities[size];
615 public String toString() {
616 int[] types = getTransportTypes();
617 String transports = (types.length > 0 ? " Transports: " : "");
618 for (int i = 0; i < types.length;) {
620 case TRANSPORT_CELLULAR: transports += "CELLULAR"; break;
621 case TRANSPORT_WIFI: transports += "WIFI"; break;
622 case TRANSPORT_BLUETOOTH: transports += "BLUETOOTH"; break;
623 case TRANSPORT_ETHERNET: transports += "ETHERNET"; break;
624 case TRANSPORT_VPN: transports += "VPN"; break;
626 if (++i < types.length) transports += "|";
629 types = getCapabilities();
630 String capabilities = (types.length > 0 ? " Capabilities: " : "");
631 for (int i = 0; i < types.length; ) {
633 case NET_CAPABILITY_MMS: capabilities += "MMS"; break;
634 case NET_CAPABILITY_SUPL: capabilities += "SUPL"; break;
635 case NET_CAPABILITY_DUN: capabilities += "DUN"; break;
636 case NET_CAPABILITY_FOTA: capabilities += "FOTA"; break;
637 case NET_CAPABILITY_IMS: capabilities += "IMS"; break;
638 case NET_CAPABILITY_CBS: capabilities += "CBS"; break;
639 case NET_CAPABILITY_WIFI_P2P: capabilities += "WIFI_P2P"; break;
640 case NET_CAPABILITY_IA: capabilities += "IA"; break;
641 case NET_CAPABILITY_RCS: capabilities += "RCS"; break;
642 case NET_CAPABILITY_XCAP: capabilities += "XCAP"; break;
643 case NET_CAPABILITY_EIMS: capabilities += "EIMS"; break;
644 case NET_CAPABILITY_NOT_METERED: capabilities += "NOT_METERED"; break;
645 case NET_CAPABILITY_INTERNET: capabilities += "INTERNET"; break;
646 case NET_CAPABILITY_NOT_RESTRICTED: capabilities += "NOT_RESTRICTED"; break;
647 case NET_CAPABILITY_TRUSTED: capabilities += "TRUSTED"; break;
648 case NET_CAPABILITY_NOT_VPN: capabilities += "NOT_VPN"; break;
650 if (++i < types.length) capabilities += "&";
653 String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" +
654 mLinkUpBandwidthKbps + "Kbps" : "");
655 String dnBand = ((mLinkDownBandwidthKbps > 0) ? " LinkDnBandwidth>=" +
656 mLinkDownBandwidthKbps + "Kbps" : "");
658 String specifier = (mNetworkSpecifier == null ?
659 "" : " Specifier: <" + mNetworkSpecifier + ">");
661 return "[" + transports + capabilities + upBand + dnBand + specifier + "]";