/*
|
* 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.annotation.NonNull;
|
import android.annotation.RequiresPermission;
|
import android.annotation.SystemApi;
|
import android.annotation.UnsupportedAppUsage;
|
import android.net.NetworkCapabilities.NetCapability;
|
import android.net.NetworkCapabilities.Transport;
|
import android.os.Build;
|
import android.os.Parcel;
|
import android.os.Parcelable;
|
import android.os.Process;
|
import android.text.TextUtils;
|
import android.util.proto.ProtoOutputStream;
|
|
import java.util.Objects;
|
import java.util.Set;
|
|
/**
|
* Defines a request for a network, made through {@link NetworkRequest.Builder} and used
|
* to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes
|
* via {@link ConnectivityManager#registerNetworkCallback}.
|
*/
|
public class NetworkRequest implements Parcelable {
|
/**
|
* The {@link NetworkCapabilities} that define this request.
|
* @hide
|
*/
|
@UnsupportedAppUsage
|
public final @NonNull NetworkCapabilities networkCapabilities;
|
|
/**
|
* Identifies the request. NetworkRequests should only be constructed by
|
* the Framework and given out to applications as tokens to be used to identify
|
* the request.
|
* @hide
|
*/
|
@UnsupportedAppUsage
|
public final int requestId;
|
|
/**
|
* Set for legacy requests and the default. Set to TYPE_NONE for none.
|
* Causes CONNECTIVITY_ACTION broadcasts to be sent.
|
* @hide
|
*/
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
public final int legacyType;
|
|
/**
|
* A NetworkRequest as used by the system can be one of the following types:
|
*
|
* - LISTEN, for which the framework will issue callbacks about any
|
* and all networks that match the specified NetworkCapabilities,
|
*
|
* - REQUEST, capable of causing a specific network to be created
|
* first (e.g. a telephony DUN request), the framework will issue
|
* callbacks about the single, highest scoring current network
|
* (if any) that matches the specified NetworkCapabilities, or
|
*
|
* - TRACK_DEFAULT, a hybrid of the two designed such that the
|
* framework will issue callbacks for the single, highest scoring
|
* current network (if any) that matches the capabilities of the
|
* default Internet request (mDefaultRequest), but which cannot cause
|
* the framework to either create or retain the existence of any
|
* specific network. Note that from the point of view of the request
|
* matching code, TRACK_DEFAULT is identical to REQUEST: its special
|
* behaviour is not due to different semantics, but to the fact that
|
* the system will only ever create a TRACK_DEFAULT with capabilities
|
* that are identical to the default request's capabilities, thus
|
* causing it to share fate in every way with the default request.
|
*
|
* - BACKGROUND_REQUEST, like REQUEST but does not cause any networks
|
* to retain the NET_CAPABILITY_FOREGROUND capability. A network with
|
* no foreground requests is in the background. A network that has
|
* one or more background requests and loses its last foreground
|
* request to a higher-scoring network will not go into the
|
* background immediately, but will linger and go into the background
|
* after the linger timeout.
|
*
|
* - The value NONE is used only by applications. When an application
|
* creates a NetworkRequest, it does not have a type; the type is set
|
* by the system depending on the method used to file the request
|
* (requestNetwork, registerNetworkCallback, etc.).
|
*
|
* @hide
|
*/
|
public static enum Type {
|
NONE,
|
LISTEN,
|
TRACK_DEFAULT,
|
REQUEST,
|
BACKGROUND_REQUEST,
|
};
|
|
/**
|
* The type of the request. This is only used by the system and is always NONE elsewhere.
|
*
|
* @hide
|
*/
|
public final Type type;
|
|
/**
|
* @hide
|
*/
|
public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type) {
|
if (nc == null) {
|
throw new NullPointerException();
|
}
|
requestId = rId;
|
networkCapabilities = nc;
|
this.legacyType = legacyType;
|
this.type = type;
|
}
|
|
/**
|
* @hide
|
*/
|
public NetworkRequest(NetworkRequest that) {
|
networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
|
requestId = that.requestId;
|
this.legacyType = that.legacyType;
|
this.type = that.type;
|
}
|
|
/**
|
* Builder used to create {@link NetworkRequest} objects. Specify the Network features
|
* needed in terms of {@link NetworkCapabilities} features
|
*/
|
public static class Builder {
|
private final NetworkCapabilities mNetworkCapabilities;
|
|
/**
|
* Default constructor for Builder.
|
*/
|
public Builder() {
|
// By default, restrict this request to networks available to this app.
|
// Apps can rescind this restriction, but ConnectivityService will enforce
|
// it for apps that do not have the NETWORK_SETTINGS permission.
|
mNetworkCapabilities = new NetworkCapabilities();
|
mNetworkCapabilities.setSingleUid(Process.myUid());
|
}
|
|
/**
|
* Build {@link NetworkRequest} give the current set of capabilities.
|
*/
|
public NetworkRequest build() {
|
// Make a copy of mNetworkCapabilities so we don't inadvertently remove NOT_RESTRICTED
|
// when later an unrestricted capability could be added to mNetworkCapabilities, in
|
// which case NOT_RESTRICTED should be returned to mNetworkCapabilities, which
|
// maybeMarkCapabilitiesRestricted() doesn't add back.
|
final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities);
|
nc.maybeMarkCapabilitiesRestricted();
|
return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE,
|
ConnectivityManager.REQUEST_ID_UNSET, Type.NONE);
|
}
|
|
/**
|
* Add the given capability requirement to this builder. These represent
|
* the requested network's required capabilities. Note that when searching
|
* for a network to satisfy a request, all capabilities requested must be
|
* satisfied.
|
*
|
* @param capability The capability to add.
|
* @return The builder to facilitate chaining
|
* {@code builder.addCapability(...).addCapability();}.
|
*/
|
public Builder addCapability(@NetworkCapabilities.NetCapability int capability) {
|
mNetworkCapabilities.addCapability(capability);
|
return this;
|
}
|
|
/**
|
* Removes (if found) the given capability from this builder instance.
|
*
|
* @param capability The capability to remove.
|
* @return The builder to facilitate chaining.
|
*/
|
public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) {
|
mNetworkCapabilities.removeCapability(capability);
|
return this;
|
}
|
|
/**
|
* Set the {@code NetworkCapabilities} for this builder instance,
|
* overriding any capabilities that had been previously set.
|
*
|
* @param nc The superseding {@code NetworkCapabilities} instance.
|
* @return The builder to facilitate chaining.
|
* @hide
|
*/
|
public Builder setCapabilities(NetworkCapabilities nc) {
|
mNetworkCapabilities.set(nc);
|
return this;
|
}
|
|
/**
|
* Set the watched UIDs for this request. This will be reset and wiped out unless
|
* the calling app holds the CHANGE_NETWORK_STATE permission.
|
*
|
* @param uids The watched UIDs as a set of UidRanges, or null for everything.
|
* @return The builder to facilitate chaining.
|
* @hide
|
*/
|
public Builder setUids(Set<UidRange> uids) {
|
mNetworkCapabilities.setUids(uids);
|
return this;
|
}
|
|
/**
|
* Add a capability that must not exist in the requested network.
|
* <p>
|
* If the capability was previously added to the list of required capabilities (for
|
* example, it was there by default or added using {@link #addCapability(int)} method), then
|
* it will be removed from the list of required capabilities as well.
|
*
|
* @see #addCapability(int)
|
*
|
* @param capability The capability to add to unwanted capability list.
|
* @return The builder to facilitate chaining.
|
*
|
* @hide
|
*/
|
public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
|
mNetworkCapabilities.addUnwantedCapability(capability);
|
return this;
|
}
|
|
/**
|
* Completely clears all the {@code NetworkCapabilities} from this builder instance,
|
* removing even the capabilities that are set by default when the object is constructed.
|
*
|
* @return The builder to facilitate chaining.
|
* @hide
|
*/
|
@UnsupportedAppUsage
|
public Builder clearCapabilities() {
|
mNetworkCapabilities.clearAll();
|
return this;
|
}
|
|
/**
|
* Adds the given transport requirement to this builder. These represent
|
* the set of allowed transports for the request. Only networks using one
|
* of these transports will satisfy the request. If no particular transports
|
* are required, none should be specified here.
|
*
|
* @param transportType The transport type to add.
|
* @return The builder to facilitate chaining.
|
*/
|
public Builder addTransportType(@NetworkCapabilities.Transport int transportType) {
|
mNetworkCapabilities.addTransportType(transportType);
|
return this;
|
}
|
|
/**
|
* Removes (if found) the given transport from this builder instance.
|
*
|
* @param transportType The transport type to remove.
|
* @return The builder to facilitate chaining.
|
*/
|
public Builder removeTransportType(@NetworkCapabilities.Transport int transportType) {
|
mNetworkCapabilities.removeTransportType(transportType);
|
return this;
|
}
|
|
/**
|
* @hide
|
*/
|
public Builder setLinkUpstreamBandwidthKbps(int upKbps) {
|
mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps);
|
return this;
|
}
|
/**
|
* @hide
|
*/
|
public Builder setLinkDownstreamBandwidthKbps(int downKbps) {
|
mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps);
|
return this;
|
}
|
|
/**
|
* 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.
|
* </p>
|
* 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.
|
*
|
* @param networkSpecifier An {@code String} of opaque format used to specify the bearer
|
* specific network specifier where the bearer has a choice of
|
* networks.
|
*/
|
public Builder setNetworkSpecifier(String networkSpecifier) {
|
/*
|
* A StringNetworkSpecifier does not accept null or empty ("") strings. When network
|
* specifiers were strings a null string and an empty string were considered equivalent.
|
* Hence no meaning is attached to a null or empty ("") string.
|
*/
|
return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
|
: new StringNetworkSpecifier(networkSpecifier));
|
}
|
|
/**
|
* 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.
|
* </p>
|
*
|
* @param networkSpecifier A concrete, parcelable framework class that extends
|
* NetworkSpecifier.
|
*/
|
public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
|
MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(networkSpecifier);
|
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
|
return this;
|
}
|
|
/**
|
* 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.
|
* <p>
|
* 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.
|
*
|
* <p>This method requires the caller to hold the
|
* {@link android.Manifest.permission#NETWORK_SIGNAL_STRENGTH_WAKEUP} permission
|
*
|
* @param signalStrength the bearer-specific signal strength.
|
* @hide
|
*/
|
@SystemApi
|
@RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP)
|
public @NonNull Builder setSignalStrength(int signalStrength) {
|
mNetworkCapabilities.setSignalStrength(signalStrength);
|
return this;
|
}
|
}
|
|
// implement the Parcelable interface
|
public int describeContents() {
|
return 0;
|
}
|
public void writeToParcel(Parcel dest, int flags) {
|
networkCapabilities.writeToParcel(dest, flags);
|
dest.writeInt(legacyType);
|
dest.writeInt(requestId);
|
dest.writeString(type.name());
|
}
|
public static final @android.annotation.NonNull Creator<NetworkRequest> CREATOR =
|
new Creator<NetworkRequest>() {
|
public NetworkRequest createFromParcel(Parcel in) {
|
NetworkCapabilities nc = NetworkCapabilities.CREATOR.createFromParcel(in);
|
int legacyType = in.readInt();
|
int requestId = in.readInt();
|
Type type = Type.valueOf(in.readString()); // IllegalArgumentException if invalid.
|
NetworkRequest result = new NetworkRequest(nc, legacyType, requestId, type);
|
return result;
|
}
|
public NetworkRequest[] newArray(int size) {
|
return new NetworkRequest[size];
|
}
|
};
|
|
/**
|
* Returns true iff. this NetworkRequest is of type LISTEN.
|
*
|
* @hide
|
*/
|
public boolean isListen() {
|
return type == Type.LISTEN;
|
}
|
|
/**
|
* Returns true iff. the contained NetworkRequest is one that:
|
*
|
* - should be associated with at most one satisfying network
|
* at a time;
|
*
|
* - should cause a network to be kept up, but not necessarily in
|
* the foreground, if it is the best network which can satisfy the
|
* NetworkRequest.
|
*
|
* For full detail of how isRequest() is used for pairing Networks with
|
* NetworkRequests read rematchNetworkAndRequests().
|
*
|
* @hide
|
*/
|
public boolean isRequest() {
|
return isForegroundRequest() || isBackgroundRequest();
|
}
|
|
/**
|
* Returns true iff. the contained NetworkRequest is one that:
|
*
|
* - should be associated with at most one satisfying network
|
* at a time;
|
*
|
* - should cause a network to be kept up and in the foreground if
|
* it is the best network which can satisfy the NetworkRequest.
|
*
|
* For full detail of how isRequest() is used for pairing Networks with
|
* NetworkRequests read rematchNetworkAndRequests().
|
*
|
* @hide
|
*/
|
public boolean isForegroundRequest() {
|
return type == Type.TRACK_DEFAULT || type == Type.REQUEST;
|
}
|
|
/**
|
* Returns true iff. this NetworkRequest is of type BACKGROUND_REQUEST.
|
*
|
* @hide
|
*/
|
public boolean isBackgroundRequest() {
|
return type == Type.BACKGROUND_REQUEST;
|
}
|
|
/**
|
* @see Builder#addCapability(int)
|
*/
|
public boolean hasCapability(@NetCapability int capability) {
|
return networkCapabilities.hasCapability(capability);
|
}
|
|
/**
|
* @see Builder#addUnwantedCapability(int)
|
*
|
* @hide
|
*/
|
public boolean hasUnwantedCapability(@NetCapability int capability) {
|
return networkCapabilities.hasUnwantedCapability(capability);
|
}
|
|
/**
|
* @see Builder#addTransportType(int)
|
*/
|
public boolean hasTransport(@Transport int transportType) {
|
return networkCapabilities.hasTransport(transportType);
|
}
|
|
public String toString() {
|
return "NetworkRequest [ " + type + " id=" + requestId +
|
(legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
|
", " + networkCapabilities.toString() + " ]";
|
}
|
|
private int typeToProtoEnum(Type t) {
|
switch (t) {
|
case NONE:
|
return NetworkRequestProto.TYPE_NONE;
|
case LISTEN:
|
return NetworkRequestProto.TYPE_LISTEN;
|
case TRACK_DEFAULT:
|
return NetworkRequestProto.TYPE_TRACK_DEFAULT;
|
case REQUEST:
|
return NetworkRequestProto.TYPE_REQUEST;
|
case BACKGROUND_REQUEST:
|
return NetworkRequestProto.TYPE_BACKGROUND_REQUEST;
|
default:
|
return NetworkRequestProto.TYPE_UNKNOWN;
|
}
|
}
|
|
/** @hide */
|
public void writeToProto(ProtoOutputStream proto, long fieldId) {
|
final long token = proto.start(fieldId);
|
|
proto.write(NetworkRequestProto.TYPE, typeToProtoEnum(type));
|
proto.write(NetworkRequestProto.REQUEST_ID, requestId);
|
proto.write(NetworkRequestProto.LEGACY_TYPE, legacyType);
|
networkCapabilities.writeToProto(proto, NetworkRequestProto.NETWORK_CAPABILITIES);
|
|
proto.end(token);
|
}
|
|
public boolean equals(Object obj) {
|
if (obj instanceof NetworkRequest == false) return false;
|
NetworkRequest that = (NetworkRequest)obj;
|
return (that.legacyType == this.legacyType &&
|
that.requestId == this.requestId &&
|
that.type == this.type &&
|
Objects.equals(that.networkCapabilities, this.networkCapabilities));
|
}
|
|
public int hashCode() {
|
return Objects.hash(requestId, legacyType, networkCapabilities, type);
|
}
|
}
|