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.util.SparseArray; 32 33 import com.android.internal.util.AsyncChannel; 34 import com.android.server.ConnectivityService; 35 import com.android.server.connectivity.NetworkMonitor; 36 37 import java.util.ArrayList; 38 import java.util.Comparator; 39 40 /** 41 * A bag class used by ConnectivityService for holding a collection of most recent 42 * information published by a particular NetworkAgent as well as the 43 * AsyncChannel/messenger for reaching that NetworkAgent and lists of NetworkRequests 44 * interested in using it. Default sort order is descending by score. 45 */ 46 // States of a network: 47 // -------------------- 48 // 1. registered, uncreated, disconnected, unvalidated 49 // This state is entered when a NetworkFactory registers a NetworkAgent in any state except 50 // the CONNECTED state. 51 // 2. registered, uncreated, connecting, unvalidated 52 // This state is entered when a registered NetworkAgent for a VPN network transitions to the 53 // CONNECTING state (TODO: go through this state for every network, not just VPNs). 54 // ConnectivityService will tell netd to create the network early in order to add extra UID 55 // routing rules referencing the netID. These rules need to be in place before the network is 56 // connected to avoid racing against client apps trying to connect to a half-setup network. 57 // 3. registered, uncreated, connected, unvalidated 58 // This state is entered when a registered NetworkAgent transitions to the CONNECTED state. 59 // ConnectivityService will tell netd to create the network if it was not already created, and 60 // immediately transition to state #4. 61 // 4. registered, created, connected, unvalidated 62 // If this network can satisfy the default NetworkRequest, then NetworkMonitor will 63 // probe for Internet connectivity. 64 // If this network cannot satisfy the default NetworkRequest, it will immediately be 65 // transitioned to state #5. 66 // A network may remain in this state if NetworkMonitor fails to find Internet connectivity, 67 // for example: 68 // a. a captive portal is present, or 69 // b. a WiFi router whose Internet backhaul is down, or 70 // c. a wireless connection stops transfering packets temporarily (e.g. device is in elevator 71 // or tunnel) but does not disconnect from the AP/cell tower, or 72 // d. a stand-alone device offering a WiFi AP without an uplink for configuration purposes. 73 // 5. registered, created, connected, validated 74 // 75 // The device's default network connection: 76 // ---------------------------------------- 77 // Networks in states #4 and #5 may be used as a device's default network connection if they 78 // satisfy the default NetworkRequest. 79 // A network, that satisfies the default NetworkRequest, in state #5 should always be chosen 80 // in favor of a network, that satisfies the default NetworkRequest, in state #4. 81 // When deciding between two networks, that both satisfy the default NetworkRequest, to select 82 // for the default network connection, the one with the higher score should be chosen. 83 // 84 // When a network disconnects: 85 // --------------------------- 86 // If a network's transport disappears, for example: 87 // a. WiFi turned off, or 88 // b. cellular data turned off, or 89 // c. airplane mode is turned on, or 90 // d. a wireless connection disconnects from AP/cell tower entirely (e.g. device is out of range 91 // of AP for an extended period of time, or switches to another AP without roaming) 92 // then that network can transition from any state (#1-#5) to unregistered. This happens by 93 // the transport disconnecting their NetworkAgent's AsyncChannel with ConnectivityManager. 94 // ConnectivityService also tells netd to destroy the network. 95 // 96 // When ConnectivityService disconnects a network: 97 // ----------------------------------------------- 98 // If a network has no chance of satisfying any requests (even if it were to become validated 99 // and enter state #5), ConnectivityService will disconnect the NetworkAgent's AsyncChannel. 100 // If the network ever for any period of time had satisfied a NetworkRequest (i.e. had been 101 // the highest scoring that satisfied the NetworkRequest's constraints), but is no longer the 102 // highest scoring network for any NetworkRequest, then there will be a 30s pause before 103 // ConnectivityService disconnects the NetworkAgent's AsyncChannel. During this pause the 104 // network is considered "lingering". This pause exists to allow network communication to be 105 // wrapped up rather than abruptly terminated. During this pause if the network begins satisfying 106 // a NetworkRequest, ConnectivityService will cancel the future disconnection of the NetworkAgent's 107 // AsyncChannel, and the network is no longer considered "lingering". 108 public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { 109 public NetworkInfo networkInfo; 110 // This Network object should always be used if possible, so as to encourage reuse of the 111 // enclosed socket factory and connection pool. Avoid creating other Network objects. 112 // This Network object is always valid. 113 public final Network network; 114 public LinkProperties linkProperties; 115 // This should only be modified via ConnectivityService.updateCapabilities(). 116 public NetworkCapabilities networkCapabilities; 117 public final NetworkMonitor networkMonitor; 118 public final NetworkMisc networkMisc; 119 // Indicates if netd has been told to create this Network. From this point on the appropriate 120 // routing rules are setup and routes are added so packets can begin flowing over the Network. 121 // This is a sticky bit; once set it is never cleared. 122 public boolean created; 123 // Set to true after the first time this network is marked as CONNECTED. Once set, the network 124 // shows up in API calls, is able to satisfy NetworkRequests and can become the default network. 125 // This is a sticky bit; once set it is never cleared. 126 public boolean everConnected; 127 // Set to true if this Network successfully passed validation or if it did not satisfy the 128 // default NetworkRequest in which case validation will not be attempted. 129 // This is a sticky bit; once set it is never cleared even if future validation attempts fail. 130 public boolean everValidated; 131 132 // The result of the last validation attempt on this network (true if validated, false if not). 133 // This bit exists only because we never unvalidate a network once it's been validated, and that 134 // is because the network scoring and revalidation code does not (may not?) deal properly with 135 // networks becoming unvalidated. 136 // TODO: Fix the network scoring code, remove this, and rename everValidated to validated. 137 public boolean lastValidated; 138 139 // Whether a captive portal was ever detected on this network. 140 // This is a sticky bit; once set it is never cleared. 141 public boolean everCaptivePortalDetected; 142 143 // Whether a captive portal was found during the last network validation attempt. 144 public boolean lastCaptivePortalDetected; 145 146 // Indicates whether the network is lingering. Networks are lingered when they become unneeded 147 // as a result of their NetworkRequests being satisfied by a different network, so as to allow 148 // communication to wrap up before the network is taken down. This usually only happens to the 149 // default network. Lingering ends with either the linger timeout expiring and the network 150 // being taken down, or the network satisfying a request again. 151 public boolean lingering; 152 153 // This represents the last score received from the NetworkAgent. 154 private int currentScore; 155 // Penalty applied to scores of Networks that have not been validated. 156 private static final int UNVALIDATED_SCORE_PENALTY = 40; 157 158 // Score for explicitly connected network. 159 // 160 // This ensures that a) the explicitly selected network is never trumped by anything else, and 161 // b) the explicitly selected network is never torn down. 162 private static final int MAXIMUM_NETWORK_SCORE = 100; 163 164 // The list of NetworkRequests being satisfied by this Network. 165 public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>(); 166 // The list of NetworkRequests that this Network previously satisfied with the highest 167 // score. A non-empty list indicates that if this Network was validated it is lingered. 168 // NOTE: This list is only used for debugging. 169 public final ArrayList<NetworkRequest> networkLingered = new ArrayList<NetworkRequest>(); 170 171 public final Messenger messenger; 172 public final AsyncChannel asyncChannel; 173 174 // Used by ConnectivityService to keep track of 464xlat. 175 public Nat464Xlat clatd; 176 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)177 public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, 178 LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, 179 NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService) { 180 this.messenger = messenger; 181 asyncChannel = ac; 182 network = net; 183 networkInfo = info; 184 linkProperties = lp; 185 networkCapabilities = nc; 186 currentScore = score; 187 networkMonitor = connService.createNetworkMonitor(context, handler, this, defaultRequest); 188 networkMisc = misc; 189 } 190 191 /** 192 * Add {@code networkRequest} to this network as it's satisfied by this network. 193 * NOTE: This function must only be called on ConnectivityService's main thread. 194 * @return true if {@code networkRequest} was added or false if {@code networkRequest} was 195 * already present. 196 */ addRequest(NetworkRequest networkRequest)197 public boolean addRequest(NetworkRequest networkRequest) { 198 if (networkRequests.get(networkRequest.requestId) == networkRequest) return false; 199 networkRequests.put(networkRequest.requestId, networkRequest); 200 return true; 201 } 202 203 // Does this network satisfy request? satisfies(NetworkRequest request)204 public boolean satisfies(NetworkRequest request) { 205 return created && 206 request.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities); 207 } 208 satisfiesImmutableCapabilitiesOf(NetworkRequest request)209 public boolean satisfiesImmutableCapabilitiesOf(NetworkRequest request) { 210 return created && 211 request.networkCapabilities.satisfiedByImmutableNetworkCapabilities( 212 networkCapabilities); 213 } 214 isVPN()215 public boolean isVPN() { 216 return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN); 217 } 218 getCurrentScore(boolean pretendValidated)219 private int getCurrentScore(boolean pretendValidated) { 220 // TODO: We may want to refactor this into a NetworkScore class that takes a base score from 221 // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the 222 // score. The NetworkScore class would provide a nice place to centralize score constants 223 // so they are not scattered about the transports. 224 225 // If this network is explicitly selected and the user has decided to use it even if it's 226 // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly 227 // selected and we're trying to see what its score could be. This ensures that we don't tear 228 // down an explicitly selected network before the user gets a chance to prefer it when 229 // a higher-scoring network (e.g., Ethernet) is available. 230 if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) { 231 return MAXIMUM_NETWORK_SCORE; 232 } 233 234 int score = currentScore; 235 // Use NET_CAPABILITY_VALIDATED here instead of lastValidated, this allows 236 // ConnectivityService.updateCapabilities() to compute the old score prior to updating 237 // networkCapabilities (with a potentially different validated state). 238 if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) && !pretendValidated) { 239 score -= UNVALIDATED_SCORE_PENALTY; 240 } 241 if (score < 0) score = 0; 242 return score; 243 } 244 245 // Get the current score for this Network. This may be modified from what the 246 // NetworkAgent sent, as it has modifiers applied to it. getCurrentScore()247 public int getCurrentScore() { 248 return getCurrentScore(false); 249 } 250 251 // Get the current score for this Network as if it was validated. This may be modified from 252 // what the NetworkAgent sent, as it has modifiers applied to it. getCurrentScoreAsValidated()253 public int getCurrentScoreAsValidated() { 254 return getCurrentScore(true); 255 } 256 setCurrentScore(int newScore)257 public void setCurrentScore(int newScore) { 258 currentScore = newScore; 259 } 260 getNetworkState()261 public NetworkState getNetworkState() { 262 synchronized (this) { 263 // Network objects are outwardly immutable so there is no point to duplicating. 264 // Duplicating also precludes sharing socket factories and connection pools. 265 final String subscriberId = (networkMisc != null) ? networkMisc.subscriberId : null; 266 return new NetworkState(new NetworkInfo(networkInfo), 267 new LinkProperties(linkProperties), 268 new NetworkCapabilities(networkCapabilities), network, subscriberId, null); 269 } 270 } 271 toString()272 public String toString() { 273 return "NetworkAgentInfo{ ni{" + networkInfo + "} " + 274 "network{" + network + "} nethandle{" + network.getNetworkHandle() + "} " + 275 "lp{" + linkProperties + "} " + 276 "nc{" + networkCapabilities + "} Score{" + getCurrentScore() + "} " + 277 "everValidated{" + everValidated + "} lastValidated{" + lastValidated + "} " + 278 "created{" + created + "} lingering{" + lingering + "} " + 279 "explicitlySelected{" + networkMisc.explicitlySelected + "} " + 280 "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " + 281 "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " + 282 "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " + 283 "}"; 284 } 285 name()286 public String name() { 287 return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" + 288 networkInfo.getSubtypeName() + ") - " + 289 (network == null ? "null" : network.toString()) + "]"; 290 } 291 292 // Enables sorting in descending order of score. 293 @Override compareTo(NetworkAgentInfo other)294 public int compareTo(NetworkAgentInfo other) { 295 return other.getCurrentScore() - getCurrentScore(); 296 } 297 } 298