/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import java.lang.IllegalArgumentException; /** * This class represents the capabilities of a network. This is used both to specify * needs to {@link ConnectivityManager} and when inspecting a network. * * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method * of network selection. Rather than indicate a need for Wi-Fi because an application * needs high bandwidth and risk obsolescence when a new, fast network appears (like LTE), * the application should specify it needs high bandwidth. Similarly if an application * needs an unmetered network for a bulk transfer it can specify that rather than assuming * all cellular based connections are metered and all Wi-Fi based connections are not. */ public final class NetworkCapabilities implements Parcelable { /** * @hide */ public NetworkCapabilities() { clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { if (nc != null) { mNetworkCapabilities = nc.mNetworkCapabilities; mTransportTypes = nc.mTransportTypes; mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; mSignalStrength = nc.mSignalStrength; } } /** * Completely clears the contents of this object, removing even the capabilities that are set * by default when the object is constructed. * @hide */ public void clearAll() { mNetworkCapabilities = mTransportTypes = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0; mNetworkSpecifier = null; mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; } /** * Represents the network's capabilities. If any are specified they will be satisfied * by any Network that matches all of them. */ private long mNetworkCapabilities; /** * Indicates this is a network that has the ability to reach the * carrier's MMSC for sending and receiving MMS messages. */ public static final int NET_CAPABILITY_MMS = 0; /** * Indicates this is a network that has the ability to reach the carrier's * SUPL server, used to retrieve GPS information. */ public static final int NET_CAPABILITY_SUPL = 1; /** * Indicates this is a network that has the ability to reach the carrier's * DUN or tethering gateway. */ public static final int NET_CAPABILITY_DUN = 2; /** * Indicates this is a network that has the ability to reach the carrier's * FOTA portal, used for over the air updates. */ public static final int NET_CAPABILITY_FOTA = 3; /** * Indicates this is a network that has the ability to reach the carrier's * IMS servers, used for network registration and signaling. */ public static final int NET_CAPABILITY_IMS = 4; /** * Indicates this is a network that has the ability to reach the carrier's * CBS servers, used for carrier specific services. */ public static final int NET_CAPABILITY_CBS = 5; /** * Indicates this is a network that has the ability to reach a Wi-Fi direct * peer. */ public static final int NET_CAPABILITY_WIFI_P2P = 6; /** * Indicates this is a network that has the ability to reach a carrier's * Initial Attach servers. */ public static final int NET_CAPABILITY_IA = 7; /** * Indicates this is a network that has the ability to reach a carrier's * RCS servers, used for Rich Communication Services. */ public static final int NET_CAPABILITY_RCS = 8; /** * Indicates this is a network that has the ability to reach a carrier's * XCAP servers, used for configuration and control. */ public static final int NET_CAPABILITY_XCAP = 9; /** * Indicates this is a network that has the ability to reach a carrier's * Emergency IMS servers or other services, used for network signaling * during emergency calls. */ public static final int NET_CAPABILITY_EIMS = 10; /** * Indicates that this network is unmetered. */ public static final int NET_CAPABILITY_NOT_METERED = 11; /** * Indicates that this network should be able to reach the internet. */ public static final int NET_CAPABILITY_INTERNET = 12; /** * Indicates that this network is available for general use. If this is not set * applications should not attempt to communicate on this network. Note that this * is simply informative and not enforcement - enforcement is handled via other means. * Set by default. */ public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; /** * Indicates that the user has indicated implicit trust of this network. This * generally means it's a sim-selected carrier, a plugged in ethernet, a paired * BT device or a wifi the user asked to connect to. Untrusted networks * are probably limited to unknown wifi AP. Set by default. */ public static final int NET_CAPABILITY_TRUSTED = 14; /** * Indicates that this network is not a VPN. This capability is set by default and should be * explicitly cleared for VPN networks. */ public static final int NET_CAPABILITY_NOT_VPN = 15; /** * Indicates that connectivity on this network was successfully validated. For example, for a * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully * detected. */ public static final int NET_CAPABILITY_VALIDATED = 16; /** * Indicates that this network was found to have a captive portal in place last time it was * probed. */ public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; /** * Indicates that this network is available for use by apps, and not a network that is being * kept up in the background to facilitate fast network switching. * @hide */ public static final int NET_CAPABILITY_FOREGROUND = 18; private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular * network is connected. */ private static final long MUTABLE_CAPABILITIES = // TRUSTED can change when user explicitly connects to an untrusted network in Settings. // http://b/18206275 (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_VALIDATED) | (1 << NET_CAPABILITY_CAPTIVE_PORTAL) | (1 << NET_CAPABILITY_FOREGROUND); /** * Network specifier for factories which want to match any network specifier * (NS) in a request. Behavior: *
* Note that when used to request a network, this specifies the minimum acceptable. * When received as the state of an existing network this specifies the typical * first hop bandwidth expected. This is never measured, but rather is inferred * from technology type and other link parameters. It could be used to differentiate * between very slow 1xRTT cellular links and other faster networks or even between * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between * fast backhauls and slow backhauls. * * @param upKbps the estimated first hop upstream (device to network) bandwidth. * @hide */ public void setLinkUpstreamBandwidthKbps(int upKbps) { mLinkUpBandwidthKbps = upKbps; } /** * Retrieves the upstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. * * @return The estimated first hop upstream (device to network) bandwidth. */ public int getLinkUpstreamBandwidthKbps() { return mLinkUpBandwidthKbps; } /** * Sets the downstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. *
* Note that when used to request a network, this specifies the minimum acceptable. * When received as the state of an existing network this specifies the typical * first hop bandwidth expected. This is never measured, but rather is inferred * from technology type and other link parameters. It could be used to differentiate * between very slow 1xRTT cellular links and other faster networks or even between * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between * fast backhauls and slow backhauls. * * @param downKbps the estimated first hop downstream (network to device) bandwidth. * @hide */ public void setLinkDownstreamBandwidthKbps(int downKbps) { mLinkDownBandwidthKbps = downKbps; } /** * Retrieves the downstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. * * @return The estimated first hop downstream (network to device) bandwidth. */ public int getLinkDownstreamBandwidthKbps() { return mLinkDownBandwidthKbps; } private void combineLinkBandwidths(NetworkCapabilities nc) { this.mLinkUpBandwidthKbps = Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps); this.mLinkDownBandwidthKbps = Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps); } private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) { return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps || this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps); } private boolean equalsLinkBandwidths(NetworkCapabilities nc) { return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps && this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps); } private String mNetworkSpecifier; /** * Sets the optional bearer specific network specifier. * This has no meaning if a single transport is also not specified, so calling * this without a single transport set will generate an exception, as will * subsequently adding or removing transports after this is set. *
* The interpretation of this {@code String} is bearer specific and bearers that use * it should document their particulars. For example, Bluetooth may use some sort of * device id while WiFi could used SSID and/or BSSID. Cellular may use carrier SPN (name) * or Subscription ID. * * @param networkSpecifier An {@code String} of opaque format used to specify the bearer * specific network specifier where the bearer has a choice of * networks. * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ public NetworkCapabilities setNetworkSpecifier(String networkSpecifier) { if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) { throw new IllegalStateException("Must have a single transport specified to use " + "setNetworkSpecifier"); } mNetworkSpecifier = networkSpecifier; return this; } /** * Gets the optional bearer specific network specifier. * * @return The optional {@code String} specifying the bearer specific network specifier. * See {@link #setNetworkSpecifier}. * @hide */ public String getNetworkSpecifier() { return mNetworkSpecifier; } private void combineSpecifiers(NetworkCapabilities nc) { String otherSpecifier = nc.getNetworkSpecifier(); if (TextUtils.isEmpty(otherSpecifier)) return; if (TextUtils.isEmpty(mNetworkSpecifier) == false) { throw new IllegalStateException("Can't combine two networkSpecifiers"); } setNetworkSpecifier(otherSpecifier); } private boolean satisfiedBySpecifier(NetworkCapabilities nc) { return (TextUtils.isEmpty(mNetworkSpecifier) || mNetworkSpecifier.equals(nc.mNetworkSpecifier) || MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(nc.mNetworkSpecifier)); } private boolean equalsSpecifier(NetworkCapabilities nc) { if (TextUtils.isEmpty(mNetworkSpecifier)) { return TextUtils.isEmpty(nc.mNetworkSpecifier); } else { return mNetworkSpecifier.equals(nc.mNetworkSpecifier); } } /** * Magic value that indicates no signal strength provided. A request specifying this value is * always satisfied. * * @hide */ public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE; /** * Signal strength. This is a signed integer, and higher values indicate better signal. * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI. */ private int mSignalStrength; /** * Sets the signal strength. This is a signed integer, with higher values indicating a stronger * signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units * reported by WifiManager. *
* Note that when used to register a network callback, this specifies the minimum acceptable
* signal strength. When received as the state of an existing network it specifies the current
* value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no
* effect when requesting a callback.
*
* @param signalStrength the bearer-specific signal strength.
* @hide
*/
public void setSignalStrength(int signalStrength) {
mSignalStrength = signalStrength;
}
/**
* Returns {@code true} if this object specifies a signal strength.
*
* @hide
*/
public boolean hasSignalStrength() {
return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED;
}
/**
* Retrieves the signal strength.
*
* @return The bearer-specific signal strength.
* @hide
*/
public int getSignalStrength() {
return mSignalStrength;
}
private void combineSignalStrength(NetworkCapabilities nc) {
this.mSignalStrength = Math.max(this.mSignalStrength, nc.mSignalStrength);
}
private boolean satisfiedBySignalStrength(NetworkCapabilities nc) {
return this.mSignalStrength <= nc.mSignalStrength;
}
private boolean equalsSignalStrength(NetworkCapabilities nc) {
return this.mSignalStrength == nc.mSignalStrength;
}
/**
* Combine a set of Capabilities to this one. Useful for coming up with the complete set
* @hide
*/
public void combineCapabilities(NetworkCapabilities nc) {
combineNetCapabilities(nc);
combineTransportTypes(nc);
combineLinkBandwidths(nc);
combineSpecifiers(nc);
combineSignalStrength(nc);
}
/**
* Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
*
* @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
* @param onlyImmutable if {@code true}, do not consider mutable requirements such as link
* bandwidth, signal strength, or validation / captive portal status.
*
* @hide
*/
private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
return (nc != null &&
satisfiedByNetCapabilities(nc, onlyImmutable) &&
satisfiedByTransportTypes(nc) &&
(onlyImmutable || satisfiedByLinkBandwidths(nc)) &&
satisfiedBySpecifier(nc) &&
(onlyImmutable || satisfiedBySignalStrength(nc)));
}
/**
* Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
*
* @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
*
* @hide
*/
public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
return satisfiedByNetworkCapabilities(nc, false);
}
/**
* Check if our immutable requirements are satisfied by the given {@code NetworkCapabilities}.
*
* @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
*
* @hide
*/
public boolean satisfiedByImmutableNetworkCapabilities(NetworkCapabilities nc) {
return satisfiedByNetworkCapabilities(nc, true);
}
/**
* Checks that our immutable capabilities are the same as those of the given
* {@code NetworkCapabilities}.
*
* @hide
*/
public boolean equalImmutableCapabilities(NetworkCapabilities nc) {
if (nc == null) return false;
return (equalsNetCapabilitiesImmutable(nc) &&
equalsTransportTypes(nc) &&
equalsSpecifier(nc));
}
/**
* Checks that our requestable capabilities are the same as those of the given
* {@code NetworkCapabilities}.
*
* @hide
*/
public boolean equalRequestableCapabilities(NetworkCapabilities nc) {
if (nc == null) return false;
return (equalsNetCapabilitiesRequestable(nc) &&
equalsTransportTypes(nc) &&
equalsSpecifier(nc));
}
@Override
public boolean equals(Object obj) {
if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
NetworkCapabilities that = (NetworkCapabilities)obj;
return (equalsNetCapabilities(that) &&
equalsTransportTypes(that) &&
equalsLinkBandwidths(that) &&
equalsSignalStrength(that) &&
equalsSpecifier(that));
}
@Override
public int hashCode() {
return ((int)(mNetworkCapabilities & 0xFFFFFFFF) +
((int)(mNetworkCapabilities >> 32) * 3) +
((int)(mTransportTypes & 0xFFFFFFFF) * 5) +
((int)(mTransportTypes >> 32) * 7) +
(mLinkUpBandwidthKbps * 11) +
(mLinkDownBandwidthKbps * 13) +
(TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17) +
(mSignalStrength * 19));
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mNetworkCapabilities);
dest.writeLong(mTransportTypes);
dest.writeInt(mLinkUpBandwidthKbps);
dest.writeInt(mLinkDownBandwidthKbps);
dest.writeString(mNetworkSpecifier);
dest.writeInt(mSignalStrength);
}
public static final Creator