NetworkRequest.java revision 67d3dfd9681d8a3307e19a947e110ce60d7e25cb
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
17package android.net;
18
19import android.annotation.NonNull;
20import android.net.NetworkCapabilities.NetCapability;
21import android.net.NetworkCapabilities.Transport;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.os.Process;
25import android.text.TextUtils;
26import android.util.proto.ProtoOutputStream;
27
28import java.util.Objects;
29import 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 */
36public 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     */
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     */
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         */
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         */
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         * <p>
172         * If the given capability was previously added to the list of unwanted capabilities
173         * then the capability will also be removed from the list of unwanted capabilities.
174         *
175         * @see #addUnwantedCapability(int)
176         *
177         * @param capability The capability to add.
178         * @return The builder to facilitate chaining
179         *         {@code builder.addCapability(...).addCapability();}.
180         */
181        public Builder addCapability(@NetworkCapabilities.NetCapability int capability) {
182            mNetworkCapabilities.addCapability(capability);
183            return this;
184        }
185
186        /**
187         * Removes (if found) the given capability from this builder instance from both required
188         * and unwanted capabilities lists.
189         *
190         * @param capability The capability to remove.
191         * @return The builder to facilitate chaining.
192         */
193        public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) {
194            mNetworkCapabilities.removeCapability(capability);
195            return this;
196        }
197
198        /**
199         * Set the {@code NetworkCapabilities} for this builder instance,
200         * overriding any capabilities that had been previously set.
201         *
202         * @param nc The superseding {@code NetworkCapabilities} instance.
203         * @return The builder to facilitate chaining.
204         * @hide
205         */
206        public Builder setCapabilities(NetworkCapabilities nc) {
207            mNetworkCapabilities.clearAll();
208            mNetworkCapabilities.combineCapabilities(nc);
209            return this;
210        }
211
212        /**
213         * Set the watched UIDs for this request. This will be reset and wiped out unless
214         * the calling app holds the CHANGE_NETWORK_STATE permission.
215         *
216         * @param uids The watched UIDs as a set of UidRanges, or null for everything.
217         * @return The builder to facilitate chaining.
218         * @hide
219         */
220        public Builder setUids(Set<UidRange> uids) {
221            mNetworkCapabilities.setUids(uids);
222            return this;
223        }
224
225        /**
226         * Add a capability that must not exist in the requested network.
227         * <p>
228         * If the capability was previously added to the list of required capabilities (for
229         * example, it was there by default or added using {@link #addCapability(int)} method), then
230         * it will be removed from the list of required capabilities as well.
231         *
232         * @see #addCapability(int)
233         *
234         * @param capability The capability to add to unwanted capability list.
235         * @return The builder to facilitate chaining.
236         */
237        public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
238            mNetworkCapabilities.addUnwantedCapability(capability);
239            return this;
240        }
241
242        /**
243         * Completely clears all the {@code NetworkCapabilities} from this builder instance,
244         * removing even the capabilities that are set by default when the object is constructed.
245         *
246         * @return The builder to facilitate chaining.
247         * @hide
248         */
249        public Builder clearCapabilities() {
250            mNetworkCapabilities.clearAll();
251            return this;
252        }
253
254        /**
255         * Adds the given transport requirement to this builder.  These represent
256         * the set of allowed transports for the request.  Only networks using one
257         * of these transports will satisfy the request.  If no particular transports
258         * are required, none should be specified here.
259         *
260         * @param transportType The transport type to add.
261         * @return The builder to facilitate chaining.
262         */
263        public Builder addTransportType(@NetworkCapabilities.Transport int transportType) {
264            mNetworkCapabilities.addTransportType(transportType);
265            return this;
266        }
267
268        /**
269         * Removes (if found) the given transport from this builder instance.
270         *
271         * @param transportType The transport type to remove.
272         * @return The builder to facilitate chaining.
273         */
274        public Builder removeTransportType(@NetworkCapabilities.Transport int transportType) {
275            mNetworkCapabilities.removeTransportType(transportType);
276            return this;
277        }
278
279        /**
280         * @hide
281         */
282        public Builder setLinkUpstreamBandwidthKbps(int upKbps) {
283            mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps);
284            return this;
285        }
286        /**
287         * @hide
288         */
289        public Builder setLinkDownstreamBandwidthKbps(int downKbps) {
290            mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps);
291            return this;
292        }
293
294        /**
295         * Sets the optional bearer specific network specifier.
296         * This has no meaning if a single transport is also not specified, so calling
297         * this without a single transport set will generate an exception, as will
298         * subsequently adding or removing transports after this is set.
299         * </p>
300         * The interpretation of this {@code String} is bearer specific and bearers that use
301         * it should document their particulars.  For example, Bluetooth may use some sort of
302         * device id while WiFi could used ssid and/or bssid.  Cellular may use carrier spn.
303         *
304         * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
305         *                         specific network specifier where the bearer has a choice of
306         *                         networks.
307         */
308        public Builder setNetworkSpecifier(String networkSpecifier) {
309            /*
310             * A StringNetworkSpecifier does not accept null or empty ("") strings. When network
311             * specifiers were strings a null string and an empty string were considered equivalent.
312             * Hence no meaning is attached to a null or empty ("") string.
313             */
314            return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
315                    : new StringNetworkSpecifier(networkSpecifier));
316        }
317
318        /**
319         * Sets the optional bearer specific network specifier.
320         * This has no meaning if a single transport is also not specified, so calling
321         * this without a single transport set will generate an exception, as will
322         * subsequently adding or removing transports after this is set.
323         * </p>
324         *
325         * @param networkSpecifier A concrete, parcelable framework class that extends
326         *                         NetworkSpecifier.
327         */
328        public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
329            MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(networkSpecifier);
330            mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
331            return this;
332        }
333
334        /**
335         * Sets the signal strength. This is a signed integer, with higher values indicating a
336         * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same
337         * RSSI units reported by WifiManager.
338         * <p>
339         * Note that when used to register a network callback, this specifies the minimum acceptable
340         * signal strength. When received as the state of an existing network it specifies the
341         * current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when
342         * received and has no effect when requesting a callback.
343         *
344         * @param signalStrength the bearer-specific signal strength.
345         * @hide
346         */
347        public Builder setSignalStrength(int signalStrength) {
348            mNetworkCapabilities.setSignalStrength(signalStrength);
349            return this;
350        }
351    }
352
353    // implement the Parcelable interface
354    public int describeContents() {
355        return 0;
356    }
357    public void writeToParcel(Parcel dest, int flags) {
358        networkCapabilities.writeToParcel(dest, flags);
359        dest.writeInt(legacyType);
360        dest.writeInt(requestId);
361        dest.writeString(type.name());
362    }
363    public static final Creator<NetworkRequest> CREATOR =
364        new Creator<NetworkRequest>() {
365            public NetworkRequest createFromParcel(Parcel in) {
366                NetworkCapabilities nc = NetworkCapabilities.CREATOR.createFromParcel(in);
367                int legacyType = in.readInt();
368                int requestId = in.readInt();
369                Type type = Type.valueOf(in.readString());  // IllegalArgumentException if invalid.
370                NetworkRequest result = new NetworkRequest(nc, legacyType, requestId, type);
371                return result;
372            }
373            public NetworkRequest[] newArray(int size) {
374                return new NetworkRequest[size];
375            }
376        };
377
378    /**
379     * Returns true iff. this NetworkRequest is of type LISTEN.
380     *
381     * @hide
382     */
383    public boolean isListen() {
384        return type == Type.LISTEN;
385    }
386
387    /**
388     * Returns true iff. the contained NetworkRequest is one that:
389     *
390     *     - should be associated with at most one satisfying network
391     *       at a time;
392     *
393     *     - should cause a network to be kept up, but not necessarily in
394     *       the foreground, if it is the best network which can satisfy the
395     *       NetworkRequest.
396     *
397     * For full detail of how isRequest() is used for pairing Networks with
398     * NetworkRequests read rematchNetworkAndRequests().
399     *
400     * @hide
401     */
402    public boolean isRequest() {
403        return isForegroundRequest() || isBackgroundRequest();
404    }
405
406    /**
407     * Returns true iff. the contained NetworkRequest is one that:
408     *
409     *     - should be associated with at most one satisfying network
410     *       at a time;
411     *
412     *     - should cause a network to be kept up and in the foreground if
413     *       it is the best network which can satisfy the NetworkRequest.
414     *
415     * For full detail of how isRequest() is used for pairing Networks with
416     * NetworkRequests read rematchNetworkAndRequests().
417     *
418     * @hide
419     */
420    public boolean isForegroundRequest() {
421        return type == Type.TRACK_DEFAULT || type == Type.REQUEST;
422    }
423
424    /**
425     * Returns true iff. this NetworkRequest is of type BACKGROUND_REQUEST.
426     *
427     * @hide
428     */
429    public boolean isBackgroundRequest() {
430        return type == Type.BACKGROUND_REQUEST;
431    }
432
433    /**
434     * @see Builder#addCapability(int)
435     */
436    public boolean hasCapability(@NetCapability int capability) {
437        return networkCapabilities.hasCapability(capability);
438    }
439
440    /**
441     * @see Builder#addUnwantedCapability(int)
442     */
443    public boolean hasUnwantedCapability(@NetCapability int capability) {
444        return networkCapabilities.hasUnwantedCapability(capability);
445    }
446
447    /**
448     * @see Builder#addTransportType(int)
449     */
450    public boolean hasTransport(@Transport int transportType) {
451        return networkCapabilities.hasTransport(transportType);
452    }
453
454    public String toString() {
455        return "NetworkRequest [ " + type + " id=" + requestId +
456                (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
457                ", " + networkCapabilities.toString() + " ]";
458    }
459
460    private int typeToProtoEnum(Type t) {
461        switch (t) {
462            case NONE:
463                return NetworkRequestProto.TYPE_NONE;
464            case LISTEN:
465                return NetworkRequestProto.TYPE_LISTEN;
466            case TRACK_DEFAULT:
467                return NetworkRequestProto.TYPE_TRACK_DEFAULT;
468            case REQUEST:
469                return NetworkRequestProto.TYPE_REQUEST;
470            case BACKGROUND_REQUEST:
471                return NetworkRequestProto.TYPE_BACKGROUND_REQUEST;
472            default:
473                return NetworkRequestProto.TYPE_UNKNOWN;
474        }
475    }
476
477    /** @hide */
478    public void writeToProto(ProtoOutputStream proto, long fieldId) {
479        final long token = proto.start(fieldId);
480
481        proto.write(NetworkRequestProto.TYPE, typeToProtoEnum(type));
482        proto.write(NetworkRequestProto.REQUEST_ID, requestId);
483        proto.write(NetworkRequestProto.LEGACY_TYPE, legacyType);
484        networkCapabilities.writeToProto(proto, NetworkRequestProto.NETWORK_CAPABILITIES);
485
486        proto.end(token);
487    }
488
489    public boolean equals(Object obj) {
490        if (obj instanceof NetworkRequest == false) return false;
491        NetworkRequest that = (NetworkRequest)obj;
492        return (that.legacyType == this.legacyType &&
493                that.requestId == this.requestId &&
494                that.type == this.type &&
495                Objects.equals(that.networkCapabilities, this.networkCapabilities));
496    }
497
498    public int hashCode() {
499        return Objects.hash(requestId, legacyType, networkCapabilities, type);
500    }
501}
502