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