OSDN Git Service

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