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