• 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.TRANSPORT_CELLULAR;
21 import static android.net.NetworkCapabilities.transportNamesOf;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.content.Context;
26 import android.net.CaptivePortalData;
27 import android.net.IDnsResolver;
28 import android.net.INetd;
29 import android.net.INetworkAgent;
30 import android.net.INetworkAgentRegistry;
31 import android.net.INetworkMonitor;
32 import android.net.LinkProperties;
33 import android.net.NattKeepalivePacketData;
34 import android.net.Network;
35 import android.net.NetworkAgent;
36 import android.net.NetworkAgentConfig;
37 import android.net.NetworkCapabilities;
38 import android.net.NetworkInfo;
39 import android.net.NetworkMonitorManager;
40 import android.net.NetworkRequest;
41 import android.net.NetworkScore;
42 import android.net.NetworkStateSnapshot;
43 import android.net.QosCallbackException;
44 import android.net.QosFilter;
45 import android.net.QosFilterParcelable;
46 import android.net.QosSession;
47 import android.net.TcpKeepalivePacketData;
48 import android.os.Handler;
49 import android.os.IBinder;
50 import android.os.RemoteException;
51 import android.os.SystemClock;
52 import android.telephony.data.EpsBearerQosSessionAttributes;
53 import android.telephony.data.NrQosSessionAttributes;
54 import android.util.Log;
55 import android.util.Pair;
56 import android.util.SparseArray;
57 
58 import com.android.internal.util.WakeupMessage;
59 import com.android.server.ConnectivityService;
60 
61 import java.io.PrintWriter;
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.List;
65 import java.util.NoSuchElementException;
66 import java.util.Objects;
67 import java.util.SortedSet;
68 import java.util.TreeSet;
69 
70 /**
71  * A bag class used by ConnectivityService for holding a collection of most recent
72  * information published by a particular NetworkAgent as well as the
73  * AsyncChannel/messenger for reaching that NetworkAgent and lists of NetworkRequests
74  * interested in using it.  Default sort order is descending by score.
75  */
76 // States of a network:
77 // --------------------
78 // 1. registered, uncreated, disconnected, unvalidated
79 //    This state is entered when a NetworkFactory registers a NetworkAgent in any state except
80 //    the CONNECTED state.
81 // 2. registered, uncreated, connecting, unvalidated
82 //    This state is entered when a registered NetworkAgent for a VPN network transitions to the
83 //    CONNECTING state (TODO: go through this state for every network, not just VPNs).
84 //    ConnectivityService will tell netd to create the network early in order to add extra UID
85 //    routing rules referencing the netID. These rules need to be in place before the network is
86 //    connected to avoid racing against client apps trying to connect to a half-setup network.
87 // 3. registered, uncreated, connected, unvalidated
88 //    This state is entered when a registered NetworkAgent transitions to the CONNECTED state.
89 //    ConnectivityService will tell netd to create the network if it was not already created, and
90 //    immediately transition to state #4.
91 // 4. registered, created, connected, unvalidated
92 //    If this network can satisfy the default NetworkRequest, then NetworkMonitor will
93 //    probe for Internet connectivity.
94 //    If this network cannot satisfy the default NetworkRequest, it will immediately be
95 //    transitioned to state #5.
96 //    A network may remain in this state if NetworkMonitor fails to find Internet connectivity,
97 //    for example:
98 //    a. a captive portal is present, or
99 //    b. a WiFi router whose Internet backhaul is down, or
100 //    c. a wireless connection stops transfering packets temporarily (e.g. device is in elevator
101 //       or tunnel) but does not disconnect from the AP/cell tower, or
102 //    d. a stand-alone device offering a WiFi AP without an uplink for configuration purposes.
103 // 5. registered, created, connected, validated
104 //
105 // The device's default network connection:
106 // ----------------------------------------
107 // Networks in states #4 and #5 may be used as a device's default network connection if they
108 // satisfy the default NetworkRequest.
109 // A network, that satisfies the default NetworkRequest, in state #5 should always be chosen
110 // in favor of a network, that satisfies the default NetworkRequest, in state #4.
111 // When deciding between two networks, that both satisfy the default NetworkRequest, to select
112 // for the default network connection, the one with the higher score should be chosen.
113 //
114 // When a network disconnects:
115 // ---------------------------
116 // If a network's transport disappears, for example:
117 // a. WiFi turned off, or
118 // b. cellular data turned off, or
119 // c. airplane mode is turned on, or
120 // d. a wireless connection disconnects from AP/cell tower entirely (e.g. device is out of range
121 //    of AP for an extended period of time, or switches to another AP without roaming)
122 // then that network can transition from any state (#1-#5) to unregistered.  This happens by
123 // the transport disconnecting their NetworkAgent's AsyncChannel with ConnectivityManager.
124 // ConnectivityService also tells netd to destroy the network.
125 //
126 // When ConnectivityService disconnects a network:
127 // -----------------------------------------------
128 // If a network is just connected, ConnectivityService will think it will be used soon, but might
129 // not be used. Thus, a 5s timer will be held to prevent the network being torn down immediately.
130 // This "nascent" state is implemented by the "lingering" logic below without relating to any
131 // request, and is used in some cases where network requests race with network establishment. The
132 // nascent state ends when the 5-second timer fires, or as soon as the network satisfies a
133 // request, whichever is earlier. In this state, the network is considered in the background.
134 //
135 // If a network has no chance of satisfying any requests (even if it were to become validated
136 // and enter state #5), ConnectivityService will disconnect the NetworkAgent's AsyncChannel.
137 //
138 // If the network was satisfying a foreground NetworkRequest (i.e. had been the highest scoring that
139 // satisfied the NetworkRequest's constraints), but is no longer the highest scoring network for any
140 // foreground NetworkRequest, then there will be a 30s pause to allow network communication to be
141 // wrapped up rather than abruptly terminated. During this pause the network is said to be
142 // "lingering". During this pause if the network begins satisfying a foreground NetworkRequest,
143 // ConnectivityService will cancel the future disconnection of the NetworkAgent's AsyncChannel, and
144 // the network is no longer considered "lingering". After the linger timer expires, if the network
145 // is satisfying one or more background NetworkRequests it is kept up in the background. If it is
146 // not, ConnectivityService disconnects the NetworkAgent's AsyncChannel.
147 public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRanker.Scoreable {
148 
149     @NonNull public NetworkInfo networkInfo;
150     // This Network object should always be used if possible, so as to encourage reuse of the
151     // enclosed socket factory and connection pool.  Avoid creating other Network objects.
152     // This Network object is always valid.
153     @NonNull public final Network network;
154     @NonNull public LinkProperties linkProperties;
155     // This should only be modified by ConnectivityService, via setNetworkCapabilities().
156     // TODO: make this private with a getter.
157     @NonNull public NetworkCapabilities networkCapabilities;
158     @NonNull public final NetworkAgentConfig networkAgentConfig;
159 
160     // Underlying networks declared by the agent.
161     // The networks in this list might be declared by a VPN using setUnderlyingNetworks and are
162     // not guaranteed to be current or correct, or even to exist.
163     //
164     // This array is read and iterated on multiple threads with no locking so its contents must
165     // never be modified. When the list of networks changes, replace with a new array, on the
166     // handler thread.
167     public @Nullable volatile Network[] declaredUnderlyingNetworks;
168 
169     // The capabilities originally announced by the NetworkAgent, regardless of any capabilities
170     // that were added or removed due to this network's underlying networks.
171     // Only set if #propagateUnderlyingCapabilities is true.
172     public @Nullable NetworkCapabilities declaredCapabilities;
173 
174     // Indicates if netd has been told to create this Network. From this point on the appropriate
175     // routing rules are setup and routes are added so packets can begin flowing over the Network.
176     // This is a sticky bit; once set it is never cleared.
177     public boolean created;
178     // Set to true after the first time this network is marked as CONNECTED. Once set, the network
179     // shows up in API calls, is able to satisfy NetworkRequests and can become the default network.
180     // This is a sticky bit; once set it is never cleared.
181     public boolean everConnected;
182     // Set to true if this Network successfully passed validation or if it did not satisfy the
183     // default NetworkRequest in which case validation will not be attempted.
184     // This is a sticky bit; once set it is never cleared even if future validation attempts fail.
185     public boolean everValidated;
186 
187     // The result of the last validation attempt on this network (true if validated, false if not).
188     public boolean lastValidated;
189 
190     // If true, becoming unvalidated will lower the network's score. This is only meaningful if the
191     // system is configured not to do this for certain networks, e.g., if the
192     // config_networkAvoidBadWifi option is set to 0 and the user has not overridden that via
193     // Settings.Global.NETWORK_AVOID_BAD_WIFI.
194     public boolean avoidUnvalidated;
195 
196     // Whether a captive portal was ever detected on this network.
197     // This is a sticky bit; once set it is never cleared.
198     public boolean everCaptivePortalDetected;
199 
200     // Whether a captive portal was found during the last network validation attempt.
201     public boolean lastCaptivePortalDetected;
202 
203     // Set to true when partial connectivity was detected.
204     public boolean partialConnectivity;
205 
206     // Delay between when the network is disconnected and when the native network is destroyed.
207     public int teardownDelayMs;
208 
209     // Captive portal info of the network from RFC8908, if any.
210     // Obtained by ConnectivityService and merged into NetworkAgent-provided information.
211     public CaptivePortalData capportApiData;
212 
213     // The UID of the remote entity that created this Network.
214     public final int creatorUid;
215 
216     // Network agent portal info of the network, if any. This information is provided from
217     // non-RFC8908 sources, such as Wi-Fi Passpoint, which can provide information such as Venue
218     // URL, Terms & Conditions URL, and network friendly name.
219     public CaptivePortalData networkAgentPortalData;
220 
221     // Networks are lingered when they become unneeded as a result of their NetworkRequests being
222     // satisfied by a higher-scoring network. so as to allow communication to wrap up before the
223     // network is taken down.  This usually only happens to the default network. Lingering ends with
224     // either the linger timeout expiring and the network being taken down, or the network
225     // satisfying a request again.
226     public static class InactivityTimer implements Comparable<InactivityTimer> {
227         public final int requestId;
228         public final long expiryMs;
229 
InactivityTimer(int requestId, long expiryMs)230         public InactivityTimer(int requestId, long expiryMs) {
231             this.requestId = requestId;
232             this.expiryMs = expiryMs;
233         }
equals(Object o)234         public boolean equals(Object o) {
235             if (!(o instanceof InactivityTimer)) return false;
236             InactivityTimer other = (InactivityTimer) o;
237             return (requestId == other.requestId) && (expiryMs == other.expiryMs);
238         }
hashCode()239         public int hashCode() {
240             return Objects.hash(requestId, expiryMs);
241         }
compareTo(InactivityTimer other)242         public int compareTo(InactivityTimer other) {
243             return (expiryMs != other.expiryMs) ?
244                     Long.compare(expiryMs, other.expiryMs) :
245                     Integer.compare(requestId, other.requestId);
246         }
toString()247         public String toString() {
248             return String.format("%s, expires %dms", requestId,
249                     expiryMs - SystemClock.elapsedRealtime());
250         }
251     }
252 
253     /**
254      * Inform ConnectivityService that the network LINGER period has
255      * expired.
256      * obj = this NetworkAgentInfo
257      */
258     public static final int EVENT_NETWORK_LINGER_COMPLETE = 1001;
259 
260     /**
261      * Inform ConnectivityService that the agent is half-connected.
262      * arg1 = ARG_AGENT_SUCCESS or ARG_AGENT_FAILURE
263      * obj = NetworkAgentInfo
264      * @hide
265      */
266     public static final int EVENT_AGENT_REGISTERED = 1002;
267 
268     /**
269      * Inform ConnectivityService that the agent was disconnected.
270      * obj = NetworkAgentInfo
271      * @hide
272      */
273     public static final int EVENT_AGENT_DISCONNECTED = 1003;
274 
275     /**
276      * Argument for EVENT_AGENT_HALF_CONNECTED indicating failure.
277      */
278     public static final int ARG_AGENT_FAILURE = 0;
279 
280     /**
281      * Argument for EVENT_AGENT_HALF_CONNECTED indicating success.
282      */
283     public static final int ARG_AGENT_SUCCESS = 1;
284 
285     // How long this network should linger for.
286     private int mLingerDurationMs;
287 
288     // All inactivity timers for this network, sorted by expiry time. A timer is added whenever
289     // a request is moved to a network with a better score, regardless of whether the network is or
290     // was lingering or not. An inactivity timer is also added when a network connects
291     // without immediately satisfying any requests.
292     // TODO: determine if we can replace this with a smaller or unsorted data structure. (e.g.,
293     // SparseLongArray) combined with the timestamp of when the last timer is scheduled to fire.
294     private final SortedSet<InactivityTimer> mInactivityTimers = new TreeSet<>();
295 
296     // For fast lookups. Indexes into mInactivityTimers by request ID.
297     private final SparseArray<InactivityTimer> mInactivityTimerForRequest = new SparseArray<>();
298 
299     // Inactivity expiry timer. Armed whenever mInactivityTimers is non-empty, regardless of
300     // whether the network is inactive or not. Always set to the expiry of the mInactivityTimers
301     // that expires last. When the timer fires, all inactivity state is cleared, and if the network
302     // has no requests, it is torn down.
303     private WakeupMessage mInactivityMessage;
304 
305     // Inactivity expiry. Holds the expiry time of the inactivity timer, or 0 if the timer is not
306     // armed.
307     private long mInactivityExpiryMs;
308 
309     // Whether the network is inactive or not. Must be maintained separately from the above because
310     // it depends on the state of other networks and requests, which only ConnectivityService knows.
311     // (Example: we don't linger a network if it would become the best for a NetworkRequest if it
312     // validated).
313     private boolean mInactive;
314 
315     // This represents the quality of the network. As opposed to NetworkScore, FullScore includes
316     // the ConnectivityService-managed bits.
317     private FullScore mScore;
318 
319     // The list of NetworkRequests being satisfied by this Network.
320     private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
321 
322     // How many of the satisfied requests are actual requests and not listens.
323     private int mNumRequestNetworkRequests = 0;
324 
325     // How many of the satisfied requests are of type BACKGROUND_REQUEST.
326     private int mNumBackgroundNetworkRequests = 0;
327 
328     // The last ConnectivityReport made available for this network. This value is only null before a
329     // report is generated. Once non-null, it will never be null again.
330     @Nullable private ConnectivityReport mConnectivityReport;
331 
332     public final INetworkAgent networkAgent;
333     // Only accessed from ConnectivityService handler thread
334     private final AgentDeathMonitor mDeathMonitor = new AgentDeathMonitor();
335 
336     public final int factorySerialNumber;
337 
338     // Used by ConnectivityService to keep track of 464xlat.
339     public final Nat464Xlat clatd;
340 
341     // Set after asynchronous creation of the NetworkMonitor.
342     private volatile NetworkMonitorManager mNetworkMonitor;
343 
344     private static final String TAG = ConnectivityService.class.getSimpleName();
345     private static final boolean VDBG = false;
346     private final ConnectivityService mConnService;
347     private final Context mContext;
348     private final Handler mHandler;
349     private final QosCallbackTracker mQosCallbackTracker;
350 
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)351     public NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info,
352             @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
353             @NonNull NetworkScore score, Context context,
354             Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
355             IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
356             int lingerDurationMs, QosCallbackTracker qosCallbackTracker,
357             ConnectivityService.Dependencies deps) {
358         Objects.requireNonNull(net);
359         Objects.requireNonNull(info);
360         Objects.requireNonNull(lp);
361         Objects.requireNonNull(nc);
362         Objects.requireNonNull(context);
363         Objects.requireNonNull(config);
364         Objects.requireNonNull(qosCallbackTracker);
365         networkAgent = na;
366         network = net;
367         networkInfo = info;
368         linkProperties = lp;
369         networkCapabilities = nc;
370         networkAgentConfig = config;
371         mConnService = connService;
372         setScore(score); // uses members connService, networkCapabilities and networkAgentConfig
373         clatd = new Nat464Xlat(this, netd, dnsResolver, deps);
374         mContext = context;
375         mHandler = handler;
376         this.factorySerialNumber = factorySerialNumber;
377         this.creatorUid = creatorUid;
378         mLingerDurationMs = lingerDurationMs;
379         mQosCallbackTracker = qosCallbackTracker;
380     }
381 
382     private class AgentDeathMonitor implements IBinder.DeathRecipient {
383         @Override
binderDied()384         public void binderDied() {
385             notifyDisconnected();
386         }
387     }
388 
389     /**
390      * Notify the NetworkAgent that it was registered, and should be unregistered if it dies.
391      *
392      * Must be called from the ConnectivityService handler thread. A NetworkAgent can only be
393      * registered once.
394      */
notifyRegistered()395     public void notifyRegistered() {
396         try {
397             networkAgent.asBinder().linkToDeath(mDeathMonitor, 0);
398             networkAgent.onRegistered(new NetworkAgentMessageHandler(mHandler));
399         } catch (RemoteException e) {
400             Log.e(TAG, "Error registering NetworkAgent", e);
401             maybeUnlinkDeathMonitor();
402             mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_FAILURE, 0, this)
403                     .sendToTarget();
404             return;
405         }
406 
407         mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_SUCCESS, 0, this).sendToTarget();
408     }
409 
410     /**
411      * Disconnect the NetworkAgent. Must be called from the ConnectivityService handler thread.
412      */
disconnect()413     public void disconnect() {
414         try {
415             networkAgent.onDisconnected();
416         } catch (RemoteException e) {
417             Log.i(TAG, "Error disconnecting NetworkAgent", e);
418             // Fall through: it's fine if the remote has died
419         }
420 
421         notifyDisconnected();
422         maybeUnlinkDeathMonitor();
423     }
424 
maybeUnlinkDeathMonitor()425     private void maybeUnlinkDeathMonitor() {
426         try {
427             networkAgent.asBinder().unlinkToDeath(mDeathMonitor, 0);
428         } catch (NoSuchElementException e) {
429             // Was not linked: ignore
430         }
431     }
432 
notifyDisconnected()433     private void notifyDisconnected() {
434         // Note this may be called multiple times if ConnectivityService disconnects while the
435         // NetworkAgent also dies. ConnectivityService ignores disconnects of already disconnected
436         // agents.
437         mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED, this).sendToTarget();
438     }
439 
440     /**
441      * Notify the NetworkAgent that bandwidth update was requested.
442      */
onBandwidthUpdateRequested()443     public void onBandwidthUpdateRequested() {
444         try {
445             networkAgent.onBandwidthUpdateRequested();
446         } catch (RemoteException e) {
447             Log.e(TAG, "Error sending bandwidth update request event", e);
448         }
449     }
450 
451     /**
452      * Notify the NetworkAgent that validation status has changed.
453      */
onValidationStatusChanged(int validationStatus, @Nullable String captivePortalUrl)454     public void onValidationStatusChanged(int validationStatus, @Nullable String captivePortalUrl) {
455         try {
456             networkAgent.onValidationStatusChanged(validationStatus, captivePortalUrl);
457         } catch (RemoteException e) {
458             Log.e(TAG, "Error sending validation status change event", e);
459         }
460     }
461 
462     /**
463      * Notify the NetworkAgent that the acceptUnvalidated setting should be saved.
464      */
onSaveAcceptUnvalidated(boolean acceptUnvalidated)465     public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) {
466         try {
467             networkAgent.onSaveAcceptUnvalidated(acceptUnvalidated);
468         } catch (RemoteException e) {
469             Log.e(TAG, "Error sending accept unvalidated event", e);
470         }
471     }
472 
473     /**
474      * Notify the NetworkAgent that NATT socket keepalive should be started.
475      */
onStartNattSocketKeepalive(int slot, int intervalDurationMs, @NonNull NattKeepalivePacketData packetData)476     public void onStartNattSocketKeepalive(int slot, int intervalDurationMs,
477             @NonNull NattKeepalivePacketData packetData) {
478         try {
479             networkAgent.onStartNattSocketKeepalive(slot, intervalDurationMs, packetData);
480         } catch (RemoteException e) {
481             Log.e(TAG, "Error sending NATT socket keepalive start event", e);
482         }
483     }
484 
485     /**
486      * Notify the NetworkAgent that TCP socket keepalive should be started.
487      */
onStartTcpSocketKeepalive(int slot, int intervalDurationMs, @NonNull TcpKeepalivePacketData packetData)488     public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs,
489             @NonNull TcpKeepalivePacketData packetData) {
490         try {
491             networkAgent.onStartTcpSocketKeepalive(slot, intervalDurationMs, packetData);
492         } catch (RemoteException e) {
493             Log.e(TAG, "Error sending TCP socket keepalive start event", e);
494         }
495     }
496 
497     /**
498      * Notify the NetworkAgent that socket keepalive should be stopped.
499      */
onStopSocketKeepalive(int slot)500     public void onStopSocketKeepalive(int slot) {
501         try {
502             networkAgent.onStopSocketKeepalive(slot);
503         } catch (RemoteException e) {
504             Log.e(TAG, "Error sending TCP socket keepalive stop event", e);
505         }
506     }
507 
508     /**
509      * Notify the NetworkAgent that signal strength thresholds should be updated.
510      */
onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)511     public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
512         try {
513             networkAgent.onSignalStrengthThresholdsUpdated(thresholds);
514         } catch (RemoteException e) {
515             Log.e(TAG, "Error sending signal strength thresholds event", e);
516         }
517     }
518 
519     /**
520      * Notify the NetworkAgent that automatic reconnect should be prevented.
521      */
onPreventAutomaticReconnect()522     public void onPreventAutomaticReconnect() {
523         try {
524             networkAgent.onPreventAutomaticReconnect();
525         } catch (RemoteException e) {
526             Log.e(TAG, "Error sending prevent automatic reconnect event", e);
527         }
528     }
529 
530     /**
531      * Notify the NetworkAgent that a NATT keepalive packet filter should be added.
532      */
onAddNattKeepalivePacketFilter(int slot, @NonNull NattKeepalivePacketData packetData)533     public void onAddNattKeepalivePacketFilter(int slot,
534             @NonNull NattKeepalivePacketData packetData) {
535         try {
536             networkAgent.onAddNattKeepalivePacketFilter(slot, packetData);
537         } catch (RemoteException e) {
538             Log.e(TAG, "Error sending add NATT keepalive packet filter event", e);
539         }
540     }
541 
542     /**
543      * Notify the NetworkAgent that a TCP keepalive packet filter should be added.
544      */
onAddTcpKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketData packetData)545     public void onAddTcpKeepalivePacketFilter(int slot,
546             @NonNull TcpKeepalivePacketData packetData) {
547         try {
548             networkAgent.onAddTcpKeepalivePacketFilter(slot, packetData);
549         } catch (RemoteException e) {
550             Log.e(TAG, "Error sending add TCP keepalive packet filter event", e);
551         }
552     }
553 
554     /**
555      * Notify the NetworkAgent that a keepalive packet filter should be removed.
556      */
onRemoveKeepalivePacketFilter(int slot)557     public void onRemoveKeepalivePacketFilter(int slot) {
558         try {
559             networkAgent.onRemoveKeepalivePacketFilter(slot);
560         } catch (RemoteException e) {
561             Log.e(TAG, "Error sending remove keepalive packet filter event", e);
562         }
563     }
564 
565     /**
566      * Notify the NetworkAgent that the qos filter should be registered against the given qos
567      * callback id.
568      */
onQosFilterCallbackRegistered(final int qosCallbackId, final QosFilter qosFilter)569     public void onQosFilterCallbackRegistered(final int qosCallbackId,
570             final QosFilter qosFilter) {
571         try {
572             networkAgent.onQosFilterCallbackRegistered(qosCallbackId,
573                     new QosFilterParcelable(qosFilter));
574         } catch (final RemoteException e) {
575             Log.e(TAG, "Error registering a qos callback id against a qos filter", e);
576         }
577     }
578 
579     /**
580      * Notify the NetworkAgent that the given qos callback id should be unregistered.
581      */
onQosCallbackUnregistered(final int qosCallbackId)582     public void onQosCallbackUnregistered(final int qosCallbackId) {
583         try {
584             networkAgent.onQosCallbackUnregistered(qosCallbackId);
585         } catch (RemoteException e) {
586             Log.e(TAG, "Error unregistering a qos callback id", e);
587         }
588     }
589 
590     /**
591      * Notify the NetworkAgent that the network is successfully connected.
592      */
onNetworkCreated()593     public void onNetworkCreated() {
594         try {
595             networkAgent.onNetworkCreated();
596         } catch (RemoteException e) {
597             Log.e(TAG, "Error sending network created event", e);
598         }
599     }
600 
601     /**
602      * Notify the NetworkAgent that the native network has been destroyed.
603      */
onNetworkDestroyed()604     public void onNetworkDestroyed() {
605         try {
606             networkAgent.onNetworkDestroyed();
607         } catch (RemoteException e) {
608             Log.e(TAG, "Error sending network destroyed event", e);
609         }
610     }
611 
612     // TODO: consider moving out of NetworkAgentInfo into its own class
613     private class NetworkAgentMessageHandler extends INetworkAgentRegistry.Stub {
614         private final Handler mHandler;
615 
NetworkAgentMessageHandler(Handler handler)616         private NetworkAgentMessageHandler(Handler handler) {
617             mHandler = handler;
618         }
619 
620         @Override
sendNetworkCapabilities(@onNull NetworkCapabilities nc)621         public void sendNetworkCapabilities(@NonNull NetworkCapabilities nc) {
622             Objects.requireNonNull(nc);
623             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED,
624                     new Pair<>(NetworkAgentInfo.this, nc)).sendToTarget();
625         }
626 
627         @Override
sendLinkProperties(@onNull LinkProperties lp)628         public void sendLinkProperties(@NonNull LinkProperties lp) {
629             Objects.requireNonNull(lp);
630             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED,
631                     new Pair<>(NetworkAgentInfo.this, lp)).sendToTarget();
632         }
633 
634         @Override
sendNetworkInfo(@onNull NetworkInfo info)635         public void sendNetworkInfo(@NonNull NetworkInfo info) {
636             Objects.requireNonNull(info);
637             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_INFO_CHANGED,
638                     new Pair<>(NetworkAgentInfo.this, info)).sendToTarget();
639         }
640 
641         @Override
sendScore(@onNull final NetworkScore score)642         public void sendScore(@NonNull final NetworkScore score) {
643             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED,
644                     new Pair<>(NetworkAgentInfo.this, score)).sendToTarget();
645         }
646 
647         @Override
sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial)648         public void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial) {
649             mHandler.obtainMessage(NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED,
650                     explicitlySelected ? 1 : 0, acceptPartial ? 1 : 0,
651                     new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
652         }
653 
654         @Override
sendSocketKeepaliveEvent(int slot, int reason)655         public void sendSocketKeepaliveEvent(int slot, int reason) {
656             mHandler.obtainMessage(NetworkAgent.EVENT_SOCKET_KEEPALIVE,
657                     slot, reason, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
658         }
659 
660         @Override
sendUnderlyingNetworks(@ullable List<Network> networks)661         public void sendUnderlyingNetworks(@Nullable List<Network> networks) {
662             mHandler.obtainMessage(NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED,
663                     new Pair<>(NetworkAgentInfo.this, networks)).sendToTarget();
664         }
665 
666         @Override
sendEpsQosSessionAvailable(final int qosCallbackId, final QosSession session, final EpsBearerQosSessionAttributes attributes)667         public void sendEpsQosSessionAvailable(final int qosCallbackId, final QosSession session,
668                 final EpsBearerQosSessionAttributes attributes) {
669             mQosCallbackTracker.sendEventEpsQosSessionAvailable(qosCallbackId, session, attributes);
670         }
671 
672         @Override
sendNrQosSessionAvailable(final int qosCallbackId, final QosSession session, final NrQosSessionAttributes attributes)673         public void sendNrQosSessionAvailable(final int qosCallbackId, final QosSession session,
674                 final NrQosSessionAttributes attributes) {
675             mQosCallbackTracker.sendEventNrQosSessionAvailable(qosCallbackId, session, attributes);
676         }
677 
678         @Override
sendQosSessionLost(final int qosCallbackId, final QosSession session)679         public void sendQosSessionLost(final int qosCallbackId, final QosSession session) {
680             mQosCallbackTracker.sendEventQosSessionLost(qosCallbackId, session);
681         }
682 
683         @Override
sendQosCallbackError(final int qosCallbackId, @QosCallbackException.ExceptionType final int exceptionType)684         public void sendQosCallbackError(final int qosCallbackId,
685                 @QosCallbackException.ExceptionType final int exceptionType) {
686             mQosCallbackTracker.sendEventQosCallbackError(qosCallbackId, exceptionType);
687         }
688 
689         @Override
sendTeardownDelayMs(int teardownDelayMs)690         public void sendTeardownDelayMs(int teardownDelayMs) {
691             mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
692                     teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
693         }
694 
695         @Override
sendLingerDuration(final int durationMs)696         public void sendLingerDuration(final int durationMs) {
697             mHandler.obtainMessage(NetworkAgent.EVENT_LINGER_DURATION_CHANGED,
698                     new Pair<>(NetworkAgentInfo.this, durationMs)).sendToTarget();
699         }
700     }
701 
702     /**
703      * Inform NetworkAgentInfo that a new NetworkMonitor was created.
704      */
onNetworkMonitorCreated(INetworkMonitor networkMonitor)705     public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
706         mNetworkMonitor = new NetworkMonitorManager(networkMonitor);
707     }
708 
709     /**
710      * Set the NetworkCapabilities on this NetworkAgentInfo. Also attempts to notify NetworkMonitor
711      * of the new capabilities, if NetworkMonitor has been created.
712      *
713      * <p>If {@link NetworkMonitor#notifyNetworkCapabilitiesChanged(NetworkCapabilities)} fails,
714      * the exception is logged but not reported to callers.
715      *
716      * @return the old capabilities of this network.
717      */
getAndSetNetworkCapabilities( @onNull final NetworkCapabilities nc)718     @NonNull public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
719             @NonNull final NetworkCapabilities nc) {
720         final NetworkCapabilities oldNc = networkCapabilities;
721         networkCapabilities = nc;
722         mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, everValidatedForYield(),
723                 yieldToBadWiFi());
724         final NetworkMonitorManager nm = mNetworkMonitor;
725         if (nm != null) {
726             nm.notifyNetworkCapabilitiesChanged(nc);
727         }
728         return oldNc;
729     }
730 
yieldToBadWiFi()731     private boolean yieldToBadWiFi() {
732         // Only cellular networks yield to bad wifi
733         return networkCapabilities.hasTransport(TRANSPORT_CELLULAR) && !mConnService.avoidBadWifi();
734     }
735 
connService()736     public ConnectivityService connService() {
737         return mConnService;
738     }
739 
netAgentConfig()740     public NetworkAgentConfig netAgentConfig() {
741         return networkAgentConfig;
742     }
743 
handler()744     public Handler handler() {
745         return mHandler;
746     }
747 
network()748     public Network network() {
749         return network;
750     }
751 
752     /**
753      * Get the NetworkMonitorManager in this NetworkAgentInfo.
754      *
755      * <p>This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called.
756      */
networkMonitor()757     public NetworkMonitorManager networkMonitor() {
758         return mNetworkMonitor;
759     }
760 
761     // Functions for manipulating the requests satisfied by this network.
762     //
763     // These functions must only called on ConnectivityService's main thread.
764 
765     private static final boolean ADD = true;
766     private static final boolean REMOVE = false;
767 
updateRequestCounts(boolean add, NetworkRequest request)768     private void updateRequestCounts(boolean add, NetworkRequest request) {
769         int delta = add ? +1 : -1;
770         switch (request.type) {
771             case REQUEST:
772                 mNumRequestNetworkRequests += delta;
773                 break;
774 
775             case BACKGROUND_REQUEST:
776                 mNumRequestNetworkRequests += delta;
777                 mNumBackgroundNetworkRequests += delta;
778                 break;
779 
780             case LISTEN:
781             case LISTEN_FOR_BEST:
782             case TRACK_DEFAULT:
783             case TRACK_SYSTEM_DEFAULT:
784                 break;
785 
786             case NONE:
787             default:
788                 Log.wtf(TAG, "Unhandled request type " + request.type);
789                 break;
790         }
791     }
792 
793     /**
794      * Add {@code networkRequest} to this network as it's satisfied by this network.
795      * @return true if {@code networkRequest} was added or false if {@code networkRequest} was
796      *         already present.
797      */
addRequest(NetworkRequest networkRequest)798     public boolean addRequest(NetworkRequest networkRequest) {
799         NetworkRequest existing = mNetworkRequests.get(networkRequest.requestId);
800         if (existing == networkRequest) return false;
801         if (existing != null) {
802             // Should only happen if the requestId wraps. If that happens lots of other things will
803             // be broken as well.
804             Log.wtf(TAG, String.format("Duplicate requestId for %s and %s on %s",
805                     networkRequest, existing, toShortString()));
806             updateRequestCounts(REMOVE, existing);
807         }
808         mNetworkRequests.put(networkRequest.requestId, networkRequest);
809         updateRequestCounts(ADD, networkRequest);
810         return true;
811     }
812 
813     /**
814      * Remove the specified request from this network.
815      */
removeRequest(int requestId)816     public void removeRequest(int requestId) {
817         NetworkRequest existing = mNetworkRequests.get(requestId);
818         if (existing == null) return;
819         updateRequestCounts(REMOVE, existing);
820         mNetworkRequests.remove(requestId);
821         if (existing.isRequest()) {
822             unlingerRequest(existing.requestId);
823         }
824     }
825 
826     /**
827      * Returns whether this network is currently satisfying the request with the specified ID.
828      */
isSatisfyingRequest(int id)829     public boolean isSatisfyingRequest(int id) {
830         return mNetworkRequests.get(id) != null;
831     }
832 
833     /**
834      * Returns the request at the specified position in the list of requests satisfied by this
835      * network.
836      */
requestAt(int index)837     public NetworkRequest requestAt(int index) {
838         return mNetworkRequests.valueAt(index);
839     }
840 
841     /**
842      * Returns the number of requests currently satisfied by this network for which
843      * {@link android.net.NetworkRequest#isRequest} returns {@code true}.
844      */
numRequestNetworkRequests()845     public int numRequestNetworkRequests() {
846         return mNumRequestNetworkRequests;
847     }
848 
849     /**
850      * Returns the number of requests currently satisfied by this network of type
851      * {@link android.net.NetworkRequest.Type.BACKGROUND_REQUEST}.
852      */
numBackgroundNetworkRequests()853     public int numBackgroundNetworkRequests() {
854         return mNumBackgroundNetworkRequests;
855     }
856 
857     /**
858      * Returns the number of foreground requests currently satisfied by this network.
859      */
numForegroundNetworkRequests()860     public int numForegroundNetworkRequests() {
861         return mNumRequestNetworkRequests - mNumBackgroundNetworkRequests;
862     }
863 
864     /**
865      * Returns the number of requests of any type currently satisfied by this network.
866      */
numNetworkRequests()867     public int numNetworkRequests() {
868         return mNetworkRequests.size();
869     }
870 
871     /**
872      * Returns whether the network is a background network. A network is a background network if it
873      * does not have the NET_CAPABILITY_FOREGROUND capability, which implies it is satisfying no
874      * foreground request, is not lingering (i.e. kept for a while after being outscored), and is
875      * not a speculative network (i.e. kept pending validation when validation would have it
876      * outscore another foreground network). That implies it is being kept up by some background
877      * request (otherwise it would be torn down), maybe the mobile always-on request.
878      */
isBackgroundNetwork()879     public boolean isBackgroundNetwork() {
880         return !isVPN() && numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0
881                 && !isLingering();
882     }
883 
884     // Does this network satisfy request?
satisfies(NetworkRequest request)885     public boolean satisfies(NetworkRequest request) {
886         return created &&
887                 request.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities);
888     }
889 
satisfiesImmutableCapabilitiesOf(NetworkRequest request)890     public boolean satisfiesImmutableCapabilitiesOf(NetworkRequest request) {
891         return created &&
892                 request.networkCapabilities.satisfiedByImmutableNetworkCapabilities(
893                         networkCapabilities);
894     }
895 
896     /** Whether this network is a VPN. */
isVPN()897     public boolean isVPN() {
898         return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
899     }
900 
901     /**
902      * Whether this network should propagate the capabilities from its underlying networks.
903      * Currently only true for VPNs.
904      */
propagateUnderlyingCapabilities()905     public boolean propagateUnderlyingCapabilities() {
906         return isVPN();
907     }
908 
909     // Caller must not mutate. This method is called frequently and making a defensive copy
910     // would be too expensive. This is used by NetworkRanker.Scoreable, so it can be compared
911     // against other scoreables.
getCapsNoCopy()912     @Override public NetworkCapabilities getCapsNoCopy() {
913         return networkCapabilities;
914     }
915 
916     // NetworkRanker.Scoreable
getScore()917     @Override public FullScore getScore() {
918         return mScore;
919     }
920 
921     // Get the current score for this Network.  This may be modified from what the
922     // NetworkAgent sent, as it has modifiers applied to it.
getCurrentScore()923     public int getCurrentScore() {
924         return mScore.getLegacyInt();
925     }
926 
927     // Get the current score for this Network as if it was validated.  This may be modified from
928     // what the NetworkAgent sent, as it has modifiers applied to it.
getCurrentScoreAsValidated()929     public int getCurrentScoreAsValidated() {
930         return mScore.getLegacyIntAsValidated();
931     }
932 
933     /**
934      * Mix-in the ConnectivityService-managed bits in the score.
935      */
setScore(final NetworkScore score)936     public void setScore(final NetworkScore score) {
937         mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig,
938                 everValidatedForYield(), yieldToBadWiFi());
939     }
940 
941     /**
942      * Update the ConnectivityService-managed bits in the score.
943      *
944      * Call this after updating the network agent config.
945      */
updateScoreForNetworkAgentUpdate()946     public void updateScoreForNetworkAgentUpdate() {
947         mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig,
948                 everValidatedForYield(), yieldToBadWiFi());
949     }
950 
everValidatedForYield()951     private boolean everValidatedForYield() {
952         return everValidated && !avoidUnvalidated;
953     }
954 
955     /**
956      * Returns a Scoreable identical to this NAI, but validated.
957      *
958      * This is useful to probe what scoring would be if this network validated, to know
959      * whether to provisionally keep a network that may or may not validate.
960      *
961      * @return a Scoreable identical to this NAI, but validated.
962      */
getValidatedScoreable()963     public NetworkRanker.Scoreable getValidatedScoreable() {
964         return new NetworkRanker.Scoreable() {
965             @Override public FullScore getScore() {
966                 return mScore.asValidated();
967             }
968 
969             @Override public NetworkCapabilities getCapsNoCopy() {
970                 return networkCapabilities;
971             }
972         };
973     }
974 
975     /**
976      * Return a {@link NetworkStateSnapshot} for this network.
977      */
978     @NonNull
979     public NetworkStateSnapshot getNetworkStateSnapshot() {
980         synchronized (this) {
981             // Network objects are outwardly immutable so there is no point in duplicating.
982             // Duplicating also precludes sharing socket factories and connection pools.
983             final String subscriberId = (networkAgentConfig != null)
984                     ? networkAgentConfig.subscriberId : null;
985             return new NetworkStateSnapshot(network, new NetworkCapabilities(networkCapabilities),
986                     new LinkProperties(linkProperties), subscriberId, networkInfo.getType());
987         }
988     }
989 
990     /**
991      * Sets the specified requestId to linger on this network for the specified time. Called by
992      * ConnectivityService when any request is moved to another network with a higher score, or
993      * when a network is newly created.
994      *
995      * @param requestId The requestId of the request that no longer need to be served by this
996      *                  network. Or {@link NetworkRequest.REQUEST_ID_NONE} if this is the
997      *                  {@code InactivityTimer} for a newly created network.
998      */
999     // TODO: Consider creating a dedicated function for nascent network, e.g. start/stopNascent.
1000     public void lingerRequest(int requestId, long now, long duration) {
1001         if (mInactivityTimerForRequest.get(requestId) != null) {
1002             // Cannot happen. Once a request is lingering on a particular network, we cannot
1003             // re-linger it unless that network becomes the best for that request again, in which
1004             // case we should have unlingered it.
1005             Log.wtf(TAG, toShortString() + ": request " + requestId + " already lingered");
1006         }
1007         final long expiryMs = now + duration;
1008         InactivityTimer timer = new InactivityTimer(requestId, expiryMs);
1009         if (VDBG) Log.d(TAG, "Adding InactivityTimer " + timer + " to " + toShortString());
1010         mInactivityTimers.add(timer);
1011         mInactivityTimerForRequest.put(requestId, timer);
1012     }
1013 
1014     /**
1015      * Sets the specified requestId to linger on this network for the timeout set when
1016      * initializing or modified by {@link #setLingerDuration(int)}. Called by
1017      * ConnectivityService when any request is moved to another network with a higher score.
1018      *
1019      * @param requestId The requestId of the request that no longer need to be served by this
1020      *                  network.
1021      * @param now current system timestamp obtained by {@code SystemClock.elapsedRealtime}.
1022      */
1023     public void lingerRequest(int requestId, long now) {
1024         lingerRequest(requestId, now, mLingerDurationMs);
1025     }
1026 
1027     /**
1028      * Cancel lingering. Called by ConnectivityService when a request is added to this network.
1029      * Returns true if the given requestId was lingering on this network, false otherwise.
1030      */
1031     public boolean unlingerRequest(int requestId) {
1032         InactivityTimer timer = mInactivityTimerForRequest.get(requestId);
1033         if (timer != null) {
1034             if (VDBG) {
1035                 Log.d(TAG, "Removing InactivityTimer " + timer + " from " + toShortString());
1036             }
1037             mInactivityTimers.remove(timer);
1038             mInactivityTimerForRequest.remove(requestId);
1039             return true;
1040         }
1041         return false;
1042     }
1043 
1044     public long getInactivityExpiry() {
1045         return mInactivityExpiryMs;
1046     }
1047 
1048     public void updateInactivityTimer() {
1049         long newExpiry = mInactivityTimers.isEmpty() ? 0 : mInactivityTimers.last().expiryMs;
1050         if (newExpiry == mInactivityExpiryMs) return;
1051 
1052         // Even if we're going to reschedule the timer, cancel it first. This is because the
1053         // semantics of WakeupMessage guarantee that if cancel is called then the alarm will
1054         // never call its callback (handleLingerComplete), even if it has already fired.
1055         // WakeupMessage makes no such guarantees about rescheduling a message, so if mLingerMessage
1056         // has already been dispatched, rescheduling to some time in the future won't stop it
1057         // from calling its callback immediately.
1058         if (mInactivityMessage != null) {
1059             mInactivityMessage.cancel();
1060             mInactivityMessage = null;
1061         }
1062 
1063         if (newExpiry > 0) {
1064             // If the newExpiry timestamp is in the past, the wakeup message will fire immediately.
1065             mInactivityMessage = new WakeupMessage(
1066                     mContext, mHandler,
1067                     "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
1068                     EVENT_NETWORK_LINGER_COMPLETE /* cmd */,
1069                     0 /* arg1 (unused) */, 0 /* arg2 (unused) */,
1070                     this /* obj (NetworkAgentInfo) */);
1071             mInactivityMessage.schedule(newExpiry);
1072         }
1073 
1074         mInactivityExpiryMs = newExpiry;
1075     }
1076 
1077     public void setInactive() {
1078         mInactive = true;
1079     }
1080 
1081     public void unsetInactive() {
1082         mInactive = false;
1083     }
1084 
1085     public boolean isInactive() {
1086         return mInactive;
1087     }
1088 
1089     public boolean isLingering() {
1090         return mInactive && !isNascent();
1091     }
1092 
1093     /**
1094      * Set the linger duration for this NAI.
1095      * @param durationMs The new linger duration, in milliseconds.
1096      */
1097     public void setLingerDuration(final int durationMs) {
1098         final long diff = durationMs - mLingerDurationMs;
1099         final ArrayList<InactivityTimer> newTimers = new ArrayList<>();
1100         for (final InactivityTimer timer : mInactivityTimers) {
1101             if (timer.requestId == NetworkRequest.REQUEST_ID_NONE) {
1102                 // Don't touch nascent timer, re-add as is.
1103                 newTimers.add(timer);
1104             } else {
1105                 newTimers.add(new InactivityTimer(timer.requestId, timer.expiryMs + diff));
1106             }
1107         }
1108         mInactivityTimers.clear();
1109         mInactivityTimers.addAll(newTimers);
1110         updateInactivityTimer();
1111         mLingerDurationMs = durationMs;
1112     }
1113 
1114     /**
1115      * Return whether the network satisfies no request, but is still being kept up
1116      * because it has just connected less than
1117      * {@code ConnectivityService#DEFAULT_NASCENT_DELAY_MS}ms ago and is thus still considered
1118      * nascent. Note that nascent mechanism uses inactivity timer which isn't
1119      * associated with a request. Thus, use {@link NetworkRequest#REQUEST_ID_NONE} to identify it.
1120      *
1121      */
1122     public boolean isNascent() {
1123         return mInactive && mInactivityTimers.size() == 1
1124                 && mInactivityTimers.first().requestId == NetworkRequest.REQUEST_ID_NONE;
1125     }
1126 
1127     public void clearInactivityState() {
1128         if (mInactivityMessage != null) {
1129             mInactivityMessage.cancel();
1130             mInactivityMessage = null;
1131         }
1132         mInactivityTimers.clear();
1133         mInactivityTimerForRequest.clear();
1134         // Sets mInactivityExpiryMs, cancels and nulls out mInactivityMessage.
1135         updateInactivityTimer();
1136         mInactive = false;
1137     }
1138 
1139     public void dumpInactivityTimers(PrintWriter pw) {
1140         for (InactivityTimer timer : mInactivityTimers) {
1141             pw.println(timer);
1142         }
1143     }
1144 
1145     /**
1146      * Sets the most recent ConnectivityReport for this network.
1147      *
1148      * <p>This should only be called from the ConnectivityService thread.
1149      *
1150      * @hide
1151      */
1152     public void setConnectivityReport(@NonNull ConnectivityReport connectivityReport) {
1153         mConnectivityReport = connectivityReport;
1154     }
1155 
1156     /**
1157      * Returns the most recent ConnectivityReport for this network, or null if none have been
1158      * reported yet.
1159      *
1160      * <p>This should only be called from the ConnectivityService thread.
1161      *
1162      * @hide
1163      */
1164     @Nullable
1165     public ConnectivityReport getConnectivityReport() {
1166         return mConnectivityReport;
1167     }
1168 
1169     // TODO: Print shorter members first and only print the boolean variable which value is true
1170     // to improve readability.
1171     public String toString() {
1172         return "NetworkAgentInfo{"
1173                 + "network{" + network + "}  handle{" + network.getNetworkHandle() + "}  ni{"
1174                 + networkInfo.toShortString() + "} "
1175                 + mScore + " "
1176                 + (isNascent() ? " nascent" : (isLingering() ? " lingering" : ""))
1177                 + (everValidated ? " everValidated" : "")
1178                 + (lastValidated ? " lastValidated" : "")
1179                 + (partialConnectivity ? " partialConnectivity" : "")
1180                 + (everCaptivePortalDetected ? " everCaptivePortal" : "")
1181                 + (lastCaptivePortalDetected ? " isCaptivePortal" : "")
1182                 + (networkAgentConfig.explicitlySelected ? " explicitlySelected" : "")
1183                 + (networkAgentConfig.acceptUnvalidated ? " acceptUnvalidated" : "")
1184                 + (networkAgentConfig.acceptPartialConnectivity ? " acceptPartialConnectivity" : "")
1185                 + (clatd.isStarted() ? " clat{" + clatd + "} " : "")
1186                 + (declaredUnderlyingNetworks != null
1187                         ? " underlying{" + Arrays.toString(declaredUnderlyingNetworks) + "}" : "")
1188                 + "  lp{" + linkProperties + "}"
1189                 + "  nc{" + networkCapabilities + "}"
1190                 + "}";
1191     }
1192 
1193     /**
1194      * Show a short string representing a Network.
1195      *
1196      * This is often not enough for debugging purposes for anything complex, but the full form
1197      * is very long and hard to read, so this is useful when there isn't a lot of ambiguity.
1198      * This represents the network with something like "[100 WIFI|VPN]" or "[108 MOBILE]".
1199      */
1200     public String toShortString() {
1201         return "[" + network.getNetId() + " "
1202                 + transportNamesOf(networkCapabilities.getTransportTypes()) + "]";
1203     }
1204 
1205     // Enables sorting in descending order of score.
1206     @Override
1207     public int compareTo(NetworkAgentInfo other) {
1208         return other.getCurrentScore() - getCurrentScore();
1209     }
1210 
1211     /**
1212      * Null-guarding version of NetworkAgentInfo#toShortString()
1213      */
1214     @NonNull
1215     public static String toShortString(@Nullable final NetworkAgentInfo nai) {
1216         return null != nai ? nai.toShortString() : "[null]";
1217     }
1218 }
1219