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