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