blob: db12dd9724dc409d6abe2704503cc19ecfe551fd [file] [log] [blame]
Robert Greenwalt1448f052014-04-08 13:41:39 -07001/*
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
Jeff Sharkeyde570312017-10-24 21:25:50 -060019import android.annotation.IntDef;
Robert Greenwalt1448f052014-04-08 13:41:39 -070020import android.os.Parcel;
21import android.os.Parcelable;
Robert Greenwalta7e148a2017-04-10 14:32:23 -070022
23import com.android.internal.annotations.VisibleForTesting;
Hugo Benichi9910dbc2017-03-22 18:29:58 +090024import com.android.internal.util.BitUtils;
Hugo Benichi16f0a942017-06-20 14:07:59 +090025import com.android.internal.util.Preconditions;
Etan Cohena7434272017-04-03 12:17:51 -070026
Jeff Sharkeyde570312017-10-24 21:25:50 -060027import java.lang.annotation.Retention;
28import java.lang.annotation.RetentionPolicy;
Etan Cohena7434272017-04-03 12:17:51 -070029import java.util.Objects;
Hugo Benichieae7a222017-07-25 11:40:56 +090030import java.util.StringJoiner;
Robert Greenwalt1448f052014-04-08 13:41:39 -070031
32/**
Robert Greenwalt01d004e2014-05-18 15:24:21 -070033 * This class represents the capabilities of a network. This is used both to specify
34 * needs to {@link ConnectivityManager} and when inspecting a network.
35 *
36 * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method
37 * of network selection. Rather than indicate a need for Wi-Fi because an application
Wink Saville4e2dea72014-09-20 11:04:03 -070038 * needs high bandwidth and risk obsolescence when a new, fast network appears (like LTE),
Robert Greenwalt01d004e2014-05-18 15:24:21 -070039 * the application should specify it needs high bandwidth. Similarly if an application
40 * needs an unmetered network for a bulk transfer it can specify that rather than assuming
41 * all cellular based connections are metered and all Wi-Fi based connections are not.
Robert Greenwalt1448f052014-04-08 13:41:39 -070042 */
43public final class NetworkCapabilities implements Parcelable {
Etan Cohena7434272017-04-03 12:17:51 -070044 private static final String TAG = "NetworkCapabilities";
45
Robert Greenwalt7569f182014-06-08 16:42:59 -070046 /**
47 * @hide
48 */
Robert Greenwalt01d004e2014-05-18 15:24:21 -070049 public NetworkCapabilities() {
Lorenzo Colittif7058f52015-04-27 11:31:55 +090050 clearAll();
Lorenzo Colitti260a36d2015-07-08 12:49:04 +090051 mNetworkCapabilities = DEFAULT_CAPABILITIES;
Robert Greenwalt01d004e2014-05-18 15:24:21 -070052 }
53
54 public NetworkCapabilities(NetworkCapabilities nc) {
55 if (nc != null) {
56 mNetworkCapabilities = nc.mNetworkCapabilities;
57 mTransportTypes = nc.mTransportTypes;
58 mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
59 mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
Robert Greenwalt94badcc2014-07-10 14:53:24 -070060 mNetworkSpecifier = nc.mNetworkSpecifier;
Lorenzo Colittic3f21f32015-07-06 23:50:27 +090061 mSignalStrength = nc.mSignalStrength;
Robert Greenwalt01d004e2014-05-18 15:24:21 -070062 }
63 }
Robert Greenwalt1448f052014-04-08 13:41:39 -070064
65 /**
Lorenzo Colittif7058f52015-04-27 11:31:55 +090066 * Completely clears the contents of this object, removing even the capabilities that are set
67 * by default when the object is constructed.
68 * @hide
69 */
70 public void clearAll() {
71 mNetworkCapabilities = mTransportTypes = 0;
72 mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0;
73 mNetworkSpecifier = null;
Lorenzo Colittic3f21f32015-07-06 23:50:27 +090074 mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
Lorenzo Colittif7058f52015-04-27 11:31:55 +090075 }
76
77 /**
Robert Greenwalt1448f052014-04-08 13:41:39 -070078 * Represents the network's capabilities. If any are specified they will be satisfied
79 * by any Network that matches all of them.
80 */
Lorenzo Colittif7058f52015-04-27 11:31:55 +090081 private long mNetworkCapabilities;
Robert Greenwalt1448f052014-04-08 13:41:39 -070082
Jeff Sharkeyde570312017-10-24 21:25:50 -060083 /** @hide */
84 @Retention(RetentionPolicy.SOURCE)
85 @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
86 NET_CAPABILITY_MMS,
87 NET_CAPABILITY_SUPL,
88 NET_CAPABILITY_DUN,
89 NET_CAPABILITY_FOTA,
90 NET_CAPABILITY_IMS,
91 NET_CAPABILITY_CBS,
92 NET_CAPABILITY_WIFI_P2P,
93 NET_CAPABILITY_IA,
94 NET_CAPABILITY_RCS,
95 NET_CAPABILITY_XCAP,
96 NET_CAPABILITY_EIMS,
97 NET_CAPABILITY_NOT_METERED,
98 NET_CAPABILITY_INTERNET,
99 NET_CAPABILITY_NOT_RESTRICTED,
100 NET_CAPABILITY_TRUSTED,
101 NET_CAPABILITY_NOT_VPN,
102 NET_CAPABILITY_VALIDATED,
103 NET_CAPABILITY_CAPTIVE_PORTAL,
104 NET_CAPABILITY_FOREGROUND,
105 })
106 public @interface NetCapability { }
107
Robert Greenwalt1448f052014-04-08 13:41:39 -0700108 /**
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700109 * Indicates this is a network that has the ability to reach the
110 * carrier's MMSC for sending and receiving MMS messages.
Robert Greenwalt1448f052014-04-08 13:41:39 -0700111 */
112 public static final int NET_CAPABILITY_MMS = 0;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700113
114 /**
115 * Indicates this is a network that has the ability to reach the carrier's
116 * SUPL server, used to retrieve GPS information.
117 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700118 public static final int NET_CAPABILITY_SUPL = 1;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700119
120 /**
121 * Indicates this is a network that has the ability to reach the carrier's
122 * DUN or tethering gateway.
123 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700124 public static final int NET_CAPABILITY_DUN = 2;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700125
126 /**
127 * Indicates this is a network that has the ability to reach the carrier's
128 * FOTA portal, used for over the air updates.
129 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700130 public static final int NET_CAPABILITY_FOTA = 3;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700131
132 /**
133 * Indicates this is a network that has the ability to reach the carrier's
134 * IMS servers, used for network registration and signaling.
135 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700136 public static final int NET_CAPABILITY_IMS = 4;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700137
138 /**
139 * Indicates this is a network that has the ability to reach the carrier's
140 * CBS servers, used for carrier specific services.
141 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700142 public static final int NET_CAPABILITY_CBS = 5;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700143
144 /**
145 * Indicates this is a network that has the ability to reach a Wi-Fi direct
146 * peer.
147 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700148 public static final int NET_CAPABILITY_WIFI_P2P = 6;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700149
150 /**
151 * Indicates this is a network that has the ability to reach a carrier's
152 * Initial Attach servers.
153 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700154 public static final int NET_CAPABILITY_IA = 7;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700155
156 /**
157 * Indicates this is a network that has the ability to reach a carrier's
158 * RCS servers, used for Rich Communication Services.
159 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700160 public static final int NET_CAPABILITY_RCS = 8;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700161
162 /**
163 * Indicates this is a network that has the ability to reach a carrier's
164 * XCAP servers, used for configuration and control.
165 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700166 public static final int NET_CAPABILITY_XCAP = 9;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700167
168 /**
169 * Indicates this is a network that has the ability to reach a carrier's
Robert Greenwalt4bd43892015-07-09 14:49:35 -0700170 * Emergency IMS servers or other services, used for network signaling
171 * during emergency calls.
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700172 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700173 public static final int NET_CAPABILITY_EIMS = 10;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700174
175 /**
176 * Indicates that this network is unmetered.
177 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700178 public static final int NET_CAPABILITY_NOT_METERED = 11;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700179
180 /**
181 * Indicates that this network should be able to reach the internet.
182 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700183 public static final int NET_CAPABILITY_INTERNET = 12;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700184
185 /**
186 * Indicates that this network is available for general use. If this is not set
187 * applications should not attempt to communicate on this network. Note that this
188 * is simply informative and not enforcement - enforcement is handled via other means.
189 * Set by default.
190 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700191 public static final int NET_CAPABILITY_NOT_RESTRICTED = 13;
192
Robert Greenwalt16e12ab2014-07-08 15:31:37 -0700193 /**
194 * Indicates that the user has indicated implicit trust of this network. This
195 * generally means it's a sim-selected carrier, a plugged in ethernet, a paired
196 * BT device or a wifi the user asked to connect to. Untrusted networks
197 * are probably limited to unknown wifi AP. Set by default.
198 */
199 public static final int NET_CAPABILITY_TRUSTED = 14;
200
Paul Jensen76b610a2015-03-18 09:33:07 -0400201 /**
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400202 * Indicates that this network is not a VPN. This capability is set by default and should be
Paul Jensen76b610a2015-03-18 09:33:07 -0400203 * explicitly cleared for VPN networks.
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400204 */
205 public static final int NET_CAPABILITY_NOT_VPN = 15;
206
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900207 /**
208 * Indicates that connectivity on this network was successfully validated. For example, for a
209 * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully
210 * detected.
Lorenzo Colitti403aa262014-11-28 11:21:30 +0900211 */
212 public static final int NET_CAPABILITY_VALIDATED = 16;
Robert Greenwalt16e12ab2014-07-08 15:31:37 -0700213
Paul Jensen3d194ea2015-06-16 14:27:36 -0400214 /**
215 * Indicates that this network was found to have a captive portal in place last time it was
216 * probed.
217 */
218 public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17;
219
Lorenzo Colittif0e9a332016-07-18 18:40:42 +0900220 /**
221 * Indicates that this network is available for use by apps, and not a network that is being
222 * kept up in the background to facilitate fast network switching.
223 * @hide
224 */
225 public static final int NET_CAPABILITY_FOREGROUND = 18;
226
Robert Greenwalt1448f052014-04-08 13:41:39 -0700227 private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
Lorenzo Colittif0e9a332016-07-18 18:40:42 +0900228 private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND;
Robert Greenwalt1448f052014-04-08 13:41:39 -0700229
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700230 /**
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900231 * Network capabilities that are expected to be mutable, i.e., can change while a particular
232 * network is connected.
233 */
234 private static final long MUTABLE_CAPABILITIES =
235 // TRUSTED can change when user explicitly connects to an untrusted network in Settings.
236 // http://b/18206275
237 (1 << NET_CAPABILITY_TRUSTED) |
238 (1 << NET_CAPABILITY_VALIDATED) |
Lorenzo Colittif0e9a332016-07-18 18:40:42 +0900239 (1 << NET_CAPABILITY_CAPTIVE_PORTAL) |
240 (1 << NET_CAPABILITY_FOREGROUND);
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900241
242 /**
243 * Network capabilities that are not allowed in NetworkRequests. This exists because the
244 * NetworkFactory / NetworkAgent model does not deal well with the situation where a
245 * capability's presence cannot be known in advance. If such a capability is requested, then we
246 * can get into a cycle where the NetworkFactory endlessly churns out NetworkAgents that then
247 * get immediately torn down because they do not have the requested capability.
248 */
249 private static final long NON_REQUESTABLE_CAPABILITIES =
Lorenzo Colittif0e9a332016-07-18 18:40:42 +0900250 MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_TRUSTED);
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900251
252 /**
253 * Capabilities that are set by default when the object is constructed.
254 */
255 private static final long DEFAULT_CAPABILITIES =
256 (1 << NET_CAPABILITY_NOT_RESTRICTED) |
257 (1 << NET_CAPABILITY_TRUSTED) |
258 (1 << NET_CAPABILITY_NOT_VPN);
259
260 /**
Paul Jensen487ffe72015-07-24 15:57:11 -0400261 * Capabilities that suggest that a network is restricted.
262 * {@see #maybeMarkCapabilitiesRestricted}.
263 */
Robert Greenwalta7e148a2017-04-10 14:32:23 -0700264 @VisibleForTesting
265 /* package */ static final long RESTRICTED_CAPABILITIES =
Paul Jensen487ffe72015-07-24 15:57:11 -0400266 (1 << NET_CAPABILITY_CBS) |
267 (1 << NET_CAPABILITY_DUN) |
268 (1 << NET_CAPABILITY_EIMS) |
269 (1 << NET_CAPABILITY_FOTA) |
270 (1 << NET_CAPABILITY_IA) |
271 (1 << NET_CAPABILITY_IMS) |
272 (1 << NET_CAPABILITY_RCS) |
273 (1 << NET_CAPABILITY_XCAP);
274
275 /**
Robert Greenwalta7e148a2017-04-10 14:32:23 -0700276 * Capabilities that suggest that a network is unrestricted.
277 * {@see #maybeMarkCapabilitiesRestricted}.
278 */
279 @VisibleForTesting
280 /* package */ static final long UNRESTRICTED_CAPABILITIES =
281 (1 << NET_CAPABILITY_INTERNET) |
282 (1 << NET_CAPABILITY_MMS) |
283 (1 << NET_CAPABILITY_SUPL) |
284 (1 << NET_CAPABILITY_WIFI_P2P);
285
286 /**
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700287 * Adds the given capability to this {@code NetworkCapability} instance.
288 * Multiple capabilities may be applied sequentially. Note that when searching
289 * for a network to satisfy a request, all capabilities requested must be satisfied.
290 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600291 * @param capability the capability to be added.
Pierre Imaic8419a82016-03-22 17:54:54 +0900292 * @return This NetworkCapabilities instance, to facilitate chaining.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700293 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700294 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600295 public NetworkCapabilities addCapability(@NetCapability int capability) {
Robert Greenwalt7569f182014-06-08 16:42:59 -0700296 if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
Robert Greenwalt1448f052014-04-08 13:41:39 -0700297 throw new IllegalArgumentException("NetworkCapability out of range");
298 }
Robert Greenwalt7569f182014-06-08 16:42:59 -0700299 mNetworkCapabilities |= 1 << capability;
300 return this;
Robert Greenwalt1448f052014-04-08 13:41:39 -0700301 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700302
303 /**
304 * Removes (if found) the given capability from this {@code NetworkCapability} instance.
305 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600306 * @param capability the capability to be removed.
Pierre Imaic8419a82016-03-22 17:54:54 +0900307 * @return This NetworkCapabilities instance, to facilitate chaining.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700308 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700309 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600310 public NetworkCapabilities removeCapability(@NetCapability int capability) {
Robert Greenwalt7569f182014-06-08 16:42:59 -0700311 if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
Robert Greenwalt1448f052014-04-08 13:41:39 -0700312 throw new IllegalArgumentException("NetworkCapability out of range");
313 }
Robert Greenwalt7569f182014-06-08 16:42:59 -0700314 mNetworkCapabilities &= ~(1 << capability);
315 return this;
Robert Greenwalt1448f052014-04-08 13:41:39 -0700316 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700317
318 /**
319 * Gets all the capabilities set on this {@code NetworkCapability} instance.
320 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600321 * @return an array of capability values for this instance.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700322 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700323 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600324 public @NetCapability int[] getCapabilities() {
Hugo Benichi9910dbc2017-03-22 18:29:58 +0900325 return BitUtils.unpackBits(mNetworkCapabilities);
Robert Greenwalt1448f052014-04-08 13:41:39 -0700326 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700327
328 /**
329 * Tests for the presence of a capabilitity on this instance.
330 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600331 * @param capability the capabilities to be tested for.
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700332 * @return {@code true} if set on this instance.
333 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600334 public boolean hasCapability(@NetCapability int capability) {
Robert Greenwalt7569f182014-06-08 16:42:59 -0700335 if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
Robert Greenwalt5c55e332014-05-08 00:02:04 -0700336 return false;
337 }
Robert Greenwalt7569f182014-06-08 16:42:59 -0700338 return ((mNetworkCapabilities & (1 << capability)) != 0);
Robert Greenwalt5c55e332014-05-08 00:02:04 -0700339 }
Robert Greenwalt1448f052014-04-08 13:41:39 -0700340
Robert Greenwalt1448f052014-04-08 13:41:39 -0700341 private void combineNetCapabilities(NetworkCapabilities nc) {
342 this.mNetworkCapabilities |= nc.mNetworkCapabilities;
343 }
344
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900345 /**
346 * Convenience function that returns a human-readable description of the first mutable
347 * capability we find. Used to present an error message to apps that request mutable
348 * capabilities.
349 *
350 * @hide
351 */
352 public String describeFirstNonRequestableCapability() {
353 if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED";
354 if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL";
Lorenzo Colittif0e9a332016-07-18 18:40:42 +0900355 if (hasCapability(NET_CAPABILITY_FOREGROUND)) return "NET_CAPABILITY_FOREGROUND";
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900356 // This cannot happen unless the preceding checks are incomplete.
357 if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) {
358 return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities);
359 }
360 if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth";
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900361 if (hasSignalStrength()) return "signalStrength";
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900362 return null;
363 }
364
365 private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
366 long networkCapabilities = this.mNetworkCapabilities;
367 if (onlyImmutable) {
368 networkCapabilities = networkCapabilities & ~MUTABLE_CAPABILITIES;
369 }
370 return ((nc.mNetworkCapabilities & networkCapabilities) == networkCapabilities);
Robert Greenwalt1448f052014-04-08 13:41:39 -0700371 }
372
Robert Greenwalt06314e42014-10-29 14:04:06 -0700373 /** @hide */
374 public boolean equalsNetCapabilities(NetworkCapabilities nc) {
Robert Greenwalt1448f052014-04-08 13:41:39 -0700375 return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
376 }
377
Lorenzo Colittif0e9a332016-07-18 18:40:42 +0900378 private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) {
379 return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
380 (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
381 }
382
Robert Greenwalt1448f052014-04-08 13:41:39 -0700383 /**
Paul Jensen487ffe72015-07-24 15:57:11 -0400384 * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
385 * typically provided by restricted networks.
386 *
387 * TODO: consider:
388 * - Renaming it to guessRestrictedCapability and make it set the
389 * restricted capability bit in addition to clearing it.
390 * @hide
391 */
392 public void maybeMarkCapabilitiesRestricted() {
Robert Greenwalta7e148a2017-04-10 14:32:23 -0700393 // Verify there aren't any unrestricted capabilities. If there are we say
394 // the whole thing is unrestricted.
395 final boolean hasUnrestrictedCapabilities =
396 ((mNetworkCapabilities & UNRESTRICTED_CAPABILITIES) != 0);
397
398 // Must have at least some restricted capabilities.
399 final boolean hasRestrictedCapabilities =
400 ((mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0);
401
402 if (hasRestrictedCapabilities && !hasUnrestrictedCapabilities) {
Paul Jensen487ffe72015-07-24 15:57:11 -0400403 removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
Paul Jensenaae613d2015-08-19 11:06:15 -0400404 }
Paul Jensen487ffe72015-07-24 15:57:11 -0400405 }
406
407 /**
Robert Greenwalt1448f052014-04-08 13:41:39 -0700408 * Representing the transport type. Apps should generally not care about transport. A
409 * request for a fast internet connection could be satisfied by a number of different
410 * transports. If any are specified here it will be satisfied a Network that matches
411 * any of them. If a caller doesn't care about the transport it should not specify any.
412 */
413 private long mTransportTypes;
414
Jeff Sharkeyde570312017-10-24 21:25:50 -0600415 /** @hide */
416 @Retention(RetentionPolicy.SOURCE)
417 @IntDef(prefix = { "TRANSPORT_" }, value = {
418 TRANSPORT_CELLULAR,
419 TRANSPORT_WIFI,
420 TRANSPORT_BLUETOOTH,
421 TRANSPORT_ETHERNET,
422 TRANSPORT_VPN,
423 TRANSPORT_WIFI_AWARE,
424 TRANSPORT_LOWPAN,
425 })
426 public @interface Transport { }
427
Robert Greenwalt1448f052014-04-08 13:41:39 -0700428 /**
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700429 * Indicates this network uses a Cellular transport.
Robert Greenwalt1448f052014-04-08 13:41:39 -0700430 */
431 public static final int TRANSPORT_CELLULAR = 0;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700432
433 /**
434 * Indicates this network uses a Wi-Fi transport.
435 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700436 public static final int TRANSPORT_WIFI = 1;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700437
438 /**
439 * Indicates this network uses a Bluetooth transport.
440 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700441 public static final int TRANSPORT_BLUETOOTH = 2;
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700442
443 /**
444 * Indicates this network uses an Ethernet transport.
445 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700446 public static final int TRANSPORT_ETHERNET = 3;
447
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400448 /**
449 * Indicates this network uses a VPN transport.
450 */
451 public static final int TRANSPORT_VPN = 4;
452
Etan Cohen305ea282016-06-20 09:27:12 -0700453 /**
Etan Cohen0849ded2016-10-26 11:22:06 -0700454 * Indicates this network uses a Wi-Fi Aware transport.
Etan Cohen305ea282016-06-20 09:27:12 -0700455 */
Etan Cohen0849ded2016-10-26 11:22:06 -0700456 public static final int TRANSPORT_WIFI_AWARE = 5;
Etan Cohen305ea282016-06-20 09:27:12 -0700457
Robert Quattlebaum5f915762017-05-15 15:53:29 -0700458 /**
459 * Indicates this network uses a LoWPAN transport.
Robert Quattlebaum5f915762017-05-15 15:53:29 -0700460 */
461 public static final int TRANSPORT_LOWPAN = 6;
462
Hugo Benichi6a9bb8e2017-03-15 23:05:01 +0900463 /** @hide */
464 public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
465 /** @hide */
Robert Quattlebaum5f915762017-05-15 15:53:29 -0700466 public static final int MAX_TRANSPORT = TRANSPORT_LOWPAN;
Robert Greenwalt1448f052014-04-08 13:41:39 -0700467
Hugo Benichi16f0a942017-06-20 14:07:59 +0900468 /** @hide */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600469 public static boolean isValidTransport(@Transport int transportType) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900470 return (MIN_TRANSPORT <= transportType) && (transportType <= MAX_TRANSPORT);
471 }
472
Hugo Benichi9910dbc2017-03-22 18:29:58 +0900473 private static final String[] TRANSPORT_NAMES = {
474 "CELLULAR",
475 "WIFI",
476 "BLUETOOTH",
477 "ETHERNET",
478 "VPN",
Robert Quattlebaum5f915762017-05-15 15:53:29 -0700479 "WIFI_AWARE",
480 "LOWPAN"
Hugo Benichi9910dbc2017-03-22 18:29:58 +0900481 };
482
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700483 /**
484 * Adds the given transport type to this {@code NetworkCapability} instance.
485 * Multiple transports may be applied sequentially. Note that when searching
486 * for a network to satisfy a request, any listed in the request will satisfy the request.
487 * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a
488 * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network
489 * to be selected. This is logically different than
490 * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
491 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600492 * @param transportType the transport type to be added.
Pierre Imaic8419a82016-03-22 17:54:54 +0900493 * @return This NetworkCapabilities instance, to facilitate chaining.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700494 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700495 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600496 public NetworkCapabilities addTransportType(@Transport int transportType) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900497 checkValidTransportType(transportType);
Robert Greenwalt1448f052014-04-08 13:41:39 -0700498 mTransportTypes |= 1 << transportType;
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700499 setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
Robert Greenwalt7569f182014-06-08 16:42:59 -0700500 return this;
Robert Greenwalt1448f052014-04-08 13:41:39 -0700501 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700502
503 /**
504 * Removes (if found) the given transport from this {@code NetworkCapability} instance.
505 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600506 * @param transportType the transport type to be removed.
Pierre Imaic8419a82016-03-22 17:54:54 +0900507 * @return This NetworkCapabilities instance, to facilitate chaining.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700508 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700509 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600510 public NetworkCapabilities removeTransportType(@Transport int transportType) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900511 checkValidTransportType(transportType);
Robert Greenwalt1448f052014-04-08 13:41:39 -0700512 mTransportTypes &= ~(1 << transportType);
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700513 setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
Robert Greenwalt7569f182014-06-08 16:42:59 -0700514 return this;
Robert Greenwalt1448f052014-04-08 13:41:39 -0700515 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700516
517 /**
518 * Gets all the transports set on this {@code NetworkCapability} instance.
519 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600520 * @return an array of transport type values for this instance.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700521 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700522 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600523 public @Transport int[] getTransportTypes() {
Hugo Benichi9910dbc2017-03-22 18:29:58 +0900524 return BitUtils.unpackBits(mTransportTypes);
Robert Greenwalt1448f052014-04-08 13:41:39 -0700525 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700526
527 /**
528 * Tests for the presence of a transport on this instance.
529 *
Jeff Sharkeyde570312017-10-24 21:25:50 -0600530 * @param transportType the transport type to be tested for.
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700531 * @return {@code true} if set on this instance.
532 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600533 public boolean hasTransport(@Transport int transportType) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900534 return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0);
Robert Greenwalt5c55e332014-05-08 00:02:04 -0700535 }
Robert Greenwalt1448f052014-04-08 13:41:39 -0700536
537 private void combineTransportTypes(NetworkCapabilities nc) {
538 this.mTransportTypes |= nc.mTransportTypes;
539 }
Hugo Benichieae7a222017-07-25 11:40:56 +0900540
Robert Greenwalt1448f052014-04-08 13:41:39 -0700541 private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
542 return ((this.mTransportTypes == 0) ||
543 ((this.mTransportTypes & nc.mTransportTypes) != 0));
544 }
Hugo Benichieae7a222017-07-25 11:40:56 +0900545
Robert Greenwalt06314e42014-10-29 14:04:06 -0700546 /** @hide */
547 public boolean equalsTransportTypes(NetworkCapabilities nc) {
Robert Greenwalt1448f052014-04-08 13:41:39 -0700548 return (nc.mTransportTypes == this.mTransportTypes);
549 }
550
551 /**
552 * Passive link bandwidth. This is a rough guide of the expected peak bandwidth
553 * for the first hop on the given transport. It is not measured, but may take into account
554 * link parameters (Radio technology, allocated channels, etc).
555 */
556 private int mLinkUpBandwidthKbps;
557 private int mLinkDownBandwidthKbps;
558
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700559 /**
560 * Sets the upstream bandwidth for this network in Kbps. This always only refers to
561 * the estimated first hop transport bandwidth.
562 * <p>
563 * Note that when used to request a network, this specifies the minimum acceptable.
564 * When received as the state of an existing network this specifies the typical
565 * first hop bandwidth expected. This is never measured, but rather is inferred
566 * from technology type and other link parameters. It could be used to differentiate
567 * between very slow 1xRTT cellular links and other faster networks or even between
568 * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between
569 * fast backhauls and slow backhauls.
570 *
571 * @param upKbps the estimated first hop upstream (device to network) bandwidth.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700572 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700573 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700574 public void setLinkUpstreamBandwidthKbps(int upKbps) {
575 mLinkUpBandwidthKbps = upKbps;
576 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700577
578 /**
579 * Retrieves the upstream bandwidth for this network in Kbps. This always only refers to
580 * the estimated first hop transport bandwidth.
581 *
582 * @return The estimated first hop upstream (device to network) bandwidth.
583 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700584 public int getLinkUpstreamBandwidthKbps() {
585 return mLinkUpBandwidthKbps;
586 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700587
588 /**
589 * Sets the downstream bandwidth for this network in Kbps. This always only refers to
590 * the estimated first hop transport bandwidth.
591 * <p>
592 * Note that when used to request a network, this specifies the minimum acceptable.
593 * When received as the state of an existing network this specifies the typical
594 * first hop bandwidth expected. This is never measured, but rather is inferred
595 * from technology type and other link parameters. It could be used to differentiate
596 * between very slow 1xRTT cellular links and other faster networks or even between
597 * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between
598 * fast backhauls and slow backhauls.
599 *
600 * @param downKbps the estimated first hop downstream (network to device) bandwidth.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700601 * @hide
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700602 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700603 public void setLinkDownstreamBandwidthKbps(int downKbps) {
604 mLinkDownBandwidthKbps = downKbps;
605 }
Robert Greenwalt01d004e2014-05-18 15:24:21 -0700606
607 /**
608 * Retrieves the downstream bandwidth for this network in Kbps. This always only refers to
609 * the estimated first hop transport bandwidth.
610 *
611 * @return The estimated first hop downstream (network to device) bandwidth.
612 */
Robert Greenwalt1448f052014-04-08 13:41:39 -0700613 public int getLinkDownstreamBandwidthKbps() {
614 return mLinkDownBandwidthKbps;
615 }
616
617 private void combineLinkBandwidths(NetworkCapabilities nc) {
618 this.mLinkUpBandwidthKbps =
619 Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps);
620 this.mLinkDownBandwidthKbps =
621 Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps);
622 }
623 private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) {
624 return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps ||
625 this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
626 }
627 private boolean equalsLinkBandwidths(NetworkCapabilities nc) {
628 return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
629 this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
630 }
631
Etan Cohena7434272017-04-03 12:17:51 -0700632 private NetworkSpecifier mNetworkSpecifier = null;
633
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700634 /**
635 * Sets the optional bearer specific network specifier.
636 * This has no meaning if a single transport is also not specified, so calling
637 * this without a single transport set will generate an exception, as will
638 * subsequently adding or removing transports after this is set.
639 * </p>
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700640 *
Etan Cohena7434272017-04-03 12:17:51 -0700641 * @param networkSpecifier A concrete, parcelable framework class that extends
642 * NetworkSpecifier.
Pierre Imaic8419a82016-03-22 17:54:54 +0900643 * @return This NetworkCapabilities instance, to facilitate chaining.
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700644 * @hide
645 */
Etan Cohena7434272017-04-03 12:17:51 -0700646 public NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
647 if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) {
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700648 throw new IllegalStateException("Must have a single transport specified to use " +
649 "setNetworkSpecifier");
650 }
Etan Cohena7434272017-04-03 12:17:51 -0700651
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700652 mNetworkSpecifier = networkSpecifier;
Etan Cohena7434272017-04-03 12:17:51 -0700653
Pierre Imaic8419a82016-03-22 17:54:54 +0900654 return this;
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700655 }
656
657 /**
658 * Gets the optional bearer specific network specifier.
659 *
Etan Cohena7434272017-04-03 12:17:51 -0700660 * @return The optional {@link NetworkSpecifier} specifying the bearer specific network
661 * specifier. See {@link #setNetworkSpecifier}.
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700662 * @hide
663 */
Etan Cohena7434272017-04-03 12:17:51 -0700664 public NetworkSpecifier getNetworkSpecifier() {
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700665 return mNetworkSpecifier;
666 }
667
668 private void combineSpecifiers(NetworkCapabilities nc) {
Etan Cohena7434272017-04-03 12:17:51 -0700669 if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) {
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700670 throw new IllegalStateException("Can't combine two networkSpecifiers");
671 }
Etan Cohena7434272017-04-03 12:17:51 -0700672 setNetworkSpecifier(nc.mNetworkSpecifier);
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700673 }
Etan Cohena7434272017-04-03 12:17:51 -0700674
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700675 private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
Etan Cohena7434272017-04-03 12:17:51 -0700676 return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier)
677 || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier;
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700678 }
Etan Cohena7434272017-04-03 12:17:51 -0700679
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700680 private boolean equalsSpecifier(NetworkCapabilities nc) {
Etan Cohena7434272017-04-03 12:17:51 -0700681 return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier);
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700682 }
683
Robert Greenwalt1448f052014-04-08 13:41:39 -0700684 /**
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900685 * Magic value that indicates no signal strength provided. A request specifying this value is
686 * always satisfied.
687 *
688 * @hide
689 */
690 public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE;
691
692 /**
693 * Signal strength. This is a signed integer, and higher values indicate better signal.
694 * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI.
695 */
696 private int mSignalStrength;
697
698 /**
699 * Sets the signal strength. This is a signed integer, with higher values indicating a stronger
700 * signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units
701 * reported by WifiManager.
702 * <p>
703 * Note that when used to register a network callback, this specifies the minimum acceptable
704 * signal strength. When received as the state of an existing network it specifies the current
705 * value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no
706 * effect when requesting a callback.
707 *
708 * @param signalStrength the bearer-specific signal strength.
709 * @hide
710 */
711 public void setSignalStrength(int signalStrength) {
712 mSignalStrength = signalStrength;
713 }
714
715 /**
716 * Returns {@code true} if this object specifies a signal strength.
717 *
718 * @hide
719 */
720 public boolean hasSignalStrength() {
721 return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED;
722 }
723
724 /**
725 * Retrieves the signal strength.
726 *
727 * @return The bearer-specific signal strength.
728 * @hide
729 */
730 public int getSignalStrength() {
731 return mSignalStrength;
732 }
733
734 private void combineSignalStrength(NetworkCapabilities nc) {
735 this.mSignalStrength = Math.max(this.mSignalStrength, nc.mSignalStrength);
736 }
737
738 private boolean satisfiedBySignalStrength(NetworkCapabilities nc) {
739 return this.mSignalStrength <= nc.mSignalStrength;
740 }
741
742 private boolean equalsSignalStrength(NetworkCapabilities nc) {
743 return this.mSignalStrength == nc.mSignalStrength;
744 }
745
746 /**
Robert Greenwalt1448f052014-04-08 13:41:39 -0700747 * Combine a set of Capabilities to this one. Useful for coming up with the complete set
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900748 * @hide
Robert Greenwalt1448f052014-04-08 13:41:39 -0700749 */
750 public void combineCapabilities(NetworkCapabilities nc) {
751 combineNetCapabilities(nc);
752 combineTransportTypes(nc);
753 combineLinkBandwidths(nc);
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700754 combineSpecifiers(nc);
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900755 combineSignalStrength(nc);
Robert Greenwalt1448f052014-04-08 13:41:39 -0700756 }
757
758 /**
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900759 * Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
760 *
761 * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
762 * @param onlyImmutable if {@code true}, do not consider mutable requirements such as link
763 * bandwidth, signal strength, or validation / captive portal status.
764 *
765 * @hide
766 */
767 private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
768 return (nc != null &&
769 satisfiedByNetCapabilities(nc, onlyImmutable) &&
770 satisfiedByTransportTypes(nc) &&
771 (onlyImmutable || satisfiedByLinkBandwidths(nc)) &&
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900772 satisfiedBySpecifier(nc) &&
773 (onlyImmutable || satisfiedBySignalStrength(nc)));
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900774 }
775
776 /**
777 * Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
778 *
779 * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
780 *
781 * @hide
Robert Greenwalt1448f052014-04-08 13:41:39 -0700782 */
783 public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900784 return satisfiedByNetworkCapabilities(nc, false);
785 }
786
787 /**
788 * Check if our immutable requirements are satisfied by the given {@code NetworkCapabilities}.
789 *
790 * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
791 *
792 * @hide
793 */
794 public boolean satisfiedByImmutableNetworkCapabilities(NetworkCapabilities nc) {
795 return satisfiedByNetworkCapabilities(nc, true);
796 }
797
798 /**
799 * Checks that our immutable capabilities are the same as those of the given
Hugo Benichieae7a222017-07-25 11:40:56 +0900800 * {@code NetworkCapabilities} and return a String describing any difference.
801 * The returned String is empty if there is no difference.
Lorenzo Colitti260a36d2015-07-08 12:49:04 +0900802 *
803 * @hide
804 */
Hugo Benichieae7a222017-07-25 11:40:56 +0900805 public String describeImmutableDifferences(NetworkCapabilities that) {
806 if (that == null) {
807 return "other NetworkCapabilities was null";
808 }
809
810 StringJoiner joiner = new StringJoiner(", ");
811
Hugo Benichieae7a222017-07-25 11:40:56 +0900812 // Ignore NOT_METERED being added or removed as it is effectively dynamic. http://b/63326103
813 // TODO: properly support NOT_METERED as a mutable and requestable capability.
Hugo Benichi2ecb9402017-08-04 13:18:40 +0900814 final long mask = ~MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_NOT_METERED);
Hugo Benichieae7a222017-07-25 11:40:56 +0900815 long oldImmutableCapabilities = this.mNetworkCapabilities & mask;
816 long newImmutableCapabilities = that.mNetworkCapabilities & mask;
817 if (oldImmutableCapabilities != newImmutableCapabilities) {
818 String before = capabilityNamesOf(BitUtils.unpackBits(oldImmutableCapabilities));
819 String after = capabilityNamesOf(BitUtils.unpackBits(newImmutableCapabilities));
820 joiner.add(String.format("immutable capabilities changed: %s -> %s", before, after));
821 }
822
823 if (!equalsSpecifier(that)) {
824 NetworkSpecifier before = this.getNetworkSpecifier();
825 NetworkSpecifier after = that.getNetworkSpecifier();
826 joiner.add(String.format("specifier changed: %s -> %s", before, after));
827 }
828
829 if (!equalsTransportTypes(that)) {
830 String before = transportNamesOf(this.getTransportTypes());
831 String after = transportNamesOf(that.getTransportTypes());
832 joiner.add(String.format("transports changed: %s -> %s", before, after));
833 }
834
835 return joiner.toString();
Robert Greenwalt1448f052014-04-08 13:41:39 -0700836 }
837
Lorenzo Colittif0e9a332016-07-18 18:40:42 +0900838 /**
839 * Checks that our requestable capabilities are the same as those of the given
840 * {@code NetworkCapabilities}.
841 *
842 * @hide
843 */
844 public boolean equalRequestableCapabilities(NetworkCapabilities nc) {
845 if (nc == null) return false;
846 return (equalsNetCapabilitiesRequestable(nc) &&
847 equalsTransportTypes(nc) &&
848 equalsSpecifier(nc));
849 }
850
Robert Greenwalt1448f052014-04-08 13:41:39 -0700851 @Override
852 public boolean equals(Object obj) {
853 if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
854 NetworkCapabilities that = (NetworkCapabilities)obj;
855 return (equalsNetCapabilities(that) &&
856 equalsTransportTypes(that) &&
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700857 equalsLinkBandwidths(that) &&
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900858 equalsSignalStrength(that) &&
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700859 equalsSpecifier(that));
Robert Greenwalt1448f052014-04-08 13:41:39 -0700860 }
861
862 @Override
863 public int hashCode() {
864 return ((int)(mNetworkCapabilities & 0xFFFFFFFF) +
865 ((int)(mNetworkCapabilities >> 32) * 3) +
866 ((int)(mTransportTypes & 0xFFFFFFFF) * 5) +
867 ((int)(mTransportTypes >> 32) * 7) +
868 (mLinkUpBandwidthKbps * 11) +
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700869 (mLinkDownBandwidthKbps * 13) +
Etan Cohena7434272017-04-03 12:17:51 -0700870 Objects.hashCode(mNetworkSpecifier) * 17 +
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900871 (mSignalStrength * 19));
Robert Greenwalt1448f052014-04-08 13:41:39 -0700872 }
873
Wink Saville4e2dea72014-09-20 11:04:03 -0700874 @Override
Robert Greenwalt1448f052014-04-08 13:41:39 -0700875 public int describeContents() {
876 return 0;
877 }
Wink Saville4e2dea72014-09-20 11:04:03 -0700878 @Override
Robert Greenwalt1448f052014-04-08 13:41:39 -0700879 public void writeToParcel(Parcel dest, int flags) {
880 dest.writeLong(mNetworkCapabilities);
881 dest.writeLong(mTransportTypes);
882 dest.writeInt(mLinkUpBandwidthKbps);
883 dest.writeInt(mLinkDownBandwidthKbps);
Etan Cohena7434272017-04-03 12:17:51 -0700884 dest.writeParcelable((Parcelable) mNetworkSpecifier, flags);
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900885 dest.writeInt(mSignalStrength);
Robert Greenwalt1448f052014-04-08 13:41:39 -0700886 }
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900887
Robert Greenwalt1448f052014-04-08 13:41:39 -0700888 public static final Creator<NetworkCapabilities> CREATOR =
889 new Creator<NetworkCapabilities>() {
Wink Saville4e2dea72014-09-20 11:04:03 -0700890 @Override
Robert Greenwalt1448f052014-04-08 13:41:39 -0700891 public NetworkCapabilities createFromParcel(Parcel in) {
892 NetworkCapabilities netCap = new NetworkCapabilities();
893
894 netCap.mNetworkCapabilities = in.readLong();
895 netCap.mTransportTypes = in.readLong();
896 netCap.mLinkUpBandwidthKbps = in.readInt();
897 netCap.mLinkDownBandwidthKbps = in.readInt();
Etan Cohena7434272017-04-03 12:17:51 -0700898 netCap.mNetworkSpecifier = in.readParcelable(null);
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900899 netCap.mSignalStrength = in.readInt();
Robert Greenwalt1448f052014-04-08 13:41:39 -0700900 return netCap;
901 }
Wink Saville4e2dea72014-09-20 11:04:03 -0700902 @Override
Robert Greenwalt1448f052014-04-08 13:41:39 -0700903 public NetworkCapabilities[] newArray(int size) {
904 return new NetworkCapabilities[size];
905 }
906 };
907
Wink Saville4e2dea72014-09-20 11:04:03 -0700908 @Override
Robert Greenwalt1448f052014-04-08 13:41:39 -0700909 public String toString() {
Hugo Benichieae7a222017-07-25 11:40:56 +0900910 // TODO: enumerate bits for transports and capabilities instead of creating arrays.
911 // TODO: use a StringBuilder instead of string concatenation.
Robert Greenwalt7569f182014-06-08 16:42:59 -0700912 int[] types = getTransportTypes();
Hugo Benichi5df9d722016-04-25 17:16:35 +0900913 String transports = (types.length > 0) ? " Transports: " + transportNamesOf(types) : "";
Robert Greenwalt1448f052014-04-08 13:41:39 -0700914
Robert Greenwalt7569f182014-06-08 16:42:59 -0700915 types = getCapabilities();
916 String capabilities = (types.length > 0 ? " Capabilities: " : "");
917 for (int i = 0; i < types.length; ) {
Hugo Benichieae7a222017-07-25 11:40:56 +0900918 capabilities += capabilityNameOf(types[i]);
Robert Greenwalt7569f182014-06-08 16:42:59 -0700919 if (++i < types.length) capabilities += "&";
Robert Greenwalt1448f052014-04-08 13:41:39 -0700920 }
921
922 String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" +
923 mLinkUpBandwidthKbps + "Kbps" : "");
924 String dnBand = ((mLinkDownBandwidthKbps > 0) ? " LinkDnBandwidth>=" +
925 mLinkDownBandwidthKbps + "Kbps" : "");
926
Robert Greenwalt5f90bcc2014-07-09 17:25:41 -0700927 String specifier = (mNetworkSpecifier == null ?
928 "" : " Specifier: <" + mNetworkSpecifier + ">");
929
Lorenzo Colittic3f21f32015-07-06 23:50:27 +0900930 String signalStrength = (hasSignalStrength() ? " SignalStrength: " + mSignalStrength : "");
931
932 return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + "]";
Robert Greenwalt1448f052014-04-08 13:41:39 -0700933 }
Hugo Benichi5df9d722016-04-25 17:16:35 +0900934
935 /**
936 * @hide
937 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600938 public static String capabilityNamesOf(@NetCapability int[] capabilities) {
Hugo Benichieae7a222017-07-25 11:40:56 +0900939 StringJoiner joiner = new StringJoiner("|");
940 if (capabilities != null) {
941 for (int c : capabilities) {
942 joiner.add(capabilityNameOf(c));
943 }
944 }
945 return joiner.toString();
946 }
947
948 /**
949 * @hide
950 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600951 public static String capabilityNameOf(@NetCapability int capability) {
Hugo Benichieae7a222017-07-25 11:40:56 +0900952 switch (capability) {
953 case NET_CAPABILITY_MMS: return "MMS";
954 case NET_CAPABILITY_SUPL: return "SUPL";
955 case NET_CAPABILITY_DUN: return "DUN";
956 case NET_CAPABILITY_FOTA: return "FOTA";
957 case NET_CAPABILITY_IMS: return "IMS";
958 case NET_CAPABILITY_CBS: return "CBS";
959 case NET_CAPABILITY_WIFI_P2P: return "WIFI_P2P";
960 case NET_CAPABILITY_IA: return "IA";
961 case NET_CAPABILITY_RCS: return "RCS";
962 case NET_CAPABILITY_XCAP: return "XCAP";
963 case NET_CAPABILITY_EIMS: return "EIMS";
964 case NET_CAPABILITY_NOT_METERED: return "NOT_METERED";
965 case NET_CAPABILITY_INTERNET: return "INTERNET";
966 case NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED";
967 case NET_CAPABILITY_TRUSTED: return "TRUSTED";
968 case NET_CAPABILITY_NOT_VPN: return "NOT_VPN";
969 case NET_CAPABILITY_VALIDATED: return "VALIDATED";
970 case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL";
971 case NET_CAPABILITY_FOREGROUND: return "FOREGROUND";
972 default: return Integer.toString(capability);
973 }
974 }
975
976 /**
977 * @hide
978 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600979 public static String transportNamesOf(@Transport int[] types) {
Hugo Benichieae7a222017-07-25 11:40:56 +0900980 StringJoiner joiner = new StringJoiner("|");
981 if (types != null) {
982 for (int t : types) {
983 joiner.add(transportNameOf(t));
984 }
Hugo Benichi5df9d722016-04-25 17:16:35 +0900985 }
Hugo Benichieae7a222017-07-25 11:40:56 +0900986 return joiner.toString();
Hugo Benichi9910dbc2017-03-22 18:29:58 +0900987 }
988
989 /**
990 * @hide
991 */
Jeff Sharkeyde570312017-10-24 21:25:50 -0600992 public static String transportNameOf(@Transport int transport) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900993 if (!isValidTransport(transport)) {
Hugo Benichi9910dbc2017-03-22 18:29:58 +0900994 return "UNKNOWN";
995 }
996 return TRANSPORT_NAMES[transport];
Hugo Benichi5df9d722016-04-25 17:16:35 +0900997 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900998
Jeff Sharkeyde570312017-10-24 21:25:50 -0600999 private static void checkValidTransportType(@Transport int transport) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001000 Preconditions.checkArgument(
1001 isValidTransport(transport), "Invalid TransportType " + transport);
1002 }
Robert Greenwalt1448f052014-04-08 13:41:39 -07001003}