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 
17 package android.net;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 
22 import com.android.internal.annotations.VisibleForTesting;
23 import com.android.internal.util.BitUtils;
24 
25 import java.util.Objects;
26 
27 /**
28  * This class represents the capabilities of a network.  This is used both to specify
29  * needs to {@link ConnectivityManager} and when inspecting a network.
30  *
31  * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method
32  * of network selection.  Rather than indicate a need for Wi-Fi because an application
33  * needs high bandwidth and risk obsolescence when a new, fast network appears (like LTE),
34  * the application should specify it needs high bandwidth.  Similarly if an application
35  * needs an unmetered network for a bulk transfer it can specify that rather than assuming
36  * all cellular based connections are metered and all Wi-Fi based connections are not.
37  */
38 public final class NetworkCapabilities implements Parcelable {
39     private static final String TAG = "NetworkCapabilities";
40 
41     /**
42      * @hide
43      */
NetworkCapabilities()44     public NetworkCapabilities() {
45         clearAll();
46         mNetworkCapabilities = DEFAULT_CAPABILITIES;
47     }
48 
NetworkCapabilities(NetworkCapabilities nc)49     public NetworkCapabilities(NetworkCapabilities nc) {
50         if (nc != null) {
51             mNetworkCapabilities = nc.mNetworkCapabilities;
52             mTransportTypes = nc.mTransportTypes;
53             mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
54             mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
55             mNetworkSpecifier = nc.mNetworkSpecifier;
56             mSignalStrength = nc.mSignalStrength;
57         }
58     }
59 
60     /**
61      * Completely clears the contents of this object, removing even the capabilities that are set
62      * by default when the object is constructed.
63      * @hide
64      */
clearAll()65     public void clearAll() {
66         mNetworkCapabilities = mTransportTypes = 0;
67         mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0;
68         mNetworkSpecifier = null;
69         mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
70     }
71 
72     /**
73      * Represents the network's capabilities.  If any are specified they will be satisfied
74      * by any Network that matches all of them.
75      */
76     private long mNetworkCapabilities;
77 
78     /**
79      * Indicates this is a network that has the ability to reach the
80      * carrier's MMSC for sending and receiving MMS messages.
81      */
82     public static final int NET_CAPABILITY_MMS            = 0;
83 
84     /**
85      * Indicates this is a network that has the ability to reach the carrier's
86      * SUPL server, used to retrieve GPS information.
87      */
88     public static final int NET_CAPABILITY_SUPL           = 1;
89 
90     /**
91      * Indicates this is a network that has the ability to reach the carrier's
92      * DUN or tethering gateway.
93      */
94     public static final int NET_CAPABILITY_DUN            = 2;
95 
96     /**
97      * Indicates this is a network that has the ability to reach the carrier's
98      * FOTA portal, used for over the air updates.
99      */
100     public static final int NET_CAPABILITY_FOTA           = 3;
101 
102     /**
103      * Indicates this is a network that has the ability to reach the carrier's
104      * IMS servers, used for network registration and signaling.
105      */
106     public static final int NET_CAPABILITY_IMS            = 4;
107 
108     /**
109      * Indicates this is a network that has the ability to reach the carrier's
110      * CBS servers, used for carrier specific services.
111      */
112     public static final int NET_CAPABILITY_CBS            = 5;
113 
114     /**
115      * Indicates this is a network that has the ability to reach a Wi-Fi direct
116      * peer.
117      */
118     public static final int NET_CAPABILITY_WIFI_P2P       = 6;
119 
120     /**
121      * Indicates this is a network that has the ability to reach a carrier's
122      * Initial Attach servers.
123      */
124     public static final int NET_CAPABILITY_IA             = 7;
125 
126     /**
127      * Indicates this is a network that has the ability to reach a carrier's
128      * RCS servers, used for Rich Communication Services.
129      */
130     public static final int NET_CAPABILITY_RCS            = 8;
131 
132     /**
133      * Indicates this is a network that has the ability to reach a carrier's
134      * XCAP servers, used for configuration and control.
135      */
136     public static final int NET_CAPABILITY_XCAP           = 9;
137 
138     /**
139      * Indicates this is a network that has the ability to reach a carrier's
140      * Emergency IMS servers or other services, used for network signaling
141      * during emergency calls.
142      */
143     public static final int NET_CAPABILITY_EIMS           = 10;
144 
145     /**
146      * Indicates that this network is unmetered.
147      */
148     public static final int NET_CAPABILITY_NOT_METERED    = 11;
149 
150     /**
151      * Indicates that this network should be able to reach the internet.
152      */
153     public static final int NET_CAPABILITY_INTERNET       = 12;
154 
155     /**
156      * Indicates that this network is available for general use.  If this is not set
157      * applications should not attempt to communicate on this network.  Note that this
158      * is simply informative and not enforcement - enforcement is handled via other means.
159      * Set by default.
160      */
161     public static final int NET_CAPABILITY_NOT_RESTRICTED = 13;
162 
163     /**
164      * Indicates that the user has indicated implicit trust of this network.  This
165      * generally means it's a sim-selected carrier, a plugged in ethernet, a paired
166      * BT device or a wifi the user asked to connect to.  Untrusted networks
167      * are probably limited to unknown wifi AP.  Set by default.
168      */
169     public static final int NET_CAPABILITY_TRUSTED        = 14;
170 
171     /**
172      * Indicates that this network is not a VPN.  This capability is set by default and should be
173      * explicitly cleared for VPN networks.
174      */
175     public static final int NET_CAPABILITY_NOT_VPN        = 15;
176 
177     /**
178      * Indicates that connectivity on this network was successfully validated. For example, for a
179      * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully
180      * detected.
181      */
182     public static final int NET_CAPABILITY_VALIDATED      = 16;
183 
184     /**
185      * Indicates that this network was found to have a captive portal in place last time it was
186      * probed.
187      */
188     public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17;
189 
190     /**
191      * Indicates that this network is available for use by apps, and not a network that is being
192      * kept up in the background to facilitate fast network switching.
193      * @hide
194      */
195     public static final int NET_CAPABILITY_FOREGROUND = 18;
196 
197     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
198     private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND;
199 
200     /**
201      * Network capabilities that are expected to be mutable, i.e., can change while a particular
202      * network is connected.
203      */
204     private static final long MUTABLE_CAPABILITIES =
205             // TRUSTED can change when user explicitly connects to an untrusted network in Settings.
206             // http://b/18206275
207             (1 << NET_CAPABILITY_TRUSTED) |
208             (1 << NET_CAPABILITY_VALIDATED) |
209             (1 << NET_CAPABILITY_CAPTIVE_PORTAL) |
210             (1 << NET_CAPABILITY_FOREGROUND);
211 
212     /**
213      * Network capabilities that are not allowed in NetworkRequests. This exists because the
214      * NetworkFactory / NetworkAgent model does not deal well with the situation where a
215      * capability's presence cannot be known in advance. If such a capability is requested, then we
216      * can get into a cycle where the NetworkFactory endlessly churns out NetworkAgents that then
217      * get immediately torn down because they do not have the requested capability.
218      */
219     private static final long NON_REQUESTABLE_CAPABILITIES =
220             MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_TRUSTED);
221 
222     /**
223      * Capabilities that are set by default when the object is constructed.
224      */
225     private static final long DEFAULT_CAPABILITIES =
226             (1 << NET_CAPABILITY_NOT_RESTRICTED) |
227             (1 << NET_CAPABILITY_TRUSTED) |
228             (1 << NET_CAPABILITY_NOT_VPN);
229 
230     /**
231      * Capabilities that suggest that a network is restricted.
232      * {@see #maybeMarkCapabilitiesRestricted}.
233      */
234     @VisibleForTesting
235     /* package */ static final long RESTRICTED_CAPABILITIES =
236             (1 << NET_CAPABILITY_CBS) |
237             (1 << NET_CAPABILITY_DUN) |
238             (1 << NET_CAPABILITY_EIMS) |
239             (1 << NET_CAPABILITY_FOTA) |
240             (1 << NET_CAPABILITY_IA) |
241             (1 << NET_CAPABILITY_IMS) |
242             (1 << NET_CAPABILITY_RCS) |
243             (1 << NET_CAPABILITY_XCAP);
244 
245     /**
246      * Capabilities that suggest that a network is unrestricted.
247      * {@see #maybeMarkCapabilitiesRestricted}.
248      */
249     @VisibleForTesting
250     /* package */ static final long UNRESTRICTED_CAPABILITIES =
251             (1 << NET_CAPABILITY_INTERNET) |
252             (1 << NET_CAPABILITY_MMS) |
253             (1 << NET_CAPABILITY_SUPL) |
254             (1 << NET_CAPABILITY_WIFI_P2P);
255 
256     /**
257      * Adds the given capability to this {@code NetworkCapability} instance.
258      * Multiple capabilities may be applied sequentially.  Note that when searching
259      * for a network to satisfy a request, all capabilities requested must be satisfied.
260      *
261      * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
262      * @return This NetworkCapabilities instance, to facilitate chaining.
263      * @hide
264      */
addCapability(int capability)265     public NetworkCapabilities addCapability(int capability) {
266         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
267             throw new IllegalArgumentException("NetworkCapability out of range");
268         }
269         mNetworkCapabilities |= 1 << capability;
270         return this;
271     }
272 
273     /**
274      * Removes (if found) the given capability from this {@code NetworkCapability} instance.
275      *
276      * @param capability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
277      * @return This NetworkCapabilities instance, to facilitate chaining.
278      * @hide
279      */
removeCapability(int capability)280     public NetworkCapabilities removeCapability(int capability) {
281         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
282             throw new IllegalArgumentException("NetworkCapability out of range");
283         }
284         mNetworkCapabilities &= ~(1 << capability);
285         return this;
286     }
287 
288     /**
289      * Gets all the capabilities set on this {@code NetworkCapability} instance.
290      *
291      * @return an array of {@code NetworkCapabilities.NET_CAPABILITY_*} values
292      *         for this instance.
293      * @hide
294      */
getCapabilities()295     public int[] getCapabilities() {
296         return BitUtils.unpackBits(mNetworkCapabilities);
297     }
298 
299     /**
300      * Tests for the presence of a capabilitity on this instance.
301      *
302      * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
303      * @return {@code true} if set on this instance.
304      */
hasCapability(int capability)305     public boolean hasCapability(int capability) {
306         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
307             return false;
308         }
309         return ((mNetworkCapabilities & (1 << capability)) != 0);
310     }
311 
combineNetCapabilities(NetworkCapabilities nc)312     private void combineNetCapabilities(NetworkCapabilities nc) {
313         this.mNetworkCapabilities |= nc.mNetworkCapabilities;
314     }
315 
316     /**
317      * Convenience function that returns a human-readable description of the first mutable
318      * capability we find. Used to present an error message to apps that request mutable
319      * capabilities.
320      *
321      * @hide
322      */
describeFirstNonRequestableCapability()323     public String describeFirstNonRequestableCapability() {
324         if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED";
325         if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL";
326         if (hasCapability(NET_CAPABILITY_FOREGROUND)) return "NET_CAPABILITY_FOREGROUND";
327         // This cannot happen unless the preceding checks are incomplete.
328         if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) {
329             return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities);
330         }
331         if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth";
332         if (hasSignalStrength()) return "signalStrength";
333         return null;
334     }
335 
satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable)336     private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
337         long networkCapabilities = this.mNetworkCapabilities;
338         if (onlyImmutable) {
339             networkCapabilities = networkCapabilities & ~MUTABLE_CAPABILITIES;
340         }
341         return ((nc.mNetworkCapabilities & networkCapabilities) == networkCapabilities);
342     }
343 
344     /** @hide */
equalsNetCapabilities(NetworkCapabilities nc)345     public boolean equalsNetCapabilities(NetworkCapabilities nc) {
346         return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
347     }
348 
equalsNetCapabilitiesImmutable(NetworkCapabilities that)349     private boolean equalsNetCapabilitiesImmutable(NetworkCapabilities that) {
350         return ((this.mNetworkCapabilities & ~MUTABLE_CAPABILITIES) ==
351                 (that.mNetworkCapabilities & ~MUTABLE_CAPABILITIES));
352     }
353 
equalsNetCapabilitiesRequestable(NetworkCapabilities that)354     private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) {
355         return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
356                 (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
357     }
358 
359     /**
360      * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
361      * typically provided by restricted networks.
362      *
363      * TODO: consider:
364      * - Renaming it to guessRestrictedCapability and make it set the
365      *   restricted capability bit in addition to clearing it.
366      * @hide
367      */
maybeMarkCapabilitiesRestricted()368     public void maybeMarkCapabilitiesRestricted() {
369         // Verify there aren't any unrestricted capabilities.  If there are we say
370         // the whole thing is unrestricted.
371         final boolean hasUnrestrictedCapabilities =
372                 ((mNetworkCapabilities & UNRESTRICTED_CAPABILITIES) != 0);
373 
374         // Must have at least some restricted capabilities.
375         final boolean hasRestrictedCapabilities =
376                 ((mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0);
377 
378         if (hasRestrictedCapabilities && !hasUnrestrictedCapabilities) {
379             removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
380         }
381     }
382 
383     /**
384      * Representing the transport type.  Apps should generally not care about transport.  A
385      * request for a fast internet connection could be satisfied by a number of different
386      * transports.  If any are specified here it will be satisfied a Network that matches
387      * any of them.  If a caller doesn't care about the transport it should not specify any.
388      */
389     private long mTransportTypes;
390 
391     /**
392      * Indicates this network uses a Cellular transport.
393      */
394     public static final int TRANSPORT_CELLULAR = 0;
395 
396     /**
397      * Indicates this network uses a Wi-Fi transport.
398      */
399     public static final int TRANSPORT_WIFI = 1;
400 
401     /**
402      * Indicates this network uses a Bluetooth transport.
403      */
404     public static final int TRANSPORT_BLUETOOTH = 2;
405 
406     /**
407      * Indicates this network uses an Ethernet transport.
408      */
409     public static final int TRANSPORT_ETHERNET = 3;
410 
411     /**
412      * Indicates this network uses a VPN transport.
413      */
414     public static final int TRANSPORT_VPN = 4;
415 
416     /**
417      * Indicates this network uses a Wi-Fi Aware transport.
418      */
419     public static final int TRANSPORT_WIFI_AWARE = 5;
420 
421     /** @hide */
422     public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
423     /** @hide */
424     public static final int MAX_TRANSPORT = TRANSPORT_WIFI_AWARE;
425 
426     private static final String[] TRANSPORT_NAMES = {
427         "CELLULAR",
428         "WIFI",
429         "BLUETOOTH",
430         "ETHERNET",
431         "VPN",
432         "WIFI_AWARE"
433     };
434 
435     /**
436      * Adds the given transport type to this {@code NetworkCapability} instance.
437      * Multiple transports may be applied sequentially.  Note that when searching
438      * for a network to satisfy a request, any listed in the request will satisfy the request.
439      * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a
440      * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network
441      * to be selected.  This is logically different than
442      * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
443      *
444      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
445      * @return This NetworkCapabilities instance, to facilitate chaining.
446      * @hide
447      */
addTransportType(int transportType)448     public NetworkCapabilities addTransportType(int transportType) {
449         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
450             throw new IllegalArgumentException("TransportType out of range");
451         }
452         mTransportTypes |= 1 << transportType;
453         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
454         return this;
455     }
456 
457     /**
458      * Removes (if found) the given transport from this {@code NetworkCapability} instance.
459      *
460      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
461      * @return This NetworkCapabilities instance, to facilitate chaining.
462      * @hide
463      */
removeTransportType(int transportType)464     public NetworkCapabilities removeTransportType(int transportType) {
465         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
466             throw new IllegalArgumentException("TransportType out of range");
467         }
468         mTransportTypes &= ~(1 << transportType);
469         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
470         return this;
471     }
472 
473     /**
474      * Gets all the transports set on this {@code NetworkCapability} instance.
475      *
476      * @return an array of {@code NetworkCapabilities.TRANSPORT_*} values
477      *         for this instance.
478      * @hide
479      */
getTransportTypes()480     public int[] getTransportTypes() {
481         return BitUtils.unpackBits(mTransportTypes);
482     }
483 
484     /**
485      * Tests for the presence of a transport on this instance.
486      *
487      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be tested for.
488      * @return {@code true} if set on this instance.
489      */
hasTransport(int transportType)490     public boolean hasTransport(int transportType) {
491         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
492             return false;
493         }
494         return ((mTransportTypes & (1 << transportType)) != 0);
495     }
496 
combineTransportTypes(NetworkCapabilities nc)497     private void combineTransportTypes(NetworkCapabilities nc) {
498         this.mTransportTypes |= nc.mTransportTypes;
499     }
satisfiedByTransportTypes(NetworkCapabilities nc)500     private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
501         return ((this.mTransportTypes == 0) ||
502                 ((this.mTransportTypes & nc.mTransportTypes) != 0));
503     }
504     /** @hide */
equalsTransportTypes(NetworkCapabilities nc)505     public boolean equalsTransportTypes(NetworkCapabilities nc) {
506         return (nc.mTransportTypes == this.mTransportTypes);
507     }
508 
509     /**
510      * Passive link bandwidth.  This is a rough guide of the expected peak bandwidth
511      * for the first hop on the given transport.  It is not measured, but may take into account
512      * link parameters (Radio technology, allocated channels, etc).
513      */
514     private int mLinkUpBandwidthKbps;
515     private int mLinkDownBandwidthKbps;
516 
517     /**
518      * Sets the upstream bandwidth for this network in Kbps.  This always only refers to
519      * the estimated first hop transport bandwidth.
520      * <p>
521      * Note that when used to request a network, this specifies the minimum acceptable.
522      * When received as the state of an existing network this specifies the typical
523      * first hop bandwidth expected.  This is never measured, but rather is inferred
524      * from technology type and other link parameters.  It could be used to differentiate
525      * between very slow 1xRTT cellular links and other faster networks or even between
526      * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
527      * fast backhauls and slow backhauls.
528      *
529      * @param upKbps the estimated first hop upstream (device to network) bandwidth.
530      * @hide
531      */
setLinkUpstreamBandwidthKbps(int upKbps)532     public void setLinkUpstreamBandwidthKbps(int upKbps) {
533         mLinkUpBandwidthKbps = upKbps;
534     }
535 
536     /**
537      * Retrieves the upstream bandwidth for this network in Kbps.  This always only refers to
538      * the estimated first hop transport bandwidth.
539      *
540      * @return The estimated first hop upstream (device to network) bandwidth.
541      */
getLinkUpstreamBandwidthKbps()542     public int getLinkUpstreamBandwidthKbps() {
543         return mLinkUpBandwidthKbps;
544     }
545 
546     /**
547      * Sets the downstream bandwidth for this network in Kbps.  This always only refers to
548      * the estimated first hop transport bandwidth.
549      * <p>
550      * Note that when used to request a network, this specifies the minimum acceptable.
551      * When received as the state of an existing network this specifies the typical
552      * first hop bandwidth expected.  This is never measured, but rather is inferred
553      * from technology type and other link parameters.  It could be used to differentiate
554      * between very slow 1xRTT cellular links and other faster networks or even between
555      * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
556      * fast backhauls and slow backhauls.
557      *
558      * @param downKbps the estimated first hop downstream (network to device) bandwidth.
559      * @hide
560      */
setLinkDownstreamBandwidthKbps(int downKbps)561     public void setLinkDownstreamBandwidthKbps(int downKbps) {
562         mLinkDownBandwidthKbps = downKbps;
563     }
564 
565     /**
566      * Retrieves the downstream bandwidth for this network in Kbps.  This always only refers to
567      * the estimated first hop transport bandwidth.
568      *
569      * @return The estimated first hop downstream (network to device) bandwidth.
570      */
getLinkDownstreamBandwidthKbps()571     public int getLinkDownstreamBandwidthKbps() {
572         return mLinkDownBandwidthKbps;
573     }
574 
combineLinkBandwidths(NetworkCapabilities nc)575     private void combineLinkBandwidths(NetworkCapabilities nc) {
576         this.mLinkUpBandwidthKbps =
577                 Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps);
578         this.mLinkDownBandwidthKbps =
579                 Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps);
580     }
satisfiedByLinkBandwidths(NetworkCapabilities nc)581     private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) {
582         return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps ||
583                 this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
584     }
equalsLinkBandwidths(NetworkCapabilities nc)585     private boolean equalsLinkBandwidths(NetworkCapabilities nc) {
586         return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
587                 this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
588     }
589 
590     private NetworkSpecifier mNetworkSpecifier = null;
591 
592     /**
593      * Sets the optional bearer specific network specifier.
594      * This has no meaning if a single transport is also not specified, so calling
595      * this without a single transport set will generate an exception, as will
596      * subsequently adding or removing transports after this is set.
597      * </p>
598      *
599      * @param networkSpecifier A concrete, parcelable framework class that extends
600      *                         NetworkSpecifier.
601      * @return This NetworkCapabilities instance, to facilitate chaining.
602      * @hide
603      */
setNetworkSpecifier(NetworkSpecifier networkSpecifier)604     public NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
605         if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) {
606             throw new IllegalStateException("Must have a single transport specified to use " +
607                     "setNetworkSpecifier");
608         }
609 
610         mNetworkSpecifier = networkSpecifier;
611 
612         return this;
613     }
614 
615     /**
616      * Gets the optional bearer specific network specifier.
617      *
618      * @return The optional {@link NetworkSpecifier} specifying the bearer specific network
619      *         specifier. See {@link #setNetworkSpecifier}.
620      * @hide
621      */
getNetworkSpecifier()622     public NetworkSpecifier getNetworkSpecifier() {
623         return mNetworkSpecifier;
624     }
625 
combineSpecifiers(NetworkCapabilities nc)626     private void combineSpecifiers(NetworkCapabilities nc) {
627         if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) {
628             throw new IllegalStateException("Can't combine two networkSpecifiers");
629         }
630         setNetworkSpecifier(nc.mNetworkSpecifier);
631     }
632 
satisfiedBySpecifier(NetworkCapabilities nc)633     private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
634         return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier)
635                 || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier;
636     }
637 
equalsSpecifier(NetworkCapabilities nc)638     private boolean equalsSpecifier(NetworkCapabilities nc) {
639         return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier);
640     }
641 
642     /**
643      * Magic value that indicates no signal strength provided. A request specifying this value is
644      * always satisfied.
645      *
646      * @hide
647      */
648     public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE;
649 
650     /**
651      * Signal strength. This is a signed integer, and higher values indicate better signal.
652      * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI.
653      */
654     private int mSignalStrength;
655 
656     /**
657      * Sets the signal strength. This is a signed integer, with higher values indicating a stronger
658      * signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units
659      * reported by WifiManager.
660      * <p>
661      * Note that when used to register a network callback, this specifies the minimum acceptable
662      * signal strength. When received as the state of an existing network it specifies the current
663      * value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no
664      * effect when requesting a callback.
665      *
666      * @param signalStrength the bearer-specific signal strength.
667      * @hide
668      */
setSignalStrength(int signalStrength)669     public void setSignalStrength(int signalStrength) {
670         mSignalStrength = signalStrength;
671     }
672 
673     /**
674      * Returns {@code true} if this object specifies a signal strength.
675      *
676      * @hide
677      */
hasSignalStrength()678     public boolean hasSignalStrength() {
679         return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED;
680     }
681 
682     /**
683      * Retrieves the signal strength.
684      *
685      * @return The bearer-specific signal strength.
686      * @hide
687      */
getSignalStrength()688     public int getSignalStrength() {
689         return mSignalStrength;
690     }
691 
combineSignalStrength(NetworkCapabilities nc)692     private void combineSignalStrength(NetworkCapabilities nc) {
693         this.mSignalStrength = Math.max(this.mSignalStrength, nc.mSignalStrength);
694     }
695 
satisfiedBySignalStrength(NetworkCapabilities nc)696     private boolean satisfiedBySignalStrength(NetworkCapabilities nc) {
697         return this.mSignalStrength <= nc.mSignalStrength;
698     }
699 
equalsSignalStrength(NetworkCapabilities nc)700     private boolean equalsSignalStrength(NetworkCapabilities nc) {
701         return this.mSignalStrength == nc.mSignalStrength;
702     }
703 
704     /**
705      * Combine a set of Capabilities to this one.  Useful for coming up with the complete set
706      * @hide
707      */
combineCapabilities(NetworkCapabilities nc)708     public void combineCapabilities(NetworkCapabilities nc) {
709         combineNetCapabilities(nc);
710         combineTransportTypes(nc);
711         combineLinkBandwidths(nc);
712         combineSpecifiers(nc);
713         combineSignalStrength(nc);
714     }
715 
716     /**
717      * Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
718      *
719      * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
720      * @param onlyImmutable if {@code true}, do not consider mutable requirements such as link
721      *         bandwidth, signal strength, or validation / captive portal status.
722      *
723      * @hide
724      */
satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable)725     private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
726         return (nc != null &&
727                 satisfiedByNetCapabilities(nc, onlyImmutable) &&
728                 satisfiedByTransportTypes(nc) &&
729                 (onlyImmutable || satisfiedByLinkBandwidths(nc)) &&
730                 satisfiedBySpecifier(nc) &&
731                 (onlyImmutable || satisfiedBySignalStrength(nc)));
732     }
733 
734     /**
735      * Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
736      *
737      * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
738      *
739      * @hide
740      */
satisfiedByNetworkCapabilities(NetworkCapabilities nc)741     public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
742         return satisfiedByNetworkCapabilities(nc, false);
743     }
744 
745     /**
746      * Check if our immutable requirements are satisfied by the given {@code NetworkCapabilities}.
747      *
748      * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
749      *
750      * @hide
751      */
satisfiedByImmutableNetworkCapabilities(NetworkCapabilities nc)752     public boolean satisfiedByImmutableNetworkCapabilities(NetworkCapabilities nc) {
753         return satisfiedByNetworkCapabilities(nc, true);
754     }
755 
756     /**
757      * Checks that our immutable capabilities are the same as those of the given
758      * {@code NetworkCapabilities}.
759      *
760      * @hide
761      */
equalImmutableCapabilities(NetworkCapabilities nc)762     public boolean equalImmutableCapabilities(NetworkCapabilities nc) {
763         if (nc == null) return false;
764         return (equalsNetCapabilitiesImmutable(nc) &&
765                 equalsTransportTypes(nc) &&
766                 equalsSpecifier(nc));
767     }
768 
769     /**
770      * Checks that our requestable capabilities are the same as those of the given
771      * {@code NetworkCapabilities}.
772      *
773      * @hide
774      */
equalRequestableCapabilities(NetworkCapabilities nc)775     public boolean equalRequestableCapabilities(NetworkCapabilities nc) {
776         if (nc == null) return false;
777         return (equalsNetCapabilitiesRequestable(nc) &&
778                 equalsTransportTypes(nc) &&
779                 equalsSpecifier(nc));
780     }
781 
782     @Override
equals(Object obj)783     public boolean equals(Object obj) {
784         if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
785         NetworkCapabilities that = (NetworkCapabilities)obj;
786         return (equalsNetCapabilities(that) &&
787                 equalsTransportTypes(that) &&
788                 equalsLinkBandwidths(that) &&
789                 equalsSignalStrength(that) &&
790                 equalsSpecifier(that));
791     }
792 
793     @Override
hashCode()794     public int hashCode() {
795         return ((int)(mNetworkCapabilities & 0xFFFFFFFF) +
796                 ((int)(mNetworkCapabilities >> 32) * 3) +
797                 ((int)(mTransportTypes & 0xFFFFFFFF) * 5) +
798                 ((int)(mTransportTypes >> 32) * 7) +
799                 (mLinkUpBandwidthKbps * 11) +
800                 (mLinkDownBandwidthKbps * 13) +
801                 Objects.hashCode(mNetworkSpecifier) * 17 +
802                 (mSignalStrength * 19));
803     }
804 
805     @Override
describeContents()806     public int describeContents() {
807         return 0;
808     }
809     @Override
writeToParcel(Parcel dest, int flags)810     public void writeToParcel(Parcel dest, int flags) {
811         dest.writeLong(mNetworkCapabilities);
812         dest.writeLong(mTransportTypes);
813         dest.writeInt(mLinkUpBandwidthKbps);
814         dest.writeInt(mLinkDownBandwidthKbps);
815         dest.writeParcelable((Parcelable) mNetworkSpecifier, flags);
816         dest.writeInt(mSignalStrength);
817     }
818 
819     public static final Creator<NetworkCapabilities> CREATOR =
820         new Creator<NetworkCapabilities>() {
821             @Override
822             public NetworkCapabilities createFromParcel(Parcel in) {
823                 NetworkCapabilities netCap = new NetworkCapabilities();
824 
825                 netCap.mNetworkCapabilities = in.readLong();
826                 netCap.mTransportTypes = in.readLong();
827                 netCap.mLinkUpBandwidthKbps = in.readInt();
828                 netCap.mLinkDownBandwidthKbps = in.readInt();
829                 netCap.mNetworkSpecifier = in.readParcelable(null);
830                 netCap.mSignalStrength = in.readInt();
831                 return netCap;
832             }
833             @Override
834             public NetworkCapabilities[] newArray(int size) {
835                 return new NetworkCapabilities[size];
836             }
837         };
838 
839     @Override
toString()840     public String toString() {
841         int[] types = getTransportTypes();
842         String transports = (types.length > 0) ? " Transports: " + transportNamesOf(types) : "";
843 
844         types = getCapabilities();
845         String capabilities = (types.length > 0 ? " Capabilities: " : "");
846         for (int i = 0; i < types.length; ) {
847             switch (types[i]) {
848                 case NET_CAPABILITY_MMS:            capabilities += "MMS"; break;
849                 case NET_CAPABILITY_SUPL:           capabilities += "SUPL"; break;
850                 case NET_CAPABILITY_DUN:            capabilities += "DUN"; break;
851                 case NET_CAPABILITY_FOTA:           capabilities += "FOTA"; break;
852                 case NET_CAPABILITY_IMS:            capabilities += "IMS"; break;
853                 case NET_CAPABILITY_CBS:            capabilities += "CBS"; break;
854                 case NET_CAPABILITY_WIFI_P2P:       capabilities += "WIFI_P2P"; break;
855                 case NET_CAPABILITY_IA:             capabilities += "IA"; break;
856                 case NET_CAPABILITY_RCS:            capabilities += "RCS"; break;
857                 case NET_CAPABILITY_XCAP:           capabilities += "XCAP"; break;
858                 case NET_CAPABILITY_EIMS:           capabilities += "EIMS"; break;
859                 case NET_CAPABILITY_NOT_METERED:    capabilities += "NOT_METERED"; break;
860                 case NET_CAPABILITY_INTERNET:       capabilities += "INTERNET"; break;
861                 case NET_CAPABILITY_NOT_RESTRICTED: capabilities += "NOT_RESTRICTED"; break;
862                 case NET_CAPABILITY_TRUSTED:        capabilities += "TRUSTED"; break;
863                 case NET_CAPABILITY_NOT_VPN:        capabilities += "NOT_VPN"; break;
864                 case NET_CAPABILITY_VALIDATED:      capabilities += "VALIDATED"; break;
865                 case NET_CAPABILITY_CAPTIVE_PORTAL: capabilities += "CAPTIVE_PORTAL"; break;
866                 case NET_CAPABILITY_FOREGROUND:     capabilities += "FOREGROUND"; break;
867             }
868             if (++i < types.length) capabilities += "&";
869         }
870 
871         String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" +
872                 mLinkUpBandwidthKbps + "Kbps" : "");
873         String dnBand = ((mLinkDownBandwidthKbps > 0) ? " LinkDnBandwidth>=" +
874                 mLinkDownBandwidthKbps + "Kbps" : "");
875 
876         String specifier = (mNetworkSpecifier == null ?
877                 "" : " Specifier: <" + mNetworkSpecifier + ">");
878 
879         String signalStrength = (hasSignalStrength() ? " SignalStrength: " + mSignalStrength : "");
880 
881         return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + "]";
882     }
883 
884     /**
885      * @hide
886      */
transportNamesOf(int[] types)887     public static String transportNamesOf(int[] types) {
888         if (types == null || types.length == 0) {
889             return "";
890         }
891         StringBuilder transports = new StringBuilder();
892         for (int t : types) {
893             transports.append("|").append(transportNameOf(t));
894         }
895         return transports.substring(1);
896     }
897 
898     /**
899      * @hide
900      */
transportNameOf(int transport)901     public static String transportNameOf(int transport) {
902         if (transport < 0 || TRANSPORT_NAMES.length <= transport) {
903             return "UNKNOWN";
904         }
905         return TRANSPORT_NAMES[transport];
906     }
907 }
908