OSDN Git Service

am fe5e7e92: Merge "docs: Fix issue with onCreate() method declaration in file backup...
[android-x86/frameworks-base.git] / core / java / android / net / NetworkCapabilities.java
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 android.util.Log;
23
24 import java.lang.IllegalArgumentException;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.Set;
32
33 /**
34  * This class represents the capabilities of a network.  This is used both to specify
35  * needs to {@link ConnectivityManager} and when inspecting a network.
36  *
37  * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method
38  * of network selection.  Rather than indicate a need for Wi-Fi because an application
39  * needs high bandwidth and risk obselence when a new, fast network appears (like LTE),
40  * the application should specify it needs high bandwidth.  Similarly if an application
41  * needs an unmetered network for a bulk transfer it can specify that rather than assuming
42  * all cellular based connections are metered and all Wi-Fi based connections are not.
43  */
44 public final class NetworkCapabilities implements Parcelable {
45     private static final String TAG = "NetworkCapabilities";
46     private static final boolean DBG = false;
47
48     /**
49      * @hide
50      */
51     public NetworkCapabilities() {
52     }
53
54     public NetworkCapabilities(NetworkCapabilities nc) {
55         if (nc != null) {
56             mNetworkCapabilities = nc.mNetworkCapabilities;
57             mTransportTypes = nc.mTransportTypes;
58             mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
59             mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
60             mNetworkSpecifier = nc.mNetworkSpecifier;
61         }
62     }
63
64     /**
65      * Represents the network's capabilities.  If any are specified they will be satisfied
66      * by any Network that matches all of them.
67      */
68     private long mNetworkCapabilities = (1 << NET_CAPABILITY_NOT_RESTRICTED) |
69             (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_NOT_VPN);
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, used for network signaling during emergency calls.
134      */
135     public static final int NET_CAPABILITY_EIMS           = 10;
136
137     /**
138      * Indicates that this network is unmetered.
139      */
140     public static final int NET_CAPABILITY_NOT_METERED    = 11;
141
142     /**
143      * Indicates that this network should be able to reach the internet.
144      */
145     public static final int NET_CAPABILITY_INTERNET       = 12;
146
147     /**
148      * Indicates that this network is available for general use.  If this is not set
149      * applications should not attempt to communicate on this network.  Note that this
150      * is simply informative and not enforcement - enforcement is handled via other means.
151      * Set by default.
152      */
153     public static final int NET_CAPABILITY_NOT_RESTRICTED = 13;
154
155     /**
156      * Indicates that the user has indicated implicit trust of this network.  This
157      * generally means it's a sim-selected carrier, a plugged in ethernet, a paired
158      * BT device or a wifi the user asked to connect to.  Untrusted networks
159      * are probably limited to unknown wifi AP.  Set by default.
160      */
161     public static final int NET_CAPABILITY_TRUSTED        = 14;
162
163     /*
164      * Indicates that this network is not a VPN.  This capability is set by default and should be
165      * explicitly cleared when creating VPN networks.
166      */
167     public static final int NET_CAPABILITY_NOT_VPN        = 15;
168
169
170     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
171     private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VPN;
172
173     /**
174      * Adds the given capability to this {@code NetworkCapability} instance.
175      * Multiple capabilities may be applied sequentially.  Note that when searching
176      * for a network to satisfy a request, all capabilities requested must be satisfied.
177      *
178      * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
179      * @return This NetworkCapability to facilitate chaining.
180      * @hide
181      */
182     public NetworkCapabilities addCapability(int capability) {
183         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
184             throw new IllegalArgumentException("NetworkCapability out of range");
185         }
186         mNetworkCapabilities |= 1 << capability;
187         return this;
188     }
189
190     /**
191      * Removes (if found) the given capability from this {@code NetworkCapability} instance.
192      *
193      * @param capability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
194      * @return This NetworkCapability to facilitate chaining.
195      * @hide
196      */
197     public NetworkCapabilities removeCapability(int capability) {
198         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
199             throw new IllegalArgumentException("NetworkCapability out of range");
200         }
201         mNetworkCapabilities &= ~(1 << capability);
202         return this;
203     }
204
205     /**
206      * Gets all the capabilities set on this {@code NetworkCapability} instance.
207      *
208      * @return an array of {@code NetworkCapabilities.NET_CAPABILITY_*} values
209      *         for this instance.
210      * @hide
211      */
212     public int[] getCapabilities() {
213         return enumerateBits(mNetworkCapabilities);
214     }
215
216     /**
217      * Tests for the presence of a capabilitity on this instance.
218      *
219      * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
220      * @return {@code true} if set on this instance.
221      */
222     public boolean hasCapability(int capability) {
223         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
224             return false;
225         }
226         return ((mNetworkCapabilities & (1 << capability)) != 0);
227     }
228
229     private int[] enumerateBits(long val) {
230         int size = Long.bitCount(val);
231         int[] result = new int[size];
232         int index = 0;
233         int resource = 0;
234         while (val > 0) {
235             if ((val & 1) == 1) result[index++] = resource;
236             val = val >> 1;
237             resource++;
238         }
239         return result;
240     }
241
242     private void combineNetCapabilities(NetworkCapabilities nc) {
243         this.mNetworkCapabilities |= nc.mNetworkCapabilities;
244     }
245
246     private boolean satisfiedByNetCapabilities(NetworkCapabilities nc) {
247         return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities);
248     }
249
250     private boolean equalsNetCapabilities(NetworkCapabilities nc) {
251         return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
252     }
253
254     /**
255      * Representing the transport type.  Apps should generally not care about transport.  A
256      * request for a fast internet connection could be satisfied by a number of different
257      * transports.  If any are specified here it will be satisfied a Network that matches
258      * any of them.  If a caller doesn't care about the transport it should not specify any.
259      */
260     private long mTransportTypes;
261
262     /**
263      * Indicates this network uses a Cellular transport.
264      */
265     public static final int TRANSPORT_CELLULAR = 0;
266
267     /**
268      * Indicates this network uses a Wi-Fi transport.
269      */
270     public static final int TRANSPORT_WIFI = 1;
271
272     /**
273      * Indicates this network uses a Bluetooth transport.
274      */
275     public static final int TRANSPORT_BLUETOOTH = 2;
276
277     /**
278      * Indicates this network uses an Ethernet transport.
279      */
280     public static final int TRANSPORT_ETHERNET = 3;
281
282     /**
283      * Indicates this network uses a VPN transport.
284      */
285     public static final int TRANSPORT_VPN = 4;
286
287     private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
288     private static final int MAX_TRANSPORT = TRANSPORT_VPN;
289
290     /**
291      * Adds the given transport type to this {@code NetworkCapability} instance.
292      * Multiple transports may be applied sequentially.  Note that when searching
293      * for a network to satisfy a request, any listed in the request will satisfy the request.
294      * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a
295      * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network
296      * to be selected.  This is logically different than
297      * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
298      *
299      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
300      * @return This NetworkCapability to facilitate chaining.
301      * @hide
302      */
303     public NetworkCapabilities addTransportType(int transportType) {
304         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
305             throw new IllegalArgumentException("TransportType out of range");
306         }
307         mTransportTypes |= 1 << transportType;
308         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
309         return this;
310     }
311
312     /**
313      * Removes (if found) the given transport from this {@code NetworkCapability} instance.
314      *
315      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
316      * @return This NetworkCapability to facilitate chaining.
317      * @hide
318      */
319     public NetworkCapabilities removeTransportType(int transportType) {
320         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
321             throw new IllegalArgumentException("TransportType out of range");
322         }
323         mTransportTypes &= ~(1 << transportType);
324         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
325         return this;
326     }
327
328     /**
329      * Gets all the transports set on this {@code NetworkCapability} instance.
330      *
331      * @return an array of {@code NetworkCapabilities.TRANSPORT_*} values
332      *         for this instance.
333      * @hide
334      */
335     public int[] getTransportTypes() {
336         return enumerateBits(mTransportTypes);
337     }
338
339     /**
340      * Tests for the presence of a transport on this instance.
341      *
342      * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be tested for.
343      * @return {@code true} if set on this instance.
344      */
345     public boolean hasTransport(int transportType) {
346         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
347             return false;
348         }
349         return ((mTransportTypes & (1 << transportType)) != 0);
350     }
351
352     private void combineTransportTypes(NetworkCapabilities nc) {
353         this.mTransportTypes |= nc.mTransportTypes;
354     }
355     private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
356         return ((this.mTransportTypes == 0) ||
357                 ((this.mTransportTypes & nc.mTransportTypes) != 0));
358     }
359     private boolean equalsTransportTypes(NetworkCapabilities nc) {
360         return (nc.mTransportTypes == this.mTransportTypes);
361     }
362
363     /**
364      * Passive link bandwidth.  This is a rough guide of the expected peak bandwidth
365      * for the first hop on the given transport.  It is not measured, but may take into account
366      * link parameters (Radio technology, allocated channels, etc).
367      */
368     private int mLinkUpBandwidthKbps;
369     private int mLinkDownBandwidthKbps;
370
371     /**
372      * Sets the upstream bandwidth for this network in Kbps.  This always only refers to
373      * the estimated first hop transport bandwidth.
374      * <p>
375      * Note that when used to request a network, this specifies the minimum acceptable.
376      * When received as the state of an existing network this specifies the typical
377      * first hop bandwidth expected.  This is never measured, but rather is inferred
378      * from technology type and other link parameters.  It could be used to differentiate
379      * between very slow 1xRTT cellular links and other faster networks or even between
380      * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
381      * fast backhauls and slow backhauls.
382      *
383      * @param upKbps the estimated first hop upstream (device to network) bandwidth.
384      * @hide
385      */
386     public void setLinkUpstreamBandwidthKbps(int upKbps) {
387         mLinkUpBandwidthKbps = upKbps;
388     }
389
390     /**
391      * Retrieves the upstream bandwidth for this network in Kbps.  This always only refers to
392      * the estimated first hop transport bandwidth.
393      *
394      * @return The estimated first hop upstream (device to network) bandwidth.
395      */
396     public int getLinkUpstreamBandwidthKbps() {
397         return mLinkUpBandwidthKbps;
398     }
399
400     /**
401      * Sets the downstream bandwidth for this network in Kbps.  This always only refers to
402      * the estimated first hop transport bandwidth.
403      * <p>
404      * Note that when used to request a network, this specifies the minimum acceptable.
405      * When received as the state of an existing network this specifies the typical
406      * first hop bandwidth expected.  This is never measured, but rather is inferred
407      * from technology type and other link parameters.  It could be used to differentiate
408      * between very slow 1xRTT cellular links and other faster networks or even between
409      * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
410      * fast backhauls and slow backhauls.
411      *
412      * @param downKbps the estimated first hop downstream (network to device) bandwidth.
413      * @hide
414      */
415     public void setLinkDownstreamBandwidthKbps(int downKbps) {
416         mLinkDownBandwidthKbps = downKbps;
417     }
418
419     /**
420      * Retrieves the downstream bandwidth for this network in Kbps.  This always only refers to
421      * the estimated first hop transport bandwidth.
422      *
423      * @return The estimated first hop downstream (network to device) bandwidth.
424      */
425     public int getLinkDownstreamBandwidthKbps() {
426         return mLinkDownBandwidthKbps;
427     }
428
429     private void combineLinkBandwidths(NetworkCapabilities nc) {
430         this.mLinkUpBandwidthKbps =
431                 Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps);
432         this.mLinkDownBandwidthKbps =
433                 Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps);
434     }
435     private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) {
436         return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps ||
437                 this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
438     }
439     private boolean equalsLinkBandwidths(NetworkCapabilities nc) {
440         return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
441                 this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
442     }
443
444     private String mNetworkSpecifier;
445     /**
446      * Sets the optional bearer specific network specifier.
447      * This has no meaning if a single transport is also not specified, so calling
448      * this without a single transport set will generate an exception, as will
449      * subsequently adding or removing transports after this is set.
450      * </p>
451      * The interpretation of this {@code String} is bearer specific and bearers that use
452      * it should document their particulars.  For example, Bluetooth may use some sort of
453      * device id while WiFi could used SSID and/or BSSID.  Cellular may use carrier SPN (name)
454      * or Subscription ID.
455      *
456      * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
457      *                         specific network specifier where the bearer has a choice of
458      *                         networks.
459      * @hide
460      */
461     public void setNetworkSpecifier(String networkSpecifier) {
462         if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) {
463             throw new IllegalStateException("Must have a single transport specified to use " +
464                     "setNetworkSpecifier");
465         }
466         mNetworkSpecifier = networkSpecifier;
467     }
468
469     /**
470      * Gets the optional bearer specific network specifier.
471      *
472      * @return The optional {@code String} specifying the bearer specific network specifier.
473      *         See {@link #setNetworkSpecifier}.
474      * @hide
475      */
476     public String getNetworkSpecifier() {
477         return mNetworkSpecifier;
478     }
479
480     private void combineSpecifiers(NetworkCapabilities nc) {
481         String otherSpecifier = nc.getNetworkSpecifier();
482         if (TextUtils.isEmpty(otherSpecifier)) return;
483         if (TextUtils.isEmpty(mNetworkSpecifier) == false) {
484             throw new IllegalStateException("Can't combine two networkSpecifiers");
485         }
486         setNetworkSpecifier(otherSpecifier);
487     }
488     private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
489         return (TextUtils.isEmpty(mNetworkSpecifier) ||
490                 mNetworkSpecifier.equals(nc.mNetworkSpecifier));
491     }
492     private boolean equalsSpecifier(NetworkCapabilities nc) {
493         if (TextUtils.isEmpty(mNetworkSpecifier)) {
494             return TextUtils.isEmpty(nc.mNetworkSpecifier);
495         } else {
496             return mNetworkSpecifier.equals(nc.mNetworkSpecifier);
497         }
498     }
499
500     /**
501      * Combine a set of Capabilities to this one.  Useful for coming up with the complete set
502      * {@hide}
503      */
504     public void combineCapabilities(NetworkCapabilities nc) {
505         combineNetCapabilities(nc);
506         combineTransportTypes(nc);
507         combineLinkBandwidths(nc);
508         combineSpecifiers(nc);
509     }
510
511     /**
512      * Check if our requirements are satisfied by the given Capabilities.
513      * {@hide}
514      */
515     public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
516         return (nc != null &&
517                 satisfiedByNetCapabilities(nc) &&
518                 satisfiedByTransportTypes(nc) &&
519                 satisfiedByLinkBandwidths(nc) &&
520                 satisfiedBySpecifier(nc));
521     }
522
523     @Override
524     public boolean equals(Object obj) {
525         if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
526         NetworkCapabilities that = (NetworkCapabilities)obj;
527         return (equalsNetCapabilities(that) &&
528                 equalsTransportTypes(that) &&
529                 equalsLinkBandwidths(that) &&
530                 equalsSpecifier(that));
531     }
532
533     @Override
534     public int hashCode() {
535         return ((int)(mNetworkCapabilities & 0xFFFFFFFF) +
536                 ((int)(mNetworkCapabilities >> 32) * 3) +
537                 ((int)(mTransportTypes & 0xFFFFFFFF) * 5) +
538                 ((int)(mTransportTypes >> 32) * 7) +
539                 (mLinkUpBandwidthKbps * 11) +
540                 (mLinkDownBandwidthKbps * 13) +
541                 (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17));
542     }
543
544     public int describeContents() {
545         return 0;
546     }
547     public void writeToParcel(Parcel dest, int flags) {
548         dest.writeLong(mNetworkCapabilities);
549         dest.writeLong(mTransportTypes);
550         dest.writeInt(mLinkUpBandwidthKbps);
551         dest.writeInt(mLinkDownBandwidthKbps);
552         dest.writeString(mNetworkSpecifier);
553     }
554     public static final Creator<NetworkCapabilities> CREATOR =
555         new Creator<NetworkCapabilities>() {
556             public NetworkCapabilities createFromParcel(Parcel in) {
557                 NetworkCapabilities netCap = new NetworkCapabilities();
558
559                 netCap.mNetworkCapabilities = in.readLong();
560                 netCap.mTransportTypes = in.readLong();
561                 netCap.mLinkUpBandwidthKbps = in.readInt();
562                 netCap.mLinkDownBandwidthKbps = in.readInt();
563                 netCap.mNetworkSpecifier = in.readString();
564                 return netCap;
565             }
566             public NetworkCapabilities[] newArray(int size) {
567                 return new NetworkCapabilities[size];
568             }
569         };
570
571     public String toString() {
572         int[] types = getTransportTypes();
573         String transports = (types.length > 0 ? " Transports: " : "");
574         for (int i = 0; i < types.length;) {
575             switch (types[i]) {
576                 case TRANSPORT_CELLULAR:    transports += "CELLULAR"; break;
577                 case TRANSPORT_WIFI:        transports += "WIFI"; break;
578                 case TRANSPORT_BLUETOOTH:   transports += "BLUETOOTH"; break;
579                 case TRANSPORT_ETHERNET:    transports += "ETHERNET"; break;
580                 case TRANSPORT_VPN:         transports += "VPN"; break;
581             }
582             if (++i < types.length) transports += "|";
583         }
584
585         types = getCapabilities();
586         String capabilities = (types.length > 0 ? " Capabilities: " : "");
587         for (int i = 0; i < types.length; ) {
588             switch (types[i]) {
589                 case NET_CAPABILITY_MMS:            capabilities += "MMS"; break;
590                 case NET_CAPABILITY_SUPL:           capabilities += "SUPL"; break;
591                 case NET_CAPABILITY_DUN:            capabilities += "DUN"; break;
592                 case NET_CAPABILITY_FOTA:           capabilities += "FOTA"; break;
593                 case NET_CAPABILITY_IMS:            capabilities += "IMS"; break;
594                 case NET_CAPABILITY_CBS:            capabilities += "CBS"; break;
595                 case NET_CAPABILITY_WIFI_P2P:       capabilities += "WIFI_P2P"; break;
596                 case NET_CAPABILITY_IA:             capabilities += "IA"; break;
597                 case NET_CAPABILITY_RCS:            capabilities += "RCS"; break;
598                 case NET_CAPABILITY_XCAP:           capabilities += "XCAP"; break;
599                 case NET_CAPABILITY_EIMS:           capabilities += "EIMS"; break;
600                 case NET_CAPABILITY_NOT_METERED:    capabilities += "NOT_METERED"; break;
601                 case NET_CAPABILITY_INTERNET:       capabilities += "INTERNET"; break;
602                 case NET_CAPABILITY_NOT_RESTRICTED: capabilities += "NOT_RESTRICTED"; break;
603                 case NET_CAPABILITY_TRUSTED:        capabilities += "TRUSTED"; break;
604                 case NET_CAPABILITY_NOT_VPN:        capabilities += "NOT_VPN"; break;
605             }
606             if (++i < types.length) capabilities += "&";
607         }
608
609         String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" +
610                 mLinkUpBandwidthKbps + "Kbps" : "");
611         String dnBand = ((mLinkDownBandwidthKbps > 0) ? " LinkDnBandwidth>=" +
612                 mLinkDownBandwidthKbps + "Kbps" : "");
613
614         String specifier = (mNetworkSpecifier == null ?
615                 "" : " Specifier: <" + mNetworkSpecifier + ">");
616
617         return "[" + transports + capabilities + upBand + dnBand + specifier + "]";
618     }
619 }