• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.server.connectivity;
18 
19 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
20 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
21 import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
22 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
23 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
24 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
25 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
26 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
27 import static android.net.NetworkCapabilities.transportNamesOf;
28 import static android.system.OsConstants.EEXIST;
29 import static android.system.OsConstants.EIO;
30 import static android.system.OsConstants.ENOENT;
31 
32 import static com.android.net.module.util.FrameworkConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED;
33 import static com.android.net.module.util.FrameworkConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_DISALLOW_BYPASS_VPN_FOR_DELEGATE_UID_ENOENT;
34 
35 import android.annotation.NonNull;
36 import android.annotation.Nullable;
37 import android.content.Context;
38 import android.content.pm.PackageManager;
39 import android.net.CaptivePortalData;
40 import android.net.DscpPolicy;
41 import android.net.IDnsResolver;
42 import android.net.INetd;
43 import android.net.INetworkAgent;
44 import android.net.INetworkAgentRegistry;
45 import android.net.INetworkMonitor;
46 import android.net.LinkProperties;
47 import android.net.LocalNetworkConfig;
48 import android.net.NattKeepalivePacketData;
49 import android.net.Network;
50 import android.net.NetworkAgent;
51 import android.net.NetworkAgentConfig;
52 import android.net.NetworkCapabilities;
53 import android.net.NetworkInfo;
54 import android.net.NetworkMonitorManager;
55 import android.net.NetworkRequest;
56 import android.net.NetworkScore;
57 import android.net.NetworkStateSnapshot;
58 import android.net.QosCallbackException;
59 import android.net.QosFilter;
60 import android.net.QosFilterParcelable;
61 import android.net.QosSession;
62 import android.net.TcpKeepalivePacketData;
63 import android.os.Handler;
64 import android.os.IBinder;
65 import android.os.Message;
66 import android.os.RemoteException;
67 import android.os.ServiceSpecificException;
68 import android.os.SystemClock;
69 import android.telephony.data.EpsBearerQosSessionAttributes;
70 import android.telephony.data.NrQosSessionAttributes;
71 import android.util.ArrayMap;
72 import android.util.ArraySet;
73 import android.util.Log;
74 import android.util.Pair;
75 import android.util.SparseArray;
76 
77 import com.android.internal.annotations.VisibleForTesting;
78 import com.android.internal.util.IndentingPrintWriter;
79 import com.android.internal.util.WakeupMessage;
80 import com.android.net.module.util.FrameworkConnectivityStatsLog;
81 import com.android.net.module.util.HandlerUtils;
82 import com.android.server.ConnectivityService;
83 import com.android.server.ConnectivityService.CaptivePortalImpl;
84 
85 import java.io.PrintWriter;
86 import java.net.Inet4Address;
87 import java.net.Inet6Address;
88 import java.time.Instant;
89 import java.util.ArrayList;
90 import java.util.Arrays;
91 import java.util.List;
92 import java.util.NoSuchElementException;
93 import java.util.Objects;
94 import java.util.SortedSet;
95 import java.util.TreeSet;
96 import java.util.function.Consumer;
97 
98 /**
99  * A bag class used by ConnectivityService for holding a collection of most recent
100  * information published by a particular NetworkAgent as well as the
101  * AsyncChannel/messenger for reaching that NetworkAgent and lists of NetworkRequests
102  * interested in using it.  Default sort order is descending by score.
103  */
104 // States of a network:
105 // --------------------
106 // 1. registered, uncreated, disconnected, unvalidated
107 //    This state is entered when a NetworkFactory registers a NetworkAgent in any state except
108 //    the CONNECTED state.
109 // 2. registered, uncreated, connecting, unvalidated
110 //    This state is entered when a registered NetworkAgent for a VPN network transitions to the
111 //    CONNECTING state (TODO: go through this state for every network, not just VPNs).
112 //    ConnectivityService will tell netd to create the network early in order to add extra UID
113 //    routing rules referencing the netID. These rules need to be in place before the network is
114 //    connected to avoid racing against client apps trying to connect to a half-setup network.
115 // 3. registered, uncreated, connected, unvalidated
116 //    This state is entered when a registered NetworkAgent transitions to the CONNECTED state.
117 //    ConnectivityService will tell netd to create the network if it was not already created, and
118 //    immediately transition to state #4.
119 // 4. registered, created, connected, unvalidated
120 //    If this network can satisfy the default NetworkRequest, then NetworkMonitor will
121 //    probe for Internet connectivity.
122 //    If this network cannot satisfy the default NetworkRequest, it will immediately be
123 //    transitioned to state #5.
124 //    A network may remain in this state if NetworkMonitor fails to find Internet connectivity,
125 //    for example:
126 //    a. a captive portal is present, or
127 //    b. a WiFi router whose Internet backhaul is down, or
128 //    c. a wireless connection stops transferring packets temporarily (e.g. device is in elevator
129 //       or tunnel) but does not disconnect from the AP/cell tower, or
130 //    d. a stand-alone device offering a WiFi AP without an uplink for configuration purposes.
131 // 5. registered, created, connected, validated
132 // 6. registered, created, connected, (validated or unvalidated), destroyed
133 //    This is an optional state where the underlying native network is destroyed but the network is
134 //    still connected for scoring purposes, so can satisfy requests, including the default request.
135 //    It is used when the transport layer wants to replace a network with another network (e.g.,
136 //    when Wi-Fi has roamed to a different BSSID that is part of a different L3 network) and does
137 //    not want the device to switch to another network until the replacement connects and validates.
138 //
139 // The device's default network connection:
140 // ----------------------------------------
141 // Networks in states #4 and #5 may be used as a device's default network connection if they
142 // satisfy the default NetworkRequest.
143 // A network, that satisfies the default NetworkRequest, in state #5 should always be chosen
144 // in favor of a network, that satisfies the default NetworkRequest, in state #4.
145 // When deciding between two networks, that both satisfy the default NetworkRequest, to select
146 // for the default network connection, the one with the higher score should be chosen.
147 //
148 // When a network disconnects:
149 // ---------------------------
150 // If a network's transport disappears, for example:
151 // a. WiFi turned off, or
152 // b. cellular data turned off, or
153 // c. airplane mode is turned on, or
154 // d. a wireless connection disconnects from AP/cell tower entirely (e.g. device is out of range
155 //    of AP for an extended period of time, or switches to another AP without roaming)
156 // then that network can transition from any state (#1-#5) to unregistered.  This happens by
157 // the transport disconnecting their NetworkAgent's AsyncChannel with ConnectivityManager.
158 // ConnectivityService also tells netd to destroy the network.
159 //
160 // When ConnectivityService disconnects a network:
161 // -----------------------------------------------
162 // If a network is just connected, ConnectivityService will think it will be used soon, but might
163 // not be used. Thus, a 5s timer will be held to prevent the network being torn down immediately.
164 // This "nascent" state is implemented by the "lingering" logic below without relating to any
165 // request, and is used in some cases where network requests race with network establishment. The
166 // nascent state ends when the 5-second timer fires, or as soon as the network satisfies a
167 // request, whichever is earlier. In this state, the network is considered in the background.
168 //
169 // If a network has no chance of satisfying any requests (even if it were to become validated
170 // and enter state #5), ConnectivityService will disconnect the NetworkAgent's AsyncChannel.
171 //
172 // If the network was satisfying a foreground NetworkRequest (i.e. had been the highest scoring that
173 // satisfied the NetworkRequest's constraints), but is no longer the highest scoring network for any
174 // foreground NetworkRequest, then there will be a 30s pause to allow network communication to be
175 // wrapped up rather than abruptly terminated. During this pause the network is said to be
176 // "lingering". During this pause if the network begins satisfying a foreground NetworkRequest,
177 // ConnectivityService will cancel the future disconnection of the NetworkAgent's AsyncChannel, and
178 // the network is no longer considered "lingering". After the linger timer expires, if the network
179 // is satisfying one or more background NetworkRequests it is kept up in the background. If it is
180 // not, ConnectivityService disconnects the NetworkAgent's AsyncChannel.
181 public class NetworkAgentInfo implements NetworkRanker.Scoreable {
182 
183     @NonNull public NetworkInfo networkInfo;
184     // This Network object should always be used if possible, so as to encourage reuse of the
185     // enclosed socket factory and connection pool.  Avoid creating other Network objects.
186     // This Network object is always valid.
187     @NonNull public final Network network;
188     @NonNull public LinkProperties linkProperties;
189     // This should only be modified by ConnectivityService, via setNetworkCapabilities().
190     // TODO: make this private with a getter.
191     @NonNull public NetworkCapabilities networkCapabilities;
192     @NonNull public final NetworkAgentConfig networkAgentConfig;
193     @Nullable public LocalNetworkConfig localNetworkConfig;
194 
195     // Underlying networks declared by the agent.
196     // The networks in this list might be declared by a VPN using setUnderlyingNetworks and are
197     // not guaranteed to be current or correct, or even to exist.
198     //
199     // This array is read and iterated on multiple threads with no locking so its contents must
200     // never be modified. When the list of networks changes, replace with a new array, on the
201     // handler thread.
202     public @Nullable volatile Network[] declaredUnderlyingNetworks;
203 
204     // The capabilities originally announced by the NetworkAgent, regardless of any capabilities
205     // that were added or removed due to this network's underlying networks.
206     //
207     // As the name implies, these capabilities are not sanitized and are not to
208     // be trusted. Most callers should simply use the {@link networkCapabilities}
209     // field instead.
210     private @Nullable NetworkCapabilities mDeclaredCapabilitiesUnsanitized;
211 
212     // Timestamp (SystemClock.elapsedRealtime()) when netd has been told to create this Network, or
213     // 0 if it hasn't been done yet.
214     // From this point on, the appropriate routing rules are setup and routes are added so packets
215     // can begin flowing over the Network.
216     // This is a sticky value; once set != 0 it is never changed.
217     private long mCreatedTime;
218 
219     /** Notify this NAI that netd was just told to create this network */
setCreated()220     public void setCreated() {
221         if (0L != mCreatedTime) throw new IllegalStateException("Already created");
222         mCreatedTime = SystemClock.elapsedRealtime();
223     }
224 
225     /** Returns whether netd was told to create this network */
isCreated()226     public boolean isCreated() {
227         return mCreatedTime != 0L;
228     }
229 
230     // Get the time (SystemClock.elapsedRealTime) when this network was created (or 0 if never).
getCreatedTime()231     public long getCreatedTime() {
232         return mCreatedTime;
233     }
234 
235     // Timestamp of the first time (SystemClock.elapsedRealtime()) this network is marked as
236     // connected, or 0 if this network has never been marked connected. Once set to non-zero, the
237     // network shows up in API calls, is able to satisfy NetworkRequests and can become the default
238     // network.
239     // This is a sticky value; once set != 0 it is never changed.
240     private long mConnectedTime;
241 
242     /** Notify this NAI that this network just connected */
setConnected()243     public void setConnected() {
244         if (0L != mConnectedTime) throw new IllegalStateException("Already connected");
245         mConnectedTime = SystemClock.elapsedRealtime();
246     }
247 
248     /** Return whether this network ever connected */
everConnected()249     public boolean everConnected() {
250         return mConnectedTime != 0L;
251     }
252 
253     // Get the time (SystemClock.elapsedRealTime()) when this network was first connected, or 0 if
254     // never.
getConnectedTime()255     public long getConnectedTime() {
256         return mConnectedTime;
257     }
258 
259     // When this network has been destroyed and is being kept temporarily until it is replaced,
260     // this is set to that timestamp (SystemClock.elapsedRealtime()). Zero otherwise.
261     private long mDestroyedTime;
262 
263     /** Notify this NAI that this network was destroyed */
setDestroyed()264     public void setDestroyed() {
265         if (0L != mDestroyedTime) throw new IllegalStateException("Already destroyed");
266         mDestroyedTime = SystemClock.elapsedRealtime();
267     }
268 
269     /** Return whether this network was destroyed */
isDestroyed()270     public boolean isDestroyed() {
271         return 0L != mDestroyedTime;
272     }
273 
274     // Timestamp of the last roaming (SystemClock.elapsedRealtime()) or 0 if never roamed.
275     public long lastRoamTime;
276 
277     // Timestamp (SystemClock.elapsedRealtime()) of the first time this network successfully
278     // passed validation or was deemed exempt of validation (see
279     // {@link NetworkMonitorUtils#isValidationRequired}). Zero if the network requires
280     // validation but never passed it successfully.
281     // This is a sticky value; once set it is never changed even if further validation attempts are
282     // made (whether they succeed or fail).
283     private long mFirstValidationTime;
284 
285     // Timestamp (SystemClock.elapsedRealtime()) at which the latest validation attempt succeeded,
286     // or 0 if the latest validation attempt failed.
287     private long mCurrentValidationTime;
288 
289     /** Notify this NAI that this network just finished a validation check */
setValidated(final boolean validated)290     public void setValidated(final boolean validated) {
291         final long nowOrZero = validated ? SystemClock.elapsedRealtime() : 0L;
292         if (validated && 0L == mFirstValidationTime) {
293             mFirstValidationTime = nowOrZero;
294         }
295         mCurrentValidationTime = nowOrZero;
296     }
297 
298     /**
299      * Returns whether this network is currently validated.
300      *
301      * This is the result of the latest validation check. {@see #getCurrentValidationTime} for
302      * when that check was performed.
303      */
isValidated()304     public boolean isValidated() {
305         return 0L != mCurrentValidationTime;
306     }
307 
308     /**
309      * Returns whether this network ever passed the validation checks successfully.
310      *
311      * Note that the network may no longer be validated at this time ever if this is true.
312      * @see #isValidated
313      */
everValidated()314     public boolean everValidated() {
315         return 0L != mFirstValidationTime;
316     }
317 
318     // Get the time (SystemClock.elapsedRealTime()) when this network was most recently validated,
319     // or 0 if this network was found not to validate on the last attempt.
getCurrentValidationTime()320     public long getCurrentValidationTime() {
321         return mCurrentValidationTime;
322     }
323 
324     // Get the time (SystemClock.elapsedRealTime()) when this network was validated for the first
325     // time (or 0 if never).
getFirstValidationTime()326     public long getFirstValidationTime() {
327         return mFirstValidationTime;
328     }
329 
330     // Timestamp (SystemClock.elapsedRealtime()) at which the user requested this network be
331     // avoided when unvalidated. Zero if this never happened for this network.
332     // This is only meaningful if the system is configured to have some cell networks yield
333     // to bad wifi, e.g., if the config_networkAvoidBadWifi option is set to 0 and the user has
334     // not overridden that via Settings.Global.NETWORK_AVOID_BAD_WIFI.
335     //
336     // Normally the system always prefers a validated network to a non-validated one, even if
337     // the non-validated one is cheaper. However, some cell networks may be configured by the
338     // setting above to yield to WiFi even if that WiFi network goes bad. When this configuration
339     // is active, specific networks can be marked to override this configuration so that the
340     // system will revert to preferring such a cell to this network when this network goes bad. This
341     // is achieved by calling {@link ConnectivityManager#setAvoidUnvalidated()}, and this field
342     // is set to non-zero when this happened to this network.
343     private long mAvoidUnvalidated;
344 
345     /** Set this network as being avoided when unvalidated. {@see mAvoidUnvalidated} */
setAvoidUnvalidated()346     public void setAvoidUnvalidated() {
347         if (0L != mAvoidUnvalidated) throw new IllegalStateException("Already avoided unvalidated");
348         mAvoidUnvalidated = SystemClock.elapsedRealtime();
349     }
350 
351     // Get the time (SystemClock.elapsedRealTime()) when this network was set to being avoided
352     // when unvalidated, or 0 if this never happened.
getAvoidUnvalidated()353     public long getAvoidUnvalidated() {
354         return mAvoidUnvalidated;
355     }
356 
357     // Timestamp (SystemClock.elapsedRealtime()) at which a captive portal was first detected
358     // on this network, or zero if this never happened.
359     // This is a sticky value; once set != 0 it is never changed.
360     private long mFirstCaptivePortalDetectedTime;
361 
362     // Timestamp (SystemClock.elapsedRealtime()) at which the latest validation attempt found a
363     // captive portal, or zero if the latest attempt didn't find a captive portal.
364     private long mCurrentCaptivePortalDetectedTime;
365 
366     /** Notify this NAI that a captive portal has just been detected on this network */
setCaptivePortalDetected(final boolean hasCaptivePortal)367     public void setCaptivePortalDetected(final boolean hasCaptivePortal) {
368         if (!hasCaptivePortal) {
369             mCurrentCaptivePortalDetectedTime = 0L;
370             return;
371         }
372         final long now = SystemClock.elapsedRealtime();
373         if (0L == mFirstCaptivePortalDetectedTime) mFirstCaptivePortalDetectedTime = now;
374         mCurrentCaptivePortalDetectedTime = now;
375     }
376 
377     /** Return whether a captive portal has ever been detected on this network */
everCaptivePortalDetected()378     public boolean everCaptivePortalDetected() {
379         return 0L != mFirstCaptivePortalDetectedTime;
380     }
381 
382     /** Return whether this network has been detected to be behind a captive portal at the moment */
captivePortalDetected()383     public boolean captivePortalDetected() {
384         return 0L != mCurrentCaptivePortalDetectedTime;
385     }
386 
387     // Timestamp (SystemClock.elapsedRealtime()) at which the latest validation attempt found
388     // partial connectivity, or zero if the latest attempt didn't find partial connectivity.
389     private long mPartialConnectivityTime;
390 
setPartialConnectivity(final boolean value)391     public void setPartialConnectivity(final boolean value) {
392         mPartialConnectivityTime = value ? SystemClock.elapsedRealtime() : 0L;
393     }
394 
395     /** Return whether this NAI has partial connectivity */
partialConnectivity()396     public boolean partialConnectivity() {
397         return 0L != mPartialConnectivityTime;
398     }
399 
400     // Timestamp (SystemClock.elapsedRealTime()) at which the first validation attempt concluded,
401     // or timed out after {@link ConnectivityService#PROMPT_UNVALIDATED_DELAY_MS}. 0 if not yet.
402     private long mFirstEvaluationConcludedTime;
403 
404     /**
405      * Notify this NAI that this network has been evaluated.
406      *
407      * The stack considers that any result finding some working connectivity (valid, partial,
408      * captive portal) is an initial validation. Negative result (not valid), however, is not
409      * considered initial validation until {@link ConnectivityService#PROMPT_UNVALIDATED_DELAY_MS}
410      * have elapsed. This is because some networks may spuriously fail for a short time immediately
411      * after associating. If no positive result is found after the timeout has elapsed, then
412      * the network has been evaluated once.
413      *
414      * @return true the first time this is called on this object, then always returns false.
415      */
setEvaluated()416     public boolean setEvaluated() {
417         if (0L != mFirstEvaluationConcludedTime) return false;
418         mFirstEvaluationConcludedTime = SystemClock.elapsedRealtime();
419         return true;
420     }
421 
422     /** When this network ever concluded its first evaluation, or 0 if this never happened. */
423     @VisibleForTesting
getFirstEvaluationConcludedTime()424     public long getFirstEvaluationConcludedTime() {
425         return mFirstEvaluationConcludedTime;
426     }
427 
428     // Delay between when the network is disconnected and when the native network is destroyed.
429     public int teardownDelayMs;
430 
431     // Captive portal info of the network from RFC8908, if any.
432     // Obtained by ConnectivityService and merged into NetworkAgent-provided information.
433     public CaptivePortalData capportApiData;
434 
435     // The UID of the remote entity that created this Network.
436     public final int creatorUid;
437 
438     // Network agent portal info of the network, if any. This information is provided from
439     // non-RFC8908 sources, such as Wi-Fi Passpoint, which can provide information such as Venue
440     // URL, Terms & Conditions URL, and network friendly name.
441     public CaptivePortalData networkAgentPortalData;
442 
443     // Indicate whether this device has the automotive feature.
444     private final boolean mHasAutomotiveFeature;
445 
446     /**
447      * Checks that a proposed update to the NCs of this NAI satisfies structural constraints.
448      *
449      * Some changes to NetworkCapabilities are structurally not supported by the stack, and
450      * NetworkAgents are absolutely never allowed to try and do them. When one of these is
451      * violated, this method returns false, which has ConnectivityService disconnect the network ;
452      * this is meant to guarantee that no implementor ever tries to do this.
453      */
respectsNcStructuralConstraints(@onNull final NetworkCapabilities proposedNc)454     public boolean respectsNcStructuralConstraints(@NonNull final NetworkCapabilities proposedNc) {
455         if (networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)
456                 != proposedNc.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)) {
457             return false;
458         }
459         return true;
460     }
461 
462     /**
463      * Sets the capabilities sent by the agent for later retrieval.
464      * <p>
465      * This method does not sanitize the capabilities before storing them ; instead, use
466      * {@link #getDeclaredCapabilitiesSanitized} to retrieve a sanitized copy of the capabilities
467      * as they were passed here.
468      * <p>
469      * This method makes a defensive copy to avoid issues where the passed object is later mutated.
470      *
471      * @param caps the caps sent by the agent
472      */
setDeclaredCapabilities(@onNull final NetworkCapabilities caps)473     public void setDeclaredCapabilities(@NonNull final NetworkCapabilities caps) {
474         mDeclaredCapabilitiesUnsanitized = new NetworkCapabilities(caps);
475     }
476 
477     /**
478      * Get the latest capabilities sent by the network agent, after sanitizing them.
479      *
480      * These are the capabilities as they were sent by the agent (but sanitized to conform to
481      * their restrictions). They are NOT the capabilities currently applying to this agent ;
482      * for that, use {@link #networkCapabilities}.
483      *
484      * Agents have restrictions on what capabilities they can send to Connectivity. For example,
485      * they can't change the owner UID from what they declared before, and complex restrictions
486      * apply to the allowedUids field.
487      * They also should not mutate immutable capabilities, although for backward-compatibility
488      * this is not enforced and limited to just a log.
489      * Forbidden capabilities also make no sense for networks, so they are disallowed and
490      * will be ignored with a warning.
491      *
492      * @param carrierPrivilegeAuthenticator the authenticator, to check access UIDs.
493      */
getDeclaredCapabilitiesSanitized( final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator)494     public NetworkCapabilities getDeclaredCapabilitiesSanitized(
495             final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator) {
496         final NetworkCapabilities nc = new NetworkCapabilities(mDeclaredCapabilitiesUnsanitized);
497         if (nc.hasConnectivityManagedCapability()) {
498             Log.wtf(TAG, "BUG: " + this + " has CS-managed capability.");
499             nc.removeAllForbiddenCapabilities();
500         }
501         if (networkCapabilities.getOwnerUid() != nc.getOwnerUid()) {
502             Log.e(TAG, toShortString() + ": ignoring attempt to change owner from "
503                     + networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid());
504             nc.setOwnerUid(networkCapabilities.getOwnerUid());
505         }
506         restrictCapabilitiesFromNetworkAgent(nc, creatorUid, mHasAutomotiveFeature,
507                 mConnServiceDeps, carrierPrivilegeAuthenticator);
508         return nc;
509     }
510 
511     // Networks are lingered when they become unneeded as a result of their NetworkRequests being
512     // satisfied by a higher-scoring network. so as to allow communication to wrap up before the
513     // network is taken down.  This usually only happens to the default network. Lingering ends with
514     // either the linger timeout expiring and the network being taken down, or the network
515     // satisfying a request again.
516     public static class InactivityTimer implements Comparable<InactivityTimer> {
517         public final int requestId;
518         public final long expiryMs;
519 
InactivityTimer(int requestId, long expiryMs)520         public InactivityTimer(int requestId, long expiryMs) {
521             this.requestId = requestId;
522             this.expiryMs = expiryMs;
523         }
equals(Object o)524         public boolean equals(Object o) {
525             if (!(o instanceof InactivityTimer)) return false;
526             InactivityTimer other = (InactivityTimer) o;
527             return (requestId == other.requestId) && (expiryMs == other.expiryMs);
528         }
hashCode()529         public int hashCode() {
530             return Objects.hash(requestId, expiryMs);
531         }
compareTo(InactivityTimer other)532         public int compareTo(InactivityTimer other) {
533             return (expiryMs != other.expiryMs) ?
534                     Long.compare(expiryMs, other.expiryMs) :
535                     Integer.compare(requestId, other.requestId);
536         }
toString()537         public String toString() {
538             return String.format("%s, expires %dms", requestId,
539                     expiryMs - SystemClock.elapsedRealtime());
540         }
541     }
542 
543     /**
544      * Inform ConnectivityService that the network LINGER period has
545      * expired.
546      * obj = this NetworkAgentInfo
547      */
548     public static final int EVENT_NETWORK_LINGER_COMPLETE = 1001;
549 
550     /**
551      * Inform ConnectivityService that the agent is half-connected.
552      * arg1 = ARG_AGENT_SUCCESS or ARG_AGENT_FAILURE
553      * obj = NetworkAgentInfo
554      * @hide
555      */
556     public static final int EVENT_AGENT_REGISTERED = 1002;
557 
558     /**
559      * Inform ConnectivityService that the agent was disconnected.
560      * obj = NetworkAgentInfo
561      * @hide
562      */
563     public static final int EVENT_AGENT_DISCONNECTED = 1003;
564 
565     /**
566      * Argument for EVENT_AGENT_HALF_CONNECTED indicating failure.
567      */
568     public static final int ARG_AGENT_FAILURE = 0;
569 
570     /**
571      * Argument for EVENT_AGENT_HALF_CONNECTED indicating success.
572      */
573     public static final int ARG_AGENT_SUCCESS = 1;
574 
575     // How long this network should linger for.
576     private int mLingerDurationMs;
577 
578     // All inactivity timers for this network, sorted by expiry time. A timer is added whenever
579     // a request is moved to a network with a better score, regardless of whether the network is or
580     // was lingering or not. An inactivity timer is also added when a network connects
581     // without immediately satisfying any requests.
582     // TODO: determine if we can replace this with a smaller or unsorted data structure. (e.g.,
583     // SparseLongArray) combined with the timestamp of when the last timer is scheduled to fire.
584     private final SortedSet<InactivityTimer> mInactivityTimers = new TreeSet<>();
585 
586     // For fast lookups. Indexes into mInactivityTimers by request ID.
587     private final SparseArray<InactivityTimer> mInactivityTimerForRequest = new SparseArray<>();
588 
589     // Map of delegated UIDs used to bypass VPN and its captive portal app caller.
590     private final ArrayMap<CaptivePortalImpl, Integer> mCaptivePortalDelegateUids =
591             new ArrayMap<>();
592 
593     // Inactivity expiry timer. Armed whenever mInactivityTimers is non-empty, regardless of
594     // whether the network is inactive or not. Always set to the expiry of the mInactivityTimers
595     // that expires last. When the timer fires, all inactivity state is cleared, and if the network
596     // has no requests, it is torn down.
597     private WakeupMessage mInactivityMessage;
598 
599     // Inactivity expiry. Holds the expiry time of the inactivity timer, or 0 if the timer is not
600     // armed.
601     private long mInactivityExpiryMs;
602 
603     // Whether the network is inactive or not. Must be maintained separately from the above because
604     // it depends on the state of other networks and requests, which only ConnectivityService knows.
605     // (Example: we don't linger a network if it would become the best for a NetworkRequest if it
606     // validated).
607     private boolean mInactive;
608 
609     // This represents the quality of the network. As opposed to NetworkScore, FullScore includes
610     // the ConnectivityService-managed bits.
611     private FullScore mScore;
612 
613     // The list of NetworkRequests being satisfied by this Network.
614     private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
615 
616     // How many of the satisfied requests are actual requests and not listens.
617     private int mNumRequestNetworkRequests = 0;
618 
619     // How many of the satisfied requests are of type BACKGROUND_REQUEST.
620     private int mNumBackgroundNetworkRequests = 0;
621 
622     // The last ConnectivityReport made available for this network. This value is only null before a
623     // report is generated. Once non-null, it will never be null again.
624     @Nullable private ConnectivityReport mConnectivityReport;
625 
626     public final INetworkAgent networkAgent;
627     // Only accessed from ConnectivityService handler thread
628     private final AgentDeathMonitor mDeathMonitor = new AgentDeathMonitor();
629 
630     public final int factorySerialNumber;
631 
632     // Used by ConnectivityService to keep track of 464xlat.
633     public final Nat464Xlat clatd;
634 
635     private final ArrayList<Message> mMessagesPendingRegistration = new ArrayList<>();
636     // Set after asynchronous creation of the NetworkMonitor.
637     private volatile NetworkMonitorManager mNetworkMonitor;
638 
639     private static final String TAG = ConnectivityService.class.getSimpleName();
640     private static final boolean VDBG = false;
641     private final ConnectivityService mConnService;
642     private final ConnectivityService.Dependencies mConnServiceDeps;
643     private final Context mContext;
644     private final Handler mHandler;
645     private final NetworkAgentMessageHandler mRegistry;
646     private final QosCallbackTracker mQosCallbackTracker;
647     private final INetd mNetd;
648 
649     private final long mCreationTime;
650 
NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info, @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc, @Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score, Context context, Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid, int lingerDurationMs, QosCallbackTracker qosCallbackTracker, ConnectivityService.Dependencies deps)651     public NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info,
652             @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
653             @Nullable LocalNetworkConfig localNetworkConfig,
654             @NonNull NetworkScore score, Context context,
655             Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
656             IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
657             int lingerDurationMs, QosCallbackTracker qosCallbackTracker,
658             ConnectivityService.Dependencies deps) {
659         Objects.requireNonNull(net);
660         Objects.requireNonNull(info);
661         Objects.requireNonNull(lp);
662         Objects.requireNonNull(nc);
663         Objects.requireNonNull(context);
664         Objects.requireNonNull(config);
665         Objects.requireNonNull(qosCallbackTracker);
666         networkAgent = na;
667         network = net;
668         networkInfo = info;
669         linkProperties = lp;
670         networkCapabilities = nc;
671         this.localNetworkConfig = localNetworkConfig;
672         networkAgentConfig = config;
673         mConnService = connService;
674         mConnServiceDeps = deps;
675         setScore(score); // uses members connService, networkCapabilities and networkAgentConfig
676         clatd = new Nat464Xlat(this, netd, dnsResolver, deps);
677         mNetd = netd;
678         mContext = context;
679         mHandler = handler;
680         mRegistry = new NetworkAgentMessageHandler(mHandler);
681         this.factorySerialNumber = factorySerialNumber;
682         this.creatorUid = creatorUid;
683         mLingerDurationMs = lingerDurationMs;
684         mQosCallbackTracker = qosCallbackTracker;
685         declaredUnderlyingNetworks = (nc.getUnderlyingNetworks() != null)
686                 ? nc.getUnderlyingNetworks().toArray(new Network[0])
687                 : null;
688         mCreationTime = System.currentTimeMillis();
689         mHasAutomotiveFeature =
690                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
691     }
692 
693     private class AgentDeathMonitor implements IBinder.DeathRecipient {
694         @Override
binderDied()695         public void binderDied() {
696             notifyDisconnected();
697         }
698     }
699 
700     /**
701      * Notify the NetworkAgent that it was registered, and should be unregistered if it dies.
702      *
703      * Must be called from the ConnectivityService handler thread. A NetworkAgent can only be
704      * registered once.
705      */
notifyRegistered(final INetworkMonitor nm)706     public void notifyRegistered(final INetworkMonitor nm) {
707         HandlerUtils.ensureRunningOnHandlerThread(mHandler);
708         mNetworkMonitor = new NetworkMonitorManager(nm);
709         try {
710             networkAgent.asBinder().linkToDeath(mDeathMonitor, 0);
711             networkAgent.onRegistered();
712         } catch (RemoteException e) {
713             Log.e(TAG, "Error registering NetworkAgent", e);
714             maybeUnlinkDeathMonitor();
715             mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_FAILURE, 0, this)
716                     .sendToTarget();
717             return;
718         }
719 
720         mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_SUCCESS, 0, this).sendToTarget();
721     }
722 
723     /**
724      * Pass all enqueued messages to the message processor argument, and clear the queue.
725      *
726      * This is called by ConnectivityService when it is ready to receive messages for this
727      * network agent. The processor may process the messages synchronously or asynchronously
728      * at its option.
729      *
730      * @param messageProcessor a function to process the messages
731      */
processEnqueuedMessages(final Consumer<Message> messageProcessor)732     public void processEnqueuedMessages(final Consumer<Message> messageProcessor) {
733         for (final Message enqueued : mMessagesPendingRegistration) {
734             messageProcessor.accept(enqueued);
735         }
736         mMessagesPendingRegistration.clear();
737     }
738 
739     /**
740      * Enqueues a message if it needs to be enqueued, and returns whether it was enqueued.
741      *
742      * The message is enqueued iff it can't be sent just yet. If it can be sent
743      * immediately, this method returns false and doesn't enqueue.
744      *
745      * If it enqueues, this method will make a copy of the message for enqueuing since
746      * messages can't be reused or recycled before the end of their processing by the
747      * handler.
748      */
maybeEnqueueMessage(final Message msg)749     public boolean maybeEnqueueMessage(final Message msg) {
750         HandlerUtils.ensureRunningOnHandlerThread(mHandler);
751         if (null != mNetworkMonitor) return false;
752         final Message m = mHandler.obtainMessage();
753         m.copyFrom(msg);
754         mMessagesPendingRegistration.add(m);
755         return true;
756     }
757 
758     /**
759      * Disconnect the NetworkAgent. Must be called from the ConnectivityService handler thread.
760      */
disconnect()761     public void disconnect() {
762         try {
763             networkAgent.onDisconnected();
764         } catch (RemoteException e) {
765             Log.i(TAG, "Error disconnecting NetworkAgent", e);
766             // Fall through: it's fine if the remote has died
767         }
768 
769         notifyDisconnected();
770         maybeUnlinkDeathMonitor();
771     }
772 
maybeUnlinkDeathMonitor()773     private void maybeUnlinkDeathMonitor() {
774         try {
775             networkAgent.asBinder().unlinkToDeath(mDeathMonitor, 0);
776         } catch (NoSuchElementException e) {
777             // Was not linked: ignore
778         }
779     }
780 
notifyDisconnected()781     private void notifyDisconnected() {
782         // Note this may be called multiple times if ConnectivityService disconnects while the
783         // NetworkAgent also dies. ConnectivityService ignores disconnects of already disconnected
784         // agents.
785         mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED, this).sendToTarget();
786     }
787 
788     /**
789      * Notify the NetworkAgent that bandwidth update was requested.
790      */
onBandwidthUpdateRequested()791     public void onBandwidthUpdateRequested() {
792         try {
793             networkAgent.onBandwidthUpdateRequested();
794         } catch (RemoteException e) {
795             Log.e(TAG, "Error sending bandwidth update request event", e);
796         }
797     }
798 
799     /**
800      * Notify the NetworkAgent that validation status has changed.
801      */
onValidationStatusChanged(int validationStatus, @Nullable String captivePortalUrl)802     public void onValidationStatusChanged(int validationStatus, @Nullable String captivePortalUrl) {
803         try {
804             networkAgent.onValidationStatusChanged(validationStatus, captivePortalUrl);
805         } catch (RemoteException e) {
806             Log.e(TAG, "Error sending validation status change event", e);
807         }
808     }
809 
810     /**
811      * Notify the NetworkAgent that the acceptUnvalidated setting should be saved.
812      */
onSaveAcceptUnvalidated(boolean acceptUnvalidated)813     public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) {
814         try {
815             networkAgent.onSaveAcceptUnvalidated(acceptUnvalidated);
816         } catch (RemoteException e) {
817             Log.e(TAG, "Error sending accept unvalidated event", e);
818         }
819     }
820 
821     /**
822      * Notify the NetworkAgent that NATT socket keepalive should be started.
823      */
onStartNattSocketKeepalive(int slot, int intervalDurationMs, @NonNull NattKeepalivePacketData packetData)824     public void onStartNattSocketKeepalive(int slot, int intervalDurationMs,
825             @NonNull NattKeepalivePacketData packetData) {
826         try {
827             networkAgent.onStartNattSocketKeepalive(slot, intervalDurationMs, packetData);
828         } catch (RemoteException e) {
829             Log.e(TAG, "Error sending NATT socket keepalive start event", e);
830         }
831     }
832 
833     /**
834      * Notify the NetworkAgent that TCP socket keepalive should be started.
835      */
onStartTcpSocketKeepalive(int slot, int intervalDurationMs, @NonNull TcpKeepalivePacketData packetData)836     public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs,
837             @NonNull TcpKeepalivePacketData packetData) {
838         try {
839             networkAgent.onStartTcpSocketKeepalive(slot, intervalDurationMs, packetData);
840         } catch (RemoteException e) {
841             Log.e(TAG, "Error sending TCP socket keepalive start event", e);
842         }
843     }
844 
845     /**
846      * Notify the NetworkAgent that socket keepalive should be stopped.
847      */
onStopSocketKeepalive(int slot)848     public void onStopSocketKeepalive(int slot) {
849         try {
850             networkAgent.onStopSocketKeepalive(slot);
851         } catch (RemoteException e) {
852             Log.e(TAG, "Error sending TCP socket keepalive stop event", e);
853         }
854     }
855 
856     /**
857      * Notify the NetworkAgent that signal strength thresholds should be updated.
858      */
onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)859     public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
860         try {
861             networkAgent.onSignalStrengthThresholdsUpdated(thresholds);
862         } catch (RemoteException e) {
863             Log.e(TAG, "Error sending signal strength thresholds event", e);
864         }
865     }
866 
867     /**
868      * Notify the NetworkAgent that automatic reconnect should be prevented.
869      */
onPreventAutomaticReconnect()870     public void onPreventAutomaticReconnect() {
871         try {
872             networkAgent.onPreventAutomaticReconnect();
873         } catch (RemoteException e) {
874             Log.e(TAG, "Error sending prevent automatic reconnect event", e);
875         }
876     }
877 
878     /**
879      * Notify the NetworkAgent that a NATT keepalive packet filter should be added.
880      */
onAddNattKeepalivePacketFilter(int slot, @NonNull NattKeepalivePacketData packetData)881     public void onAddNattKeepalivePacketFilter(int slot,
882             @NonNull NattKeepalivePacketData packetData) {
883         try {
884             networkAgent.onAddNattKeepalivePacketFilter(slot, packetData);
885         } catch (RemoteException e) {
886             Log.e(TAG, "Error sending add NATT keepalive packet filter event", e);
887         }
888     }
889 
890     /**
891      * Notify the NetworkAgent that a TCP keepalive packet filter should be added.
892      */
onAddTcpKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketData packetData)893     public void onAddTcpKeepalivePacketFilter(int slot,
894             @NonNull TcpKeepalivePacketData packetData) {
895         try {
896             networkAgent.onAddTcpKeepalivePacketFilter(slot, packetData);
897         } catch (RemoteException e) {
898             Log.e(TAG, "Error sending add TCP keepalive packet filter event", e);
899         }
900     }
901 
902     /**
903      * Notify the NetworkAgent that a keepalive packet filter should be removed.
904      */
onRemoveKeepalivePacketFilter(int slot)905     public void onRemoveKeepalivePacketFilter(int slot) {
906         try {
907             networkAgent.onRemoveKeepalivePacketFilter(slot);
908         } catch (RemoteException e) {
909             Log.e(TAG, "Error sending remove keepalive packet filter event", e);
910         }
911     }
912 
913     /**
914      * Notify the NetworkAgent that the qos filter should be registered against the given qos
915      * callback id.
916      */
onQosFilterCallbackRegistered(final int qosCallbackId, final QosFilter qosFilter)917     public void onQosFilterCallbackRegistered(final int qosCallbackId,
918             final QosFilter qosFilter) {
919         try {
920             networkAgent.onQosFilterCallbackRegistered(qosCallbackId,
921                     new QosFilterParcelable(qosFilter));
922         } catch (final RemoteException e) {
923             Log.e(TAG, "Error registering a qos callback id against a qos filter", e);
924         }
925     }
926 
927     /**
928      * Notify the NetworkAgent that the given qos callback id should be unregistered.
929      */
onQosCallbackUnregistered(final int qosCallbackId)930     public void onQosCallbackUnregistered(final int qosCallbackId) {
931         try {
932             networkAgent.onQosCallbackUnregistered(qosCallbackId);
933         } catch (RemoteException e) {
934             Log.e(TAG, "Error unregistering a qos callback id", e);
935         }
936     }
937 
938     /**
939      * Notify the NetworkAgent that the network is successfully connected.
940      */
onNetworkCreated()941     public void onNetworkCreated() {
942         try {
943             networkAgent.onNetworkCreated();
944         } catch (RemoteException e) {
945             Log.e(TAG, "Error sending network created event", e);
946         }
947     }
948 
949     /**
950      * Notify the NetworkAgent that the native network has been destroyed.
951      */
onNetworkDestroyed()952     public void onNetworkDestroyed() {
953         try {
954             networkAgent.onNetworkDestroyed();
955         } catch (RemoteException e) {
956             Log.e(TAG, "Error sending network destroyed event", e);
957         }
958     }
959 
960     // TODO: consider moving out of NetworkAgentInfo into its own class
961     private class NetworkAgentMessageHandler extends INetworkAgentRegistry.Stub {
962         private final Handler mHandler;
963 
NetworkAgentMessageHandler(Handler handler)964         private NetworkAgentMessageHandler(Handler handler) {
965             mHandler = handler;
966         }
967 
968         @Override
sendNetworkCapabilities(@onNull NetworkCapabilities nc)969         public void sendNetworkCapabilities(@NonNull NetworkCapabilities nc) {
970             Objects.requireNonNull(nc);
971             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED,
972                     new Pair<>(NetworkAgentInfo.this, nc)).sendToTarget();
973         }
974 
975         @Override
sendLinkProperties(@onNull LinkProperties lp)976         public void sendLinkProperties(@NonNull LinkProperties lp) {
977             Objects.requireNonNull(lp);
978             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED,
979                     new Pair<>(NetworkAgentInfo.this, lp)).sendToTarget();
980         }
981 
982         @Override
sendNetworkInfo(@onNull NetworkInfo info)983         public void sendNetworkInfo(@NonNull NetworkInfo info) {
984             Objects.requireNonNull(info);
985             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_INFO_CHANGED,
986                     new Pair<>(NetworkAgentInfo.this, info)).sendToTarget();
987         }
988 
989         @Override
sendLocalNetworkConfig(@onNull final LocalNetworkConfig config)990         public void sendLocalNetworkConfig(@NonNull final LocalNetworkConfig config) {
991             mHandler.obtainMessage(NetworkAgent.EVENT_LOCAL_NETWORK_CONFIG_CHANGED,
992                     new Pair<>(NetworkAgentInfo.this, config)).sendToTarget();
993         }
994 
995         @Override
sendScore(@onNull final NetworkScore score)996         public void sendScore(@NonNull final NetworkScore score) {
997             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED,
998                     new Pair<>(NetworkAgentInfo.this, score)).sendToTarget();
999         }
1000 
1001         @Override
sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial)1002         public void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial) {
1003             mHandler.obtainMessage(NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED,
1004                     explicitlySelected ? 1 : 0, acceptPartial ? 1 : 0,
1005                     new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
1006         }
1007 
1008         @Override
sendSocketKeepaliveEvent(int slot, int reason)1009         public void sendSocketKeepaliveEvent(int slot, int reason) {
1010             mHandler.obtainMessage(NetworkAgent.EVENT_SOCKET_KEEPALIVE,
1011                     slot, reason, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
1012         }
1013 
1014         @Override
sendUnderlyingNetworks(@ullable List<Network> networks)1015         public void sendUnderlyingNetworks(@Nullable List<Network> networks) {
1016             mHandler.obtainMessage(NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED,
1017                     new Pair<>(NetworkAgentInfo.this, networks)).sendToTarget();
1018         }
1019 
1020         @Override
sendEpsQosSessionAvailable(final int qosCallbackId, final QosSession session, final EpsBearerQosSessionAttributes attributes)1021         public void sendEpsQosSessionAvailable(final int qosCallbackId, final QosSession session,
1022                 final EpsBearerQosSessionAttributes attributes) {
1023             mQosCallbackTracker.sendEventEpsQosSessionAvailable(qosCallbackId, session, attributes);
1024         }
1025 
1026         @Override
sendNrQosSessionAvailable(final int qosCallbackId, final QosSession session, final NrQosSessionAttributes attributes)1027         public void sendNrQosSessionAvailable(final int qosCallbackId, final QosSession session,
1028                 final NrQosSessionAttributes attributes) {
1029             mQosCallbackTracker.sendEventNrQosSessionAvailable(qosCallbackId, session, attributes);
1030         }
1031 
1032         @Override
sendQosSessionLost(final int qosCallbackId, final QosSession session)1033         public void sendQosSessionLost(final int qosCallbackId, final QosSession session) {
1034             mQosCallbackTracker.sendEventQosSessionLost(qosCallbackId, session);
1035         }
1036 
1037         @Override
sendQosCallbackError(final int qosCallbackId, @QosCallbackException.ExceptionType final int exceptionType)1038         public void sendQosCallbackError(final int qosCallbackId,
1039                 @QosCallbackException.ExceptionType final int exceptionType) {
1040             mQosCallbackTracker.sendEventQosCallbackError(qosCallbackId, exceptionType);
1041         }
1042 
1043         @Override
sendTeardownDelayMs(int teardownDelayMs)1044         public void sendTeardownDelayMs(int teardownDelayMs) {
1045             mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
1046                     teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
1047         }
1048 
1049         @Override
sendLingerDuration(final int durationMs)1050         public void sendLingerDuration(final int durationMs) {
1051             mHandler.obtainMessage(NetworkAgent.EVENT_LINGER_DURATION_CHANGED,
1052                     new Pair<>(NetworkAgentInfo.this, durationMs)).sendToTarget();
1053         }
1054 
1055         @Override
sendAddDscpPolicy(final DscpPolicy policy)1056         public void sendAddDscpPolicy(final DscpPolicy policy) {
1057             mHandler.obtainMessage(NetworkAgent.EVENT_ADD_DSCP_POLICY,
1058                     new Pair<>(NetworkAgentInfo.this, policy)).sendToTarget();
1059         }
1060 
1061         @Override
sendRemoveDscpPolicy(final int policyId)1062         public void sendRemoveDscpPolicy(final int policyId) {
1063             mHandler.obtainMessage(NetworkAgent.EVENT_REMOVE_DSCP_POLICY,
1064                     new Pair<>(NetworkAgentInfo.this, policyId)).sendToTarget();
1065         }
1066 
1067         @Override
sendRemoveAllDscpPolicies()1068         public void sendRemoveAllDscpPolicies() {
1069             mHandler.obtainMessage(NetworkAgent.EVENT_REMOVE_ALL_DSCP_POLICIES,
1070                     new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
1071         }
1072 
1073         @Override
sendUnregisterAfterReplacement(final int timeoutMillis)1074         public void sendUnregisterAfterReplacement(final int timeoutMillis) {
1075             mHandler.obtainMessage(NetworkAgent.EVENT_UNREGISTER_AFTER_REPLACEMENT,
1076                     new Pair<>(NetworkAgentInfo.this, timeoutMillis)).sendToTarget();
1077         }
1078     }
1079 
1080     /**
1081      * Set the NetworkCapabilities on this NetworkAgentInfo. Also attempts to notify NetworkMonitor
1082      * of the new capabilities, if NetworkMonitor has been created.
1083      *
1084      * <p>If {@link NetworkMonitor#notifyNetworkCapabilitiesChanged(NetworkCapabilities)} fails,
1085      * the exception is logged but not reported to callers.
1086      *
1087      * @return the old capabilities of this network.
1088      */
getAndSetNetworkCapabilities( @onNull final NetworkCapabilities nc)1089     @NonNull public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
1090             @NonNull final NetworkCapabilities nc) {
1091         final NetworkCapabilities oldNc = networkCapabilities;
1092         networkCapabilities = nc;
1093         updateScoreForNetworkAgentUpdate();
1094         final NetworkMonitorManager nm = mNetworkMonitor;
1095         if (nm != null) {
1096             nm.notifyNetworkCapabilitiesChanged(nc);
1097         }
1098         return oldNc;
1099     }
1100 
yieldToBadWiFi()1101     private boolean yieldToBadWiFi() {
1102         // Only cellular networks yield to bad wifi
1103         return networkCapabilities.hasTransport(TRANSPORT_CELLULAR) && !mConnService.avoidBadWifi();
1104     }
1105 
connService()1106     public ConnectivityService connService() {
1107         return mConnService;
1108     }
1109 
netAgentConfig()1110     public NetworkAgentConfig netAgentConfig() {
1111         return networkAgentConfig;
1112     }
1113 
handler()1114     public Handler handler() {
1115         return mHandler;
1116     }
1117 
network()1118     public Network network() {
1119         return network;
1120     }
1121 
1122     /**
1123      * Get the generated v6 address of clat.
1124      */
1125     @Nullable
getClatv6SrcAddress()1126     public Inet6Address getClatv6SrcAddress() {
1127         return clatd.getClatv6SrcAddress();
1128     }
1129 
1130     /**
1131      * Get the generated v4 address of clat.
1132      */
1133     @Nullable
getClatv4SrcAddress()1134     public Inet4Address getClatv4SrcAddress() {
1135         return clatd.getClatv4SrcAddress();
1136     }
1137 
1138     /**
1139      * Translate the input v4 address to v6 clat address.
1140      */
1141     @Nullable
translateV4toClatV6(@onNull Inet4Address addr)1142     public Inet6Address translateV4toClatV6(@NonNull Inet4Address addr) {
1143         return clatd.translateV4toV6(addr);
1144     }
1145 
1146     /**
1147      * Get the NetworkMonitorManager in this NetworkAgentInfo.
1148      *
1149      * <p>This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called.
1150      */
networkMonitor()1151     public NetworkMonitorManager networkMonitor() {
1152         return mNetworkMonitor;
1153     }
1154 
1155     /**
1156      * Get the registry in this NetworkAgentInfo.
1157      */
getRegistry()1158     public INetworkAgentRegistry getRegistry() {
1159         return mRegistry;
1160     }
1161 
1162     // Functions for manipulating the requests satisfied by this network.
1163     //
1164     // These functions must only called on ConnectivityService's main thread.
1165 
1166     private static final boolean ADD = true;
1167     private static final boolean REMOVE = false;
1168 
updateRequestCounts(boolean add, NetworkRequest request)1169     private void updateRequestCounts(boolean add, NetworkRequest request) {
1170         int delta = add ? +1 : -1;
1171         switch (request.type) {
1172             case REQUEST:
1173             case RESERVATION:
1174                 mNumRequestNetworkRequests += delta;
1175                 break;
1176 
1177             case BACKGROUND_REQUEST:
1178                 mNumRequestNetworkRequests += delta;
1179                 mNumBackgroundNetworkRequests += delta;
1180                 break;
1181 
1182             case LISTEN:
1183             case LISTEN_FOR_BEST:
1184             case TRACK_DEFAULT:
1185             case TRACK_SYSTEM_DEFAULT:
1186                 break;
1187 
1188             case NONE:
1189             default:
1190                 Log.wtf(TAG, "Unhandled request type " + request.type);
1191                 break;
1192         }
1193     }
1194 
1195     /**
1196      * Add {@code networkRequest} to this network as it's satisfied by this network.
1197      * @return true if {@code networkRequest} was added or false if {@code networkRequest} was
1198      *         already present.
1199      */
addRequest(NetworkRequest networkRequest)1200     public boolean addRequest(NetworkRequest networkRequest) {
1201         HandlerUtils.ensureRunningOnHandlerThread(mHandler);
1202         NetworkRequest existing = mNetworkRequests.get(networkRequest.requestId);
1203         if (existing == networkRequest) return false;
1204         if (existing != null) {
1205             // Should only happen if the requestId wraps. If that happens lots of other things will
1206             // be broken as well.
1207             Log.wtf(TAG, String.format("Duplicate requestId for %s and %s on %s",
1208                     networkRequest, existing, toShortString()));
1209             updateRequestCounts(REMOVE, existing);
1210         }
1211         mNetworkRequests.put(networkRequest.requestId, networkRequest);
1212         updateRequestCounts(ADD, networkRequest);
1213         return true;
1214     }
1215 
1216     /**
1217      * Remove the specified request from this network.
1218      */
removeRequest(int requestId)1219     public void removeRequest(int requestId) {
1220         HandlerUtils.ensureRunningOnHandlerThread(mHandler);
1221         NetworkRequest existing = mNetworkRequests.get(requestId);
1222         if (existing == null) return;
1223         updateRequestCounts(REMOVE, existing);
1224         mNetworkRequests.remove(requestId);
1225         if (existing.isRequest()) {
1226             unlingerRequest(existing.requestId);
1227         }
1228     }
1229 
1230     /**
1231      * Returns whether this network is currently satisfying the request with the specified ID.
1232      */
isSatisfyingRequest(int id)1233     public boolean isSatisfyingRequest(int id) {
1234         return mNetworkRequests.get(id) != null;
1235     }
1236 
1237     /**
1238      * Returns the request at the specified position in the list of requests satisfied by this
1239      * network.
1240      */
requestAt(int index)1241     public NetworkRequest requestAt(int index) {
1242         HandlerUtils.ensureRunningOnHandlerThread(mHandler);
1243         return mNetworkRequests.valueAt(index);
1244     }
1245 
1246     /**
1247      * Returns the number of requests currently satisfied by this network for which
1248      * {@link android.net.NetworkRequest#isRequest} returns {@code true}.
1249      */
numRequestNetworkRequests()1250     public int numRequestNetworkRequests() {
1251         return mNumRequestNetworkRequests;
1252     }
1253 
1254     /**
1255      * Returns the number of requests currently satisfied by this network of type
1256      * {@link android.net.NetworkRequest.Type#BACKGROUND_REQUEST}.
1257      */
numBackgroundNetworkRequests()1258     public int numBackgroundNetworkRequests() {
1259         return mNumBackgroundNetworkRequests;
1260     }
1261 
1262     /**
1263      * Returns the number of foreground requests currently satisfied by this network.
1264      */
numForegroundNetworkRequests()1265     public int numForegroundNetworkRequests() {
1266         return mNumRequestNetworkRequests - mNumBackgroundNetworkRequests;
1267     }
1268 
1269     /**
1270      * Returns the number of requests of any type currently satisfied by this network.
1271      */
numNetworkRequests()1272     public int numNetworkRequests() {
1273         HandlerUtils.ensureRunningOnHandlerThread(mHandler);
1274         return mNetworkRequests.size();
1275     }
1276 
1277     /**
1278      * Returns whether the network is a background network. A network is a background network if it
1279      * does not have the NET_CAPABILITY_FOREGROUND capability, which implies it is satisfying no
1280      * foreground request, is not lingering (i.e. kept for a while after being outscored), and is
1281      * not a speculative network (i.e. kept pending validation when validation would have it
1282      * outscore another foreground network). That implies it is being kept up by some background
1283      * request (otherwise it would be torn down), maybe the mobile always-on request.
1284      */
isBackgroundNetwork()1285     public boolean isBackgroundNetwork() {
1286         return !isVPN() && numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0
1287                 && !isLingering();
1288     }
1289 
1290     // Does this network satisfy request?
satisfies(NetworkRequest request)1291     public boolean satisfies(NetworkRequest request) {
1292         return everConnected()
1293                 && request.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities);
1294     }
1295 
satisfiesImmutableCapabilitiesOf(NetworkRequest request)1296     public boolean satisfiesImmutableCapabilitiesOf(NetworkRequest request) {
1297         return everConnected()
1298                 && request.networkCapabilities.satisfiedByImmutableNetworkCapabilities(
1299                         networkCapabilities);
1300     }
1301 
1302     /** Whether this network is a VPN. */
isVPN()1303     public boolean isVPN() {
1304         return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
1305     }
1306 
1307     /** Whether this network is a local network */
isLocalNetwork()1308     public boolean isLocalNetwork() {
1309         return networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK);
1310     }
1311 
1312     /**
1313      * Whether this network should propagate the capabilities from its underlying networks.
1314      * Currently only true for VPNs.
1315      */
propagateUnderlyingCapabilities()1316     public boolean propagateUnderlyingCapabilities() {
1317         return isVPN();
1318     }
1319 
1320     // Caller must not mutate. This method is called frequently and making a defensive copy
1321     // would be too expensive. This is used by NetworkRanker.Scoreable, so it can be compared
1322     // against other scoreables.
getCapsNoCopy()1323     @Override public NetworkCapabilities getCapsNoCopy() {
1324         return networkCapabilities;
1325     }
1326 
1327     // NetworkRanker.Scoreable
getScore()1328     @Override public FullScore getScore() {
1329         return mScore;
1330     }
1331 
1332     /**
1333      * Mix-in the ConnectivityService-managed bits in the score.
1334      */
setScore(final NetworkScore score)1335     public void setScore(final NetworkScore score) {
1336         final FullScore oldScore = mScore;
1337         mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig,
1338                 everValidated(), 0L != getAvoidUnvalidated(), yieldToBadWiFi(),
1339                 0L != mFirstEvaluationConcludedTime, isDestroyed());
1340         maybeLogDifferences(oldScore);
1341     }
1342 
1343     /**
1344      * Update the ConnectivityService-managed bits in the score.
1345      *
1346      * Call this after changing any data that might affect the score (e.g., agent config).
1347      */
updateScoreForNetworkAgentUpdate()1348     public void updateScoreForNetworkAgentUpdate() {
1349         final FullScore oldScore = mScore;
1350         mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig,
1351                 everValidated(), 0L != getAvoidUnvalidated(), yieldToBadWiFi(),
1352                 0L != mFirstEvaluationConcludedTime, isDestroyed());
1353         maybeLogDifferences(oldScore);
1354     }
1355 
1356     /**
1357      * Prints score differences to logcat, if any.
1358      * @param oldScore the old score. Differences from |oldScore| to |this| are logged, if any.
1359      */
maybeLogDifferences(final FullScore oldScore)1360     public void maybeLogDifferences(final FullScore oldScore) {
1361         final String differences = mScore.describeDifferencesFrom(oldScore);
1362         if (null != differences) {
1363             Log.i(TAG, "Update score for net " + network + " : " + differences);
1364         }
1365     }
1366 
1367     /**
1368      * Returns a Scoreable identical to this NAI, but validated.
1369      *
1370      * This is useful to probe what scoring would be if this network validated, to know
1371      * whether to provisionally keep a network that may or may not validate.
1372      *
1373      * @return a Scoreable identical to this NAI, but validated.
1374      */
getValidatedScoreable()1375     public NetworkRanker.Scoreable getValidatedScoreable() {
1376         return new NetworkRanker.Scoreable() {
1377             @Override public FullScore getScore() {
1378                 return mScore.asValidated();
1379             }
1380 
1381             @Override public NetworkCapabilities getCapsNoCopy() {
1382                 return networkCapabilities;
1383             }
1384         };
1385     }
1386 
1387     /**
1388      * Return a {@link NetworkStateSnapshot} for this network.
1389      */
1390     @NonNull
1391     public NetworkStateSnapshot getNetworkStateSnapshot() {
1392         synchronized (this) {
1393             // Network objects are outwardly immutable so there is no point in duplicating.
1394             // Duplicating also precludes sharing socket factories and connection pools.
1395             final String subscriberId = (networkAgentConfig != null)
1396                     ? networkAgentConfig.subscriberId : null;
1397             return new NetworkStateSnapshot(network, new NetworkCapabilities(networkCapabilities),
1398                     new LinkProperties(linkProperties), subscriberId, networkInfo.getType());
1399         }
1400     }
1401 
1402     /**
1403      * Sets the specified requestId to linger on this network for the specified time. Called by
1404      * ConnectivityService when any request is moved to another network with a higher score, or
1405      * when a network is newly created.
1406      *
1407      * @param requestId The requestId of the request that no longer need to be served by this
1408      *                  network. Or {@link NetworkRequest#REQUEST_ID_NONE} if this is the
1409      *                  {@code InactivityTimer} for a newly created network.
1410      */
1411     // TODO: Consider creating a dedicated function for nascent network, e.g. start/stopNascent.
1412     public void lingerRequest(int requestId, long now, long duration) {
1413         if (mInactivityTimerForRequest.get(requestId) != null) {
1414             // Cannot happen. Once a request is lingering on a particular network, we cannot
1415             // re-linger it unless that network becomes the best for that request again, in which
1416             // case we should have unlingered it.
1417             Log.wtf(TAG, toShortString() + ": request " + requestId + " already lingered");
1418         }
1419         final long expiryMs = now + duration;
1420         InactivityTimer timer = new InactivityTimer(requestId, expiryMs);
1421         if (VDBG) Log.d(TAG, "Adding InactivityTimer " + timer + " to " + toShortString());
1422         mInactivityTimers.add(timer);
1423         mInactivityTimerForRequest.put(requestId, timer);
1424     }
1425 
1426     /**
1427      * Sets the specified requestId to linger on this network for the timeout set when
1428      * initializing or modified by {@link #setLingerDuration(int)}. Called by
1429      * ConnectivityService when any request is moved to another network with a higher score.
1430      *
1431      * @param requestId The requestId of the request that no longer need to be served by this
1432      *                  network.
1433      * @param now current system timestamp obtained by {@code SystemClock.elapsedRealtime}.
1434      */
1435     public void lingerRequest(int requestId, long now) {
1436         lingerRequest(requestId, now, mLingerDurationMs);
1437     }
1438 
1439     /**
1440      * Cancel lingering. Called by ConnectivityService when a request is added to this network.
1441      * Returns true if the given requestId was lingering on this network, false otherwise.
1442      */
1443     public boolean unlingerRequest(int requestId) {
1444         InactivityTimer timer = mInactivityTimerForRequest.get(requestId);
1445         if (timer != null) {
1446             if (VDBG) {
1447                 Log.d(TAG, "Removing InactivityTimer " + timer + " from " + toShortString());
1448             }
1449             mInactivityTimers.remove(timer);
1450             mInactivityTimerForRequest.remove(requestId);
1451             return true;
1452         }
1453         return false;
1454     }
1455 
1456     public long getInactivityExpiry() {
1457         return mInactivityExpiryMs;
1458     }
1459 
1460     public void updateInactivityTimer() {
1461         long newExpiry = mInactivityTimers.isEmpty() ? 0 : mInactivityTimers.last().expiryMs;
1462         if (newExpiry == mInactivityExpiryMs) return;
1463 
1464         // Even if we're going to reschedule the timer, cancel it first. This is because the
1465         // semantics of WakeupMessage guarantee that if cancel is called then the alarm will
1466         // never call its callback (handleLingerComplete), even if it has already fired.
1467         // WakeupMessage makes no such guarantees about rescheduling a message, so if mLingerMessage
1468         // has already been dispatched, rescheduling to some time in the future won't stop it
1469         // from calling its callback immediately.
1470         if (mInactivityMessage != null) {
1471             mInactivityMessage.cancel();
1472             mInactivityMessage = null;
1473         }
1474 
1475         if (newExpiry > 0) {
1476             // If the newExpiry timestamp is in the past, the wakeup message will fire immediately.
1477             mInactivityMessage = new WakeupMessage(
1478                     mContext, mHandler,
1479                     "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
1480                     EVENT_NETWORK_LINGER_COMPLETE /* cmd */,
1481                     0 /* arg1 (unused) */, 0 /* arg2 (unused) */,
1482                     this /* obj (NetworkAgentInfo) */);
1483             mInactivityMessage.schedule(newExpiry);
1484         }
1485 
1486         mInactivityExpiryMs = newExpiry;
1487     }
1488 
1489     public void setInactive() {
1490         mInactive = true;
1491     }
1492 
1493     public void unsetInactive() {
1494         mInactive = false;
1495     }
1496 
1497     public boolean isInactive() {
1498         return mInactive;
1499     }
1500 
1501     public boolean isLingering() {
1502         return mInactive && !isNascent();
1503     }
1504 
1505     /**
1506      * Set the linger duration for this NAI.
1507      * @param durationMs The new linger duration, in milliseconds.
1508      */
1509     public void setLingerDuration(final int durationMs) {
1510         final long diff = durationMs - mLingerDurationMs;
1511         final ArrayList<InactivityTimer> newTimers = new ArrayList<>();
1512         for (final InactivityTimer timer : mInactivityTimers) {
1513             if (timer.requestId == NetworkRequest.REQUEST_ID_NONE) {
1514                 // Don't touch nascent timer, re-add as is.
1515                 newTimers.add(timer);
1516             } else {
1517                 newTimers.add(new InactivityTimer(timer.requestId, timer.expiryMs + diff));
1518             }
1519         }
1520         mInactivityTimers.clear();
1521         mInactivityTimers.addAll(newTimers);
1522         updateInactivityTimer();
1523         mLingerDurationMs = durationMs;
1524     }
1525 
1526     /**
1527      * Return whether the network satisfies no request, but is still being kept up
1528      * because it has just connected less than
1529      * {@code ConnectivityService#DEFAULT_NASCENT_DELAY_MS}ms ago and is thus still considered
1530      * nascent. Note that nascent mechanism uses inactivity timer which isn't
1531      * associated with a request. Thus, use {@link NetworkRequest#REQUEST_ID_NONE} to identify it.
1532      *
1533      */
1534     public boolean isNascent() {
1535         return mInactive && mInactivityTimers.size() == 1
1536                 && mInactivityTimers.first().requestId == NetworkRequest.REQUEST_ID_NONE;
1537     }
1538 
1539     public void clearInactivityState() {
1540         if (mInactivityMessage != null) {
1541             mInactivityMessage.cancel();
1542             mInactivityMessage = null;
1543         }
1544         mInactivityTimers.clear();
1545         mInactivityTimerForRequest.clear();
1546         // Sets mInactivityExpiryMs, cancels and nulls out mInactivityMessage.
1547         updateInactivityTimer();
1548         mInactive = false;
1549     }
1550 
1551     public void dumpInactivityTimers(PrintWriter pw) {
1552         for (InactivityTimer timer : mInactivityTimers) {
1553             pw.println(timer);
1554         }
1555     }
1556 
1557     /**
1558      * Dump the NAT64 xlat information.
1559      *
1560      * @param pw print writer.
1561      */
1562     public void dumpNat464Xlat(IndentingPrintWriter pw) {
1563         clatd.dump(pw);
1564     }
1565 
1566     /**
1567      * Sets the most recent ConnectivityReport for this network.
1568      *
1569      * <p>This should only be called from the ConnectivityService thread.
1570      *
1571      * @hide
1572      */
1573     public void setConnectivityReport(@NonNull ConnectivityReport connectivityReport) {
1574         mConnectivityReport = connectivityReport;
1575     }
1576 
1577     /**
1578      * Returns the most recent ConnectivityReport for this network, or null if none have been
1579      * reported yet.
1580      *
1581      * <p>This should only be called from the ConnectivityService thread.
1582      *
1583      * @hide
1584      */
1585     @Nullable
1586     public ConnectivityReport getConnectivityReport() {
1587         return mConnectivityReport;
1588     }
1589 
1590     /**
1591      * Make sure the NC from network agents don't contain stuff they shouldn't.
1592      *
1593      * @param nc the capabilities to sanitize
1594      * @param creatorUid the UID of the process creating this network agent
1595      * @param hasAutomotiveFeature true if this device has the automotive feature, false otherwise
1596      * @param authenticator the carrier privilege authenticator to check for telephony constraints
1597      */
1598     public static void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
1599             final int creatorUid, final boolean hasAutomotiveFeature,
1600             @NonNull final ConnectivityService.Dependencies deps,
1601             @Nullable final CarrierPrivilegeAuthenticator authenticator) {
1602         if (nc.hasTransport(TRANSPORT_TEST)) {
1603             nc.restrictCapabilitiesForTestNetwork(creatorUid);
1604         }
1605         if (!areAllowedUidsAcceptableFromNetworkAgent(
1606                 nc, hasAutomotiveFeature, deps, authenticator)) {
1607             nc.setAllowedUids(new ArraySet<>());
1608         }
1609     }
1610 
1611     private int allowBypassVpnOnNetwork(boolean allow, int uid, int netId) {
1612         try {
1613             mNetd.networkAllowBypassVpnOnNetwork(allow, uid, netId);
1614             return 0;
1615         } catch (RemoteException e) {
1616             // Netd has crashed, and this process is about to crash as well.
1617             return EIO;
1618         } catch (ServiceSpecificException e) {
1619             return e.errorCode;
1620         }
1621     }
1622 
1623     /**
1624      * Set the delegate UID of the app that is allowed to perform network traffic for captive
1625      * portal login, and configure the netd bypass rule with this delegated UID.
1626      *
1627      * @param caller the captive portal app to that delegated UID
1628      * @param uid the delegated UID of the captive portal app.
1629      * @return Return 0 if set the UID and VPN bypass rule successfully or bypass rule corresponding
1630      *                to this UID already exists otherwise return errno.
1631      */
1632     public int setCaptivePortalDelegateUid(@NonNull final CaptivePortalImpl caller, int uid) {
1633         final int errorCode = allowBypassVpnOnNetwork(true /* allow */, uid, network.netId);
1634         if (errorCode == 0 || errorCode == EEXIST) {
1635             mCaptivePortalDelegateUids.put(caller, uid);
1636         }
1637         return errorCode == EEXIST ? 0 : errorCode;
1638     }
1639 
1640     /**
1641      * Remove the delegate UID of the app that is allowed to perform network traffic for captive
1642      * portal login, and remove the netd bypass rule if no other caller is delegating this UID.
1643      *
1644      * @param caller the captive portal app to that delegated UID.
1645      * @return Return 0 if remove the UID and VPN bypass rule successfully or bypass rule
1646      *                corresponding to this UID doesn't exist otherwise return errno.
1647      */
1648     public int removeCaptivePortalDelegateUid(@NonNull final CaptivePortalImpl caller) {
1649         final Integer maybeDelegateUid = mCaptivePortalDelegateUids.remove(caller);
1650         if (maybeDelegateUid == null) return 0;
1651         if (mCaptivePortalDelegateUids.values().contains(maybeDelegateUid)) return 0;
1652         final int errorCode =
1653                 allowBypassVpnOnNetwork(false /* allow */, maybeDelegateUid, network.netId);
1654         if (errorCode == ENOENT) {
1655             FrameworkConnectivityStatsLog.write(
1656                     CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
1657                     CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_DISALLOW_BYPASS_VPN_FOR_DELEGATE_UID_ENOENT
1658             );
1659         }
1660         return errorCode == ENOENT ? 0 : errorCode;
1661     }
1662 
1663     private static boolean areAllowedUidsAcceptableFromNetworkAgent(
1664             @NonNull final NetworkCapabilities nc, final boolean hasAutomotiveFeature,
1665             @NonNull final ConnectivityService.Dependencies deps,
1666             @Nullable final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator) {
1667         // NCs without access UIDs are fine.
1668         if (!nc.hasAllowedUids()) return true;
1669         // S and below must never accept access UIDs, even if an agent sends them, because netd
1670         // didn't support the required feature in S.
1671         if (!deps.isAtLeastT()) return false;
1672 
1673         // On a non-restricted network, access UIDs make no sense
1674         if (nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) return false;
1675 
1676         // If this network has TRANSPORT_TEST and nothing else, then the caller can do whatever
1677         // they want to access UIDs
1678         if (nc.hasSingleTransport(TRANSPORT_TEST)) return true;
1679 
1680         if (nc.hasTransport(TRANSPORT_ETHERNET)) {
1681             // Factories that make ethernet networks can allow UIDs for automotive devices.
1682             if (hasAutomotiveFeature) return true;
1683             // It's also admissible if the ethernet network has TRANSPORT_TEST, as long as it
1684             // doesn't have NET_CAPABILITY_INTERNET so it can't become the default network.
1685             if (nc.hasTransport(TRANSPORT_TEST) && !nc.hasCapability(NET_CAPABILITY_INTERNET)) {
1686                 return true;
1687             }
1688             return false;
1689         }
1690 
1691         // Factories that make cell/wifi networks can allow the UID for the carrier service package.
1692         // This can only work in T where there is support for CarrierPrivilegeAuthenticator
1693         if (null != carrierPrivilegeAuthenticator
1694                 && (nc.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)
1695                         || nc.hasSingleTransportBesidesTest(TRANSPORT_WIFI))
1696                 && (1 == nc.getAllowedUidsNoCopy().size())
1697                 && (carrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
1698                         nc.getAllowedUidsNoCopy().valueAt(0), nc))) {
1699             return true;
1700         }
1701 
1702         return false;
1703     }
1704 
1705     // TODO: Print shorter members first and only print the boolean variable which value is true
1706     // to improve readability.
1707     public String toString() {
1708         return "NetworkAgentInfo{"
1709                 + "network{" + network + "}  handle{" + network.getNetworkHandle() + "}  ni{"
1710                 + networkInfo.toShortString() + "} "
1711                 + "created=" + Instant.ofEpochMilli(mCreationTime) + " "
1712                 + mScore + " "
1713                 + (isCreated() ? " created " + getCreatedTime() : "")
1714                 + (isDestroyed() ? " destroyed " + mDestroyedTime : "")
1715                 + (isNascent() ? " nascent" : (isLingering() ? " lingering" : ""))
1716                 + (everValidated() ? " firstValidated " + getFirstValidationTime() : "")
1717                 + (isValidated() ? " lastValidated " + getCurrentValidationTime() : "")
1718                 + (partialConnectivity()
1719                         ? " partialConnectivity " + mPartialConnectivityTime : "")
1720                 + (everCaptivePortalDetected()
1721                         ? " firstCaptivePortalDetected " + mFirstCaptivePortalDetectedTime : "")
1722                 + (captivePortalDetected()
1723                         ? " currentCaptivePortalDetected " + mCurrentCaptivePortalDetectedTime : "")
1724                 + (networkAgentConfig.explicitlySelected ? " explicitlySelected" : "")
1725                 + (networkAgentConfig.acceptUnvalidated ? " acceptUnvalidated" : "")
1726                 + (networkAgentConfig.acceptPartialConnectivity ? " acceptPartialConnectivity" : "")
1727                 + (clatd.isStarted() ? " clat{" + clatd + "} " : "")
1728                 + (declaredUnderlyingNetworks != null
1729                         ? " underlying{" + Arrays.toString(declaredUnderlyingNetworks) + "}" : "")
1730                 + "  lp{" + linkProperties + "}"
1731                 + "  nc{" + networkCapabilities + "}"
1732                 + "  factorySerialNumber=" + factorySerialNumber
1733                 + "}";
1734     }
1735 
1736     /**
1737      * Show a short string representing a Network.
1738      *
1739      * This is often not enough for debugging purposes for anything complex, but the full form
1740      * is very long and hard to read, so this is useful when there isn't a lot of ambiguity.
1741      * This represents the network with something like "[100 WIFI|VPN]" or "[108 CELLULAR]".
1742      */
1743     public String toShortString() {
1744         return "[" + network.getNetId() + " "
1745                 + transportNamesOf(networkCapabilities.getTransportTypes()) + "]";
1746     }
1747 
1748     /**
1749      * Null-guarding version of NetworkAgentInfo#toShortString()
1750      */
1751     @NonNull
1752     public static String toShortString(@Nullable final NetworkAgentInfo nai) {
1753         return null != nai ? nai.toShortString() : "[null]";
1754     }
1755 }
1756