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