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      */
NetworkCapabilities()39     public NetworkCapabilities() {
40         clearAll();
41         mNetworkCapabilities = DEFAULT_CAPABILITIES;
42     }
43 
NetworkCapabilities(NetworkCapabilities nc)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         }
52     }
53 
54     /**
55      * Completely clears the contents of this object, removing even the capabilities that are set
56      * by default when the object is constructed.
57      * @hide
58      */
clearAll()59     public void clearAll() {
60         mNetworkCapabilities = mTransportTypes = 0;
61         mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0;
62         mNetworkSpecifier = null;
63     }
64 
65     /**
66      * Represents the network's capabilities.  If any are specified they will be satisfied
67      * by any Network that matches all of them.
68      */
69     private long mNetworkCapabilities;
70 
71     /**
72      * Indicates this is a network that has the ability to reach the
73      * carrier's MMSC for sending and receiving MMS messages.
74      */
75     public static final int NET_CAPABILITY_MMS            = 0;
76 
77     /**
78      * Indicates this is a network that has the ability to reach the carrier's
79      * SUPL server, used to retrieve GPS information.
80      */
81     public static final int NET_CAPABILITY_SUPL           = 1;
82 
83     /**
84      * Indicates this is a network that has the ability to reach the carrier's
85      * DUN or tethering gateway.
86      */
87     public static final int NET_CAPABILITY_DUN            = 2;
88 
89     /**
90      * Indicates this is a network that has the ability to reach the carrier's
91      * FOTA portal, used for over the air updates.
92      */
93     public static final int NET_CAPABILITY_FOTA           = 3;
94 
95     /**
96      * Indicates this is a network that has the ability to reach the carrier's
97      * IMS servers, used for network registration and signaling.
98      */
99     public static final int NET_CAPABILITY_IMS            = 4;
100 
101     /**
102      * Indicates this is a network that has the ability to reach the carrier's
103      * CBS servers, used for carrier specific services.
104      */
105     public static final int NET_CAPABILITY_CBS            = 5;
106 
107     /**
108      * Indicates this is a network that has the ability to reach a Wi-Fi direct
109      * peer.
110      */
111     public static final int NET_CAPABILITY_WIFI_P2P       = 6;
112 
113     /**
114      * Indicates this is a network that has the ability to reach a carrier's
115      * Initial Attach servers.
116      */
117     public static final int NET_CAPABILITY_IA             = 7;
118 
119     /**
120      * Indicates this is a network that has the ability to reach a carrier's
121      * RCS servers, used for Rich Communication Services.
122      */
123     public static final int NET_CAPABILITY_RCS            = 8;
124 
125     /**
126      * Indicates this is a network that has the ability to reach a carrier's
127      * XCAP servers, used for configuration and control.
128      */
129     public static final int NET_CAPABILITY_XCAP           = 9;
130 
131     /**
132      * Indicates this is a network that has the ability to reach a carrier's
133      * Emergency IMS servers or other services, used for network signaling
134      * during emergency calls.
135      */
136     public static final int NET_CAPABILITY_EIMS           = 10;
137 
138     /**
139      * Indicates that this network is unmetered.
140      */
141     public static final int NET_CAPABILITY_NOT_METERED    = 11;
142 
143     /**
144      * Indicates that this network should be able to reach the internet.
145      */
146     public static final int NET_CAPABILITY_INTERNET       = 12;
147 
148     /**
149      * Indicates that this network is available for general use.  If this is not set
150      * applications should not attempt to communicate on this network.  Note that this
151      * is simply informative and not enforcement - enforcement is handled via other means.
152      * Set by default.
153      */
154     public static final int NET_CAPABILITY_NOT_RESTRICTED = 13;
155 
156     /**
157      * Indicates that the user has indicated implicit trust of this network.  This
158      * generally means it's a sim-selected carrier, a plugged in ethernet, a paired
159      * BT device or a wifi the user asked to connect to.  Untrusted networks
160      * are probably limited to unknown wifi AP.  Set by default.
161      */
162     public static final int NET_CAPABILITY_TRUSTED        = 14;
163 
164     /**
165      * Indicates that this network is not a VPN.  This capability is set by default and should be
166      * explicitly cleared for VPN networks.
167      */
168     public static final int NET_CAPABILITY_NOT_VPN        = 15;
169 
170     /**
171      * Indicates that connectivity on this network was successfully validated. For example, for a
172      * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully
173      * detected.
174      */
175     public static final int NET_CAPABILITY_VALIDATED      = 16;
176 
177     /**
178      * Indicates that this network was found to have a captive portal in place last time it was
179      * probed.
180      */
181     public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17;
182 
183     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
184     private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_CAPTIVE_PORTAL;
185 
186     /**
187      * Capabilities that are set by default when the object is constructed.
188      */
189     private static final long DEFAULT_CAPABILITIES =
190             (1 << NET_CAPABILITY_NOT_RESTRICTED) |
191             (1 << NET_CAPABILITY_TRUSTED) |
192             (1 << NET_CAPABILITY_NOT_VPN);
193 
194     /**
195      * Capabilities that suggest that a network is restricted.
196      * {@see #maybeMarkCapabilitiesRestricted}.
197      */
198     private static final long RESTRICTED_CAPABILITIES =
199             (1 << NET_CAPABILITY_CBS) |
200             (1 << NET_CAPABILITY_DUN) |
201             (1 << NET_CAPABILITY_EIMS) |
202             (1 << NET_CAPABILITY_FOTA) |
203             (1 << NET_CAPABILITY_IA) |
204             (1 << NET_CAPABILITY_IMS) |
205             (1 << NET_CAPABILITY_RCS) |
206             (1 << NET_CAPABILITY_XCAP);
207 
208     /**
209      * Adds the given capability to this {@code NetworkCapability} instance.
210      * Multiple capabilities may be applied sequentially.  Note that when searching
211      * for a network to satisfy a request, all capabilities requested must be satisfied.
212      *
213      * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
214      * @return This NetworkCapability to facilitate chaining.
215      * @hide
216      */
addCapability(int capability)217     public NetworkCapabilities addCapability(int capability) {
218         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
219             throw new IllegalArgumentException("NetworkCapability out of range");
220         }
221         mNetworkCapabilities |= 1 << capability;
222         return this;
223     }
224 
225     /**
226      * Removes (if found) the given capability from this {@code NetworkCapability} instance.
227      *
228      * @param capability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
229      * @return This NetworkCapability to facilitate chaining.
230      * @hide
231      */
removeCapability(int capability)232     public NetworkCapabilities removeCapability(int capability) {
233         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
234             throw new IllegalArgumentException("NetworkCapability out of range");
235         }
236         mNetworkCapabilities &= ~(1 << capability);
237         return this;
238     }
239 
240     /**
241      * Gets all the capabilities set on this {@code NetworkCapability} instance.
242      *
243      * @return an array of {@code NetworkCapabilities.NET_CAPABILITY_*} values
244      *         for this instance.
245      * @hide
246      */
getCapabilities()247     public int[] getCapabilities() {
248         return enumerateBits(mNetworkCapabilities);
249     }
250 
251     /**
252      * Tests for the presence of a capabilitity on this instance.
253      *
254      * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
255      * @return {@code true} if set on this instance.
256      */
hasCapability(int capability)257     public boolean hasCapability(int capability) {
258         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
259             return false;
260         }
261         return ((mNetworkCapabilities & (1 << capability)) != 0);
262     }
263 
enumerateBits(long val)264     private int[] enumerateBits(long val) {
265         int size = Long.bitCount(val);
266         int[] result = new int[size];
267         int index = 0;
268         int resource = 0;
269         while (val > 0) {
270             if ((val & 1) == 1) result[index++] = resource;
271             val = val >> 1;
272             resource++;
273         }
274         return result;
275     }
276 
combineNetCapabilities(NetworkCapabilities nc)277     private void combineNetCapabilities(NetworkCapabilities nc) {
278         this.mNetworkCapabilities |= nc.mNetworkCapabilities;
279     }
280 
satisfiedByNetCapabilities(NetworkCapabilities nc)281     private boolean satisfiedByNetCapabilities(NetworkCapabilities nc) {
282         return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities);
283     }
284 
285     /** @hide */
equalsNetCapabilities(NetworkCapabilities nc)286     public boolean equalsNetCapabilities(NetworkCapabilities nc) {
287         return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
288     }
289 
290     /**
291      * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
292      * typically provided by restricted networks.
293      *
294      * TODO: consider:
295      * - Renaming it to guessRestrictedCapability and make it set the
296      *   restricted capability bit in addition to clearing it.
297      * @hide
298      */
maybeMarkCapabilitiesRestricted()299     public void maybeMarkCapabilitiesRestricted() {
300         // If all the capabilities are typically provided by restricted networks, conclude that this
301         // network is restricted.
302         if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0 &&
303                 // Must have at least some restricted capabilities, otherwise a request for an
304                 // internet-less network will get marked restricted.
305                 (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0) {
306             removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
307         }
308     }
309 
310     /**
311      * Representing the transport type.  Apps should generally not care about transport.  A
312      * request for a fast internet connection could be satisfied by a number of different
313      * transports.  If any are specified here it will be satisfied a Network that matches
314      * any of them.  If a caller doesn't care about the transport it should not specify any.
315      */
316     private long mTransportTypes;
317 
318     /**
319      * Indicates this network uses a Cellular transport.
320      */
321     public static final int TRANSPORT_CELLULAR = 0;
322 
323     /**
324      * Indicates this network uses a Wi-Fi transport.
325      */
326     public static final int TRANSPORT_WIFI = 1;
327 
328     /**
329      * Indicates this network uses a Bluetooth transport.
330      */
331     public static final int TRANSPORT_BLUETOOTH = 2;
332 
333     /**
334      * Indicates this network uses an Ethernet transport.
335      */
336     public static final int TRANSPORT_ETHERNET = 3;
337 
338     /**
339      * Indicates this network uses a VPN transport.
340      */
341     public static final int TRANSPORT_VPN = 4;
342 
343     private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
344     private static final int MAX_TRANSPORT = TRANSPORT_VPN;
345 
346     /**
347      * Adds the given transport type to this {@code NetworkCapability} instance.
348      * Multiple transports may be applied sequentially.  Note that when searching
349      * for a network to satisfy a request, any listed in the request will satisfy the request.
350      * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a
351      * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network
352      * to be selected.  This is logically different than
353      * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
354      *
355      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
356      * @return This NetworkCapability to facilitate chaining.
357      * @hide
358      */
addTransportType(int transportType)359     public NetworkCapabilities addTransportType(int transportType) {
360         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
361             throw new IllegalArgumentException("TransportType out of range");
362         }
363         mTransportTypes |= 1 << transportType;
364         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
365         return this;
366     }
367 
368     /**
369      * Removes (if found) the given transport from this {@code NetworkCapability} instance.
370      *
371      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
372      * @return This NetworkCapability to facilitate chaining.
373      * @hide
374      */
removeTransportType(int transportType)375     public NetworkCapabilities removeTransportType(int transportType) {
376         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
377             throw new IllegalArgumentException("TransportType out of range");
378         }
379         mTransportTypes &= ~(1 << transportType);
380         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
381         return this;
382     }
383 
384     /**
385      * Gets all the transports set on this {@code NetworkCapability} instance.
386      *
387      * @return an array of {@code NetworkCapabilities.TRANSPORT_*} values
388      *         for this instance.
389      * @hide
390      */
getTransportTypes()391     public int[] getTransportTypes() {
392         return enumerateBits(mTransportTypes);
393     }
394 
395     /**
396      * Tests for the presence of a transport on this instance.
397      *
398      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be tested for.
399      * @return {@code true} if set on this instance.
400      */
hasTransport(int transportType)401     public boolean hasTransport(int transportType) {
402         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
403             return false;
404         }
405         return ((mTransportTypes & (1 << transportType)) != 0);
406     }
407 
combineTransportTypes(NetworkCapabilities nc)408     private void combineTransportTypes(NetworkCapabilities nc) {
409         this.mTransportTypes |= nc.mTransportTypes;
410     }
satisfiedByTransportTypes(NetworkCapabilities nc)411     private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
412         return ((this.mTransportTypes == 0) ||
413                 ((this.mTransportTypes & nc.mTransportTypes) != 0));
414     }
415     /** @hide */
equalsTransportTypes(NetworkCapabilities nc)416     public boolean equalsTransportTypes(NetworkCapabilities nc) {
417         return (nc.mTransportTypes == this.mTransportTypes);
418     }
419 
420     /**
421      * Passive link bandwidth.  This is a rough guide of the expected peak bandwidth
422      * for the first hop on the given transport.  It is not measured, but may take into account
423      * link parameters (Radio technology, allocated channels, etc).
424      */
425     private int mLinkUpBandwidthKbps;
426     private int mLinkDownBandwidthKbps;
427 
428     /**
429      * Sets the upstream bandwidth for this network in Kbps.  This always only refers to
430      * the estimated first hop transport bandwidth.
431      * <p>
432      * Note that when used to request a network, this specifies the minimum acceptable.
433      * When received as the state of an existing network this specifies the typical
434      * first hop bandwidth expected.  This is never measured, but rather is inferred
435      * from technology type and other link parameters.  It could be used to differentiate
436      * between very slow 1xRTT cellular links and other faster networks or even between
437      * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
438      * fast backhauls and slow backhauls.
439      *
440      * @param upKbps the estimated first hop upstream (device to network) bandwidth.
441      * @hide
442      */
setLinkUpstreamBandwidthKbps(int upKbps)443     public void setLinkUpstreamBandwidthKbps(int upKbps) {
444         mLinkUpBandwidthKbps = upKbps;
445     }
446 
447     /**
448      * Retrieves the upstream bandwidth for this network in Kbps.  This always only refers to
449      * the estimated first hop transport bandwidth.
450      *
451      * @return The estimated first hop upstream (device to network) bandwidth.
452      */
getLinkUpstreamBandwidthKbps()453     public int getLinkUpstreamBandwidthKbps() {
454         return mLinkUpBandwidthKbps;
455     }
456 
457     /**
458      * Sets the downstream bandwidth for this network in Kbps.  This always only refers to
459      * the estimated first hop transport bandwidth.
460      * <p>
461      * Note that when used to request a network, this specifies the minimum acceptable.
462      * When received as the state of an existing network this specifies the typical
463      * first hop bandwidth expected.  This is never measured, but rather is inferred
464      * from technology type and other link parameters.  It could be used to differentiate
465      * between very slow 1xRTT cellular links and other faster networks or even between
466      * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
467      * fast backhauls and slow backhauls.
468      *
469      * @param downKbps the estimated first hop downstream (network to device) bandwidth.
470      * @hide
471      */
setLinkDownstreamBandwidthKbps(int downKbps)472     public void setLinkDownstreamBandwidthKbps(int downKbps) {
473         mLinkDownBandwidthKbps = downKbps;
474     }
475 
476     /**
477      * Retrieves the downstream bandwidth for this network in Kbps.  This always only refers to
478      * the estimated first hop transport bandwidth.
479      *
480      * @return The estimated first hop downstream (network to device) bandwidth.
481      */
getLinkDownstreamBandwidthKbps()482     public int getLinkDownstreamBandwidthKbps() {
483         return mLinkDownBandwidthKbps;
484     }
485 
combineLinkBandwidths(NetworkCapabilities nc)486     private void combineLinkBandwidths(NetworkCapabilities nc) {
487         this.mLinkUpBandwidthKbps =
488                 Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps);
489         this.mLinkDownBandwidthKbps =
490                 Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps);
491     }
satisfiedByLinkBandwidths(NetworkCapabilities nc)492     private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) {
493         return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps ||
494                 this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
495     }
equalsLinkBandwidths(NetworkCapabilities nc)496     private boolean equalsLinkBandwidths(NetworkCapabilities nc) {
497         return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
498                 this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
499     }
500 
501     private String mNetworkSpecifier;
502     /**
503      * Sets the optional bearer specific network specifier.
504      * This has no meaning if a single transport is also not specified, so calling
505      * this without a single transport set will generate an exception, as will
506      * subsequently adding or removing transports after this is set.
507      * </p>
508      * The interpretation of this {@code String} is bearer specific and bearers that use
509      * it should document their particulars.  For example, Bluetooth may use some sort of
510      * device id while WiFi could used SSID and/or BSSID.  Cellular may use carrier SPN (name)
511      * or Subscription ID.
512      *
513      * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
514      *                         specific network specifier where the bearer has a choice of
515      *                         networks.
516      * @hide
517      */
setNetworkSpecifier(String networkSpecifier)518     public void setNetworkSpecifier(String networkSpecifier) {
519         if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) {
520             throw new IllegalStateException("Must have a single transport specified to use " +
521                     "setNetworkSpecifier");
522         }
523         mNetworkSpecifier = networkSpecifier;
524     }
525 
526     /**
527      * Gets the optional bearer specific network specifier.
528      *
529      * @return The optional {@code String} specifying the bearer specific network specifier.
530      *         See {@link #setNetworkSpecifier}.
531      * @hide
532      */
getNetworkSpecifier()533     public String getNetworkSpecifier() {
534         return mNetworkSpecifier;
535     }
536 
combineSpecifiers(NetworkCapabilities nc)537     private void combineSpecifiers(NetworkCapabilities nc) {
538         String otherSpecifier = nc.getNetworkSpecifier();
539         if (TextUtils.isEmpty(otherSpecifier)) return;
540         if (TextUtils.isEmpty(mNetworkSpecifier) == false) {
541             throw new IllegalStateException("Can't combine two networkSpecifiers");
542         }
543         setNetworkSpecifier(otherSpecifier);
544     }
satisfiedBySpecifier(NetworkCapabilities nc)545     private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
546         return (TextUtils.isEmpty(mNetworkSpecifier) ||
547                 mNetworkSpecifier.equals(nc.mNetworkSpecifier));
548     }
equalsSpecifier(NetworkCapabilities nc)549     private boolean equalsSpecifier(NetworkCapabilities nc) {
550         if (TextUtils.isEmpty(mNetworkSpecifier)) {
551             return TextUtils.isEmpty(nc.mNetworkSpecifier);
552         } else {
553             return mNetworkSpecifier.equals(nc.mNetworkSpecifier);
554         }
555     }
556 
557     /**
558      * Combine a set of Capabilities to this one.  Useful for coming up with the complete set
559      * {@hide}
560      */
combineCapabilities(NetworkCapabilities nc)561     public void combineCapabilities(NetworkCapabilities nc) {
562         combineNetCapabilities(nc);
563         combineTransportTypes(nc);
564         combineLinkBandwidths(nc);
565         combineSpecifiers(nc);
566     }
567 
568     /**
569      * Check if our requirements are satisfied by the given Capabilities.
570      * {@hide}
571      */
satisfiedByNetworkCapabilities(NetworkCapabilities nc)572     public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
573         return (nc != null &&
574                 satisfiedByNetCapabilities(nc) &&
575                 satisfiedByTransportTypes(nc) &&
576                 satisfiedByLinkBandwidths(nc) &&
577                 satisfiedBySpecifier(nc));
578     }
579 
580     @Override
equals(Object obj)581     public boolean equals(Object obj) {
582         if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
583         NetworkCapabilities that = (NetworkCapabilities)obj;
584         return (equalsNetCapabilities(that) &&
585                 equalsTransportTypes(that) &&
586                 equalsLinkBandwidths(that) &&
587                 equalsSpecifier(that));
588     }
589 
590     @Override
hashCode()591     public int hashCode() {
592         return ((int)(mNetworkCapabilities & 0xFFFFFFFF) +
593                 ((int)(mNetworkCapabilities >> 32) * 3) +
594                 ((int)(mTransportTypes & 0xFFFFFFFF) * 5) +
595                 ((int)(mTransportTypes >> 32) * 7) +
596                 (mLinkUpBandwidthKbps * 11) +
597                 (mLinkDownBandwidthKbps * 13) +
598                 (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17));
599     }
600 
601     @Override
describeContents()602     public int describeContents() {
603         return 0;
604     }
605     @Override
writeToParcel(Parcel dest, int flags)606     public void writeToParcel(Parcel dest, int flags) {
607         dest.writeLong(mNetworkCapabilities);
608         dest.writeLong(mTransportTypes);
609         dest.writeInt(mLinkUpBandwidthKbps);
610         dest.writeInt(mLinkDownBandwidthKbps);
611         dest.writeString(mNetworkSpecifier);
612     }
613     public static final Creator<NetworkCapabilities> CREATOR =
614         new Creator<NetworkCapabilities>() {
615             @Override
616             public NetworkCapabilities createFromParcel(Parcel in) {
617                 NetworkCapabilities netCap = new NetworkCapabilities();
618 
619                 netCap.mNetworkCapabilities = in.readLong();
620                 netCap.mTransportTypes = in.readLong();
621                 netCap.mLinkUpBandwidthKbps = in.readInt();
622                 netCap.mLinkDownBandwidthKbps = in.readInt();
623                 netCap.mNetworkSpecifier = in.readString();
624                 return netCap;
625             }
626             @Override
627             public NetworkCapabilities[] newArray(int size) {
628                 return new NetworkCapabilities[size];
629             }
630         };
631 
632     @Override
toString()633     public String toString() {
634         int[] types = getTransportTypes();
635         String transports = (types.length > 0 ? " Transports: " : "");
636         for (int i = 0; i < types.length;) {
637             switch (types[i]) {
638                 case TRANSPORT_CELLULAR:    transports += "CELLULAR"; break;
639                 case TRANSPORT_WIFI:        transports += "WIFI"; break;
640                 case TRANSPORT_BLUETOOTH:   transports += "BLUETOOTH"; break;
641                 case TRANSPORT_ETHERNET:    transports += "ETHERNET"; break;
642                 case TRANSPORT_VPN:         transports += "VPN"; break;
643             }
644             if (++i < types.length) transports += "|";
645         }
646 
647         types = getCapabilities();
648         String capabilities = (types.length > 0 ? " Capabilities: " : "");
649         for (int i = 0; i < types.length; ) {
650             switch (types[i]) {
651                 case NET_CAPABILITY_MMS:            capabilities += "MMS"; break;
652                 case NET_CAPABILITY_SUPL:           capabilities += "SUPL"; break;
653                 case NET_CAPABILITY_DUN:            capabilities += "DUN"; break;
654                 case NET_CAPABILITY_FOTA:           capabilities += "FOTA"; break;
655                 case NET_CAPABILITY_IMS:            capabilities += "IMS"; break;
656                 case NET_CAPABILITY_CBS:            capabilities += "CBS"; break;
657                 case NET_CAPABILITY_WIFI_P2P:       capabilities += "WIFI_P2P"; break;
658                 case NET_CAPABILITY_IA:             capabilities += "IA"; break;
659                 case NET_CAPABILITY_RCS:            capabilities += "RCS"; break;
660                 case NET_CAPABILITY_XCAP:           capabilities += "XCAP"; break;
661                 case NET_CAPABILITY_EIMS:           capabilities += "EIMS"; break;
662                 case NET_CAPABILITY_NOT_METERED:    capabilities += "NOT_METERED"; break;
663                 case NET_CAPABILITY_INTERNET:       capabilities += "INTERNET"; break;
664                 case NET_CAPABILITY_NOT_RESTRICTED: capabilities += "NOT_RESTRICTED"; break;
665                 case NET_CAPABILITY_TRUSTED:        capabilities += "TRUSTED"; break;
666                 case NET_CAPABILITY_NOT_VPN:        capabilities += "NOT_VPN"; break;
667                 case NET_CAPABILITY_VALIDATED:      capabilities += "VALIDATED"; break;
668                 case NET_CAPABILITY_CAPTIVE_PORTAL: capabilities += "CAPTIVE_PORTAL"; break;
669             }
670             if (++i < types.length) capabilities += "&";
671         }
672 
673         String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" +
674                 mLinkUpBandwidthKbps + "Kbps" : "");
675         String dnBand = ((mLinkDownBandwidthKbps > 0) ? " LinkDnBandwidth>=" +
676                 mLinkDownBandwidthKbps + "Kbps" : "");
677 
678         String specifier = (mNetworkSpecifier == null ?
679                 "" : " Specifier: <" + mNetworkSpecifier + ">");
680 
681         return "[" + transports + capabilities + upBand + dnBand + specifier + "]";
682     }
683 }
684