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.os.Parcel;
20import android.os.Parcelable;
21
22import java.util.Objects;
23
24/**
25 * Defines a request for a network, made through {@link NetworkRequest.Builder} and used
26 * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes
27 * via {@link ConnectivityManager#registerNetworkCallback}.
28 */
29public class NetworkRequest implements Parcelable {
30    /**
31     * The {@link NetworkCapabilities} that define this request.
32     * @hide
33     */
34    public final NetworkCapabilities networkCapabilities;
35
36    /**
37     * Identifies the request.  NetworkRequests should only be constructed by
38     * the Framework and given out to applications as tokens to be used to identify
39     * the request.
40     * @hide
41     */
42    public final int requestId;
43
44    /**
45     * Set for legacy requests and the default.  Set to TYPE_NONE for none.
46     * Causes CONNECTIVITY_ACTION broadcasts to be sent.
47     * @hide
48     */
49    public final int legacyType;
50
51    /**
52     * A NetworkRequest as used by the system can be one of the following types:
53     *
54     *     - LISTEN, for which the framework will issue callbacks about any
55     *       and all networks that match the specified NetworkCapabilities,
56     *
57     *     - REQUEST, capable of causing a specific network to be created
58     *       first (e.g. a telephony DUN request), the framework will issue
59     *       callbacks about the single, highest scoring current network
60     *       (if any) that matches the specified NetworkCapabilities, or
61     *
62     *     - TRACK_DEFAULT, a hybrid of the two designed such that the
63     *       framework will issue callbacks for the single, highest scoring
64     *       current network (if any) that matches the capabilities of the
65     *       default Internet request (mDefaultRequest), but which cannot cause
66     *       the framework to either create or retain the existence of any
67     *       specific network. Note that from the point of view of the request
68     *       matching code, TRACK_DEFAULT is identical to REQUEST: its special
69     *       behaviour is not due to different semantics, but to the fact that
70     *       the system will only ever create a TRACK_DEFAULT with capabilities
71     *       that are identical to the default request's capabilities, thus
72     *       causing it to share fate in every way with the default request.
73     *
74     *     - BACKGROUND_REQUEST, like REQUEST but does not cause any networks
75     *       to retain the NET_CAPABILITY_FOREGROUND capability. A network with
76     *       no foreground requests is in the background. A network that has
77     *       one or more background requests and loses its last foreground
78     *       request to a higher-scoring network will not go into the
79     *       background immediately, but will linger and go into the background
80     *       after the linger timeout.
81     *
82     *     - The value NONE is used only by applications. When an application
83     *       creates a NetworkRequest, it does not have a type; the type is set
84     *       by the system depending on the method used to file the request
85     *       (requestNetwork, registerNetworkCallback, etc.).
86     *
87     * @hide
88     */
89    public static enum Type {
90        NONE,
91        LISTEN,
92        TRACK_DEFAULT,
93        REQUEST,
94        BACKGROUND_REQUEST,
95    };
96
97    /**
98     * The type of the request. This is only used by the system and is always NONE elsewhere.
99     *
100     * @hide
101     */
102    public final Type type;
103
104    /**
105     * @hide
106     */
107    public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type) {
108        if (nc == null) {
109            throw new NullPointerException();
110        }
111        requestId = rId;
112        networkCapabilities = nc;
113        this.legacyType = legacyType;
114        this.type = type;
115    }
116
117    /**
118     * @hide
119     */
120    public NetworkRequest(NetworkRequest that) {
121        networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
122        requestId = that.requestId;
123        this.legacyType = that.legacyType;
124        this.type = that.type;
125    }
126
127    /**
128     * Builder used to create {@link NetworkRequest} objects.  Specify the Network features
129     * needed in terms of {@link NetworkCapabilities} features
130     */
131    public static class Builder {
132        private final NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities();
133
134        /**
135         * Default constructor for Builder.
136         */
137        public Builder() {}
138
139        /**
140         * Build {@link NetworkRequest} give the current set of capabilities.
141         */
142        public NetworkRequest build() {
143            // Make a copy of mNetworkCapabilities so we don't inadvertently remove NOT_RESTRICTED
144            // when later an unrestricted capability could be added to mNetworkCapabilities, in
145            // which case NOT_RESTRICTED should be returned to mNetworkCapabilities, which
146            // maybeMarkCapabilitiesRestricted() doesn't add back.
147            final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities);
148            nc.maybeMarkCapabilitiesRestricted();
149            return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE,
150                    ConnectivityManager.REQUEST_ID_UNSET, Type.NONE);
151        }
152
153        /**
154         * Add the given capability requirement to this builder.  These represent
155         * the requested network's required capabilities.  Note that when searching
156         * for a network to satisfy a request, all capabilities requested must be
157         * satisfied.  See {@link NetworkCapabilities} for {@code NET_CAPABILITY_*}
158         * definitions.
159         *
160         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to add.
161         * @return The builder to facilitate chaining
162         *         {@code builder.addCapability(...).addCapability();}.
163         */
164        public Builder addCapability(int capability) {
165            mNetworkCapabilities.addCapability(capability);
166            return this;
167        }
168
169        /**
170         * Removes (if found) the given capability from this builder instance.
171         *
172         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to remove.
173         * @return The builder to facilitate chaining.
174         */
175        public Builder removeCapability(int capability) {
176            mNetworkCapabilities.removeCapability(capability);
177            return this;
178        }
179
180        /**
181         * Completely clears all the {@code NetworkCapabilities} from this builder instance,
182         * removing even the capabilities that are set by default when the object is constructed.
183         *
184         * @return The builder to facilitate chaining.
185         * @hide
186         */
187        public Builder clearCapabilities() {
188            mNetworkCapabilities.clearAll();
189            return this;
190        }
191
192        /**
193         * Adds the given transport requirement to this builder.  These represent
194         * the set of allowed transports for the request.  Only networks using one
195         * of these transports will satisfy the request.  If no particular transports
196         * are required, none should be specified here.  See {@link NetworkCapabilities}
197         * for {@code TRANSPORT_*} definitions.
198         *
199         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to add.
200         * @return The builder to facilitate chaining.
201         */
202        public Builder addTransportType(int transportType) {
203            mNetworkCapabilities.addTransportType(transportType);
204            return this;
205        }
206
207        /**
208         * Removes (if found) the given transport from this builder instance.
209         *
210         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to remove.
211         * @return The builder to facilitate chaining.
212         */
213        public Builder removeTransportType(int transportType) {
214            mNetworkCapabilities.removeTransportType(transportType);
215            return this;
216        }
217
218        /**
219         * @hide
220         */
221        public Builder setLinkUpstreamBandwidthKbps(int upKbps) {
222            mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps);
223            return this;
224        }
225        /**
226         * @hide
227         */
228        public Builder setLinkDownstreamBandwidthKbps(int downKbps) {
229            mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps);
230            return this;
231        }
232
233        /**
234         * Sets the optional bearer specific network specifier.
235         * This has no meaning if a single transport is also not specified, so calling
236         * this without a single transport set will generate an exception, as will
237         * subsequently adding or removing transports after this is set.
238         * </p>
239         * The interpretation of this {@code String} is bearer specific and bearers that use
240         * it should document their particulars.  For example, Bluetooth may use some sort of
241         * device id while WiFi could used ssid and/or bssid.  Cellular may use carrier spn.
242         *
243         * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
244         *                         specific network specifier where the bearer has a choice of
245         *                         networks.
246         */
247        public Builder setNetworkSpecifier(String networkSpecifier) {
248            if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(networkSpecifier)) {
249                throw new IllegalArgumentException("Invalid network specifier - must not be '"
250                        + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
251            }
252            mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
253            return this;
254        }
255
256        /**
257         * Sets the signal strength. This is a signed integer, with higher values indicating a
258         * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same
259         * RSSI units reported by WifiManager.
260         * <p>
261         * Note that when used to register a network callback, this specifies the minimum acceptable
262         * signal strength. When received as the state of an existing network it specifies the
263         * current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when
264         * received and has no effect when requesting a callback.
265         *
266         * @param signalStrength the bearer-specific signal strength.
267         * @hide
268         */
269        public Builder setSignalStrength(int signalStrength) {
270            mNetworkCapabilities.setSignalStrength(signalStrength);
271            return this;
272        }
273    }
274
275    // implement the Parcelable interface
276    public int describeContents() {
277        return 0;
278    }
279    public void writeToParcel(Parcel dest, int flags) {
280        dest.writeParcelable(networkCapabilities, flags);
281        dest.writeInt(legacyType);
282        dest.writeInt(requestId);
283        dest.writeString(type.name());
284    }
285    public static final Creator<NetworkRequest> CREATOR =
286        new Creator<NetworkRequest>() {
287            public NetworkRequest createFromParcel(Parcel in) {
288                NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null);
289                int legacyType = in.readInt();
290                int requestId = in.readInt();
291                Type type = Type.valueOf(in.readString());  // IllegalArgumentException if invalid.
292                NetworkRequest result = new NetworkRequest(nc, legacyType, requestId, type);
293                return result;
294            }
295            public NetworkRequest[] newArray(int size) {
296                return new NetworkRequest[size];
297            }
298        };
299
300    /**
301     * Returns true iff. this NetworkRequest is of type LISTEN.
302     *
303     * @hide
304     */
305    public boolean isListen() {
306        return type == Type.LISTEN;
307    }
308
309    /**
310     * Returns true iff. the contained NetworkRequest is one that:
311     *
312     *     - should be associated with at most one satisfying network
313     *       at a time;
314     *
315     *     - should cause a network to be kept up, but not necessarily in
316     *       the foreground, if it is the best network which can satisfy the
317     *       NetworkRequest.
318     *
319     * For full detail of how isRequest() is used for pairing Networks with
320     * NetworkRequests read rematchNetworkAndRequests().
321     *
322     * @hide
323     */
324    public boolean isRequest() {
325        return isForegroundRequest() || isBackgroundRequest();
326    }
327
328    /**
329     * Returns true iff. the contained NetworkRequest is one that:
330     *
331     *     - should be associated with at most one satisfying network
332     *       at a time;
333     *
334     *     - should cause a network to be kept up and in the foreground if
335     *       it is the best network which can satisfy the NetworkRequest.
336     *
337     * For full detail of how isRequest() is used for pairing Networks with
338     * NetworkRequests read rematchNetworkAndRequests().
339     *
340     * @hide
341     */
342    public boolean isForegroundRequest() {
343        return type == Type.TRACK_DEFAULT || type == Type.REQUEST;
344    }
345
346    /**
347     * Returns true iff. this NetworkRequest is of type BACKGROUND_REQUEST.
348     *
349     * @hide
350     */
351    public boolean isBackgroundRequest() {
352        return type == Type.BACKGROUND_REQUEST;
353    }
354
355    public String toString() {
356        return "NetworkRequest [ " + type + " id=" + requestId +
357                (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
358                ", " + networkCapabilities.toString() + " ]";
359    }
360
361    public boolean equals(Object obj) {
362        if (obj instanceof NetworkRequest == false) return false;
363        NetworkRequest that = (NetworkRequest)obj;
364        return (that.legacyType == this.legacyType &&
365                that.requestId == this.requestId &&
366                that.type == this.type &&
367                Objects.equals(that.networkCapabilities, this.networkCapabilities));
368    }
369
370    public int hashCode() {
371        return Objects.hash(requestId, legacyType, networkCapabilities, type);
372    }
373}
374