Home | History | Annotate | Download | only in net
      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 import android.text.TextUtils;
     22 import 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  */
     35 public 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