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