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.concurrent.atomic.AtomicInteger;
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     * @hide
53     */
54    public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) {
55        if (nc == null) {
56            throw new NullPointerException();
57        }
58        requestId = rId;
59        networkCapabilities = nc;
60        this.legacyType = legacyType;
61    }
62
63    /**
64     * @hide
65     */
66    public NetworkRequest(NetworkRequest that) {
67        networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
68        requestId = that.requestId;
69        this.legacyType = that.legacyType;
70    }
71
72    /**
73     * Builder used to create {@link NetworkRequest} objects.  Specify the Network features
74     * needed in terms of {@link NetworkCapabilities} features
75     */
76    public static class Builder {
77        private final NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities();
78
79        /**
80         * Default constructor for Builder.
81         */
82        public Builder() {}
83
84        /**
85         * Build {@link NetworkRequest} give the current set of capabilities.
86         */
87        public NetworkRequest build() {
88            return new NetworkRequest(mNetworkCapabilities, ConnectivityManager.TYPE_NONE,
89                    ConnectivityManager.REQUEST_ID_UNSET);
90        }
91
92        /**
93         * Add the given capability requirement to this builder.  These represent
94         * the requested network's required capabilities.  Note that when searching
95         * for a network to satisfy a request, all capabilities requested must be
96         * satisfied.  See {@link NetworkCapabilities} for {@code NET_CAPABILITIY_*}
97         * definitions.
98         *
99         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to add.
100         * @return The builder to facilitate chaining
101         *         {@code builder.addCapability(...).addCapability();}.
102         */
103        public Builder addCapability(int capability) {
104            mNetworkCapabilities.addCapability(capability);
105            return this;
106        }
107
108        /**
109         * Removes (if found) the given capability from this builder instance.
110         *
111         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to remove.
112         * @return The builder to facilitate chaining.
113         */
114        public Builder removeCapability(int capability) {
115            mNetworkCapabilities.removeCapability(capability);
116            return this;
117        }
118
119        /**
120         * Adds the given transport requirement to this builder.  These represent
121         * the set of allowed transports for the request.  Only networks using one
122         * of these transports will satisfy the request.  If no particular transports
123         * are required, none should be specified here.  See {@link NetworkCapabilities}
124         * for {@code TRANSPORT_*} definitions.
125         *
126         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to add.
127         * @return The builder to facilitate chaining.
128         */
129        public Builder addTransportType(int transportType) {
130            mNetworkCapabilities.addTransportType(transportType);
131            return this;
132        }
133
134        /**
135         * Removes (if found) the given transport from this builder instance.
136         *
137         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to remove.
138         * @return The builder to facilitate chaining.
139         */
140        public Builder removeTransportType(int transportType) {
141            mNetworkCapabilities.removeTransportType(transportType);
142            return this;
143        }
144
145        /**
146         * @hide
147         */
148        public Builder setLinkUpstreamBandwidthKbps(int upKbps) {
149            mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps);
150            return this;
151        }
152        /**
153         * @hide
154         */
155        public Builder setLinkDownstreamBandwidthKbps(int downKbps) {
156            mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps);
157            return this;
158        }
159
160        /**
161         * Sets the optional bearer specific network specifier.
162         * This has no meaning if a single transport is also not specified, so calling
163         * this without a single transport set will generate an exception, as will
164         * subsequently adding or removing transports after this is set.
165         * </p>
166         * The interpretation of this {@code String} is bearer specific and bearers that use
167         * it should document their particulars.  For example, Bluetooth may use some sort of
168         * device id while WiFi could used ssid and/or bssid.  Cellular may use carrier spn.
169         *
170         * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
171         *                         specific network specifier where the bearer has a choice of
172         *                         networks.
173         */
174        public Builder setNetworkSpecifier(String networkSpecifier) {
175            mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
176            return this;
177        }
178    }
179
180    // implement the Parcelable interface
181    public int describeContents() {
182        return 0;
183    }
184    public void writeToParcel(Parcel dest, int flags) {
185        dest.writeParcelable(networkCapabilities, flags);
186        dest.writeInt(legacyType);
187        dest.writeInt(requestId);
188    }
189    public static final Creator<NetworkRequest> CREATOR =
190        new Creator<NetworkRequest>() {
191            public NetworkRequest createFromParcel(Parcel in) {
192                NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null);
193                int legacyType = in.readInt();
194                int requestId = in.readInt();
195                NetworkRequest result = new NetworkRequest(nc, legacyType, requestId);
196                return result;
197            }
198            public NetworkRequest[] newArray(int size) {
199                return new NetworkRequest[size];
200            }
201        };
202
203    public String toString() {
204        return "NetworkRequest [ id=" + requestId + ", legacyType=" + legacyType +
205                ", " + networkCapabilities.toString() + " ]";
206    }
207
208    public boolean equals(Object obj) {
209        if (obj instanceof NetworkRequest == false) return false;
210        NetworkRequest that = (NetworkRequest)obj;
211        return (that.legacyType == this.legacyType &&
212                that.requestId == this.requestId &&
213                ((that.networkCapabilities == null && this.networkCapabilities == null) ||
214                 (that.networkCapabilities != null &&
215                  that.networkCapabilities.equals(this.networkCapabilities))));
216    }
217
218    public int hashCode() {
219        return requestId + (legacyType * 1013) +
220                (networkCapabilities.hashCode() * 1051);
221    }
222}
223