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.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 20 21 import android.content.Context; 22 import android.net.LinkProperties; 23 import android.net.Network; 24 import android.net.NetworkCapabilities; 25 import android.net.NetworkInfo; 26 import android.net.NetworkMisc; 27 import android.net.NetworkRequest; 28 import android.net.NetworkState; 29 import android.os.Handler; 30 import android.os.Messenger; 31 import android.os.SystemClock; 32 import android.util.Log; 33 import android.util.SparseArray; 34 35 import com.android.internal.util.AsyncChannel; 36 import com.android.internal.util.WakeupMessage; 37 import com.android.server.ConnectivityService; 38 import com.android.server.connectivity.NetworkMonitor; 39 40 import java.io.PrintWriter; 41 import java.util.ArrayList; 42 import java.util.Comparator; 43 import java.util.Objects; 44 import java.util.SortedSet; 45 import java.util.TreeSet; 46 47 /** 48 * A bag class used by ConnectivityService for holding a collection of most recent 49 * information published by a particular NetworkAgent as well as the 50 * AsyncChannel/messenger for reaching that NetworkAgent and lists of NetworkRequests 51 * interested in using it. Default sort order is descending by score. 52 */ 53 // States of a network: 54 // -------------------- 55 // 1. registered, uncreated, disconnected, unvalidated 56 // This state is entered when a NetworkFactory registers a NetworkAgent in any state except 57 // the CONNECTED state. 58 // 2. registered, uncreated, connecting, unvalidated 59 // This state is entered when a registered NetworkAgent for a VPN network transitions to the 60 // CONNECTING state (TODO: go through this state for every network, not just VPNs). 61 // ConnectivityService will tell netd to create the network early in order to add extra UID 62 // routing rules referencing the netID. These rules need to be in place before the network is 63 // connected to avoid racing against client apps trying to connect to a half-setup network. 64 // 3. registered, uncreated, connected, unvalidated 65 // This state is entered when a registered NetworkAgent transitions to the CONNECTED state. 66 // ConnectivityService will tell netd to create the network if it was not already created, and 67 // immediately transition to state #4. 68 // 4. registered, created, connected, unvalidated 69 // If this network can satisfy the default NetworkRequest, then NetworkMonitor will 70 // probe for Internet connectivity. 71 // If this network cannot satisfy the default NetworkRequest, it will immediately be 72 // transitioned to state #5. 73 // A network may remain in this state if NetworkMonitor fails to find Internet connectivity, 74 // for example: 75 // a. a captive portal is present, or 76 // b. a WiFi router whose Internet backhaul is down, or 77 // c. a wireless connection stops transfering packets temporarily (e.g. device is in elevator 78 // or tunnel) but does not disconnect from the AP/cell tower, or 79 // d. a stand-alone device offering a WiFi AP without an uplink for configuration purposes. 80 // 5. registered, created, connected, validated 81 // 82 // The device's default network connection: 83 // ---------------------------------------- 84 // Networks in states #4 and #5 may be used as a device's default network connection if they 85 // satisfy the default NetworkRequest. 86 // A network, that satisfies the default NetworkRequest, in state #5 should always be chosen 87 // in favor of a network, that satisfies the default NetworkRequest, in state #4. 88 // When deciding between two networks, that both satisfy the default NetworkRequest, to select 89 // for the default network connection, the one with the higher score should be chosen. 90 // 91 // When a network disconnects: 92 // --------------------------- 93 // If a network's transport disappears, for example: 94 // a. WiFi turned off, or 95 // b. cellular data turned off, or 96 // c. airplane mode is turned on, or 97 // d. a wireless connection disconnects from AP/cell tower entirely (e.g. device is out of range 98 // of AP for an extended period of time, or switches to another AP without roaming) 99 // then that network can transition from any state (#1-#5) to unregistered. This happens by 100 // the transport disconnecting their NetworkAgent's AsyncChannel with ConnectivityManager. 101 // ConnectivityService also tells netd to destroy the network. 102 // 103 // When ConnectivityService disconnects a network: 104 // ----------------------------------------------- 105 // If a network has no chance of satisfying any requests (even if it were to become validated 106 // and enter state #5), ConnectivityService will disconnect the NetworkAgent's AsyncChannel. 107 // If the network ever for any period of time had satisfied a NetworkRequest (i.e. had been 108 // the highest scoring that satisfied the NetworkRequest's constraints), but is no longer the 109 // highest scoring network for any NetworkRequest, then there will be a 30s pause before 110 // ConnectivityService disconnects the NetworkAgent's AsyncChannel. During this pause the 111 // network is considered "lingering". This pause exists to allow network communication to be 112 // wrapped up rather than abruptly terminated. During this pause if the network begins satisfying 113 // a NetworkRequest, ConnectivityService will cancel the future disconnection of the NetworkAgent's 114 // AsyncChannel, and the network is no longer considered "lingering". 115 public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { 116 117 public NetworkInfo networkInfo; 118 // This Network object should always be used if possible, so as to encourage reuse of the 119 // enclosed socket factory and connection pool. Avoid creating other Network objects. 120 // This Network object is always valid. 121 public final Network network; 122 public LinkProperties linkProperties; 123 // This should only be modified via ConnectivityService.updateCapabilities(). 124 public NetworkCapabilities networkCapabilities; 125 public final NetworkMonitor networkMonitor; 126 public final NetworkMisc networkMisc; 127 // Indicates if netd has been told to create this Network. From this point on the appropriate 128 // routing rules are setup and routes are added so packets can begin flowing over the Network. 129 // This is a sticky bit; once set it is never cleared. 130 public boolean created; 131 // Set to true after the first time this network is marked as CONNECTED. Once set, the network 132 // shows up in API calls, is able to satisfy NetworkRequests and can become the default network. 133 // This is a sticky bit; once set it is never cleared. 134 public boolean everConnected; 135 // Set to true if this Network successfully passed validation or if it did not satisfy the 136 // default NetworkRequest in which case validation will not be attempted. 137 // This is a sticky bit; once set it is never cleared even if future validation attempts fail. 138 public boolean everValidated; 139 140 // The result of the last validation attempt on this network (true if validated, false if not). 141 public boolean lastValidated; 142 143 // If true, becoming unvalidated will lower the network's score. This is only meaningful if the 144 // system is configured not to do this for certain networks, e.g., if the 145 // config_networkAvoidBadWifi option is set to 0 and the user has not overridden that via 146 // Settings.Global.NETWORK_AVOID_BAD_WIFI. 147 public boolean avoidUnvalidated; 148 149 // Whether a captive portal was ever detected on this network. 150 // This is a sticky bit; once set it is never cleared. 151 public boolean everCaptivePortalDetected; 152 153 // Whether a captive portal was found during the last network validation attempt. 154 public boolean lastCaptivePortalDetected; 155 156 // Networks are lingered when they become unneeded as a result of their NetworkRequests being 157 // satisfied by a higher-scoring network. so as to allow communication to wrap up before the 158 // network is taken down. This usually only happens to the default network. Lingering ends with 159 // either the linger timeout expiring and the network being taken down, or the network 160 // satisfying a request again. 161 public static class LingerTimer implements Comparable<LingerTimer> { 162 public final NetworkRequest request; 163 public final long expiryMs; 164 LingerTimer(NetworkRequest request, long expiryMs)165 public LingerTimer(NetworkRequest request, long expiryMs) { 166 this.request = request; 167 this.expiryMs = expiryMs; 168 } equals(Object o)169 public boolean equals(Object o) { 170 if (!(o instanceof LingerTimer)) return false; 171 LingerTimer other = (LingerTimer) o; 172 return (request.requestId == other.request.requestId) && (expiryMs == other.expiryMs); 173 } hashCode()174 public int hashCode() { 175 return Objects.hash(request.requestId, expiryMs); 176 } compareTo(LingerTimer other)177 public int compareTo(LingerTimer other) { 178 return (expiryMs != other.expiryMs) ? 179 Long.compare(expiryMs, other.expiryMs) : 180 Integer.compare(request.requestId, other.request.requestId); 181 } toString()182 public String toString() { 183 return String.format("%s, expires %dms", request.toString(), 184 expiryMs - SystemClock.elapsedRealtime()); 185 } 186 } 187 188 /** 189 * Inform ConnectivityService that the network LINGER period has 190 * expired. 191 * obj = this NetworkAgentInfo 192 */ 193 public static final int EVENT_NETWORK_LINGER_COMPLETE = 1001; 194 195 // All linger timers for this network, sorted by expiry time. A linger timer is added whenever 196 // a request is moved to a network with a better score, regardless of whether the network is or 197 // was lingering or not. 198 // TODO: determine if we can replace this with a smaller or unsorted data structure. (e.g., 199 // SparseLongArray) combined with the timestamp of when the last timer is scheduled to fire. 200 private final SortedSet<LingerTimer> mLingerTimers = new TreeSet<>(); 201 202 // For fast lookups. Indexes into mLingerTimers by request ID. 203 private final SparseArray<LingerTimer> mLingerTimerForRequest = new SparseArray<>(); 204 205 // Linger expiry timer. Armed whenever mLingerTimers is non-empty, regardless of whether the 206 // network is lingering or not. Always set to the expiry of the LingerTimer that expires last. 207 // When the timer fires, all linger state is cleared, and if the network has no requests, it is 208 // torn down. 209 private WakeupMessage mLingerMessage; 210 211 // Linger expiry. Holds the expiry time of the linger timer, or 0 if the timer is not armed. 212 private long mLingerExpiryMs; 213 214 // Whether the network is lingering or not. Must be maintained separately from the above because 215 // it depends on the state of other networks and requests, which only ConnectivityService knows. 216 // (Example: we don't linger a network if it would become the best for a NetworkRequest if it 217 // validated). 218 private boolean mLingering; 219 220 // This represents the last score received from the NetworkAgent. 221 private int currentScore; 222 // Penalty applied to scores of Networks that have not been validated. 223 private static final int UNVALIDATED_SCORE_PENALTY = 40; 224 225 // Score for explicitly connected network. 226 // 227 // This ensures that a) the explicitly selected network is never trumped by anything else, and 228 // b) the explicitly selected network is never torn down. 229 private static final int MAXIMUM_NETWORK_SCORE = 100; 230 231 // The list of NetworkRequests being satisfied by this Network. 232 private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>(); 233 // The list of NetworkRequests that this Network previously satisfied with the highest 234 // score. A non-empty list indicates that if this Network was validated it is lingered. 235 // How many of the satisfied requests are actual requests and not listens. 236 private int mNumRequestNetworkRequests = 0; 237 238 public final Messenger messenger; 239 public final AsyncChannel asyncChannel; 240 241 // Used by ConnectivityService to keep track of 464xlat. 242 public Nat464Xlat clatd; 243 244 private static final String TAG = ConnectivityService.class.getSimpleName(); 245 private static final boolean VDBG = false; 246 private final ConnectivityService mConnService; 247 private final Context mContext; 248 private final Handler mHandler; 249 NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService)250 public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, 251 LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, 252 NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService) { 253 this.messenger = messenger; 254 asyncChannel = ac; 255 network = net; 256 networkInfo = info; 257 linkProperties = lp; 258 networkCapabilities = nc; 259 currentScore = score; 260 mConnService = connService; 261 mContext = context; 262 mHandler = handler; 263 networkMonitor = mConnService.createNetworkMonitor(context, handler, this, defaultRequest); 264 networkMisc = misc; 265 } 266 267 // Functions for manipulating the requests satisfied by this network. 268 // 269 // These functions must only called on ConnectivityService's main thread. 270 271 /** 272 * Add {@code networkRequest} to this network as it's satisfied by this network. 273 * @return true if {@code networkRequest} was added or false if {@code networkRequest} was 274 * already present. 275 */ addRequest(NetworkRequest networkRequest)276 public boolean addRequest(NetworkRequest networkRequest) { 277 NetworkRequest existing = mNetworkRequests.get(networkRequest.requestId); 278 if (existing == networkRequest) return false; 279 if (existing != null && existing.isRequest()) mNumRequestNetworkRequests--; 280 mNetworkRequests.put(networkRequest.requestId, networkRequest); 281 if (networkRequest.isRequest()) mNumRequestNetworkRequests++; 282 return true; 283 } 284 285 /** 286 * Remove the specified request from this network. 287 */ removeRequest(int requestId)288 public void removeRequest(int requestId) { 289 NetworkRequest existing = mNetworkRequests.get(requestId); 290 if (existing == null) return; 291 mNetworkRequests.remove(requestId); 292 if (existing.isRequest()) { 293 mNumRequestNetworkRequests--; 294 unlingerRequest(existing); 295 } 296 } 297 298 /** 299 * Returns whether this network is currently satisfying the request with the specified ID. 300 */ isSatisfyingRequest(int id)301 public boolean isSatisfyingRequest(int id) { 302 return mNetworkRequests.get(id) != null; 303 } 304 305 /** 306 * Returns the request at the specified position in the list of requests satisfied by this 307 * network. 308 */ requestAt(int index)309 public NetworkRequest requestAt(int index) { 310 return mNetworkRequests.valueAt(index); 311 } 312 313 /** 314 * Returns the number of requests currently satisfied by this network for which 315 * {@link android.net.NetworkRequest#isRequest} returns {@code true}. 316 */ numRequestNetworkRequests()317 public int numRequestNetworkRequests() { 318 return mNumRequestNetworkRequests; 319 } 320 321 /** 322 * Returns the number of requests of any type currently satisfied by this network. 323 */ numNetworkRequests()324 public int numNetworkRequests() { 325 return mNetworkRequests.size(); 326 } 327 328 // Does this network satisfy request? satisfies(NetworkRequest request)329 public boolean satisfies(NetworkRequest request) { 330 return created && 331 request.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities); 332 } 333 satisfiesImmutableCapabilitiesOf(NetworkRequest request)334 public boolean satisfiesImmutableCapabilitiesOf(NetworkRequest request) { 335 return created && 336 request.networkCapabilities.satisfiedByImmutableNetworkCapabilities( 337 networkCapabilities); 338 } 339 isVPN()340 public boolean isVPN() { 341 return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN); 342 } 343 getCurrentScore(boolean pretendValidated)344 private int getCurrentScore(boolean pretendValidated) { 345 // TODO: We may want to refactor this into a NetworkScore class that takes a base score from 346 // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the 347 // score. The NetworkScore class would provide a nice place to centralize score constants 348 // so they are not scattered about the transports. 349 350 // If this network is explicitly selected and the user has decided to use it even if it's 351 // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly 352 // selected and we're trying to see what its score could be. This ensures that we don't tear 353 // down an explicitly selected network before the user gets a chance to prefer it when 354 // a higher-scoring network (e.g., Ethernet) is available. 355 if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) { 356 return MAXIMUM_NETWORK_SCORE; 357 } 358 359 int score = currentScore; 360 if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty()) { 361 score -= UNVALIDATED_SCORE_PENALTY; 362 } 363 if (score < 0) score = 0; 364 return score; 365 } 366 367 // Return true on devices configured to ignore score penalty for wifi networks 368 // that become unvalidated (b/31075769). ignoreWifiUnvalidationPenalty()369 private boolean ignoreWifiUnvalidationPenalty() { 370 boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && 371 networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 372 boolean avoidBadWifi = mConnService.avoidBadWifi() || avoidUnvalidated; 373 return isWifi && !avoidBadWifi && everValidated; 374 } 375 376 // Get the current score for this Network. This may be modified from what the 377 // NetworkAgent sent, as it has modifiers applied to it. getCurrentScore()378 public int getCurrentScore() { 379 return getCurrentScore(false); 380 } 381 382 // Get the current score for this Network as if it was validated. This may be modified from 383 // what the NetworkAgent sent, as it has modifiers applied to it. getCurrentScoreAsValidated()384 public int getCurrentScoreAsValidated() { 385 return getCurrentScore(true); 386 } 387 setCurrentScore(int newScore)388 public void setCurrentScore(int newScore) { 389 currentScore = newScore; 390 } 391 getNetworkState()392 public NetworkState getNetworkState() { 393 synchronized (this) { 394 // Network objects are outwardly immutable so there is no point to duplicating. 395 // Duplicating also precludes sharing socket factories and connection pools. 396 final String subscriberId = (networkMisc != null) ? networkMisc.subscriberId : null; 397 return new NetworkState(new NetworkInfo(networkInfo), 398 new LinkProperties(linkProperties), 399 new NetworkCapabilities(networkCapabilities), network, subscriberId, null); 400 } 401 } 402 403 /** 404 * Sets the specified request to linger on this network for the specified time. Called by 405 * ConnectivityService when the request is moved to another network with a higher score. 406 */ lingerRequest(NetworkRequest request, long now, long duration)407 public void lingerRequest(NetworkRequest request, long now, long duration) { 408 if (mLingerTimerForRequest.get(request.requestId) != null) { 409 // Cannot happen. Once a request is lingering on a particular network, we cannot 410 // re-linger it unless that network becomes the best for that request again, in which 411 // case we should have unlingered it. 412 Log.wtf(TAG, this.name() + ": request " + request.requestId + " already lingered"); 413 } 414 final long expiryMs = now + duration; 415 LingerTimer timer = new LingerTimer(request, expiryMs); 416 if (VDBG) Log.d(TAG, "Adding LingerTimer " + timer + " to " + this.name()); 417 mLingerTimers.add(timer); 418 mLingerTimerForRequest.put(request.requestId, timer); 419 } 420 421 /** 422 * Cancel lingering. Called by ConnectivityService when a request is added to this network. 423 * Returns true if the given request was lingering on this network, false otherwise. 424 */ unlingerRequest(NetworkRequest request)425 public boolean unlingerRequest(NetworkRequest request) { 426 LingerTimer timer = mLingerTimerForRequest.get(request.requestId); 427 if (timer != null) { 428 if (VDBG) Log.d(TAG, "Removing LingerTimer " + timer + " from " + this.name()); 429 mLingerTimers.remove(timer); 430 mLingerTimerForRequest.remove(request.requestId); 431 return true; 432 } 433 return false; 434 } 435 getLingerExpiry()436 public long getLingerExpiry() { 437 return mLingerExpiryMs; 438 } 439 updateLingerTimer()440 public void updateLingerTimer() { 441 long newExpiry = mLingerTimers.isEmpty() ? 0 : mLingerTimers.last().expiryMs; 442 if (newExpiry == mLingerExpiryMs) return; 443 444 // Even if we're going to reschedule the timer, cancel it first. This is because the 445 // semantics of WakeupMessage guarantee that if cancel is called then the alarm will 446 // never call its callback (handleLingerComplete), even if it has already fired. 447 // WakeupMessage makes no such guarantees about rescheduling a message, so if mLingerMessage 448 // has already been dispatched, rescheduling to some time in the future it won't stop it 449 // from calling its callback immediately. 450 if (mLingerMessage != null) { 451 mLingerMessage.cancel(); 452 mLingerMessage = null; 453 } 454 455 if (newExpiry > 0) { 456 mLingerMessage = mConnService.makeWakeupMessage( 457 mContext, mHandler, 458 "NETWORK_LINGER_COMPLETE." + network.netId, 459 EVENT_NETWORK_LINGER_COMPLETE, this); 460 mLingerMessage.schedule(newExpiry); 461 } 462 463 mLingerExpiryMs = newExpiry; 464 } 465 linger()466 public void linger() { 467 mLingering = true; 468 } 469 unlinger()470 public void unlinger() { 471 mLingering = false; 472 } 473 isLingering()474 public boolean isLingering() { 475 return mLingering; 476 } 477 clearLingerState()478 public void clearLingerState() { 479 if (mLingerMessage != null) { 480 mLingerMessage.cancel(); 481 mLingerMessage = null; 482 } 483 mLingerTimers.clear(); 484 mLingerTimerForRequest.clear(); 485 updateLingerTimer(); // Sets mLingerExpiryMs, cancels and nulls out mLingerMessage. 486 mLingering = false; 487 } 488 dumpLingerTimers(PrintWriter pw)489 public void dumpLingerTimers(PrintWriter pw) { 490 for (LingerTimer timer : mLingerTimers) { pw.println(timer); } 491 } 492 toString()493 public String toString() { 494 return "NetworkAgentInfo{ ni{" + networkInfo + "} " + 495 "network{" + network + "} nethandle{" + network.getNetworkHandle() + "} " + 496 "lp{" + linkProperties + "} " + 497 "nc{" + networkCapabilities + "} Score{" + getCurrentScore() + "} " + 498 "everValidated{" + everValidated + "} lastValidated{" + lastValidated + "} " + 499 "created{" + created + "} lingering{" + isLingering() + "} " + 500 "explicitlySelected{" + networkMisc.explicitlySelected + "} " + 501 "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " + 502 "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " + 503 "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " + 504 "}"; 505 } 506 name()507 public String name() { 508 return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" + 509 networkInfo.getSubtypeName() + ") - " + 510 (network == null ? "null" : network.toString()) + "]"; 511 } 512 513 // Enables sorting in descending order of score. 514 @Override compareTo(NetworkAgentInfo other)515 public int compareTo(NetworkAgentInfo other) { 516 return other.getCurrentScore() - getCurrentScore(); 517 } 518 } 519