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 static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SystemApi; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import com.android.modules.utils.build.SdkLevel; 28 29 import java.util.Objects; 30 31 /** 32 * Allows a network transport to provide the system with policy and configuration information about 33 * a particular network when registering a {@link NetworkAgent}. This information cannot change once the agent is registered. 34 * 35 * @hide 36 */ 37 @SystemApi 38 public final class NetworkAgentConfig implements Parcelable { 39 // TODO : make this object immutable. The fields that should stay mutable should likely 40 // migrate to NetworkAgentInfo. 41 42 /** 43 * If the {@link Network} is a VPN, whether apps are allowed to bypass the 44 * VPN. This is set by a {@link VpnService} and used by 45 * {@link ConnectivityManager} when creating a VPN. 46 * 47 * @hide 48 */ 49 public boolean allowBypass; 50 51 /** 52 * Set if the network was manually/explicitly connected to by the user either from settings 53 * or a 3rd party app. For example, turning on cell data is not explicit but tapping on a wifi 54 * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to 55 * connect to a particular access point is also explicit, though this may change in the future 56 * as we want apps to use the multinetwork apis. 57 * TODO : this is a bad name, because it sounds like the user just tapped on the network. 58 * It's not necessarily the case ; auto-reconnection to WiFi has this true for example. 59 * @hide 60 */ 61 public boolean explicitlySelected; 62 63 /** 64 * @return whether this network was explicitly selected by the user. 65 */ isExplicitlySelected()66 public boolean isExplicitlySelected() { 67 return explicitlySelected; 68 } 69 70 /** 71 * @return whether this VPN connection can be bypassed by the apps. 72 * 73 * @hide 74 */ 75 @SystemApi(client = MODULE_LIBRARIES) isBypassableVpn()76 public boolean isBypassableVpn() { 77 return allowBypass; 78 } 79 80 /** 81 * Set if the user desires to use this network even if it is unvalidated. This field has meaning 82 * only if {@link explicitlySelected} is true. If it is, this field must also be set to the 83 * appropriate value based on previous user choice. 84 * 85 * TODO : rename this field to match its accessor 86 * @hide 87 */ 88 public boolean acceptUnvalidated; 89 90 /** 91 * @return whether the system should accept this network even if it doesn't validate. 92 */ isUnvalidatedConnectivityAcceptable()93 public boolean isUnvalidatedConnectivityAcceptable() { 94 return acceptUnvalidated; 95 } 96 97 /** 98 * Whether the user explicitly set that this network should be validated even if presence of 99 * only partial internet connectivity. 100 * 101 * TODO : rename this field to match its accessor 102 * @hide 103 */ 104 public boolean acceptPartialConnectivity; 105 106 /** 107 * @return whether the system should validate this network even if it only offers partial 108 * Internet connectivity. 109 */ isPartialConnectivityAcceptable()110 public boolean isPartialConnectivityAcceptable() { 111 return acceptPartialConnectivity; 112 } 113 114 /** 115 * Set to avoid surfacing the "Sign in to network" notification. 116 * if carrier receivers/apps are registered to handle the carrier-specific provisioning 117 * procedure, a carrier specific provisioning notification will be placed. 118 * only one notification should be displayed. This field is set based on 119 * which notification should be used for provisioning. 120 * 121 * @hide 122 */ 123 public boolean provisioningNotificationDisabled; 124 125 /** 126 * 127 * @return whether the sign in to network notification is enabled by this configuration. 128 * @hide 129 */ isProvisioningNotificationEnabled()130 public boolean isProvisioningNotificationEnabled() { 131 return !provisioningNotificationDisabled; 132 } 133 134 /** 135 * For mobile networks, this is the subscriber ID (such as IMSI). 136 * 137 * @hide 138 */ 139 public String subscriberId; 140 141 /** 142 * @return the subscriber ID, or null if none. 143 * @hide 144 */ 145 @SystemApi(client = MODULE_LIBRARIES) 146 @Nullable getSubscriberId()147 public String getSubscriberId() { 148 return subscriberId; 149 } 150 151 /** 152 * Set to skip 464xlat. This means the device will treat the network as IPv6-only and 153 * will not attempt to detect a NAT64 via RFC 7050 DNS lookups. 154 * 155 * @hide 156 */ 157 public boolean skip464xlat; 158 159 /** 160 * @return whether NAT64 prefix detection is enabled. 161 * @hide 162 */ isNat64DetectionEnabled()163 public boolean isNat64DetectionEnabled() { 164 return !skip464xlat; 165 } 166 167 /** 168 * The legacy type of this network agent, or TYPE_NONE if unset. 169 * @hide 170 */ 171 public int legacyType = ConnectivityManager.TYPE_NONE; 172 173 /** 174 * @return the legacy type 175 */ 176 @ConnectivityManager.LegacyNetworkType getLegacyType()177 public int getLegacyType() { 178 return legacyType; 179 } 180 181 /** 182 * The legacy Sub type of this network agent, or TYPE_NONE if unset. 183 * @hide 184 */ 185 public int legacySubType = ConnectivityManager.TYPE_NONE; 186 187 /** 188 * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. 189 * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. 190 * 191 * This is not parceled, because it would not make sense. It's also ignored by the 192 * equals() and hashcode() methods. 193 * 194 * @hide 195 */ 196 public transient boolean hasShownBroken; 197 198 /** 199 * The name of the legacy network type. It's a free-form string used in logging. 200 * @hide 201 */ 202 @NonNull 203 public String legacyTypeName = ""; 204 205 /** 206 * @return the name of the legacy network type. It's a free-form string used in logging. 207 */ 208 @NonNull getLegacyTypeName()209 public String getLegacyTypeName() { 210 return legacyTypeName; 211 } 212 213 /** 214 * The name of the legacy Sub network type. It's a free-form string. 215 * @hide 216 */ 217 @NonNull 218 public String legacySubTypeName = ""; 219 220 /** 221 * The legacy extra info of the agent. The extra info should only be : 222 * <ul> 223 * <li>For cellular agents, the APN name.</li> 224 * <li>For ethernet agents, the interface name.</li> 225 * </ul> 226 * @hide 227 */ 228 @NonNull 229 private String mLegacyExtraInfo = ""; 230 231 /** 232 * The legacy extra info of the agent. 233 * @hide 234 */ 235 @NonNull getLegacyExtraInfo()236 public String getLegacyExtraInfo() { 237 return mLegacyExtraInfo; 238 } 239 240 /** 241 * If the {@link Network} is a VPN, whether the local traffic is exempted from the VPN. 242 * @hide 243 */ 244 public boolean excludeLocalRouteVpn = false; 245 246 /** 247 * @return whether local traffic is excluded from the VPN network. 248 * @hide 249 */ areLocalRoutesExcludedForVpn()250 public boolean areLocalRoutesExcludedForVpn() { 251 return excludeLocalRouteVpn; 252 } 253 254 /** 255 * Whether network validation should be performed for this VPN network. 256 * @see #isVpnValidationRequired 257 * @hide 258 */ 259 private boolean mVpnRequiresValidation = false; 260 261 /** 262 * Whether network validation should be performed for this VPN network. 263 * 264 * If this network isn't a VPN this should always be {@code false}, and will be ignored 265 * if set. 266 * If this network is a VPN, false means this network should always be considered validated; 267 * true means it follows the same validation semantics as general internet networks. 268 * @hide 269 */ 270 @SystemApi(client = MODULE_LIBRARIES) isVpnValidationRequired()271 public boolean isVpnValidationRequired() { 272 return mVpnRequiresValidation; 273 } 274 275 /** @hide */ NetworkAgentConfig()276 public NetworkAgentConfig() { 277 } 278 279 /** @hide */ NetworkAgentConfig(@ullable NetworkAgentConfig nac)280 public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) { 281 if (nac != null) { 282 allowBypass = nac.allowBypass; 283 explicitlySelected = nac.explicitlySelected; 284 acceptUnvalidated = nac.acceptUnvalidated; 285 acceptPartialConnectivity = nac.acceptPartialConnectivity; 286 subscriberId = nac.subscriberId; 287 provisioningNotificationDisabled = nac.provisioningNotificationDisabled; 288 skip464xlat = nac.skip464xlat; 289 legacyType = nac.legacyType; 290 legacyTypeName = nac.legacyTypeName; 291 legacySubType = nac.legacySubType; 292 legacySubTypeName = nac.legacySubTypeName; 293 mLegacyExtraInfo = nac.mLegacyExtraInfo; 294 excludeLocalRouteVpn = nac.excludeLocalRouteVpn; 295 mVpnRequiresValidation = nac.mVpnRequiresValidation; 296 } 297 } 298 299 /** 300 * Builder class to facilitate constructing {@link NetworkAgentConfig} objects. 301 */ 302 public static final class Builder { 303 private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); 304 305 /** 306 * Sets whether the network was explicitly selected by the user. 307 * 308 * @return this builder, to facilitate chaining. 309 */ 310 @NonNull setExplicitlySelected(final boolean explicitlySelected)311 public Builder setExplicitlySelected(final boolean explicitlySelected) { 312 mConfig.explicitlySelected = explicitlySelected; 313 return this; 314 } 315 316 /** 317 * Sets whether the system should validate this network even if it is found not to offer 318 * Internet connectivity. 319 * 320 * @return this builder, to facilitate chaining. 321 */ 322 @NonNull setUnvalidatedConnectivityAcceptable( final boolean unvalidatedConnectivityAcceptable)323 public Builder setUnvalidatedConnectivityAcceptable( 324 final boolean unvalidatedConnectivityAcceptable) { 325 mConfig.acceptUnvalidated = unvalidatedConnectivityAcceptable; 326 return this; 327 } 328 329 /** 330 * Sets whether the system should validate this network even if it is found to only offer 331 * partial Internet connectivity. 332 * 333 * @return this builder, to facilitate chaining. 334 */ 335 @NonNull setPartialConnectivityAcceptable( final boolean partialConnectivityAcceptable)336 public Builder setPartialConnectivityAcceptable( 337 final boolean partialConnectivityAcceptable) { 338 mConfig.acceptPartialConnectivity = partialConnectivityAcceptable; 339 return this; 340 } 341 342 /** 343 * Sets the subscriber ID for this network. 344 * 345 * @return this builder, to facilitate chaining. 346 * @hide 347 */ 348 @NonNull 349 @SystemApi(client = MODULE_LIBRARIES) setSubscriberId(@ullable String subscriberId)350 public Builder setSubscriberId(@Nullable String subscriberId) { 351 mConfig.subscriberId = subscriberId; 352 return this; 353 } 354 355 /** 356 * Enables or disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to 357 * save power and reduce idle traffic on networks that are known to be IPv6-only without a 358 * NAT64. By default, NAT64 detection is enabled. 359 * 360 * @return this builder, to facilitate chaining. 361 */ 362 @NonNull setNat64DetectionEnabled(boolean enabled)363 public Builder setNat64DetectionEnabled(boolean enabled) { 364 mConfig.skip464xlat = !enabled; 365 return this; 366 } 367 368 /** 369 * Enables or disables the "Sign in to network" notification. Used if the network transport 370 * will perform its own carrier-specific provisioning procedure. By default, the 371 * notification is enabled. 372 * 373 * @return this builder, to facilitate chaining. 374 */ 375 @NonNull setProvisioningNotificationEnabled(boolean enabled)376 public Builder setProvisioningNotificationEnabled(boolean enabled) { 377 mConfig.provisioningNotificationDisabled = !enabled; 378 return this; 379 } 380 381 /** 382 * Sets the legacy type for this network. 383 * 384 * @param legacyType the type 385 * @return this builder, to facilitate chaining. 386 */ 387 @NonNull setLegacyType(int legacyType)388 public Builder setLegacyType(int legacyType) { 389 mConfig.legacyType = legacyType; 390 return this; 391 } 392 393 /** 394 * Sets the legacy sub-type for this network. 395 * 396 * @param legacySubType the type 397 * @return this builder, to facilitate chaining. 398 */ 399 @NonNull setLegacySubType(final int legacySubType)400 public Builder setLegacySubType(final int legacySubType) { 401 mConfig.legacySubType = legacySubType; 402 return this; 403 } 404 405 /** 406 * Sets the name of the legacy type of the agent. It's a free-form string used in logging. 407 * @param legacyTypeName the name 408 * @return this builder, to facilitate chaining. 409 */ 410 @NonNull setLegacyTypeName(@onNull String legacyTypeName)411 public Builder setLegacyTypeName(@NonNull String legacyTypeName) { 412 mConfig.legacyTypeName = legacyTypeName; 413 return this; 414 } 415 416 /** 417 * Sets the name of the legacy Sub-type of the agent. It's a free-form string. 418 * @param legacySubTypeName the name 419 * @return this builder, to facilitate chaining. 420 */ 421 @NonNull setLegacySubTypeName(@onNull String legacySubTypeName)422 public Builder setLegacySubTypeName(@NonNull String legacySubTypeName) { 423 mConfig.legacySubTypeName = legacySubTypeName; 424 return this; 425 } 426 427 /** 428 * Sets the legacy extra info of the agent. 429 * @param legacyExtraInfo the legacy extra info. 430 * @return this builder, to facilitate chaining. 431 */ 432 @NonNull setLegacyExtraInfo(@onNull String legacyExtraInfo)433 public Builder setLegacyExtraInfo(@NonNull String legacyExtraInfo) { 434 mConfig.mLegacyExtraInfo = legacyExtraInfo; 435 return this; 436 } 437 438 /** 439 * Sets whether network validation should be performed for this VPN network. 440 * 441 * Only agents registering a VPN network should use this setter. On other network 442 * types it will be ignored. 443 * False means this network should always be considered validated; 444 * true means it follows the same validation semantics as general internet. 445 * 446 * @param vpnRequiresValidation whether this VPN requires validation. 447 * Default is {@code false}. 448 * @hide 449 */ 450 @NonNull 451 @SystemApi(client = MODULE_LIBRARIES) setVpnRequiresValidation(boolean vpnRequiresValidation)452 public Builder setVpnRequiresValidation(boolean vpnRequiresValidation) { 453 mConfig.mVpnRequiresValidation = vpnRequiresValidation; 454 return this; 455 } 456 457 /** 458 * Sets whether the apps can bypass the VPN connection. 459 * 460 * @return this builder, to facilitate chaining. 461 * @hide 462 */ 463 @NonNull 464 @SystemApi(client = MODULE_LIBRARIES) setBypassableVpn(boolean allowBypass)465 public Builder setBypassableVpn(boolean allowBypass) { 466 mConfig.allowBypass = allowBypass; 467 return this; 468 } 469 470 /** 471 * Sets whether the local traffic is exempted from VPN. 472 * 473 * @return this builder, to facilitate chaining. 474 * @hide 475 */ 476 @NonNull 477 @SystemApi(client = MODULE_LIBRARIES) setLocalRoutesExcludedForVpn(boolean excludeLocalRoutes)478 public Builder setLocalRoutesExcludedForVpn(boolean excludeLocalRoutes) { 479 if (!SdkLevel.isAtLeastT()) { 480 throw new UnsupportedOperationException("Method is not supported"); 481 } 482 mConfig.excludeLocalRouteVpn = excludeLocalRoutes; 483 return this; 484 } 485 486 /** 487 * Returns the constructed {@link NetworkAgentConfig} object. 488 */ 489 @NonNull build()490 public NetworkAgentConfig build() { 491 return mConfig; 492 } 493 } 494 495 @Override equals(final Object o)496 public boolean equals(final Object o) { 497 if (this == o) return true; 498 if (o == null || getClass() != o.getClass()) return false; 499 final NetworkAgentConfig that = (NetworkAgentConfig) o; 500 return allowBypass == that.allowBypass 501 && explicitlySelected == that.explicitlySelected 502 && acceptUnvalidated == that.acceptUnvalidated 503 && acceptPartialConnectivity == that.acceptPartialConnectivity 504 && provisioningNotificationDisabled == that.provisioningNotificationDisabled 505 && skip464xlat == that.skip464xlat 506 && legacyType == that.legacyType 507 && legacySubType == that.legacySubType 508 && Objects.equals(subscriberId, that.subscriberId) 509 && Objects.equals(legacyTypeName, that.legacyTypeName) 510 && Objects.equals(legacySubTypeName, that.legacySubTypeName) 511 && Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo) 512 && excludeLocalRouteVpn == that.excludeLocalRouteVpn 513 && mVpnRequiresValidation == that.mVpnRequiresValidation; 514 } 515 516 @Override hashCode()517 public int hashCode() { 518 return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated, 519 acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId, 520 skip464xlat, legacyType, legacySubType, legacyTypeName, legacySubTypeName, 521 mLegacyExtraInfo, excludeLocalRouteVpn, mVpnRequiresValidation); 522 } 523 524 @Override toString()525 public String toString() { 526 return "NetworkAgentConfig {" 527 + " allowBypass = " + allowBypass 528 + ", explicitlySelected = " + explicitlySelected 529 + ", acceptUnvalidated = " + acceptUnvalidated 530 + ", acceptPartialConnectivity = " + acceptPartialConnectivity 531 + ", provisioningNotificationDisabled = " + provisioningNotificationDisabled 532 + ", subscriberId = '" + subscriberId + '\'' 533 + ", skip464xlat = " + skip464xlat 534 + ", legacyType = " + legacyType 535 + ", legacySubType = " + legacySubType 536 + ", hasShownBroken = " + hasShownBroken 537 + ", legacyTypeName = '" + legacyTypeName + '\'' 538 + ", legacySubTypeName = '" + legacySubTypeName + '\'' 539 + ", legacyExtraInfo = '" + mLegacyExtraInfo + '\'' 540 + ", excludeLocalRouteVpn = '" + excludeLocalRouteVpn + '\'' 541 + ", vpnRequiresValidation = '" + mVpnRequiresValidation + '\'' 542 + "}"; 543 } 544 545 @Override describeContents()546 public int describeContents() { 547 return 0; 548 } 549 550 @Override writeToParcel(@onNull Parcel out, int flags)551 public void writeToParcel(@NonNull Parcel out, int flags) { 552 out.writeInt(allowBypass ? 1 : 0); 553 out.writeInt(explicitlySelected ? 1 : 0); 554 out.writeInt(acceptUnvalidated ? 1 : 0); 555 out.writeInt(acceptPartialConnectivity ? 1 : 0); 556 out.writeString(subscriberId); 557 out.writeInt(provisioningNotificationDisabled ? 1 : 0); 558 out.writeInt(skip464xlat ? 1 : 0); 559 out.writeInt(legacyType); 560 out.writeString(legacyTypeName); 561 out.writeInt(legacySubType); 562 out.writeString(legacySubTypeName); 563 out.writeString(mLegacyExtraInfo); 564 out.writeInt(excludeLocalRouteVpn ? 1 : 0); 565 out.writeInt(mVpnRequiresValidation ? 1 : 0); 566 } 567 568 public static final @NonNull Creator<NetworkAgentConfig> CREATOR = 569 new Creator<NetworkAgentConfig>() { 570 @Override 571 public NetworkAgentConfig createFromParcel(Parcel in) { 572 NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); 573 networkAgentConfig.allowBypass = in.readInt() != 0; 574 networkAgentConfig.explicitlySelected = in.readInt() != 0; 575 networkAgentConfig.acceptUnvalidated = in.readInt() != 0; 576 networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0; 577 networkAgentConfig.subscriberId = in.readString(); 578 networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0; 579 networkAgentConfig.skip464xlat = in.readInt() != 0; 580 networkAgentConfig.legacyType = in.readInt(); 581 networkAgentConfig.legacyTypeName = in.readString(); 582 networkAgentConfig.legacySubType = in.readInt(); 583 networkAgentConfig.legacySubTypeName = in.readString(); 584 networkAgentConfig.mLegacyExtraInfo = in.readString(); 585 networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0; 586 networkAgentConfig.mVpnRequiresValidation = in.readInt() != 0; 587 return networkAgentConfig; 588 } 589 590 @Override 591 public NetworkAgentConfig[] newArray(int size) { 592 return new NetworkAgentConfig[size]; 593 } 594 }; 595 } 596