1 /*
2  * Copyright (C) 2014 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 
17 package android.net;
18 
19 import android.annotation.NonNull;
20 import android.net.NetworkCapabilities.NetCapability;
21 import android.net.NetworkCapabilities.Transport;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.Process;
25 import android.text.TextUtils;
26 import android.util.proto.ProtoOutputStream;
27 
28 import java.util.Objects;
29 import java.util.Set;
30 
31 /**
32  * Defines a request for a network, made through {@link NetworkRequest.Builder} and used
33  * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes
34  * via {@link ConnectivityManager#registerNetworkCallback}.
35  */
36 public class NetworkRequest implements Parcelable {
37     /**
38      * The {@link NetworkCapabilities} that define this request.
39      * @hide
40      */
41     public final @NonNull NetworkCapabilities networkCapabilities;
42 
43     /**
44      * Identifies the request.  NetworkRequests should only be constructed by
45      * the Framework and given out to applications as tokens to be used to identify
46      * the request.
47      * @hide
48      */
49     public final int requestId;
50 
51     /**
52      * Set for legacy requests and the default.  Set to TYPE_NONE for none.
53      * Causes CONNECTIVITY_ACTION broadcasts to be sent.
54      * @hide
55      */
56     public final int legacyType;
57 
58     /**
59      * A NetworkRequest as used by the system can be one of the following types:
60      *
61      *     - LISTEN, for which the framework will issue callbacks about any
62      *       and all networks that match the specified NetworkCapabilities,
63      *
64      *     - REQUEST, capable of causing a specific network to be created
65      *       first (e.g. a telephony DUN request), the framework will issue
66      *       callbacks about the single, highest scoring current network
67      *       (if any) that matches the specified NetworkCapabilities, or
68      *
69      *     - TRACK_DEFAULT, a hybrid of the two designed such that the
70      *       framework will issue callbacks for the single, highest scoring
71      *       current network (if any) that matches the capabilities of the
72      *       default Internet request (mDefaultRequest), but which cannot cause
73      *       the framework to either create or retain the existence of any
74      *       specific network. Note that from the point of view of the request
75      *       matching code, TRACK_DEFAULT is identical to REQUEST: its special
76      *       behaviour is not due to different semantics, but to the fact that
77      *       the system will only ever create a TRACK_DEFAULT with capabilities
78      *       that are identical to the default request's capabilities, thus
79      *       causing it to share fate in every way with the default request.
80      *
81      *     - BACKGROUND_REQUEST, like REQUEST but does not cause any networks
82      *       to retain the NET_CAPABILITY_FOREGROUND capability. A network with
83      *       no foreground requests is in the background. A network that has
84      *       one or more background requests and loses its last foreground
85      *       request to a higher-scoring network will not go into the
86      *       background immediately, but will linger and go into the background
87      *       after the linger timeout.
88      *
89      *     - The value NONE is used only by applications. When an application
90      *       creates a NetworkRequest, it does not have a type; the type is set
91      *       by the system depending on the method used to file the request
92      *       (requestNetwork, registerNetworkCallback, etc.).
93      *
94      * @hide
95      */
96     public static enum Type {
97         NONE,
98         LISTEN,
99         TRACK_DEFAULT,
100         REQUEST,
101         BACKGROUND_REQUEST,
102     };
103 
104     /**
105      * The type of the request. This is only used by the system and is always NONE elsewhere.
106      *
107      * @hide
108      */
109     public final Type type;
110 
111     /**
112      * @hide
113      */
NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type)114     public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type) {
115         if (nc == null) {
116             throw new NullPointerException();
117         }
118         requestId = rId;
119         networkCapabilities = nc;
120         this.legacyType = legacyType;
121         this.type = type;
122     }
123 
124     /**
125      * @hide
126      */
NetworkRequest(NetworkRequest that)127     public NetworkRequest(NetworkRequest that) {
128         networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
129         requestId = that.requestId;
130         this.legacyType = that.legacyType;
131         this.type = that.type;
132     }
133 
134     /**
135      * Builder used to create {@link NetworkRequest} objects.  Specify the Network features
136      * needed in terms of {@link NetworkCapabilities} features
137      */
138     public static class Builder {
139         private final NetworkCapabilities mNetworkCapabilities;
140 
141         /**
142          * Default constructor for Builder.
143          */
Builder()144         public Builder() {
145             // By default, restrict this request to networks available to this app.
146             // Apps can rescind this restriction, but ConnectivityService will enforce
147             // it for apps that do not have the NETWORK_SETTINGS permission.
148             mNetworkCapabilities = new NetworkCapabilities();
149             mNetworkCapabilities.setSingleUid(Process.myUid());
150         }
151 
152         /**
153          * Build {@link NetworkRequest} give the current set of capabilities.
154          */
build()155         public NetworkRequest build() {
156             // Make a copy of mNetworkCapabilities so we don't inadvertently remove NOT_RESTRICTED
157             // when later an unrestricted capability could be added to mNetworkCapabilities, in
158             // which case NOT_RESTRICTED should be returned to mNetworkCapabilities, which
159             // maybeMarkCapabilitiesRestricted() doesn't add back.
160             final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities);
161             nc.maybeMarkCapabilitiesRestricted();
162             return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE,
163                     ConnectivityManager.REQUEST_ID_UNSET, Type.NONE);
164         }
165 
166         /**
167          * Add the given capability requirement to this builder.  These represent
168          * the requested network's required capabilities.  Note that when searching
169          * for a network to satisfy a request, all capabilities requested must be
170          * satisfied.
171          *
172          * @param capability The capability to add.
173          * @return The builder to facilitate chaining
174          *         {@code builder.addCapability(...).addCapability();}.
175          */
addCapability(@etworkCapabilities.NetCapability int capability)176         public Builder addCapability(@NetworkCapabilities.NetCapability int capability) {
177             mNetworkCapabilities.addCapability(capability);
178             return this;
179         }
180 
181         /**
182          * Removes (if found) the given capability from this builder instance.
183          *
184          * @param capability The capability to remove.
185          * @return The builder to facilitate chaining.
186          */
removeCapability(@etworkCapabilities.NetCapability int capability)187         public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) {
188             mNetworkCapabilities.removeCapability(capability);
189             return this;
190         }
191 
192         /**
193          * Set the {@code NetworkCapabilities} for this builder instance,
194          * overriding any capabilities that had been previously set.
195          *
196          * @param nc The superseding {@code NetworkCapabilities} instance.
197          * @return The builder to facilitate chaining.
198          * @hide
199          */
setCapabilities(NetworkCapabilities nc)200         public Builder setCapabilities(NetworkCapabilities nc) {
201             mNetworkCapabilities.set(nc);
202             return this;
203         }
204 
205         /**
206          * Set the watched UIDs for this request. This will be reset and wiped out unless
207          * the calling app holds the CHANGE_NETWORK_STATE permission.
208          *
209          * @param uids The watched UIDs as a set of UidRanges, or null for everything.
210          * @return The builder to facilitate chaining.
211          * @hide
212          */
setUids(Set<UidRange> uids)213         public Builder setUids(Set<UidRange> uids) {
214             mNetworkCapabilities.setUids(uids);
215             return this;
216         }
217 
218         /**
219          * Add a capability that must not exist in the requested network.
220          * <p>
221          * If the capability was previously added to the list of required capabilities (for
222          * example, it was there by default or added using {@link #addCapability(int)} method), then
223          * it will be removed from the list of required capabilities as well.
224          *
225          * @see #addCapability(int)
226          *
227          * @param capability The capability to add to unwanted capability list.
228          * @return The builder to facilitate chaining.
229          *
230          * @hide
231          */
addUnwantedCapability(@etworkCapabilities.NetCapability int capability)232         public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
233             mNetworkCapabilities.addUnwantedCapability(capability);
234             return this;
235         }
236 
237         /**
238          * Completely clears all the {@code NetworkCapabilities} from this builder instance,
239          * removing even the capabilities that are set by default when the object is constructed.
240          *
241          * @return The builder to facilitate chaining.
242          * @hide
243          */
clearCapabilities()244         public Builder clearCapabilities() {
245             mNetworkCapabilities.clearAll();
246             return this;
247         }
248 
249         /**
250          * Adds the given transport requirement to this builder.  These represent
251          * the set of allowed transports for the request.  Only networks using one
252          * of these transports will satisfy the request.  If no particular transports
253          * are required, none should be specified here.
254          *
255          * @param transportType The transport type to add.
256          * @return The builder to facilitate chaining.
257          */
addTransportType(@etworkCapabilities.Transport int transportType)258         public Builder addTransportType(@NetworkCapabilities.Transport int transportType) {
259             mNetworkCapabilities.addTransportType(transportType);
260             return this;
261         }
262 
263         /**
264          * Removes (if found) the given transport from this builder instance.
265          *
266          * @param transportType The transport type to remove.
267          * @return The builder to facilitate chaining.
268          */
removeTransportType(@etworkCapabilities.Transport int transportType)269         public Builder removeTransportType(@NetworkCapabilities.Transport int transportType) {
270             mNetworkCapabilities.removeTransportType(transportType);
271             return this;
272         }
273 
274         /**
275          * @hide
276          */
setLinkUpstreamBandwidthKbps(int upKbps)277         public Builder setLinkUpstreamBandwidthKbps(int upKbps) {
278             mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps);
279             return this;
280         }
281         /**
282          * @hide
283          */
setLinkDownstreamBandwidthKbps(int downKbps)284         public Builder setLinkDownstreamBandwidthKbps(int downKbps) {
285             mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps);
286             return this;
287         }
288 
289         /**
290          * Sets the optional bearer specific network specifier.
291          * This has no meaning if a single transport is also not specified, so calling
292          * this without a single transport set will generate an exception, as will
293          * subsequently adding or removing transports after this is set.
294          * </p>
295          * The interpretation of this {@code String} is bearer specific and bearers that use
296          * it should document their particulars.  For example, Bluetooth may use some sort of
297          * device id while WiFi could used ssid and/or bssid.  Cellular may use carrier spn.
298          *
299          * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
300          *                         specific network specifier where the bearer has a choice of
301          *                         networks.
302          */
setNetworkSpecifier(String networkSpecifier)303         public Builder setNetworkSpecifier(String networkSpecifier) {
304             /*
305              * A StringNetworkSpecifier does not accept null or empty ("") strings. When network
306              * specifiers were strings a null string and an empty string were considered equivalent.
307              * Hence no meaning is attached to a null or empty ("") string.
308              */
309             return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
310                     : new StringNetworkSpecifier(networkSpecifier));
311         }
312 
313         /**
314          * Sets the optional bearer specific network specifier.
315          * This has no meaning if a single transport is also not specified, so calling
316          * this without a single transport set will generate an exception, as will
317          * subsequently adding or removing transports after this is set.
318          * </p>
319          *
320          * @param networkSpecifier A concrete, parcelable framework class that extends
321          *                         NetworkSpecifier.
322          */
setNetworkSpecifier(NetworkSpecifier networkSpecifier)323         public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
324             MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(networkSpecifier);
325             mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
326             return this;
327         }
328 
329         /**
330          * Sets the signal strength. This is a signed integer, with higher values indicating a
331          * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same
332          * RSSI units reported by WifiManager.
333          * <p>
334          * Note that when used to register a network callback, this specifies the minimum acceptable
335          * signal strength. When received as the state of an existing network it specifies the
336          * current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when
337          * received and has no effect when requesting a callback.
338          *
339          * @param signalStrength the bearer-specific signal strength.
340          * @hide
341          */
setSignalStrength(int signalStrength)342         public Builder setSignalStrength(int signalStrength) {
343             mNetworkCapabilities.setSignalStrength(signalStrength);
344             return this;
345         }
346     }
347 
348     // implement the Parcelable interface
describeContents()349     public int describeContents() {
350         return 0;
351     }
writeToParcel(Parcel dest, int flags)352     public void writeToParcel(Parcel dest, int flags) {
353         networkCapabilities.writeToParcel(dest, flags);
354         dest.writeInt(legacyType);
355         dest.writeInt(requestId);
356         dest.writeString(type.name());
357     }
358     public static final Creator<NetworkRequest> CREATOR =
359         new Creator<NetworkRequest>() {
360             public NetworkRequest createFromParcel(Parcel in) {
361                 NetworkCapabilities nc = NetworkCapabilities.CREATOR.createFromParcel(in);
362                 int legacyType = in.readInt();
363                 int requestId = in.readInt();
364                 Type type = Type.valueOf(in.readString());  // IllegalArgumentException if invalid.
365                 NetworkRequest result = new NetworkRequest(nc, legacyType, requestId, type);
366                 return result;
367             }
368             public NetworkRequest[] newArray(int size) {
369                 return new NetworkRequest[size];
370             }
371         };
372 
373     /**
374      * Returns true iff. this NetworkRequest is of type LISTEN.
375      *
376      * @hide
377      */
isListen()378     public boolean isListen() {
379         return type == Type.LISTEN;
380     }
381 
382     /**
383      * Returns true iff. the contained NetworkRequest is one that:
384      *
385      *     - should be associated with at most one satisfying network
386      *       at a time;
387      *
388      *     - should cause a network to be kept up, but not necessarily in
389      *       the foreground, if it is the best network which can satisfy the
390      *       NetworkRequest.
391      *
392      * For full detail of how isRequest() is used for pairing Networks with
393      * NetworkRequests read rematchNetworkAndRequests().
394      *
395      * @hide
396      */
isRequest()397     public boolean isRequest() {
398         return isForegroundRequest() || isBackgroundRequest();
399     }
400 
401     /**
402      * Returns true iff. the contained NetworkRequest is one that:
403      *
404      *     - should be associated with at most one satisfying network
405      *       at a time;
406      *
407      *     - should cause a network to be kept up and in the foreground if
408      *       it is the best network which can satisfy the NetworkRequest.
409      *
410      * For full detail of how isRequest() is used for pairing Networks with
411      * NetworkRequests read rematchNetworkAndRequests().
412      *
413      * @hide
414      */
isForegroundRequest()415     public boolean isForegroundRequest() {
416         return type == Type.TRACK_DEFAULT || type == Type.REQUEST;
417     }
418 
419     /**
420      * Returns true iff. this NetworkRequest is of type BACKGROUND_REQUEST.
421      *
422      * @hide
423      */
isBackgroundRequest()424     public boolean isBackgroundRequest() {
425         return type == Type.BACKGROUND_REQUEST;
426     }
427 
428     /**
429      * @see Builder#addCapability(int)
430      */
hasCapability(@etCapability int capability)431     public boolean hasCapability(@NetCapability int capability) {
432         return networkCapabilities.hasCapability(capability);
433     }
434 
435     /**
436      * @see Builder#addUnwantedCapability(int)
437      *
438      * @hide
439      */
hasUnwantedCapability(@etCapability int capability)440     public boolean hasUnwantedCapability(@NetCapability int capability) {
441         return networkCapabilities.hasUnwantedCapability(capability);
442     }
443 
444     /**
445      * @see Builder#addTransportType(int)
446      */
hasTransport(@ransport int transportType)447     public boolean hasTransport(@Transport int transportType) {
448         return networkCapabilities.hasTransport(transportType);
449     }
450 
toString()451     public String toString() {
452         return "NetworkRequest [ " + type + " id=" + requestId +
453                 (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
454                 ", " + networkCapabilities.toString() + " ]";
455     }
456 
typeToProtoEnum(Type t)457     private int typeToProtoEnum(Type t) {
458         switch (t) {
459             case NONE:
460                 return NetworkRequestProto.TYPE_NONE;
461             case LISTEN:
462                 return NetworkRequestProto.TYPE_LISTEN;
463             case TRACK_DEFAULT:
464                 return NetworkRequestProto.TYPE_TRACK_DEFAULT;
465             case REQUEST:
466                 return NetworkRequestProto.TYPE_REQUEST;
467             case BACKGROUND_REQUEST:
468                 return NetworkRequestProto.TYPE_BACKGROUND_REQUEST;
469             default:
470                 return NetworkRequestProto.TYPE_UNKNOWN;
471         }
472     }
473 
474     /** @hide */
writeToProto(ProtoOutputStream proto, long fieldId)475     public void writeToProto(ProtoOutputStream proto, long fieldId) {
476         final long token = proto.start(fieldId);
477 
478         proto.write(NetworkRequestProto.TYPE, typeToProtoEnum(type));
479         proto.write(NetworkRequestProto.REQUEST_ID, requestId);
480         proto.write(NetworkRequestProto.LEGACY_TYPE, legacyType);
481         networkCapabilities.writeToProto(proto, NetworkRequestProto.NETWORK_CAPABILITIES);
482 
483         proto.end(token);
484     }
485 
equals(Object obj)486     public boolean equals(Object obj) {
487         if (obj instanceof NetworkRequest == false) return false;
488         NetworkRequest that = (NetworkRequest)obj;
489         return (that.legacyType == this.legacyType &&
490                 that.requestId == this.requestId &&
491                 that.type == this.type &&
492                 Objects.equals(that.networkCapabilities, this.networkCapabilities));
493     }
494 
hashCode()495     public int hashCode() {
496         return Objects.hash(requestId, legacyType, networkCapabilities, type);
497     }
498 }
499