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. 192 * 193 * @hide 194 */ 195 public transient boolean hasShownBroken; 196 197 /** 198 * The name of the legacy network type. It's a free-form string used in logging. 199 * @hide 200 */ 201 @NonNull 202 public String legacyTypeName = ""; 203 204 /** 205 * @return the name of the legacy network type. It's a free-form string used in logging. 206 */ 207 @NonNull getLegacyTypeName()208 public String getLegacyTypeName() { 209 return legacyTypeName; 210 } 211 212 /** 213 * The name of the legacy Sub network type. It's a free-form string. 214 * @hide 215 */ 216 @NonNull 217 public String legacySubTypeName = ""; 218 219 /** 220 * The legacy extra info of the agent. The extra info should only be : 221 * <ul> 222 * <li>For cellular agents, the APN name.</li> 223 * <li>For ethernet agents, the interface name.</li> 224 * </ul> 225 * @hide 226 */ 227 @NonNull 228 private String mLegacyExtraInfo = ""; 229 230 /** 231 * The legacy extra info of the agent. 232 * @hide 233 */ 234 @NonNull getLegacyExtraInfo()235 public String getLegacyExtraInfo() { 236 return mLegacyExtraInfo; 237 } 238 239 /** 240 * If the {@link Network} is a VPN, whether the local traffic is exempted from the VPN. 241 * @hide 242 */ 243 public boolean excludeLocalRouteVpn = false; 244 245 /** 246 * @return whether local traffic is excluded from the VPN network. 247 * @hide 248 */ areLocalRoutesExcludedForVpn()249 public boolean areLocalRoutesExcludedForVpn() { 250 return excludeLocalRouteVpn; 251 } 252 253 /** 254 * Whether network validation should be performed for this VPN network. 255 * {@see #isVpnValidationRequired} 256 * @hide 257 */ 258 private boolean mVpnRequiresValidation = false; 259 260 /** 261 * Whether network validation should be performed for this VPN network. 262 * 263 * If this network isn't a VPN this should always be {@code false}, and will be ignored 264 * if set. 265 * If this network is a VPN, false means this network should always be considered validated; 266 * true means it follows the same validation semantics as general internet networks. 267 * @hide 268 */ 269 @SystemApi(client = MODULE_LIBRARIES) isVpnValidationRequired()270 public boolean isVpnValidationRequired() { 271 return mVpnRequiresValidation; 272 } 273 274 /** @hide */ NetworkAgentConfig()275 public NetworkAgentConfig() { 276 } 277 278 /** @hide */ NetworkAgentConfig(@ullable NetworkAgentConfig nac)279 public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) { 280 if (nac != null) { 281 allowBypass = nac.allowBypass; 282 explicitlySelected = nac.explicitlySelected; 283 acceptUnvalidated = nac.acceptUnvalidated; 284 acceptPartialConnectivity = nac.acceptPartialConnectivity; 285 subscriberId = nac.subscriberId; 286 provisioningNotificationDisabled = nac.provisioningNotificationDisabled; 287 skip464xlat = nac.skip464xlat; 288 legacyType = nac.legacyType; 289 legacyTypeName = nac.legacyTypeName; 290 legacySubType = nac.legacySubType; 291 legacySubTypeName = nac.legacySubTypeName; 292 mLegacyExtraInfo = nac.mLegacyExtraInfo; 293 excludeLocalRouteVpn = nac.excludeLocalRouteVpn; 294 mVpnRequiresValidation = nac.mVpnRequiresValidation; 295 } 296 } 297 298 /** 299 * Builder class to facilitate constructing {@link NetworkAgentConfig} objects. 300 */ 301 public static final class Builder { 302 private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); 303 304 /** 305 * Sets whether the network was explicitly selected by the user. 306 * 307 * @return this builder, to facilitate chaining. 308 */ 309 @NonNull setExplicitlySelected(final boolean explicitlySelected)310 public Builder setExplicitlySelected(final boolean explicitlySelected) { 311 mConfig.explicitlySelected = explicitlySelected; 312 return this; 313 } 314 315 /** 316 * Sets whether the system should validate this network even if it is found not to offer 317 * Internet connectivity. 318 * 319 * @return this builder, to facilitate chaining. 320 */ 321 @NonNull setUnvalidatedConnectivityAcceptable( final boolean unvalidatedConnectivityAcceptable)322 public Builder setUnvalidatedConnectivityAcceptable( 323 final boolean unvalidatedConnectivityAcceptable) { 324 mConfig.acceptUnvalidated = unvalidatedConnectivityAcceptable; 325 return this; 326 } 327 328 /** 329 * Sets whether the system should validate this network even if it is found to only offer 330 * partial Internet connectivity. 331 * 332 * @return this builder, to facilitate chaining. 333 */ 334 @NonNull setPartialConnectivityAcceptable( final boolean partialConnectivityAcceptable)335 public Builder setPartialConnectivityAcceptable( 336 final boolean partialConnectivityAcceptable) { 337 mConfig.acceptPartialConnectivity = partialConnectivityAcceptable; 338 return this; 339 } 340 341 /** 342 * Sets the subscriber ID for this network. 343 * 344 * @return this builder, to facilitate chaining. 345 * @hide 346 */ 347 @NonNull 348 @SystemApi(client = MODULE_LIBRARIES) setSubscriberId(@ullable String subscriberId)349 public Builder setSubscriberId(@Nullable String subscriberId) { 350 mConfig.subscriberId = subscriberId; 351 return this; 352 } 353 354 /** 355 * Enables or disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to 356 * save power and reduce idle traffic on networks that are known to be IPv6-only without a 357 * NAT64. By default, NAT64 detection is enabled. 358 * 359 * @return this builder, to facilitate chaining. 360 */ 361 @NonNull setNat64DetectionEnabled(boolean enabled)362 public Builder setNat64DetectionEnabled(boolean enabled) { 363 mConfig.skip464xlat = !enabled; 364 return this; 365 } 366 367 /** 368 * Enables or disables the "Sign in to network" notification. Used if the network transport 369 * will perform its own carrier-specific provisioning procedure. By default, the 370 * notification is enabled. 371 * 372 * @return this builder, to facilitate chaining. 373 */ 374 @NonNull setProvisioningNotificationEnabled(boolean enabled)375 public Builder setProvisioningNotificationEnabled(boolean enabled) { 376 mConfig.provisioningNotificationDisabled = !enabled; 377 return this; 378 } 379 380 /** 381 * Sets the legacy type for this network. 382 * 383 * @param legacyType the type 384 * @return this builder, to facilitate chaining. 385 */ 386 @NonNull setLegacyType(int legacyType)387 public Builder setLegacyType(int legacyType) { 388 mConfig.legacyType = legacyType; 389 return this; 390 } 391 392 /** 393 * Sets the legacy sub-type for this network. 394 * 395 * @param legacySubType the type 396 * @return this builder, to facilitate chaining. 397 */ 398 @NonNull setLegacySubType(final int legacySubType)399 public Builder setLegacySubType(final int legacySubType) { 400 mConfig.legacySubType = legacySubType; 401 return this; 402 } 403 404 /** 405 * Sets the name of the legacy type of the agent. It's a free-form string used in logging. 406 * @param legacyTypeName the name 407 * @return this builder, to facilitate chaining. 408 */ 409 @NonNull setLegacyTypeName(@onNull String legacyTypeName)410 public Builder setLegacyTypeName(@NonNull String legacyTypeName) { 411 mConfig.legacyTypeName = legacyTypeName; 412 return this; 413 } 414 415 /** 416 * Sets the name of the legacy Sub-type of the agent. It's a free-form string. 417 * @param legacySubTypeName the name 418 * @return this builder, to facilitate chaining. 419 */ 420 @NonNull setLegacySubTypeName(@onNull String legacySubTypeName)421 public Builder setLegacySubTypeName(@NonNull String legacySubTypeName) { 422 mConfig.legacySubTypeName = legacySubTypeName; 423 return this; 424 } 425 426 /** 427 * Sets the legacy extra info of the agent. 428 * @param legacyExtraInfo the legacy extra info. 429 * @return this builder, to facilitate chaining. 430 */ 431 @NonNull setLegacyExtraInfo(@onNull String legacyExtraInfo)432 public Builder setLegacyExtraInfo(@NonNull String legacyExtraInfo) { 433 mConfig.mLegacyExtraInfo = legacyExtraInfo; 434 return this; 435 } 436 437 /** 438 * Sets whether network validation should be performed for this VPN network. 439 * 440 * Only agents registering a VPN network should use this setter. On other network 441 * types it will be ignored. 442 * False means this network should always be considered validated; 443 * true means it follows the same validation semantics as general internet. 444 * 445 * @param vpnRequiresValidation whether this VPN requires validation. 446 * Default is {@code false}. 447 * @hide 448 */ 449 @NonNull 450 @SystemApi(client = MODULE_LIBRARIES) setVpnRequiresValidation(boolean vpnRequiresValidation)451 public Builder setVpnRequiresValidation(boolean vpnRequiresValidation) { 452 mConfig.mVpnRequiresValidation = vpnRequiresValidation; 453 return this; 454 } 455 456 /** 457 * Sets whether the apps can bypass the VPN connection. 458 * 459 * @return this builder, to facilitate chaining. 460 * @hide 461 */ 462 @NonNull 463 @SystemApi(client = MODULE_LIBRARIES) setBypassableVpn(boolean allowBypass)464 public Builder setBypassableVpn(boolean allowBypass) { 465 mConfig.allowBypass = allowBypass; 466 return this; 467 } 468 469 /** 470 * Sets whether the local traffic is exempted from VPN. 471 * 472 * @return this builder, to facilitate chaining. 473 * @hide 474 */ 475 @NonNull 476 @SystemApi(client = MODULE_LIBRARIES) setLocalRoutesExcludedForVpn(boolean excludeLocalRoutes)477 public Builder setLocalRoutesExcludedForVpn(boolean excludeLocalRoutes) { 478 if (!SdkLevel.isAtLeastT()) { 479 throw new UnsupportedOperationException("Method is not supported"); 480 } 481 mConfig.excludeLocalRouteVpn = excludeLocalRoutes; 482 return this; 483 } 484 485 /** 486 * Returns the constructed {@link NetworkAgentConfig} object. 487 */ 488 @NonNull build()489 public NetworkAgentConfig build() { 490 return mConfig; 491 } 492 } 493 494 @Override equals(final Object o)495 public boolean equals(final Object o) { 496 if (this == o) return true; 497 if (o == null || getClass() != o.getClass()) return false; 498 final NetworkAgentConfig that = (NetworkAgentConfig) o; 499 return allowBypass == that.allowBypass 500 && explicitlySelected == that.explicitlySelected 501 && acceptUnvalidated == that.acceptUnvalidated 502 && acceptPartialConnectivity == that.acceptPartialConnectivity 503 && provisioningNotificationDisabled == that.provisioningNotificationDisabled 504 && skip464xlat == that.skip464xlat 505 && legacyType == that.legacyType 506 && Objects.equals(subscriberId, that.subscriberId) 507 && Objects.equals(legacyTypeName, that.legacyTypeName) 508 && Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo) 509 && excludeLocalRouteVpn == that.excludeLocalRouteVpn 510 && mVpnRequiresValidation == that.mVpnRequiresValidation; 511 } 512 513 @Override hashCode()514 public int hashCode() { 515 return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated, 516 acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId, 517 skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn, 518 mVpnRequiresValidation); 519 } 520 521 @Override toString()522 public String toString() { 523 return "NetworkAgentConfig {" 524 + " allowBypass = " + allowBypass 525 + ", explicitlySelected = " + explicitlySelected 526 + ", acceptUnvalidated = " + acceptUnvalidated 527 + ", acceptPartialConnectivity = " + acceptPartialConnectivity 528 + ", provisioningNotificationDisabled = " + provisioningNotificationDisabled 529 + ", subscriberId = '" + subscriberId + '\'' 530 + ", skip464xlat = " + skip464xlat 531 + ", legacyType = " + legacyType 532 + ", hasShownBroken = " + hasShownBroken 533 + ", legacyTypeName = '" + legacyTypeName + '\'' 534 + ", legacyExtraInfo = '" + mLegacyExtraInfo + '\'' 535 + ", excludeLocalRouteVpn = '" + excludeLocalRouteVpn + '\'' 536 + ", vpnRequiresValidation = '" + mVpnRequiresValidation + '\'' 537 + "}"; 538 } 539 540 @Override describeContents()541 public int describeContents() { 542 return 0; 543 } 544 545 @Override writeToParcel(@onNull Parcel out, int flags)546 public void writeToParcel(@NonNull Parcel out, int flags) { 547 out.writeInt(allowBypass ? 1 : 0); 548 out.writeInt(explicitlySelected ? 1 : 0); 549 out.writeInt(acceptUnvalidated ? 1 : 0); 550 out.writeInt(acceptPartialConnectivity ? 1 : 0); 551 out.writeString(subscriberId); 552 out.writeInt(provisioningNotificationDisabled ? 1 : 0); 553 out.writeInt(skip464xlat ? 1 : 0); 554 out.writeInt(legacyType); 555 out.writeString(legacyTypeName); 556 out.writeInt(legacySubType); 557 out.writeString(legacySubTypeName); 558 out.writeString(mLegacyExtraInfo); 559 out.writeInt(excludeLocalRouteVpn ? 1 : 0); 560 out.writeInt(mVpnRequiresValidation ? 1 : 0); 561 } 562 563 public static final @NonNull Creator<NetworkAgentConfig> CREATOR = 564 new Creator<NetworkAgentConfig>() { 565 @Override 566 public NetworkAgentConfig createFromParcel(Parcel in) { 567 NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); 568 networkAgentConfig.allowBypass = in.readInt() != 0; 569 networkAgentConfig.explicitlySelected = in.readInt() != 0; 570 networkAgentConfig.acceptUnvalidated = in.readInt() != 0; 571 networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0; 572 networkAgentConfig.subscriberId = in.readString(); 573 networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0; 574 networkAgentConfig.skip464xlat = in.readInt() != 0; 575 networkAgentConfig.legacyType = in.readInt(); 576 networkAgentConfig.legacyTypeName = in.readString(); 577 networkAgentConfig.legacySubType = in.readInt(); 578 networkAgentConfig.legacySubTypeName = in.readString(); 579 networkAgentConfig.mLegacyExtraInfo = in.readString(); 580 networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0; 581 networkAgentConfig.mVpnRequiresValidation = in.readInt() != 0; 582 return networkAgentConfig; 583 } 584 585 @Override 586 public NetworkAgentConfig[] newArray(int size) { 587 return new NetworkAgentConfig[size]; 588 } 589 }; 590 } 591