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
22/**
23 * Defines a request for a network, made through {@link NetworkRequest.Builder} and used
24 * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes
25 * via {@link ConnectivityManager#registerNetworkCallback}.
26 */
27public class NetworkRequest implements Parcelable {
28    /**
29     * The {@link NetworkCapabilities} that define this request.
30     * @hide
31     */
32    public final NetworkCapabilities networkCapabilities;
33
34    /**
35     * Identifies the request.  NetworkRequests should only be constructed by
36     * the Framework and given out to applications as tokens to be used to identify
37     * the request.
38     * @hide
39     */
40    public final int requestId;
41
42    /**
43     * Set for legacy requests and the default.  Set to TYPE_NONE for none.
44     * Causes CONNECTIVITY_ACTION broadcasts to be sent.
45     * @hide
46     */
47    public final int legacyType;
48
49    /**
50     * @hide
51     */
52    public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) {
53        if (nc == null) {
54            throw new NullPointerException();
55        }
56        requestId = rId;
57        networkCapabilities = nc;
58        this.legacyType = legacyType;
59    }
60
61    /**
62     * @hide
63     */
64    public NetworkRequest(NetworkRequest that) {
65        networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
66        requestId = that.requestId;
67        this.legacyType = that.legacyType;
68    }
69
70    /**
71     * Builder used to create {@link NetworkRequest} objects.  Specify the Network features
72     * needed in terms of {@link NetworkCapabilities} features
73     */
74    public static class Builder {
75        private final NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities();
76
77        /**
78         * Default constructor for Builder.
79         */
80        public Builder() {}
81
82        /**
83         * Build {@link NetworkRequest} give the current set of capabilities.
84         */
85        public NetworkRequest build() {
86            // Make a copy of mNetworkCapabilities so we don't inadvertently remove NOT_RESTRICTED
87            // when later an unrestricted capability could be added to mNetworkCapabilities, in
88            // which case NOT_RESTRICTED should be returned to mNetworkCapabilities, which
89            // maybeMarkCapabilitiesRestricted() doesn't add back.
90            final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities);
91            nc.maybeMarkCapabilitiesRestricted();
92            return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE,
93                    ConnectivityManager.REQUEST_ID_UNSET);
94        }
95
96        /**
97         * Add the given capability requirement to this builder.  These represent
98         * the requested network's required capabilities.  Note that when searching
99         * for a network to satisfy a request, all capabilities requested must be
100         * satisfied.  See {@link NetworkCapabilities} for {@code NET_CAPABILITIY_*}
101         * definitions.
102         *
103         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to add.
104         * @return The builder to facilitate chaining
105         *         {@code builder.addCapability(...).addCapability();}.
106         */
107        public Builder addCapability(int capability) {
108            mNetworkCapabilities.addCapability(capability);
109            return this;
110        }
111
112        /**
113         * Removes (if found) the given capability from this builder instance.
114         *
115         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to remove.
116         * @return The builder to facilitate chaining.
117         */
118        public Builder removeCapability(int capability) {
119            mNetworkCapabilities.removeCapability(capability);
120            return this;
121        }
122
123        /**
124         * Completely clears all the {@code NetworkCapabilities} from this builder instance,
125         * removing even the capabilities that are set by default when the object is constructed.
126         *
127         * @return The builder to facilitate chaining.
128         * @hide
129         */
130        public Builder clearCapabilities() {
131            mNetworkCapabilities.clearAll();
132            return this;
133        }
134
135        /**
136         * Adds the given transport requirement to this builder.  These represent
137         * the set of allowed transports for the request.  Only networks using one
138         * of these transports will satisfy the request.  If no particular transports
139         * are required, none should be specified here.  See {@link NetworkCapabilities}
140         * for {@code TRANSPORT_*} definitions.
141         *
142         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to add.
143         * @return The builder to facilitate chaining.
144         */
145        public Builder addTransportType(int transportType) {
146            mNetworkCapabilities.addTransportType(transportType);
147            return this;
148        }
149
150        /**
151         * Removes (if found) the given transport from this builder instance.
152         *
153         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to remove.
154         * @return The builder to facilitate chaining.
155         */
156        public Builder removeTransportType(int transportType) {
157            mNetworkCapabilities.removeTransportType(transportType);
158            return this;
159        }
160
161        /**
162         * @hide
163         */
164        public Builder setLinkUpstreamBandwidthKbps(int upKbps) {
165            mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps);
166            return this;
167        }
168        /**
169         * @hide
170         */
171        public Builder setLinkDownstreamBandwidthKbps(int downKbps) {
172            mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps);
173            return this;
174        }
175
176        /**
177         * Sets the optional bearer specific network specifier.
178         * This has no meaning if a single transport is also not specified, so calling
179         * this without a single transport set will generate an exception, as will
180         * subsequently adding or removing transports after this is set.
181         * </p>
182         * The interpretation of this {@code String} is bearer specific and bearers that use
183         * it should document their particulars.  For example, Bluetooth may use some sort of
184         * device id while WiFi could used ssid and/or bssid.  Cellular may use carrier spn.
185         *
186         * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
187         *                         specific network specifier where the bearer has a choice of
188         *                         networks.
189         */
190        public Builder setNetworkSpecifier(String networkSpecifier) {
191            mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
192            return this;
193        }
194    }
195
196    // implement the Parcelable interface
197    public int describeContents() {
198        return 0;
199    }
200    public void writeToParcel(Parcel dest, int flags) {
201        dest.writeParcelable(networkCapabilities, flags);
202        dest.writeInt(legacyType);
203        dest.writeInt(requestId);
204    }
205    public static final Creator<NetworkRequest> CREATOR =
206        new Creator<NetworkRequest>() {
207            public NetworkRequest createFromParcel(Parcel in) {
208                NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null);
209                int legacyType = in.readInt();
210                int requestId = in.readInt();
211                NetworkRequest result = new NetworkRequest(nc, legacyType, requestId);
212                return result;
213            }
214            public NetworkRequest[] newArray(int size) {
215                return new NetworkRequest[size];
216            }
217        };
218
219    public String toString() {
220        return "NetworkRequest [ id=" + requestId + ", legacyType=" + legacyType +
221                ", " + networkCapabilities.toString() + " ]";
222    }
223
224    public boolean equals(Object obj) {
225        if (obj instanceof NetworkRequest == false) return false;
226        NetworkRequest that = (NetworkRequest)obj;
227        return (that.legacyType == this.legacyType &&
228                that.requestId == this.requestId &&
229                ((that.networkCapabilities == null && this.networkCapabilities == null) ||
230                 (that.networkCapabilities != null &&
231                  that.networkCapabilities.equals(this.networkCapabilities))));
232    }
233
234    public int hashCode() {
235        return requestId + (legacyType * 1013) +
236                (networkCapabilities.hashCode() * 1051);
237    }
238}
239