1 /*
2  * Copyright (C) 2008 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;
18 
19 import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
20 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
21 import static android.net.ConnectivityManager.NETID_UNSET;
22 import static android.net.ConnectivityManager.TYPE_NONE;
23 import static android.net.ConnectivityManager.TYPE_VPN;
24 import static android.net.ConnectivityManager.getNetworkTypeName;
25 import static android.net.ConnectivityManager.isNetworkTypeValid;
26 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
27 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
28 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
29 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
30 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
31 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
32 
33 import android.annotation.Nullable;
34 import android.app.BroadcastOptions;
35 import android.app.NotificationManager;
36 import android.app.PendingIntent;
37 import android.content.BroadcastReceiver;
38 import android.content.ContentResolver;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.IntentFilter;
42 import android.content.pm.PackageManager;
43 import android.content.res.Configuration;
44 import android.content.res.Resources;
45 import android.database.ContentObserver;
46 import android.net.ConnectivityManager;
47 import android.net.ConnectivityManager.PacketKeepalive;
48 import android.net.IConnectivityManager;
49 import android.net.INetworkManagementEventObserver;
50 import android.net.INetworkPolicyListener;
51 import android.net.INetworkPolicyManager;
52 import android.net.INetworkStatsService;
53 import android.net.LinkProperties;
54 import android.net.LinkProperties.CompareResult;
55 import android.net.Network;
56 import android.net.NetworkAgent;
57 import android.net.NetworkCapabilities;
58 import android.net.MatchAllNetworkSpecifier;
59 import android.net.NetworkConfig;
60 import android.net.NetworkInfo;
61 import android.net.NetworkInfo.DetailedState;
62 import android.net.NetworkMisc;
63 import android.net.NetworkQuotaInfo;
64 import android.net.NetworkRequest;
65 import android.net.NetworkState;
66 import android.net.NetworkUtils;
67 import android.net.Proxy;
68 import android.net.ProxyInfo;
69 import android.net.RouteInfo;
70 import android.net.UidRange;
71 import android.net.Uri;
72 import android.net.metrics.DefaultNetworkEvent;
73 import android.net.metrics.IpConnectivityLog;
74 import android.net.metrics.NetworkEvent;
75 import android.net.util.MultinetworkPolicyTracker;
76 import android.os.Binder;
77 import android.os.Build;
78 import android.os.Bundle;
79 import android.os.FileUtils;
80 import android.os.Handler;
81 import android.os.HandlerThread;
82 import android.os.IBinder;
83 import android.os.INetworkManagementService;
84 import android.os.Looper;
85 import android.os.Message;
86 import android.os.Messenger;
87 import android.os.ParcelFileDescriptor;
88 import android.os.PowerManager;
89 import android.os.Process;
90 import android.os.RemoteException;
91 import android.os.ResultReceiver;
92 import android.os.SystemClock;
93 import android.os.UserHandle;
94 import android.os.UserManager;
95 import android.provider.Settings;
96 import android.security.Credentials;
97 import android.security.KeyStore;
98 import android.telephony.TelephonyManager;
99 import android.text.TextUtils;
100 import android.util.LocalLog;
101 import android.util.LocalLog.ReadOnlyLocalLog;
102 import android.util.Log;
103 import android.util.Pair;
104 import android.util.Slog;
105 import android.util.SparseArray;
106 import android.util.SparseBooleanArray;
107 import android.util.SparseIntArray;
108 import android.util.Xml;
109 
110 import com.android.internal.R;
111 import com.android.internal.annotations.GuardedBy;
112 import com.android.internal.annotations.VisibleForTesting;
113 import com.android.internal.app.IBatteryStats;
114 import com.android.internal.net.LegacyVpnInfo;
115 import com.android.internal.net.NetworkStatsFactory;
116 import com.android.internal.net.VpnConfig;
117 import com.android.internal.net.VpnInfo;
118 import com.android.internal.net.VpnProfile;
119 import com.android.internal.util.AsyncChannel;
120 import com.android.internal.util.DumpUtils;
121 import com.android.internal.util.IndentingPrintWriter;
122 import com.android.internal.util.MessageUtils;
123 import com.android.internal.util.WakeupMessage;
124 import com.android.internal.util.XmlUtils;
125 import com.android.server.LocalServices;
126 import com.android.server.am.BatteryStatsService;
127 import com.android.server.connectivity.DataConnectionStats;
128 import com.android.server.connectivity.KeepaliveTracker;
129 import com.android.server.connectivity.MockableSystemProperties;
130 import com.android.server.connectivity.Nat464Xlat;
131 import com.android.server.connectivity.LingerMonitor;
132 import com.android.server.connectivity.NetworkAgentInfo;
133 import com.android.server.connectivity.NetworkDiagnostics;
134 import com.android.server.connectivity.NetworkMonitor;
135 import com.android.server.connectivity.NetworkNotificationManager;
136 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
137 import com.android.server.connectivity.PacManager;
138 import com.android.server.connectivity.PermissionMonitor;
139 import com.android.server.connectivity.Tethering;
140 import com.android.server.connectivity.Vpn;
141 import com.android.server.net.BaseNetworkObserver;
142 import com.android.server.net.LockdownVpnTracker;
143 import com.android.server.net.NetworkPolicyManagerInternal;
144 
145 import com.google.android.collect.Lists;
146 
147 import org.xmlpull.v1.XmlPullParser;
148 import org.xmlpull.v1.XmlPullParserException;
149 
150 import java.io.File;
151 import java.io.FileDescriptor;
152 import java.io.FileNotFoundException;
153 import java.io.FileReader;
154 import java.io.IOException;
155 import java.io.PrintWriter;
156 import java.net.Inet4Address;
157 import java.net.InetAddress;
158 import java.net.UnknownHostException;
159 import java.util.ArrayDeque;
160 import java.util.ArrayList;
161 import java.util.Arrays;
162 import java.util.Collection;
163 import java.util.HashMap;
164 import java.util.HashSet;
165 import java.util.List;
166 import java.util.Map;
167 import java.util.Objects;
168 import java.util.SortedSet;
169 import java.util.TreeSet;
170 
171 /**
172  * @hide
173  */
174 public class ConnectivityService extends IConnectivityManager.Stub
175         implements PendingIntent.OnFinished {
176     private static final String TAG = ConnectivityService.class.getSimpleName();
177 
178     public static final String DIAG_ARG = "--diag";
179     public static final String SHORT_ARG = "--short";
180 
181     private static final boolean DBG = true;
182     private static final boolean VDBG = false;
183 
184     private static final boolean LOGD_RULES = false;
185     private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
186 
187     // TODO: create better separation between radio types and network types
188 
189     // how long to wait before switching back to a radio's default network
190     private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
191     // system property that can override the above value
192     private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
193             "android.telephony.apn-restore";
194 
195     // How long to wait before putting up a "This network doesn't have an Internet connection,
196     // connect anyway?" dialog after the user selects a network that doesn't validate.
197     private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;
198 
199     // Default to 30s linger time-out. Modifiable only for testing.
200     private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
201     private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
202     @VisibleForTesting
203     protected int mLingerDelayMs;  // Can't be final, or test subclass constructors can't change it.
204 
205     // How long to delay to removal of a pending intent based request.
206     // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
207     private final int mReleasePendingIntentDelayMs;
208 
209     private MockableSystemProperties mSystemProperties;
210 
211     private Tethering mTethering;
212 
213     private final PermissionMonitor mPermissionMonitor;
214 
215     private KeyStore mKeyStore;
216 
217     @GuardedBy("mVpns")
218     private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
219 
220     private boolean mLockdownEnabled;
221     private LockdownVpnTracker mLockdownTracker;
222 
223     final private Context mContext;
224     private int mNetworkPreference;
225     // 0 is full bad, 100 is full good
226     private int mDefaultInetConditionPublished = 0;
227 
228     private int mNumDnsEntries;
229 
230     private boolean mTestMode;
231     private static ConnectivityService sServiceInstance;
232 
233     private INetworkManagementService mNetd;
234     private INetworkStatsService mStatsService;
235     private INetworkPolicyManager mPolicyManager;
236     private NetworkPolicyManagerInternal mPolicyManagerInternal;
237 
238     private String mCurrentTcpBufferSizes;
239 
240     private static final int ENABLED  = 1;
241     private static final int DISABLED = 0;
242 
243     private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
244             new Class[] { AsyncChannel.class, ConnectivityService.class, NetworkAgent.class,
245                     NetworkAgentInfo.class });
246 
247     private enum ReapUnvalidatedNetworks {
248         // Tear down networks that have no chance (e.g. even if validated) of becoming
249         // the highest scoring network satisfying a NetworkRequest.  This should be passed when
250         // all networks have been rematched against all NetworkRequests.
251         REAP,
252         // Don't reap networks.  This should be passed when some networks have not yet been
253         // rematched against all NetworkRequests.
254         DONT_REAP
255     };
256 
257     private enum UnneededFor {
258         LINGER,    // Determine whether this network is unneeded and should be lingered.
259         TEARDOWN,  // Determine whether this network is unneeded and should be torn down.
260     }
261 
262     /**
263      * used internally to change our mobile data enabled flag
264      */
265     private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
266 
267     /**
268      * used internally to clear a wakelock when transitioning
269      * from one net to another.  Clear happens when we get a new
270      * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
271      * after a timeout if no network is found (typically 1 min).
272      */
273     private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
274 
275     /**
276      * used internally to reload global proxy settings
277      */
278     private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
279 
280     /**
281      * PAC manager has received new port.
282      */
283     private static final int EVENT_PROXY_HAS_CHANGED = 16;
284 
285     /**
286      * used internally when registering NetworkFactories
287      * obj = NetworkFactoryInfo
288      */
289     private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
290 
291     /**
292      * used internally when registering NetworkAgents
293      * obj = Messenger
294      */
295     private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
296 
297     /**
298      * used to add a network request
299      * includes a NetworkRequestInfo
300      */
301     private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
302 
303     /**
304      * indicates a timeout period is over - check if we had a network yet or not
305      * and if not, call the timeout callback (but leave the request live until they
306      * cancel it.
307      * includes a NetworkRequestInfo
308      */
309     private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;
310 
311     /**
312      * used to add a network listener - no request
313      * includes a NetworkRequestInfo
314      */
315     private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
316 
317     /**
318      * used to remove a network request, either a listener or a real request
319      * arg1 = UID of caller
320      * obj  = NetworkRequest
321      */
322     private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
323 
324     /**
325      * used internally when registering NetworkFactories
326      * obj = Messenger
327      */
328     private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
329 
330     /**
331      * used internally to expire a wakelock when transitioning
332      * from one net to another.  Expire happens when we fail to find
333      * a new network (typically after 1 minute) -
334      * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found
335      * a replacement network.
336      */
337     private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
338 
339     /**
340      * Used internally to indicate the system is ready.
341      */
342     private static final int EVENT_SYSTEM_READY = 25;
343 
344     /**
345      * used to add a network request with a pending intent
346      * obj = NetworkRequestInfo
347      */
348     private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
349 
350     /**
351      * used to remove a pending intent and its associated network request.
352      * arg1 = UID of caller
353      * obj  = PendingIntent
354      */
355     private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
356 
357     /**
358      * used to specify whether a network should be used even if unvalidated.
359      * arg1 = whether to accept the network if it's unvalidated (1 or 0)
360      * arg2 = whether to remember this choice in the future (1 or 0)
361      * obj  = network
362      */
363     private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;
364 
365     /**
366      * used to specify whether a network should not be penalized when it becomes unvalidated.
367      */
368     private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
369 
370     /**
371      * used to ask the user to confirm a connection to an unvalidated network.
372      * obj  = network
373      */
374     private static final int EVENT_PROMPT_UNVALIDATED = 29;
375 
376     /**
377      * used internally to (re)configure mobile data always-on settings.
378      */
379     private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
380 
381     /**
382      * used to add a network listener with a pending intent
383      * obj = NetworkRequestInfo
384      */
385     private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
386 
387     /** Handler thread used for both of the handlers below. */
388     @VisibleForTesting
389     protected final HandlerThread mHandlerThread;
390     /** Handler used for internal events. */
391     final private InternalHandler mHandler;
392     /** Handler used for incoming {@link NetworkStateTracker} events. */
393     final private NetworkStateTrackerHandler mTrackerHandler;
394 
395     private boolean mSystemReady;
396     private Intent mInitialBroadcast;
397 
398     private PowerManager.WakeLock mNetTransitionWakeLock;
399     private String mNetTransitionWakeLockCausedBy = "";
400     private int mNetTransitionWakeLockSerialNumber;
401     private int mNetTransitionWakeLockTimeout;
402     private final PowerManager.WakeLock mPendingIntentWakeLock;
403 
404     // used in DBG mode to track inet condition reports
405     private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
406     private ArrayList mInetLog;
407 
408     // track the current default http proxy - tell the world if we get a new one (real change)
409     private volatile ProxyInfo mDefaultProxy = null;
410     private Object mProxyLock = new Object();
411     private boolean mDefaultProxyDisabled = false;
412 
413     // track the global proxy.
414     private ProxyInfo mGlobalProxy = null;
415 
416     private PacManager mPacManager = null;
417 
418     final private SettingsObserver mSettingsObserver;
419 
420     private UserManager mUserManager;
421 
422     NetworkConfig[] mNetConfigs;
423     int mNetworksDefined;
424 
425     // the set of network types that can only be enabled by system/sig apps
426     List mProtectedNetworks;
427 
428     private DataConnectionStats mDataConnectionStats;
429 
430     TelephonyManager mTelephonyManager;
431 
432     private KeepaliveTracker mKeepaliveTracker;
433     private NetworkNotificationManager mNotifier;
434     private LingerMonitor mLingerMonitor;
435 
436     // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
437     private final static int MIN_NET_ID = 100; // some reserved marks
438     private final static int MAX_NET_ID = 65535;
439     private int mNextNetId = MIN_NET_ID;
440 
441     // sequence number of NetworkRequests
442     private int mNextNetworkRequestId = 1;
443 
444     // NetworkRequest activity String log entries.
445     private static final int MAX_NETWORK_REQUEST_LOGS = 20;
446     private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
447 
448     // NetworkInfo blocked and unblocked String log entries
449     // TODO: consider reducing memory usage. Each log line is ~40 2B chars, for a total of ~8kB.
450     private static final int MAX_NETWORK_INFO_LOGS = 100;
451     private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS);
452 
453     // Array of <Network,ReadOnlyLocalLogs> tracking network validation and results
454     private static final int MAX_VALIDATION_LOGS = 10;
455     private static class ValidationLog {
456         final Network mNetwork;
457         final String mNetworkExtraInfo;
458         final ReadOnlyLocalLog mLog;
459 
ValidationLog(Network network, String networkExtraInfo, ReadOnlyLocalLog log)460         ValidationLog(Network network, String networkExtraInfo, ReadOnlyLocalLog log) {
461             mNetwork = network;
462             mNetworkExtraInfo = networkExtraInfo;
463             mLog = log;
464         }
465     }
466     private final ArrayDeque<ValidationLog> mValidationLogs =
467             new ArrayDeque<ValidationLog>(MAX_VALIDATION_LOGS);
468 
addValidationLogs(ReadOnlyLocalLog log, Network network, String networkExtraInfo)469     private void addValidationLogs(ReadOnlyLocalLog log, Network network, String networkExtraInfo) {
470         synchronized(mValidationLogs) {
471             while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
472                 mValidationLogs.removeLast();
473             }
474             mValidationLogs.addFirst(new ValidationLog(network, networkExtraInfo, log));
475         }
476     }
477 
478     private final IpConnectivityLog mMetricsLog;
479 
480     @VisibleForTesting
481     final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
482 
483     /**
484      * Implements support for the legacy "one network per network type" model.
485      *
486      * We used to have a static array of NetworkStateTrackers, one for each
487      * network type, but that doesn't work any more now that we can have,
488      * for example, more that one wifi network. This class stores all the
489      * NetworkAgentInfo objects that support a given type, but the legacy
490      * API will only see the first one.
491      *
492      * It serves two main purposes:
493      *
494      * 1. Provide information about "the network for a given type" (since this
495      *    API only supports one).
496      * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
497      *    the first network for a given type changes, or if the default network
498      *    changes.
499      */
500     private class LegacyTypeTracker {
501 
502         private static final boolean DBG = true;
503         private static final boolean VDBG = false;
504 
505         /**
506          * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
507          * Each list holds references to all NetworkAgentInfos that are used to
508          * satisfy requests for that network type.
509          *
510          * This array is built out at startup such that an unsupported network
511          * doesn't get an ArrayList instance, making this a tristate:
512          * unsupported, supported but not active and active.
513          *
514          * The actual lists are populated when we scan the network types that
515          * are supported on this device.
516          *
517          * Threading model:
518          *  - addSupportedType() is only called in the constructor
519          *  - add(), update(), remove() are only called from the ConnectivityService handler thread.
520          *    They are therefore not thread-safe with respect to each other.
521          *  - getNetworkForType() can be called at any time on binder threads. It is synchronized
522          *    on mTypeLists to be thread-safe with respect to a concurrent remove call.
523          *  - dump is thread-safe with respect to concurrent add and remove calls.
524          */
525         private final ArrayList<NetworkAgentInfo> mTypeLists[];
526 
LegacyTypeTracker()527         public LegacyTypeTracker() {
528             mTypeLists = (ArrayList<NetworkAgentInfo>[])
529                     new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
530         }
531 
addSupportedType(int type)532         public void addSupportedType(int type) {
533             if (mTypeLists[type] != null) {
534                 throw new IllegalStateException(
535                         "legacy list for type " + type + "already initialized");
536             }
537             mTypeLists[type] = new ArrayList<NetworkAgentInfo>();
538         }
539 
isTypeSupported(int type)540         public boolean isTypeSupported(int type) {
541             return isNetworkTypeValid(type) && mTypeLists[type] != null;
542         }
543 
getNetworkForType(int type)544         public NetworkAgentInfo getNetworkForType(int type) {
545             synchronized (mTypeLists) {
546                 if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
547                     return mTypeLists[type].get(0);
548                 }
549             }
550             return null;
551         }
552 
maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, boolean isDefaultNetwork)553         private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
554                 boolean isDefaultNetwork) {
555             if (DBG) {
556                 log("Sending " + state +
557                         " broadcast for type " + type + " " + nai.name() +
558                         " isDefaultNetwork=" + isDefaultNetwork);
559             }
560         }
561 
562         /** Adds the given network to the specified legacy type list. */
add(int type, NetworkAgentInfo nai)563         public void add(int type, NetworkAgentInfo nai) {
564             if (!isTypeSupported(type)) {
565                 return;  // Invalid network type.
566             }
567             if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
568 
569             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
570             if (list.contains(nai)) {
571                 return;
572             }
573             synchronized (mTypeLists) {
574                 list.add(nai);
575             }
576 
577             // Send a broadcast if this is the first network of its type or if it's the default.
578             final boolean isDefaultNetwork = isDefaultNetwork(nai);
579             if ((list.size() == 1) || isDefaultNetwork) {
580                 maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
581                 sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
582             }
583         }
584 
585         /** Removes the given network from the specified legacy type list. */
remove(int type, NetworkAgentInfo nai, boolean wasDefault)586         public void remove(int type, NetworkAgentInfo nai, boolean wasDefault) {
587             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
588             if (list == null || list.isEmpty()) {
589                 return;
590             }
591             final boolean wasFirstNetwork = list.get(0).equals(nai);
592 
593             synchronized (mTypeLists) {
594                 if (!list.remove(nai)) {
595                     return;
596                 }
597             }
598 
599             final DetailedState state = DetailedState.DISCONNECTED;
600 
601             if (wasFirstNetwork || wasDefault) {
602                 maybeLogBroadcast(nai, state, type, wasDefault);
603                 sendLegacyNetworkBroadcast(nai, state, type);
604             }
605 
606             if (!list.isEmpty() && wasFirstNetwork) {
607                 if (DBG) log("Other network available for type " + type +
608                               ", sending connected broadcast");
609                 final NetworkAgentInfo replacement = list.get(0);
610                 maybeLogBroadcast(replacement, state, type, isDefaultNetwork(replacement));
611                 sendLegacyNetworkBroadcast(replacement, state, type);
612             }
613         }
614 
615         /** Removes the given network from all legacy type lists. */
remove(NetworkAgentInfo nai, boolean wasDefault)616         public void remove(NetworkAgentInfo nai, boolean wasDefault) {
617             if (VDBG) log("Removing agent " + nai + " wasDefault=" + wasDefault);
618             for (int type = 0; type < mTypeLists.length; type++) {
619                 remove(type, nai, wasDefault);
620             }
621         }
622 
623         // send out another legacy broadcast - currently only used for suspend/unsuspend
624         // toggle
update(NetworkAgentInfo nai)625         public void update(NetworkAgentInfo nai) {
626             final boolean isDefault = isDefaultNetwork(nai);
627             final DetailedState state = nai.networkInfo.getDetailedState();
628             for (int type = 0; type < mTypeLists.length; type++) {
629                 final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
630                 final boolean contains = (list != null && list.contains(nai));
631                 final boolean isFirst = contains && (nai == list.get(0));
632                 if (isFirst || contains && isDefault) {
633                     maybeLogBroadcast(nai, state, type, isDefault);
634                     sendLegacyNetworkBroadcast(nai, state, type);
635                 }
636             }
637         }
638 
naiToString(NetworkAgentInfo nai)639         private String naiToString(NetworkAgentInfo nai) {
640             String name = (nai != null) ? nai.name() : "null";
641             String state = (nai.networkInfo != null) ?
642                     nai.networkInfo.getState() + "/" + nai.networkInfo.getDetailedState() :
643                     "???/???";
644             return name + " " + state;
645         }
646 
dump(IndentingPrintWriter pw)647         public void dump(IndentingPrintWriter pw) {
648             pw.println("mLegacyTypeTracker:");
649             pw.increaseIndent();
650             pw.print("Supported types:");
651             for (int type = 0; type < mTypeLists.length; type++) {
652                 if (mTypeLists[type] != null) pw.print(" " + type);
653             }
654             pw.println();
655             pw.println("Current state:");
656             pw.increaseIndent();
657             synchronized (mTypeLists) {
658                 for (int type = 0; type < mTypeLists.length; type++) {
659                     if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
660                     for (NetworkAgentInfo nai : mTypeLists[type]) {
661                         pw.println(type + " " + naiToString(nai));
662                     }
663                 }
664             }
665             pw.decreaseIndent();
666             pw.decreaseIndent();
667             pw.println();
668         }
669     }
670     private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
671 
ConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager)672     public ConnectivityService(Context context, INetworkManagementService netManager,
673             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
674         this(context, netManager, statsService, policyManager, new IpConnectivityLog());
675     }
676 
677     @VisibleForTesting
ConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, IpConnectivityLog logger)678     protected ConnectivityService(Context context, INetworkManagementService netManager,
679             INetworkStatsService statsService, INetworkPolicyManager policyManager,
680             IpConnectivityLog logger) {
681         if (DBG) log("ConnectivityService starting up");
682 
683         mSystemProperties = getSystemProperties();
684 
685         mMetricsLog = logger;
686         mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
687         NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
688         mNetworkRequests.put(mDefaultRequest, defaultNRI);
689         mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI);
690 
691         mDefaultMobileDataRequest = createInternetRequestForTransport(
692                 NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
693 
694         mHandlerThread = new HandlerThread("ConnectivityServiceThread");
695         mHandlerThread.start();
696         mHandler = new InternalHandler(mHandlerThread.getLooper());
697         mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
698 
699         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
700                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
701 
702         mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
703 
704         mContext = checkNotNull(context, "missing Context");
705         mNetd = checkNotNull(netManager, "missing INetworkManagementService");
706         mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
707         mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
708         mPolicyManagerInternal = checkNotNull(
709                 LocalServices.getService(NetworkPolicyManagerInternal.class),
710                 "missing NetworkPolicyManagerInternal");
711 
712         mKeyStore = KeyStore.getInstance();
713         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
714 
715         try {
716             mPolicyManager.registerListener(mPolicyListener);
717         } catch (RemoteException e) {
718             // ouch, no rules updates means some processes may never get network
719             loge("unable to register INetworkPolicyListener" + e);
720         }
721 
722         final PowerManager powerManager = (PowerManager) context.getSystemService(
723                 Context.POWER_SERVICE);
724         mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
725         mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
726                 com.android.internal.R.integer.config_networkTransitionTimeout);
727         mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
728 
729         mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
730 
731         // TODO: What is the "correct" way to do determine if this is a wifi only device?
732         boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
733         log("wifiOnly=" + wifiOnly);
734         String[] naStrings = context.getResources().getStringArray(
735                 com.android.internal.R.array.networkAttributes);
736         for (String naString : naStrings) {
737             try {
738                 NetworkConfig n = new NetworkConfig(naString);
739                 if (VDBG) log("naString=" + naString + " config=" + n);
740                 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
741                     loge("Error in networkAttributes - ignoring attempt to define type " +
742                             n.type);
743                     continue;
744                 }
745                 if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
746                     log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
747                             n.type);
748                     continue;
749                 }
750                 if (mNetConfigs[n.type] != null) {
751                     loge("Error in networkAttributes - ignoring attempt to redefine type " +
752                             n.type);
753                     continue;
754                 }
755                 mLegacyTypeTracker.addSupportedType(n.type);
756 
757                 mNetConfigs[n.type] = n;
758                 mNetworksDefined++;
759             } catch(Exception e) {
760                 // ignore it - leave the entry null
761             }
762         }
763 
764         // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
765         if (mNetConfigs[TYPE_VPN] == null) {
766             // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
767             // don't need to add TYPE_VPN to mNetConfigs.
768             mLegacyTypeTracker.addSupportedType(TYPE_VPN);
769             mNetworksDefined++;  // used only in the log() statement below.
770         }
771 
772         if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
773 
774         mProtectedNetworks = new ArrayList<Integer>();
775         int[] protectedNetworks = context.getResources().getIntArray(
776                 com.android.internal.R.array.config_protectedNetworks);
777         for (int p : protectedNetworks) {
778             if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
779                 mProtectedNetworks.add(p);
780             } else {
781                 if (DBG) loge("Ignoring protectedNetwork " + p);
782             }
783         }
784 
785         mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
786                 && mSystemProperties.get("ro.build.type").equals("eng");
787 
788         mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager,
789                                    IoThread.get().getLooper(), new MockableSystemProperties());
790 
791         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
792 
793         //set up the listener for user state for creating user VPNs
794         IntentFilter intentFilter = new IntentFilter();
795         intentFilter.addAction(Intent.ACTION_USER_STARTED);
796         intentFilter.addAction(Intent.ACTION_USER_STOPPED);
797         intentFilter.addAction(Intent.ACTION_USER_ADDED);
798         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
799         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
800         mContext.registerReceiverAsUser(
801                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
802         mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
803                 new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
804 
805         try {
806             mNetd.registerObserver(mTethering);
807             mNetd.registerObserver(mDataActivityObserver);
808         } catch (RemoteException e) {
809             loge("Error registering observer :" + e);
810         }
811 
812         if (DBG) {
813             mInetLog = new ArrayList();
814         }
815 
816         mSettingsObserver = new SettingsObserver(mContext, mHandler);
817         registerSettingsCallbacks();
818 
819         mDataConnectionStats = new DataConnectionStats(mContext);
820         mDataConnectionStats.startMonitoring();
821 
822         mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
823 
824         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
825 
826         mKeepaliveTracker = new KeepaliveTracker(mHandler);
827         mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
828                 mContext.getSystemService(NotificationManager.class));
829 
830         final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
831                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
832                 LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
833         final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
834                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
835                 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
836         mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
837 
838         mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
839                 mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
840         mMultinetworkPolicyTracker.start();
841     }
842 
createInternetRequestForTransport( int transportType, NetworkRequest.Type type)843     private NetworkRequest createInternetRequestForTransport(
844             int transportType, NetworkRequest.Type type) {
845         NetworkCapabilities netCap = new NetworkCapabilities();
846         netCap.addCapability(NET_CAPABILITY_INTERNET);
847         netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
848         if (transportType > -1) {
849             netCap.addTransportType(transportType);
850         }
851         return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
852     }
853 
854     // Used only for testing.
855     // TODO: Delete this and either:
856     // 1. Give Fake SettingsProvider the ability to send settings change notifications (requires
857     //    changing ContentResolver to make registerContentObserver non-final).
858     // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
859     //    by subclassing SettingsObserver.
860     @VisibleForTesting
updateMobileDataAlwaysOn()861     void updateMobileDataAlwaysOn() {
862         mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
863     }
864 
handleMobileDataAlwaysOn()865     private void handleMobileDataAlwaysOn() {
866         final boolean enable = (Settings.Global.getInt(
867                 mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1) == 1);
868         final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
869         if (enable == isEnabled) {
870             return;  // Nothing to do.
871         }
872 
873         if (enable) {
874             handleRegisterNetworkRequest(new NetworkRequestInfo(
875                     null, mDefaultMobileDataRequest, new Binder()));
876         } else {
877             handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID);
878         }
879     }
880 
registerSettingsCallbacks()881     private void registerSettingsCallbacks() {
882         // Watch for global HTTP proxy changes.
883         mSettingsObserver.observe(
884                 Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
885                 EVENT_APPLY_GLOBAL_HTTP_PROXY);
886 
887         // Watch for whether or not to keep mobile data always on.
888         mSettingsObserver.observe(
889                 Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
890                 EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
891     }
892 
nextNetworkRequestId()893     private synchronized int nextNetworkRequestId() {
894         return mNextNetworkRequestId++;
895     }
896 
897     @VisibleForTesting
reserveNetId()898     protected int reserveNetId() {
899         synchronized (mNetworkForNetId) {
900             for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
901                 int netId = mNextNetId;
902                 if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
903                 // Make sure NetID unused.  http://b/16815182
904                 if (!mNetIdInUse.get(netId)) {
905                     mNetIdInUse.put(netId, true);
906                     return netId;
907                 }
908             }
909         }
910         throw new IllegalStateException("No free netIds");
911     }
912 
getFilteredNetworkState(int networkType, int uid, boolean ignoreBlocked)913     private NetworkState getFilteredNetworkState(int networkType, int uid, boolean ignoreBlocked) {
914         if (mLegacyTypeTracker.isTypeSupported(networkType)) {
915             final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
916             final NetworkState state;
917             if (nai != null) {
918                 state = nai.getNetworkState();
919                 state.networkInfo.setType(networkType);
920             } else {
921                 final NetworkInfo info = new NetworkInfo(networkType, 0,
922                         getNetworkTypeName(networkType), "");
923                 info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
924                 info.setIsAvailable(true);
925                 state = new NetworkState(info, new LinkProperties(), new NetworkCapabilities(),
926                         null, null, null);
927             }
928             filterNetworkStateForUid(state, uid, ignoreBlocked);
929             return state;
930         } else {
931             return NetworkState.EMPTY;
932         }
933     }
934 
getNetworkAgentInfoForNetwork(Network network)935     private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
936         if (network == null) {
937             return null;
938         }
939         synchronized (mNetworkForNetId) {
940             return mNetworkForNetId.get(network.netId);
941         }
942     }
943 
getVpnUnderlyingNetworks(int uid)944     private Network[] getVpnUnderlyingNetworks(int uid) {
945         if (!mLockdownEnabled) {
946             int user = UserHandle.getUserId(uid);
947             synchronized (mVpns) {
948                 Vpn vpn = mVpns.get(user);
949                 if (vpn != null && vpn.appliesToUid(uid)) {
950                     return vpn.getUnderlyingNetworks();
951                 }
952             }
953         }
954         return null;
955     }
956 
getUnfilteredActiveNetworkState(int uid)957     private NetworkState getUnfilteredActiveNetworkState(int uid) {
958         NetworkAgentInfo nai = getDefaultNetwork();
959 
960         final Network[] networks = getVpnUnderlyingNetworks(uid);
961         if (networks != null) {
962             // getUnderlyingNetworks() returns:
963             // null => there was no VPN, or the VPN didn't specify anything, so we use the default.
964             // empty array => the VPN explicitly said "no default network".
965             // non-empty array => the VPN specified one or more default networks; we use the
966             //                    first one.
967             if (networks.length > 0) {
968                 nai = getNetworkAgentInfoForNetwork(networks[0]);
969             } else {
970                 nai = null;
971             }
972         }
973 
974         if (nai != null) {
975             return nai.getNetworkState();
976         } else {
977             return NetworkState.EMPTY;
978         }
979     }
980 
981     /**
982      * Check if UID should be blocked from using the network with the given LinkProperties.
983      */
isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid, boolean ignoreBlocked)984     private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
985             boolean ignoreBlocked) {
986         // Networks aren't blocked when ignoring blocked status
987         if (ignoreBlocked) {
988             return false;
989         }
990         // Networks are never blocked for system services
991         // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked.
992         if (isSystem(uid)) {
993             return false;
994         }
995         synchronized (mVpns) {
996             final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
997             if (vpn != null && vpn.isBlockingUid(uid)) {
998                 return true;
999             }
1000         }
1001         final String iface = (lp == null ? "" : lp.getInterfaceName());
1002         return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
1003     }
1004 
maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid)1005     private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
1006         if (ni == null || !LOGD_BLOCKED_NETWORKINFO) {
1007             return;
1008         }
1009         boolean removed = false;
1010         boolean added = false;
1011         synchronized (mBlockedAppUids) {
1012             if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) {
1013                 added = true;
1014             } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) {
1015                 removed = true;
1016             }
1017         }
1018         if (added) {
1019             log("Returning blocked NetworkInfo to uid=" + uid);
1020             mNetworkInfoBlockingLogs.log("BLOCKED " + uid);
1021         } else if (removed) {
1022             log("Returning unblocked NetworkInfo to uid=" + uid);
1023             mNetworkInfoBlockingLogs.log("UNBLOCKED " + uid);
1024         }
1025     }
1026 
1027     /**
1028      * Apply any relevant filters to {@link NetworkState} for the given UID. For
1029      * example, this may mark the network as {@link DetailedState#BLOCKED} based
1030      * on {@link #isNetworkWithLinkPropertiesBlocked}, or
1031      * {@link NetworkInfo#isMetered()} based on network policies.
1032      */
filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked)1033     private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
1034         if (state == null || state.networkInfo == null || state.linkProperties == null) return;
1035 
1036         if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
1037             state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
1038         }
1039         if (mLockdownTracker != null) {
1040             mLockdownTracker.augmentNetworkInfo(state.networkInfo);
1041         }
1042 
1043         // TODO: apply metered state closer to NetworkAgentInfo
1044         final long token = Binder.clearCallingIdentity();
1045         try {
1046             state.networkInfo.setMetered(mPolicyManager.isNetworkMetered(state));
1047         } catch (RemoteException e) {
1048         } finally {
1049             Binder.restoreCallingIdentity(token);
1050         }
1051     }
1052 
1053     /**
1054      * Return NetworkInfo for the active (i.e., connected) network interface.
1055      * It is assumed that at most one network is active at a time. If more
1056      * than one is active, it is indeterminate which will be returned.
1057      * @return the info for the active network, or {@code null} if none is
1058      * active
1059      */
1060     @Override
getActiveNetworkInfo()1061     public NetworkInfo getActiveNetworkInfo() {
1062         enforceAccessPermission();
1063         final int uid = Binder.getCallingUid();
1064         final NetworkState state = getUnfilteredActiveNetworkState(uid);
1065         filterNetworkStateForUid(state, uid, false);
1066         maybeLogBlockedNetworkInfo(state.networkInfo, uid);
1067         return state.networkInfo;
1068     }
1069 
1070     @Override
getActiveNetwork()1071     public Network getActiveNetwork() {
1072         enforceAccessPermission();
1073         return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
1074     }
1075 
1076     @Override
getActiveNetworkForUid(int uid, boolean ignoreBlocked)1077     public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
1078         enforceConnectivityInternalPermission();
1079         return getActiveNetworkForUidInternal(uid, ignoreBlocked);
1080     }
1081 
getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked)1082     private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
1083         final int user = UserHandle.getUserId(uid);
1084         int vpnNetId = NETID_UNSET;
1085         synchronized (mVpns) {
1086             final Vpn vpn = mVpns.get(user);
1087             if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
1088         }
1089         NetworkAgentInfo nai;
1090         if (vpnNetId != NETID_UNSET) {
1091             synchronized (mNetworkForNetId) {
1092                 nai = mNetworkForNetId.get(vpnNetId);
1093             }
1094             if (nai != null) return nai.network;
1095         }
1096         nai = getDefaultNetwork();
1097         if (nai != null
1098                 && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) {
1099             nai = null;
1100         }
1101         return nai != null ? nai.network : null;
1102     }
1103 
1104     // Public because it's used by mLockdownTracker.
getActiveNetworkInfoUnfiltered()1105     public NetworkInfo getActiveNetworkInfoUnfiltered() {
1106         enforceAccessPermission();
1107         final int uid = Binder.getCallingUid();
1108         NetworkState state = getUnfilteredActiveNetworkState(uid);
1109         return state.networkInfo;
1110     }
1111 
1112     @Override
getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked)1113     public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
1114         enforceConnectivityInternalPermission();
1115         final NetworkState state = getUnfilteredActiveNetworkState(uid);
1116         filterNetworkStateForUid(state, uid, ignoreBlocked);
1117         return state.networkInfo;
1118     }
1119 
1120     @Override
getNetworkInfo(int networkType)1121     public NetworkInfo getNetworkInfo(int networkType) {
1122         enforceAccessPermission();
1123         final int uid = Binder.getCallingUid();
1124         if (getVpnUnderlyingNetworks(uid) != null) {
1125             // A VPN is active, so we may need to return one of its underlying networks. This
1126             // information is not available in LegacyTypeTracker, so we have to get it from
1127             // getUnfilteredActiveNetworkState.
1128             final NetworkState state = getUnfilteredActiveNetworkState(uid);
1129             if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
1130                 filterNetworkStateForUid(state, uid, false);
1131                 return state.networkInfo;
1132             }
1133         }
1134         final NetworkState state = getFilteredNetworkState(networkType, uid, false);
1135         return state.networkInfo;
1136     }
1137 
1138     @Override
getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked)1139     public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
1140         enforceAccessPermission();
1141         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1142         if (nai != null) {
1143             final NetworkState state = nai.getNetworkState();
1144             filterNetworkStateForUid(state, uid, ignoreBlocked);
1145             return state.networkInfo;
1146         } else {
1147             return null;
1148         }
1149     }
1150 
1151     @Override
getAllNetworkInfo()1152     public NetworkInfo[] getAllNetworkInfo() {
1153         enforceAccessPermission();
1154         final ArrayList<NetworkInfo> result = Lists.newArrayList();
1155         for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
1156                 networkType++) {
1157             NetworkInfo info = getNetworkInfo(networkType);
1158             if (info != null) {
1159                 result.add(info);
1160             }
1161         }
1162         return result.toArray(new NetworkInfo[result.size()]);
1163     }
1164 
1165     @Override
getNetworkForType(int networkType)1166     public Network getNetworkForType(int networkType) {
1167         enforceAccessPermission();
1168         final int uid = Binder.getCallingUid();
1169         NetworkState state = getFilteredNetworkState(networkType, uid, false);
1170         if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
1171             return state.network;
1172         }
1173         return null;
1174     }
1175 
1176     @Override
getAllNetworks()1177     public Network[] getAllNetworks() {
1178         enforceAccessPermission();
1179         synchronized (mNetworkForNetId) {
1180             final Network[] result = new Network[mNetworkForNetId.size()];
1181             for (int i = 0; i < mNetworkForNetId.size(); i++) {
1182                 result[i] = mNetworkForNetId.valueAt(i).network;
1183             }
1184             return result;
1185         }
1186     }
1187 
1188     @Override
getDefaultNetworkCapabilitiesForUser(int userId)1189     public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
1190         // The basic principle is: if an app's traffic could possibly go over a
1191         // network, without the app doing anything multinetwork-specific,
1192         // (hence, by "default"), then include that network's capabilities in
1193         // the array.
1194         //
1195         // In the normal case, app traffic only goes over the system's default
1196         // network connection, so that's the only network returned.
1197         //
1198         // With a VPN in force, some app traffic may go into the VPN, and thus
1199         // over whatever underlying networks the VPN specifies, while other app
1200         // traffic may go over the system default network (e.g.: a split-tunnel
1201         // VPN, or an app disallowed by the VPN), so the set of networks
1202         // returned includes the VPN's underlying networks and the system
1203         // default.
1204         enforceAccessPermission();
1205 
1206         HashMap<Network, NetworkCapabilities> result = new HashMap<Network, NetworkCapabilities>();
1207 
1208         NetworkAgentInfo nai = getDefaultNetwork();
1209         NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
1210         if (nc != null) {
1211             result.put(nai.network, nc);
1212         }
1213 
1214         if (!mLockdownEnabled) {
1215             synchronized (mVpns) {
1216                 Vpn vpn = mVpns.get(userId);
1217                 if (vpn != null) {
1218                     Network[] networks = vpn.getUnderlyingNetworks();
1219                     if (networks != null) {
1220                         for (Network network : networks) {
1221                             nai = getNetworkAgentInfoForNetwork(network);
1222                             nc = getNetworkCapabilitiesInternal(nai);
1223                             if (nc != null) {
1224                                 result.put(network, nc);
1225                             }
1226                         }
1227                     }
1228                 }
1229             }
1230         }
1231 
1232         NetworkCapabilities[] out = new NetworkCapabilities[result.size()];
1233         out = result.values().toArray(out);
1234         return out;
1235     }
1236 
1237     @Override
isNetworkSupported(int networkType)1238     public boolean isNetworkSupported(int networkType) {
1239         enforceAccessPermission();
1240         return mLegacyTypeTracker.isTypeSupported(networkType);
1241     }
1242 
1243     /**
1244      * Return LinkProperties for the active (i.e., connected) default
1245      * network interface.  It is assumed that at most one default network
1246      * is active at a time. If more than one is active, it is indeterminate
1247      * which will be returned.
1248      * @return the ip properties for the active network, or {@code null} if
1249      * none is active
1250      */
1251     @Override
getActiveLinkProperties()1252     public LinkProperties getActiveLinkProperties() {
1253         enforceAccessPermission();
1254         final int uid = Binder.getCallingUid();
1255         NetworkState state = getUnfilteredActiveNetworkState(uid);
1256         return state.linkProperties;
1257     }
1258 
1259     @Override
getLinkPropertiesForType(int networkType)1260     public LinkProperties getLinkPropertiesForType(int networkType) {
1261         enforceAccessPermission();
1262         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1263         if (nai != null) {
1264             synchronized (nai) {
1265                 return new LinkProperties(nai.linkProperties);
1266             }
1267         }
1268         return null;
1269     }
1270 
1271     // TODO - this should be ALL networks
1272     @Override
getLinkProperties(Network network)1273     public LinkProperties getLinkProperties(Network network) {
1274         enforceAccessPermission();
1275         return getLinkProperties(getNetworkAgentInfoForNetwork(network));
1276     }
1277 
getLinkProperties(NetworkAgentInfo nai)1278     private LinkProperties getLinkProperties(NetworkAgentInfo nai) {
1279         if (nai == null) {
1280             return null;
1281         }
1282         synchronized (nai) {
1283             return new LinkProperties(nai.linkProperties);
1284         }
1285     }
1286 
getNetworkCapabilitiesInternal(NetworkAgentInfo nai)1287     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
1288         if (nai != null) {
1289             synchronized (nai) {
1290                 if (nai.networkCapabilities != null) {
1291                     return new NetworkCapabilities(nai.networkCapabilities);
1292                 }
1293             }
1294         }
1295         return null;
1296     }
1297 
1298     @Override
getNetworkCapabilities(Network network)1299     public NetworkCapabilities getNetworkCapabilities(Network network) {
1300         enforceAccessPermission();
1301         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
1302     }
1303 
1304     @Override
getAllNetworkState()1305     public NetworkState[] getAllNetworkState() {
1306         // Require internal since we're handing out IMSI details
1307         enforceConnectivityInternalPermission();
1308 
1309         final ArrayList<NetworkState> result = Lists.newArrayList();
1310         for (Network network : getAllNetworks()) {
1311             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1312             if (nai != null) {
1313                 result.add(nai.getNetworkState());
1314             }
1315         }
1316         return result.toArray(new NetworkState[result.size()]);
1317     }
1318 
1319     @Override
getActiveNetworkQuotaInfo()1320     public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
1321         enforceAccessPermission();
1322         final int uid = Binder.getCallingUid();
1323         final long token = Binder.clearCallingIdentity();
1324         try {
1325             final NetworkState state = getUnfilteredActiveNetworkState(uid);
1326             if (state.networkInfo != null) {
1327                 try {
1328                     return mPolicyManager.getNetworkQuotaInfo(state);
1329                 } catch (RemoteException e) {
1330                 }
1331             }
1332             return null;
1333         } finally {
1334             Binder.restoreCallingIdentity(token);
1335         }
1336     }
1337 
1338     @Override
isActiveNetworkMetered()1339     public boolean isActiveNetworkMetered() {
1340         enforceAccessPermission();
1341 
1342         final NetworkInfo info = getActiveNetworkInfo();
1343         return (info != null) ? info.isMetered() : false;
1344     }
1345 
1346     private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
1347         @Override
1348         public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
1349             int deviceType = Integer.parseInt(label);
1350             sendDataActivityBroadcast(deviceType, active, tsNanos);
1351         }
1352     };
1353 
1354     /**
1355      * Ensure that a network route exists to deliver traffic to the specified
1356      * host via the specified network interface.
1357      * @param networkType the type of the network over which traffic to the
1358      * specified host is to be routed
1359      * @param hostAddress the IP address of the host to which the route is
1360      * desired
1361      * @return {@code true} on success, {@code false} on failure
1362      */
1363     @Override
requestRouteToHostAddress(int networkType, byte[] hostAddress)1364     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
1365         enforceChangePermission();
1366         if (mProtectedNetworks.contains(networkType)) {
1367             enforceConnectivityInternalPermission();
1368         }
1369 
1370         InetAddress addr;
1371         try {
1372             addr = InetAddress.getByAddress(hostAddress);
1373         } catch (UnknownHostException e) {
1374             if (DBG) log("requestRouteToHostAddress got " + e.toString());
1375             return false;
1376         }
1377 
1378         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
1379             if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
1380             return false;
1381         }
1382 
1383         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1384         if (nai == null) {
1385             if (mLegacyTypeTracker.isTypeSupported(networkType) == false) {
1386                 if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType);
1387             } else {
1388                 if (DBG) log("requestRouteToHostAddress on down network: " + networkType);
1389             }
1390             return false;
1391         }
1392 
1393         DetailedState netState;
1394         synchronized (nai) {
1395             netState = nai.networkInfo.getDetailedState();
1396         }
1397 
1398         if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) {
1399             if (VDBG) {
1400                 log("requestRouteToHostAddress on down network "
1401                         + "(" + networkType + ") - dropped"
1402                         + " netState=" + netState);
1403             }
1404             return false;
1405         }
1406 
1407         final int uid = Binder.getCallingUid();
1408         final long token = Binder.clearCallingIdentity();
1409         try {
1410             LinkProperties lp;
1411             int netId;
1412             synchronized (nai) {
1413                 lp = nai.linkProperties;
1414                 netId = nai.network.netId;
1415             }
1416             boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
1417             if (DBG) log("requestRouteToHostAddress ok=" + ok);
1418             return ok;
1419         } finally {
1420             Binder.restoreCallingIdentity(token);
1421         }
1422     }
1423 
addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid)1424     private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) {
1425         RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
1426         if (bestRoute == null) {
1427             bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
1428         } else {
1429             String iface = bestRoute.getInterface();
1430             if (bestRoute.getGateway().equals(addr)) {
1431                 // if there is no better route, add the implied hostroute for our gateway
1432                 bestRoute = RouteInfo.makeHostRoute(addr, iface);
1433             } else {
1434                 // if we will connect to this through another route, add a direct route
1435                 // to it's gateway
1436                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
1437             }
1438         }
1439         if (DBG) log("Adding legacy route " + bestRoute +
1440                 " for UID/PID " + uid + "/" + Binder.getCallingPid());
1441         try {
1442             mNetd.addLegacyRouteForNetId(netId, bestRoute, uid);
1443         } catch (Exception e) {
1444             // never crash - catch them all
1445             if (DBG) loge("Exception trying to add a route: " + e);
1446             return false;
1447         }
1448         return true;
1449     }
1450 
1451     private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
1452         @Override
1453         public void onUidRulesChanged(int uid, int uidRules) {
1454             // TODO: notify UID when it has requested targeted updates
1455         }
1456         @Override
1457         public void onMeteredIfacesChanged(String[] meteredIfaces) {
1458         }
1459         @Override
1460         public void onRestrictBackgroundChanged(boolean restrictBackground) {
1461             // TODO: relocate this specific callback in Tethering.
1462             if (restrictBackground) {
1463                 log("onRestrictBackgroundChanged(true): disabling tethering");
1464                 mTethering.untetherAll();
1465             }
1466         }
1467         @Override
1468         public void onUidPoliciesChanged(int uid, int uidPolicies) {
1469         }
1470     };
1471 
1472     /**
1473      * Require that the caller is either in the same user or has appropriate permission to interact
1474      * across users.
1475      *
1476      * @param userId Target user for whatever operation the current IPC is supposed to perform.
1477      */
enforceCrossUserPermission(int userId)1478     private void enforceCrossUserPermission(int userId) {
1479         if (userId == UserHandle.getCallingUserId()) {
1480             // Not a cross-user call.
1481             return;
1482         }
1483         mContext.enforceCallingOrSelfPermission(
1484                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1485                 "ConnectivityService");
1486     }
1487 
enforceInternetPermission()1488     private void enforceInternetPermission() {
1489         mContext.enforceCallingOrSelfPermission(
1490                 android.Manifest.permission.INTERNET,
1491                 "ConnectivityService");
1492     }
1493 
enforceAccessPermission()1494     private void enforceAccessPermission() {
1495         mContext.enforceCallingOrSelfPermission(
1496                 android.Manifest.permission.ACCESS_NETWORK_STATE,
1497                 "ConnectivityService");
1498     }
1499 
enforceChangePermission()1500     private void enforceChangePermission() {
1501         ConnectivityManager.enforceChangePermission(mContext);
1502     }
1503 
enforceTetherAccessPermission()1504     private void enforceTetherAccessPermission() {
1505         mContext.enforceCallingOrSelfPermission(
1506                 android.Manifest.permission.ACCESS_NETWORK_STATE,
1507                 "ConnectivityService");
1508     }
1509 
enforceConnectivityInternalPermission()1510     private void enforceConnectivityInternalPermission() {
1511         mContext.enforceCallingOrSelfPermission(
1512                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1513                 "ConnectivityService");
1514     }
1515 
enforceConnectivityRestrictedNetworksPermission()1516     private void enforceConnectivityRestrictedNetworksPermission() {
1517         try {
1518             mContext.enforceCallingOrSelfPermission(
1519                     android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS,
1520                     "ConnectivityService");
1521             return;
1522         } catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ }
1523         enforceConnectivityInternalPermission();
1524     }
1525 
enforceKeepalivePermission()1526     private void enforceKeepalivePermission() {
1527         mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService");
1528     }
1529 
1530     // Public because it's used by mLockdownTracker.
sendConnectedBroadcast(NetworkInfo info)1531     public void sendConnectedBroadcast(NetworkInfo info) {
1532         enforceConnectivityInternalPermission();
1533         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
1534     }
1535 
sendInetConditionBroadcast(NetworkInfo info)1536     private void sendInetConditionBroadcast(NetworkInfo info) {
1537         sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1538     }
1539 
makeGeneralIntent(NetworkInfo info, String bcastType)1540     private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
1541         if (mLockdownTracker != null) {
1542             info = new NetworkInfo(info);
1543             mLockdownTracker.augmentNetworkInfo(info);
1544         }
1545 
1546         Intent intent = new Intent(bcastType);
1547         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
1548         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
1549         if (info.isFailover()) {
1550             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1551             info.setFailover(false);
1552         }
1553         if (info.getReason() != null) {
1554             intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1555         }
1556         if (info.getExtraInfo() != null) {
1557             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1558                     info.getExtraInfo());
1559         }
1560         intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
1561         return intent;
1562     }
1563 
sendGeneralBroadcast(NetworkInfo info, String bcastType)1564     private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1565         sendStickyBroadcast(makeGeneralIntent(info, bcastType));
1566     }
1567 
sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos)1568     private void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) {
1569         Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
1570         intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
1571         intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
1572         intent.putExtra(ConnectivityManager.EXTRA_REALTIME_NS, tsNanos);
1573         final long ident = Binder.clearCallingIdentity();
1574         try {
1575             mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
1576                     RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null);
1577         } finally {
1578             Binder.restoreCallingIdentity(ident);
1579         }
1580     }
1581 
sendStickyBroadcast(Intent intent)1582     private void sendStickyBroadcast(Intent intent) {
1583         synchronized(this) {
1584             if (!mSystemReady) {
1585                 mInitialBroadcast = new Intent(intent);
1586             }
1587             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1588             if (VDBG) {
1589                 log("sendStickyBroadcast: action=" + intent.getAction());
1590             }
1591 
1592             Bundle options = null;
1593             final long ident = Binder.clearCallingIdentity();
1594             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
1595                 final NetworkInfo ni = intent.getParcelableExtra(
1596                         ConnectivityManager.EXTRA_NETWORK_INFO);
1597                 if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
1598                     intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
1599                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1600                 } else {
1601                     BroadcastOptions opts = BroadcastOptions.makeBasic();
1602                     opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
1603                     options = opts.toBundle();
1604                 }
1605                 final IBatteryStats bs = BatteryStatsService.getService();
1606                 try {
1607                     bs.noteConnectivityChanged(intent.getIntExtra(
1608                             ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE),
1609                             ni != null ? ni.getState().toString() : "?");
1610                 } catch (RemoteException e) {
1611                 }
1612             }
1613             try {
1614                 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
1615             } finally {
1616                 Binder.restoreCallingIdentity(ident);
1617             }
1618         }
1619     }
1620 
systemReady()1621     void systemReady() {
1622         loadGlobalProxy();
1623 
1624         synchronized(this) {
1625             mSystemReady = true;
1626             if (mInitialBroadcast != null) {
1627                 mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
1628                 mInitialBroadcast = null;
1629             }
1630         }
1631         // load the global proxy at startup
1632         mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
1633 
1634         // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait
1635         // for user to unlock device too.
1636         updateLockdownVpn();
1637 
1638         // Configure whether mobile data is always on.
1639         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON));
1640 
1641         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
1642 
1643         mPermissionMonitor.startMonitoring();
1644     }
1645 
1646     /**
1647      * Setup data activity tracking for the given network.
1648      *
1649      * Every {@code setupDataActivityTracking} should be paired with a
1650      * {@link #removeDataActivityTracking} for cleanup.
1651      */
setupDataActivityTracking(NetworkAgentInfo networkAgent)1652     private void setupDataActivityTracking(NetworkAgentInfo networkAgent) {
1653         final String iface = networkAgent.linkProperties.getInterfaceName();
1654 
1655         final int timeout;
1656         int type = ConnectivityManager.TYPE_NONE;
1657 
1658         if (networkAgent.networkCapabilities.hasTransport(
1659                 NetworkCapabilities.TRANSPORT_CELLULAR)) {
1660             timeout = Settings.Global.getInt(mContext.getContentResolver(),
1661                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
1662                                              10);
1663             type = ConnectivityManager.TYPE_MOBILE;
1664         } else if (networkAgent.networkCapabilities.hasTransport(
1665                 NetworkCapabilities.TRANSPORT_WIFI)) {
1666             timeout = Settings.Global.getInt(mContext.getContentResolver(),
1667                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
1668                                              15);
1669             type = ConnectivityManager.TYPE_WIFI;
1670         } else {
1671             // do not track any other networks
1672             timeout = 0;
1673         }
1674 
1675         if (timeout > 0 && iface != null && type != ConnectivityManager.TYPE_NONE) {
1676             try {
1677                 mNetd.addIdleTimer(iface, timeout, type);
1678             } catch (Exception e) {
1679                 // You shall not crash!
1680                 loge("Exception in setupDataActivityTracking " + e);
1681             }
1682         }
1683     }
1684 
1685     /**
1686      * Remove data activity tracking when network disconnects.
1687      */
removeDataActivityTracking(NetworkAgentInfo networkAgent)1688     private void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
1689         final String iface = networkAgent.linkProperties.getInterfaceName();
1690         final NetworkCapabilities caps = networkAgent.networkCapabilities;
1691 
1692         if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
1693                               caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
1694             try {
1695                 // the call fails silently if no idletimer setup for this interface
1696                 mNetd.removeIdleTimer(iface);
1697             } catch (Exception e) {
1698                 loge("Exception in removeDataActivityTracking " + e);
1699             }
1700         }
1701     }
1702 
1703     /**
1704      * Reads the network specific MTU size from reources.
1705      * and set it on it's iface.
1706      */
updateMtu(LinkProperties newLp, LinkProperties oldLp)1707     private void updateMtu(LinkProperties newLp, LinkProperties oldLp) {
1708         final String iface = newLp.getInterfaceName();
1709         final int mtu = newLp.getMtu();
1710         if (oldLp == null && mtu == 0) {
1711             // Silently ignore unset MTU value.
1712             return;
1713         }
1714         if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
1715             if (VDBG) log("identical MTU - not setting");
1716             return;
1717         }
1718         if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) {
1719             if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
1720             return;
1721         }
1722 
1723         // Cannot set MTU without interface name
1724         if (TextUtils.isEmpty(iface)) {
1725             loge("Setting MTU size with null iface.");
1726             return;
1727         }
1728 
1729         try {
1730             if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
1731             mNetd.setMtu(iface, mtu);
1732         } catch (Exception e) {
1733             Slog.e(TAG, "exception in setMtu()" + e);
1734         }
1735     }
1736 
1737     private static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
1738     private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd";
1739 
1740     // Overridden for testing purposes to avoid writing to SystemProperties.
1741     @VisibleForTesting
getSystemProperties()1742     protected MockableSystemProperties getSystemProperties() {
1743         return new MockableSystemProperties();
1744     }
1745 
updateTcpBufferSizes(NetworkAgentInfo nai)1746     private void updateTcpBufferSizes(NetworkAgentInfo nai) {
1747         if (isDefaultNetwork(nai) == false) {
1748             return;
1749         }
1750 
1751         String tcpBufferSizes = nai.linkProperties.getTcpBufferSizes();
1752         String[] values = null;
1753         if (tcpBufferSizes != null) {
1754             values = tcpBufferSizes.split(",");
1755         }
1756 
1757         if (values == null || values.length != 6) {
1758             if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
1759             tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES;
1760             values = tcpBufferSizes.split(",");
1761         }
1762 
1763         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
1764 
1765         try {
1766             if (VDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
1767 
1768             final String prefix = "/sys/kernel/ipv4/tcp_";
1769             FileUtils.stringToFile(prefix + "rmem_min", values[0]);
1770             FileUtils.stringToFile(prefix + "rmem_def", values[1]);
1771             FileUtils.stringToFile(prefix + "rmem_max", values[2]);
1772             FileUtils.stringToFile(prefix + "wmem_min", values[3]);
1773             FileUtils.stringToFile(prefix + "wmem_def", values[4]);
1774             FileUtils.stringToFile(prefix + "wmem_max", values[5]);
1775             mCurrentTcpBufferSizes = tcpBufferSizes;
1776         } catch (IOException e) {
1777             loge("Can't set TCP buffer sizes:" + e);
1778         }
1779 
1780         Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
1781             Settings.Global.TCP_DEFAULT_INIT_RWND,
1782                     mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
1783         final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
1784         if (rwndValue != 0) {
1785             mSystemProperties.set(sysctlKey, rwndValue.toString());
1786         }
1787     }
1788 
flushVmDnsCache()1789     private void flushVmDnsCache() {
1790         /*
1791          * Tell the VMs to toss their DNS caches
1792          */
1793         Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
1794         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
1795         /*
1796          * Connectivity events can happen before boot has completed ...
1797          */
1798         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1799         final long ident = Binder.clearCallingIdentity();
1800         try {
1801             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1802         } finally {
1803             Binder.restoreCallingIdentity(ident);
1804         }
1805     }
1806 
1807     @Override
getRestoreDefaultNetworkDelay(int networkType)1808     public int getRestoreDefaultNetworkDelay(int networkType) {
1809         String restoreDefaultNetworkDelayStr = mSystemProperties.get(
1810                 NETWORK_RESTORE_DELAY_PROP_NAME);
1811         if(restoreDefaultNetworkDelayStr != null &&
1812                 restoreDefaultNetworkDelayStr.length() != 0) {
1813             try {
1814                 return Integer.parseInt(restoreDefaultNetworkDelayStr);
1815             } catch (NumberFormatException e) {
1816             }
1817         }
1818         // if the system property isn't set, use the value for the apn type
1819         int ret = RESTORE_DEFAULT_NETWORK_DELAY;
1820 
1821         if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
1822                 (mNetConfigs[networkType] != null)) {
1823             ret = mNetConfigs[networkType].restoreTime;
1824         }
1825         return ret;
1826     }
1827 
argsContain(String[] args, String target)1828     private boolean argsContain(String[] args, String target) {
1829         for (String arg : args) {
1830             if (arg.equals(target)) return true;
1831         }
1832         return false;
1833     }
1834 
dumpNetworkDiagnostics(IndentingPrintWriter pw)1835     private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
1836         final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
1837         final long DIAG_TIME_MS = 5000;
1838         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
1839             // Start gathering diagnostic information.
1840             netDiags.add(new NetworkDiagnostics(
1841                     nai.network,
1842                     new LinkProperties(nai.linkProperties),  // Must be a copy.
1843                     DIAG_TIME_MS));
1844         }
1845 
1846         for (NetworkDiagnostics netDiag : netDiags) {
1847             pw.println();
1848             netDiag.waitForMeasurements();
1849             netDiag.dump(pw);
1850         }
1851     }
1852 
1853     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)1854     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1855         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
1856         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1857 
1858         if (argsContain(args, DIAG_ARG)) {
1859             dumpNetworkDiagnostics(pw);
1860             return;
1861         }
1862 
1863         pw.print("NetworkFactories for:");
1864         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
1865             pw.print(" " + nfi.name);
1866         }
1867         pw.println();
1868         pw.println();
1869 
1870         final NetworkAgentInfo defaultNai = getDefaultNetwork();
1871         pw.print("Active default network: ");
1872         if (defaultNai == null) {
1873             pw.println("none");
1874         } else {
1875             pw.println(defaultNai.network.netId);
1876         }
1877         pw.println();
1878 
1879         pw.println("Current Networks:");
1880         pw.increaseIndent();
1881         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
1882             pw.println(nai.toString());
1883             pw.increaseIndent();
1884             pw.println(String.format(
1885                     "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
1886                     nai.numForegroundNetworkRequests(),
1887                     nai.numNetworkRequests() - nai.numRequestNetworkRequests(),
1888                     nai.numBackgroundNetworkRequests(),
1889                     nai.numNetworkRequests()));
1890             pw.increaseIndent();
1891             for (int i = 0; i < nai.numNetworkRequests(); i++) {
1892                 pw.println(nai.requestAt(i).toString());
1893             }
1894             pw.decreaseIndent();
1895             pw.println("Lingered:");
1896             pw.increaseIndent();
1897             nai.dumpLingerTimers(pw);
1898             pw.decreaseIndent();
1899             pw.decreaseIndent();
1900         }
1901         pw.decreaseIndent();
1902         pw.println();
1903 
1904         pw.println("Network Requests:");
1905         pw.increaseIndent();
1906         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
1907             pw.println(nri.toString());
1908         }
1909         pw.println();
1910         pw.decreaseIndent();
1911 
1912         mLegacyTypeTracker.dump(pw);
1913 
1914         synchronized (this) {
1915             pw.print("mNetTransitionWakeLock: currently " +
1916                     (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held");
1917             if (!TextUtils.isEmpty(mNetTransitionWakeLockCausedBy)) {
1918                 pw.println(", last requested for " + mNetTransitionWakeLockCausedBy);
1919             } else {
1920                 pw.println(", last requested never");
1921             }
1922         }
1923 
1924         pw.println();
1925         mTethering.dump(fd, pw, args);
1926 
1927         pw.println();
1928         mKeepaliveTracker.dump(pw);
1929 
1930         pw.println();
1931         dumpAvoidBadWifiSettings(pw);
1932 
1933         pw.println();
1934         if (mInetLog != null && mInetLog.size() > 0) {
1935             pw.println();
1936             pw.println("Inet condition reports:");
1937             pw.increaseIndent();
1938             for(int i = 0; i < mInetLog.size(); i++) {
1939                 pw.println(mInetLog.get(i));
1940             }
1941             pw.decreaseIndent();
1942         }
1943 
1944         if (argsContain(args, SHORT_ARG) == false) {
1945             pw.println();
1946             synchronized (mValidationLogs) {
1947                 pw.println("mValidationLogs (most recent first):");
1948                 for (ValidationLog p : mValidationLogs) {
1949                     pw.println(p.mNetwork + " - " + p.mNetworkExtraInfo);
1950                     pw.increaseIndent();
1951                     p.mLog.dump(fd, pw, args);
1952                     pw.decreaseIndent();
1953                 }
1954             }
1955 
1956             pw.println();
1957             pw.println("mNetworkRequestInfoLogs (most recent first):");
1958             pw.increaseIndent();
1959             mNetworkRequestInfoLogs.reverseDump(fd, pw, args);
1960             pw.decreaseIndent();
1961 
1962             pw.println();
1963             pw.println("mNetworkInfoBlockingLogs (most recent first):");
1964             pw.increaseIndent();
1965             mNetworkInfoBlockingLogs.reverseDump(fd, pw, args);
1966             pw.decreaseIndent();
1967         }
1968     }
1969 
isLiveNetworkAgent(NetworkAgentInfo nai, int what)1970     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
1971         if (nai.network == null) return false;
1972         final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
1973         if (officialNai != null && officialNai.equals(nai)) return true;
1974         if (officialNai != null || VDBG) {
1975             final String msg = sMagicDecoderRing.get(what, Integer.toString(what));
1976             loge(msg + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
1977                 " - " + nai);
1978         }
1979         return false;
1980     }
1981 
1982     // must be stateless - things change under us.
1983     private class NetworkStateTrackerHandler extends Handler {
NetworkStateTrackerHandler(Looper looper)1984         public NetworkStateTrackerHandler(Looper looper) {
1985             super(looper);
1986         }
1987 
maybeHandleAsyncChannelMessage(Message msg)1988         private boolean maybeHandleAsyncChannelMessage(Message msg) {
1989             switch (msg.what) {
1990                 default:
1991                     return false;
1992                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
1993                     handleAsyncChannelHalfConnect(msg);
1994                     break;
1995                 }
1996                 case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
1997                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1998                     if (nai != null) nai.asyncChannel.disconnect();
1999                     break;
2000                 }
2001                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
2002                     handleAsyncChannelDisconnected(msg);
2003                     break;
2004                 }
2005             }
2006             return true;
2007         }
2008 
maybeHandleNetworkAgentMessage(Message msg)2009         private void maybeHandleNetworkAgentMessage(Message msg) {
2010             NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2011             if (nai == null) {
2012                 if (VDBG) {
2013                     final String what = sMagicDecoderRing.get(msg.what, Integer.toString(msg.what));
2014                     log(String.format("%s from unknown NetworkAgent", what));
2015                 }
2016                 return;
2017             }
2018 
2019             switch (msg.what) {
2020                 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
2021                     final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
2022                     if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
2023                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) ||
2024                             networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
2025                         Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
2026                     }
2027                     updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
2028                     break;
2029                 }
2030                 case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
2031                     if (VDBG) {
2032                         log("Update of LinkProperties for " + nai.name() +
2033                                 "; created=" + nai.created +
2034                                 "; everConnected=" + nai.everConnected);
2035                     }
2036                     LinkProperties oldLp = nai.linkProperties;
2037                     synchronized (nai) {
2038                         nai.linkProperties = (LinkProperties)msg.obj;
2039                     }
2040                     if (nai.everConnected) updateLinkProperties(nai, oldLp);
2041                     break;
2042                 }
2043                 case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
2044                     NetworkInfo info = (NetworkInfo) msg.obj;
2045                     updateNetworkInfo(nai, info);
2046                     break;
2047                 }
2048                 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
2049                     Integer score = (Integer) msg.obj;
2050                     if (score != null) updateNetworkScore(nai, score.intValue());
2051                     break;
2052                 }
2053                 case NetworkAgent.EVENT_UID_RANGES_ADDED: {
2054                     try {
2055                         mNetd.addVpnUidRanges(nai.network.netId, (UidRange[])msg.obj);
2056                     } catch (Exception e) {
2057                         // Never crash!
2058                         loge("Exception in addVpnUidRanges: " + e);
2059                     }
2060                     break;
2061                 }
2062                 case NetworkAgent.EVENT_UID_RANGES_REMOVED: {
2063                     try {
2064                         mNetd.removeVpnUidRanges(nai.network.netId, (UidRange[])msg.obj);
2065                     } catch (Exception e) {
2066                         // Never crash!
2067                         loge("Exception in removeVpnUidRanges: " + e);
2068                     }
2069                     break;
2070                 }
2071                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
2072                     if (nai.everConnected && !nai.networkMisc.explicitlySelected) {
2073                         loge("ERROR: already-connected network explicitly selected.");
2074                     }
2075                     nai.networkMisc.explicitlySelected = true;
2076                     nai.networkMisc.acceptUnvalidated = (boolean) msg.obj;
2077                     break;
2078                 }
2079                 case NetworkAgent.EVENT_PACKET_KEEPALIVE: {
2080                     mKeepaliveTracker.handleEventPacketKeepalive(nai, msg);
2081                     break;
2082                 }
2083             }
2084         }
2085 
maybeHandleNetworkMonitorMessage(Message msg)2086         private boolean maybeHandleNetworkMonitorMessage(Message msg) {
2087             switch (msg.what) {
2088                 default:
2089                     return false;
2090                 case NetworkMonitor.EVENT_NETWORK_TESTED: {
2091                     final NetworkAgentInfo nai;
2092                     synchronized (mNetworkForNetId) {
2093                         nai = mNetworkForNetId.get(msg.arg2);
2094                     }
2095                     if (nai != null) {
2096                         final boolean valid =
2097                                 (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
2098                         final boolean wasValidated = nai.lastValidated;
2099                         if (DBG) log(nai.name() + " validation " + (valid ? "passed" : "failed") +
2100                                 (msg.obj == null ? "" : " with redirect to " + (String)msg.obj));
2101                         if (valid != nai.lastValidated) {
2102                             final int oldScore = nai.getCurrentScore();
2103                             nai.lastValidated = valid;
2104                             nai.everValidated |= valid;
2105                             updateCapabilities(oldScore, nai, nai.networkCapabilities);
2106                             // If score has changed, rebroadcast to NetworkFactories. b/17726566
2107                             if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
2108                         }
2109                         updateInetCondition(nai);
2110                         // Let the NetworkAgent know the state of its network
2111                         Bundle redirectUrlBundle = new Bundle();
2112                         redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, (String)msg.obj);
2113                         nai.asyncChannel.sendMessage(
2114                                 NetworkAgent.CMD_REPORT_NETWORK_STATUS,
2115                                 (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
2116                                 0, redirectUrlBundle);
2117                          if (wasValidated && !nai.lastValidated) {
2118                              handleNetworkUnvalidated(nai);
2119                          }
2120                     }
2121                     break;
2122                 }
2123                 case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
2124                     final int netId = msg.arg2;
2125                     final boolean visible = (msg.arg1 != 0);
2126                     final NetworkAgentInfo nai;
2127                     synchronized (mNetworkForNetId) {
2128                         nai = mNetworkForNetId.get(netId);
2129                     }
2130                     // If captive portal status has changed, update capabilities or disconnect.
2131                     if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
2132                         final int oldScore = nai.getCurrentScore();
2133                         nai.lastCaptivePortalDetected = visible;
2134                         nai.everCaptivePortalDetected |= visible;
2135                         if (nai.lastCaptivePortalDetected &&
2136                             Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
2137                             if (DBG) log("Avoiding captive portal network: " + nai.name());
2138                             nai.asyncChannel.sendMessage(
2139                                     NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
2140                             teardownUnneededNetwork(nai);
2141                             break;
2142                         }
2143                         updateCapabilities(oldScore, nai, nai.networkCapabilities);
2144                     }
2145                     if (!visible) {
2146                         mNotifier.clearNotification(netId);
2147                     } else {
2148                         if (nai == null) {
2149                             loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
2150                             break;
2151                         }
2152                         if (!nai.networkMisc.provisioningNotificationDisabled) {
2153                             mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null,
2154                                     (PendingIntent) msg.obj, nai.networkMisc.explicitlySelected);
2155                         }
2156                     }
2157                     break;
2158                 }
2159             }
2160             return true;
2161         }
2162 
getCaptivePortalMode()2163         private int getCaptivePortalMode() {
2164             return Settings.Global.getInt(mContext.getContentResolver(),
2165                     Settings.Global.CAPTIVE_PORTAL_MODE,
2166                     Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
2167         }
2168 
maybeHandleNetworkAgentInfoMessage(Message msg)2169         private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
2170             switch (msg.what) {
2171                 default:
2172                     return false;
2173                 case NetworkAgentInfo.EVENT_NETWORK_LINGER_COMPLETE: {
2174                     NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
2175                     if (nai != null && isLiveNetworkAgent(nai, msg.what)) {
2176                         handleLingerComplete(nai);
2177                     }
2178                     break;
2179                 }
2180             }
2181             return true;
2182         }
2183 
2184         @Override
handleMessage(Message msg)2185         public void handleMessage(Message msg) {
2186             if (!maybeHandleAsyncChannelMessage(msg) &&
2187                     !maybeHandleNetworkMonitorMessage(msg) &&
2188                     !maybeHandleNetworkAgentInfoMessage(msg)) {
2189                 maybeHandleNetworkAgentMessage(msg);
2190             }
2191         }
2192     }
2193 
updateLingerState(NetworkAgentInfo nai, long now)2194     private void updateLingerState(NetworkAgentInfo nai, long now) {
2195         // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm.
2196         // 2. If the network was lingering and there are now requests, unlinger it.
2197         // 3. If this network is unneeded (which implies it is not lingering), and there is at least
2198         //    one lingered request, start lingering.
2199         nai.updateLingerTimer();
2200         if (nai.isLingering() && nai.numForegroundNetworkRequests() > 0) {
2201             if (DBG) log("Unlingering " + nai.name());
2202             nai.unlinger();
2203             logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER);
2204         } else if (unneeded(nai, UnneededFor.LINGER) && nai.getLingerExpiry() > 0) {
2205             int lingerTime = (int) (nai.getLingerExpiry() - now);
2206             if (DBG) log("Lingering " + nai.name() + " for " + lingerTime + "ms");
2207             nai.linger();
2208             logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER);
2209             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime);
2210         }
2211     }
2212 
handleAsyncChannelHalfConnect(Message msg)2213     private void handleAsyncChannelHalfConnect(Message msg) {
2214         AsyncChannel ac = (AsyncChannel) msg.obj;
2215         if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
2216             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
2217                 if (VDBG) log("NetworkFactory connected");
2218                 // A network factory has connected.  Send it all current NetworkRequests.
2219                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
2220                     if (nri.request.isListen()) continue;
2221                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
2222                     ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
2223                             (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
2224                 }
2225             } else {
2226                 loge("Error connecting NetworkFactory");
2227                 mNetworkFactoryInfos.remove(msg.obj);
2228             }
2229         } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
2230             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
2231                 if (VDBG) log("NetworkAgent connected");
2232                 // A network agent has requested a connection.  Establish the connection.
2233                 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
2234                         sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
2235             } else {
2236                 loge("Error connecting NetworkAgent");
2237                 NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
2238                 if (nai != null) {
2239                     final boolean wasDefault = isDefaultNetwork(nai);
2240                     synchronized (mNetworkForNetId) {
2241                         mNetworkForNetId.remove(nai.network.netId);
2242                         mNetIdInUse.delete(nai.network.netId);
2243                     }
2244                     // Just in case.
2245                     mLegacyTypeTracker.remove(nai, wasDefault);
2246                 }
2247             }
2248         }
2249     }
2250 
handleAsyncChannelDisconnected(Message msg)2251     private void handleAsyncChannelDisconnected(Message msg) {
2252         NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2253         if (nai != null) {
2254             if (DBG) {
2255                 log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
2256             }
2257             // A network agent has disconnected.
2258             // TODO - if we move the logic to the network agent (have them disconnect
2259             // because they lost all their requests or because their score isn't good)
2260             // then they would disconnect organically, report their new state and then
2261             // disconnect the channel.
2262             if (nai.networkInfo.isConnected()) {
2263                 nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
2264                         null, null);
2265             }
2266             final boolean wasDefault = isDefaultNetwork(nai);
2267             if (wasDefault) {
2268                 mDefaultInetConditionPublished = 0;
2269                 // Log default network disconnection before required book-keeping.
2270                 // Let rematchAllNetworksAndRequests() below record a new default network event
2271                 // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
2272                 // whose timestamps tell how long it takes to recover a default network.
2273                 logDefaultNetworkEvent(null, nai);
2274             }
2275             notifyIfacesChangedForNetworkStats();
2276             // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
2277             // by other networks that are already connected. Perhaps that can be done by
2278             // sending all CALLBACK_LOST messages (for requests, not listens) at the end
2279             // of rematchAllNetworksAndRequests
2280             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
2281             mKeepaliveTracker.handleStopAllKeepalives(nai,
2282                     ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
2283             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
2284             mNetworkAgentInfos.remove(msg.replyTo);
2285             updateClat(null, nai.linkProperties, nai);
2286             synchronized (mNetworkForNetId) {
2287                 // Remove the NetworkAgent, but don't mark the netId as
2288                 // available until we've told netd to delete it below.
2289                 mNetworkForNetId.remove(nai.network.netId);
2290             }
2291             // Remove all previously satisfied requests.
2292             for (int i = 0; i < nai.numNetworkRequests(); i++) {
2293                 NetworkRequest request = nai.requestAt(i);
2294                 NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
2295                 if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
2296                     mNetworkForRequestId.remove(request.requestId);
2297                     sendUpdatedScoreToFactories(request, 0);
2298                 }
2299             }
2300             nai.clearLingerState();
2301             if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
2302                 removeDataActivityTracking(nai);
2303                 notifyLockdownVpn(nai);
2304                 requestNetworkTransitionWakelock(nai.name());
2305             }
2306             mLegacyTypeTracker.remove(nai, wasDefault);
2307             rematchAllNetworksAndRequests(null, 0);
2308             mLingerMonitor.noteDisconnect(nai);
2309             if (nai.created) {
2310                 // Tell netd to clean up the configuration for this network
2311                 // (routing rules, DNS, etc).
2312                 // This may be slow as it requires a lot of netd shelling out to ip and
2313                 // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
2314                 // after we've rematched networks with requests which should make a potential
2315                 // fallback network the default or requested a new network from the
2316                 // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
2317                 // long time.
2318                 try {
2319                     mNetd.removeNetwork(nai.network.netId);
2320                 } catch (Exception e) {
2321                     loge("Exception removing network: " + e);
2322                 }
2323             }
2324             synchronized (mNetworkForNetId) {
2325                 mNetIdInUse.delete(nai.network.netId);
2326             }
2327         } else {
2328             NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
2329             if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
2330         }
2331     }
2332 
2333     // If this method proves to be too slow then we can maintain a separate
2334     // pendingIntent => NetworkRequestInfo map.
2335     // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
findExistingNetworkRequestInfo(PendingIntent pendingIntent)2336     private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
2337         Intent intent = pendingIntent.getIntent();
2338         for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
2339             PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
2340             if (existingPendingIntent != null &&
2341                     existingPendingIntent.getIntent().filterEquals(intent)) {
2342                 return entry.getValue();
2343             }
2344         }
2345         return null;
2346     }
2347 
handleRegisterNetworkRequestWithIntent(Message msg)2348     private void handleRegisterNetworkRequestWithIntent(Message msg) {
2349         final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
2350 
2351         NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
2352         if (existingRequest != null) { // remove the existing request.
2353             if (DBG) log("Replacing " + existingRequest.request + " with "
2354                     + nri.request + " because their intents matched.");
2355             handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
2356         }
2357         handleRegisterNetworkRequest(nri);
2358     }
2359 
handleRegisterNetworkRequest(NetworkRequestInfo nri)2360     private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
2361         mNetworkRequests.put(nri.request, nri);
2362         mNetworkRequestInfoLogs.log("REGISTER " + nri);
2363         if (nri.request.isListen()) {
2364             for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
2365                 if (nri.request.networkCapabilities.hasSignalStrength() &&
2366                         network.satisfiesImmutableCapabilitiesOf(nri.request)) {
2367                     updateSignalStrengthThresholds(network, "REGISTER", nri.request);
2368                 }
2369             }
2370         }
2371         rematchAllNetworksAndRequests(null, 0);
2372         if (nri.request.isRequest() && mNetworkForRequestId.get(nri.request.requestId) == null) {
2373             sendUpdatedScoreToFactories(nri.request, 0);
2374         }
2375     }
2376 
handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent, int callingUid)2377     private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
2378             int callingUid) {
2379         NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
2380         if (nri != null) {
2381             handleReleaseNetworkRequest(nri.request, callingUid);
2382         }
2383     }
2384 
2385     // Determines whether the network is the best (or could become the best, if it validated), for
2386     // none of a particular type of NetworkRequests. The type of NetworkRequests considered depends
2387     // on the value of reason:
2388     //
2389     // - UnneededFor.TEARDOWN: non-listen NetworkRequests. If a network is unneeded for this reason,
2390     //   then it should be torn down.
2391     // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason,
2392     //   then it should be lingered.
unneeded(NetworkAgentInfo nai, UnneededFor reason)2393     private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
2394         final int numRequests;
2395         switch (reason) {
2396             case TEARDOWN:
2397                 numRequests = nai.numRequestNetworkRequests();
2398                 break;
2399             case LINGER:
2400                 numRequests = nai.numForegroundNetworkRequests();
2401                 break;
2402             default:
2403                 Slog.wtf(TAG, "Invalid reason. Cannot happen.");
2404                 return true;
2405         }
2406 
2407         if (!nai.everConnected || nai.isVPN() || nai.isLingering() || numRequests > 0) {
2408             return false;
2409         }
2410         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
2411             if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
2412                 // Background requests don't affect lingering.
2413                 continue;
2414             }
2415 
2416             // If this Network is already the highest scoring Network for a request, or if
2417             // there is hope for it to become one if it validated, then it is needed.
2418             if (nri.request.isRequest() && nai.satisfies(nri.request) &&
2419                     (nai.isSatisfyingRequest(nri.request.requestId) ||
2420                     // Note that this catches two important cases:
2421                     // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
2422                     //    is currently satisfying the request.  This is desirable when
2423                     //    cellular ends up validating but WiFi does not.
2424                     // 2. Unvalidated WiFi will not be reaped when validated cellular
2425                     //    is currently satisfying the request.  This is desirable when
2426                     //    WiFi ends up validating and out scoring cellular.
2427                     mNetworkForRequestId.get(nri.request.requestId).getCurrentScore() <
2428                             nai.getCurrentScoreAsValidated())) {
2429                 return false;
2430             }
2431         }
2432         return true;
2433     }
2434 
getNriForAppRequest( NetworkRequest request, int callingUid, String requestedOperation)2435     private NetworkRequestInfo getNriForAppRequest(
2436             NetworkRequest request, int callingUid, String requestedOperation) {
2437         final NetworkRequestInfo nri = mNetworkRequests.get(request);
2438 
2439         if (nri != null) {
2440             if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
2441                 log(String.format("UID %d attempted to %s for unowned request %s",
2442                         callingUid, requestedOperation, nri));
2443                 return null;
2444             }
2445         }
2446 
2447         return nri;
2448     }
2449 
handleTimedOutNetworkRequest(final NetworkRequestInfo nri)2450     private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
2451         if (mNetworkRequests.get(nri.request) != null && mNetworkForRequestId.get(
2452                 nri.request.requestId) == null) {
2453             handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_UNAVAIL);
2454         }
2455     }
2456 
handleReleaseNetworkRequest(NetworkRequest request, int callingUid)2457     private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
2458         final NetworkRequestInfo nri = getNriForAppRequest(
2459                 request, callingUid, "release NetworkRequest");
2460         if (nri != null) {
2461             handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_RELEASED);
2462         }
2463     }
2464 
handleRemoveNetworkRequest(final NetworkRequestInfo nri, final int whichCallback)2465     private void handleRemoveNetworkRequest(final NetworkRequestInfo nri, final int whichCallback) {
2466         final String logCallbackType = ConnectivityManager.getCallbackName(whichCallback);
2467         if (VDBG || (DBG && nri.request.isRequest())) {
2468             log("releasing " + nri.request + " (" + logCallbackType + ")");
2469         }
2470         nri.unlinkDeathRecipient();
2471         mNetworkRequests.remove(nri.request);
2472         synchronized (mUidToNetworkRequestCount) {
2473             int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
2474             if (requests < 1) {
2475                 Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " +
2476                         nri.mUid);
2477             } else if (requests == 1) {
2478                 mUidToNetworkRequestCount.removeAt(
2479                         mUidToNetworkRequestCount.indexOfKey(nri.mUid));
2480             } else {
2481                 mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
2482             }
2483         }
2484         mNetworkRequestInfoLogs.log("RELEASE " + nri);
2485         if (nri.request.isRequest()) {
2486             boolean wasKept = false;
2487             NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
2488             if (nai != null) {
2489                 boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
2490                 nai.removeRequest(nri.request.requestId);
2491                 if (VDBG) {
2492                     log(" Removing from current network " + nai.name() +
2493                             ", leaving " + nai.numNetworkRequests() + " requests.");
2494                 }
2495                 // If there are still lingered requests on this network, don't tear it down,
2496                 // but resume lingering instead.
2497                 updateLingerState(nai, SystemClock.elapsedRealtime());
2498                 if (unneeded(nai, UnneededFor.TEARDOWN)) {
2499                     if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
2500                     teardownUnneededNetwork(nai);
2501                 } else {
2502                     wasKept = true;
2503                 }
2504                 mNetworkForRequestId.remove(nri.request.requestId);
2505                 if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
2506                     // Went from foreground to background.
2507                     updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
2508                 }
2509             }
2510 
2511             // TODO: remove this code once we know that the Slog.wtf is never hit.
2512             //
2513             // Find all networks that are satisfying this request and remove the request
2514             // from their request lists.
2515             // TODO - it's my understanding that for a request there is only a single
2516             // network satisfying it, so this loop is wasteful
2517             for (NetworkAgentInfo otherNai : mNetworkAgentInfos.values()) {
2518                 if (otherNai.isSatisfyingRequest(nri.request.requestId) && otherNai != nai) {
2519                     Slog.wtf(TAG, "Request " + nri.request + " satisfied by " +
2520                             otherNai.name() + ", but mNetworkAgentInfos says " +
2521                             (nai != null ? nai.name() : "null"));
2522                 }
2523             }
2524 
2525             // Maintain the illusion.  When this request arrived, we might have pretended
2526             // that a network connected to serve it, even though the network was already
2527             // connected.  Now that this request has gone away, we might have to pretend
2528             // that the network disconnected.  LegacyTypeTracker will generate that
2529             // phantom disconnect for this type.
2530             if (nri.request.legacyType != TYPE_NONE && nai != null) {
2531                 boolean doRemove = true;
2532                 if (wasKept) {
2533                     // check if any of the remaining requests for this network are for the
2534                     // same legacy type - if so, don't remove the nai
2535                     for (int i = 0; i < nai.numNetworkRequests(); i++) {
2536                         NetworkRequest otherRequest = nai.requestAt(i);
2537                         if (otherRequest.legacyType == nri.request.legacyType &&
2538                                 otherRequest.isRequest()) {
2539                             if (DBG) log(" still have other legacy request - leaving");
2540                             doRemove = false;
2541                         }
2542                     }
2543                 }
2544 
2545                 if (doRemove) {
2546                     mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
2547                 }
2548             }
2549 
2550             for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
2551                 nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
2552                         nri.request);
2553             }
2554         } else {
2555             // listens don't have a singular affectedNetwork.  Check all networks to see
2556             // if this listen request applies and remove it.
2557             for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2558                 nai.removeRequest(nri.request.requestId);
2559                 if (nri.request.networkCapabilities.hasSignalStrength() &&
2560                         nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
2561                     updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
2562                 }
2563             }
2564         }
2565         callCallbackForRequest(nri, null, whichCallback, 0);
2566     }
2567 
2568     @Override
setAcceptUnvalidated(Network network, boolean accept, boolean always)2569     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
2570         enforceConnectivityInternalPermission();
2571         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED,
2572                 accept ? 1 : 0, always ? 1: 0, network));
2573     }
2574 
2575     @Override
setAvoidUnvalidated(Network network)2576     public void setAvoidUnvalidated(Network network) {
2577         enforceConnectivityInternalPermission();
2578         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
2579     }
2580 
handleSetAcceptUnvalidated(Network network, boolean accept, boolean always)2581     private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
2582         if (DBG) log("handleSetAcceptUnvalidated network=" + network +
2583                 " accept=" + accept + " always=" + always);
2584 
2585         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
2586         if (nai == null) {
2587             // Nothing to do.
2588             return;
2589         }
2590 
2591         if (nai.everValidated) {
2592             // The network validated while the dialog box was up. Take no action.
2593             return;
2594         }
2595 
2596         if (!nai.networkMisc.explicitlySelected) {
2597             Slog.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
2598         }
2599 
2600         if (accept != nai.networkMisc.acceptUnvalidated) {
2601             int oldScore = nai.getCurrentScore();
2602             nai.networkMisc.acceptUnvalidated = accept;
2603             rematchAllNetworksAndRequests(nai, oldScore);
2604             sendUpdatedScoreToFactories(nai);
2605         }
2606 
2607         if (always) {
2608             nai.asyncChannel.sendMessage(
2609                     NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, accept ? 1 : 0);
2610         }
2611 
2612         if (!accept) {
2613             // Tell the NetworkAgent to not automatically reconnect to the network.
2614             nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
2615             // Teardown the nework.
2616             teardownUnneededNetwork(nai);
2617         }
2618 
2619     }
2620 
handleSetAvoidUnvalidated(Network network)2621     private void handleSetAvoidUnvalidated(Network network) {
2622         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
2623         if (nai == null || nai.lastValidated) {
2624             // Nothing to do. The network either disconnected or revalidated.
2625             return;
2626         }
2627         if (!nai.avoidUnvalidated) {
2628             int oldScore = nai.getCurrentScore();
2629             nai.avoidUnvalidated = true;
2630             rematchAllNetworksAndRequests(nai, oldScore);
2631             sendUpdatedScoreToFactories(nai);
2632         }
2633     }
2634 
scheduleUnvalidatedPrompt(NetworkAgentInfo nai)2635     private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
2636         if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
2637         mHandler.sendMessageDelayed(
2638                 mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
2639                 PROMPT_UNVALIDATED_DELAY_MS);
2640     }
2641 
2642     @Override
startCaptivePortalApp(Network network)2643     public void startCaptivePortalApp(Network network) {
2644         enforceConnectivityInternalPermission();
2645         mHandler.post(() -> {
2646             NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
2647             if (nai == null) return;
2648             if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
2649             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_LAUNCH_CAPTIVE_PORTAL_APP);
2650         });
2651     }
2652 
avoidBadWifi()2653     public boolean avoidBadWifi() {
2654         return mMultinetworkPolicyTracker.getAvoidBadWifi();
2655     }
2656 
rematchForAvoidBadWifiUpdate()2657     private void rematchForAvoidBadWifiUpdate() {
2658         rematchAllNetworksAndRequests(null, 0);
2659         for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
2660             if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
2661                 sendUpdatedScoreToFactories(nai);
2662             }
2663         }
2664     }
2665 
2666     // TODO: Evaluate whether this is of interest to other consumers of
2667     // MultinetworkPolicyTracker and worth moving out of here.
dumpAvoidBadWifiSettings(IndentingPrintWriter pw)2668     private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
2669         final boolean configRestrict = mMultinetworkPolicyTracker.configRestrictsAvoidBadWifi();
2670         if (!configRestrict) {
2671             pw.println("Bad Wi-Fi avoidance: unrestricted");
2672             return;
2673         }
2674 
2675         pw.println("Bad Wi-Fi avoidance: " + avoidBadWifi());
2676         pw.increaseIndent();
2677         pw.println("Config restrict:   " + configRestrict);
2678 
2679         final String value = mMultinetworkPolicyTracker.getAvoidBadWifiSetting();
2680         String description;
2681         // Can't use a switch statement because strings are legal case labels, but null is not.
2682         if ("0".equals(value)) {
2683             description = "get stuck";
2684         } else if (value == null) {
2685             description = "prompt";
2686         } else if ("1".equals(value)) {
2687             description = "avoid";
2688         } else {
2689             description = value + " (?)";
2690         }
2691         pw.println("User setting:      " + description);
2692         pw.println("Network overrides:");
2693         pw.increaseIndent();
2694         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2695             if (nai.avoidUnvalidated) {
2696                 pw.println(nai.name());
2697             }
2698         }
2699         pw.decreaseIndent();
2700         pw.decreaseIndent();
2701     }
2702 
showValidationNotification(NetworkAgentInfo nai, NotificationType type)2703     private void showValidationNotification(NetworkAgentInfo nai, NotificationType type) {
2704         final String action;
2705         switch (type) {
2706             case NO_INTERNET:
2707                 action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
2708                 break;
2709             case LOST_INTERNET:
2710                 action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
2711                 break;
2712             default:
2713                 Slog.wtf(TAG, "Unknown notification type " + type);
2714                 return;
2715         }
2716 
2717         Intent intent = new Intent(action);
2718         intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
2719         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2720         intent.setClassName("com.android.settings",
2721                 "com.android.settings.wifi.WifiNoInternetDialog");
2722 
2723         PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
2724                 mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
2725         mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, true);
2726     }
2727 
handlePromptUnvalidated(Network network)2728     private void handlePromptUnvalidated(Network network) {
2729         if (VDBG) log("handlePromptUnvalidated " + network);
2730         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
2731 
2732         // Only prompt if the network is unvalidated and was explicitly selected by the user, and if
2733         // we haven't already been told to switch to it regardless of whether it validated or not.
2734         // Also don't prompt on captive portals because we're already prompting the user to sign in.
2735         if (nai == null || nai.everValidated || nai.everCaptivePortalDetected ||
2736                 !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated) {
2737             return;
2738         }
2739         showValidationNotification(nai, NotificationType.NO_INTERNET);
2740     }
2741 
handleNetworkUnvalidated(NetworkAgentInfo nai)2742     private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
2743         NetworkCapabilities nc = nai.networkCapabilities;
2744         if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
2745 
2746         if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
2747             mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
2748             showValidationNotification(nai, NotificationType.LOST_INTERNET);
2749         }
2750     }
2751 
2752     @Override
getMultipathPreference(Network network)2753     public int getMultipathPreference(Network network) {
2754         enforceAccessPermission();
2755 
2756         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
2757         if (nai != null && !nai.networkInfo.isMetered()) {
2758             return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED;
2759         }
2760 
2761         return mMultinetworkPolicyTracker.getMeteredMultipathPreference();
2762     }
2763 
2764     private class InternalHandler extends Handler {
InternalHandler(Looper looper)2765         public InternalHandler(Looper looper) {
2766             super(looper);
2767         }
2768 
2769         @Override
handleMessage(Message msg)2770         public void handleMessage(Message msg) {
2771             switch (msg.what) {
2772                 case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
2773                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
2774                     String causedBy = null;
2775                     synchronized (ConnectivityService.this) {
2776                         if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
2777                                 mNetTransitionWakeLock.isHeld()) {
2778                             mNetTransitionWakeLock.release();
2779                             causedBy = mNetTransitionWakeLockCausedBy;
2780                         } else {
2781                             break;
2782                         }
2783                     }
2784                     if (VDBG) {
2785                         if (msg.what == EVENT_EXPIRE_NET_TRANSITION_WAKELOCK) {
2786                             log("Failed to find a new network - expiring NetTransition Wakelock");
2787                         } else {
2788                             log("NetTransition Wakelock (" +
2789                                     (causedBy == null ? "unknown" : causedBy) +
2790                                     " cleared because we found a replacement network");
2791                         }
2792                     }
2793                     break;
2794                 }
2795                 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
2796                     handleDeprecatedGlobalHttpProxy();
2797                     break;
2798                 }
2799                 case EVENT_PROXY_HAS_CHANGED: {
2800                     handleApplyDefaultProxy((ProxyInfo)msg.obj);
2801                     break;
2802                 }
2803                 case EVENT_REGISTER_NETWORK_FACTORY: {
2804                     handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
2805                     break;
2806                 }
2807                 case EVENT_UNREGISTER_NETWORK_FACTORY: {
2808                     handleUnregisterNetworkFactory((Messenger)msg.obj);
2809                     break;
2810                 }
2811                 case EVENT_REGISTER_NETWORK_AGENT: {
2812                     handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
2813                     break;
2814                 }
2815                 case EVENT_REGISTER_NETWORK_REQUEST:
2816                 case EVENT_REGISTER_NETWORK_LISTENER: {
2817                     handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
2818                     break;
2819                 }
2820                 case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT:
2821                 case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: {
2822                     handleRegisterNetworkRequestWithIntent(msg);
2823                     break;
2824                 }
2825                 case EVENT_TIMEOUT_NETWORK_REQUEST: {
2826                     NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
2827                     handleTimedOutNetworkRequest(nri);
2828                     break;
2829                 }
2830                 case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
2831                     handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
2832                     break;
2833                 }
2834                 case EVENT_RELEASE_NETWORK_REQUEST: {
2835                     handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
2836                     break;
2837                 }
2838                 case EVENT_SET_ACCEPT_UNVALIDATED: {
2839                     handleSetAcceptUnvalidated((Network) msg.obj, msg.arg1 != 0, msg.arg2 != 0);
2840                     break;
2841                 }
2842                 case EVENT_SET_AVOID_UNVALIDATED: {
2843                     handleSetAvoidUnvalidated((Network) msg.obj);
2844                     break;
2845                 }
2846                 case EVENT_PROMPT_UNVALIDATED: {
2847                     handlePromptUnvalidated((Network) msg.obj);
2848                     break;
2849                 }
2850                 case EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON: {
2851                     handleMobileDataAlwaysOn();
2852                     break;
2853                 }
2854                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
2855                 case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
2856                     mKeepaliveTracker.handleStartKeepalive(msg);
2857                     break;
2858                 }
2859                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
2860                 case NetworkAgent.CMD_STOP_PACKET_KEEPALIVE: {
2861                     NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
2862                     int slot = msg.arg1;
2863                     int reason = msg.arg2;
2864                     mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
2865                     break;
2866                 }
2867                 case EVENT_SYSTEM_READY: {
2868                     for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2869                         nai.networkMonitor.systemReady = true;
2870                     }
2871                     break;
2872                 }
2873             }
2874         }
2875     }
2876 
2877     // javadoc from interface
2878     @Override
tether(String iface)2879     public int tether(String iface) {
2880         ConnectivityManager.enforceTetherChangePermission(mContext);
2881         if (isTetheringSupported()) {
2882             final int status = mTethering.tether(iface);
2883             return status;
2884         } else {
2885             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2886         }
2887     }
2888 
2889     // javadoc from interface
2890     @Override
untether(String iface)2891     public int untether(String iface) {
2892         ConnectivityManager.enforceTetherChangePermission(mContext);
2893 
2894         if (isTetheringSupported()) {
2895             final int status = mTethering.untether(iface);
2896             return status;
2897         } else {
2898             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2899         }
2900     }
2901 
2902     // javadoc from interface
2903     @Override
getLastTetherError(String iface)2904     public int getLastTetherError(String iface) {
2905         enforceTetherAccessPermission();
2906 
2907         if (isTetheringSupported()) {
2908             return mTethering.getLastTetherError(iface);
2909         } else {
2910             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2911         }
2912     }
2913 
2914     // TODO - proper iface API for selection by property, inspection, etc
2915     @Override
getTetherableUsbRegexs()2916     public String[] getTetherableUsbRegexs() {
2917         enforceTetherAccessPermission();
2918         if (isTetheringSupported()) {
2919             return mTethering.getTetherableUsbRegexs();
2920         } else {
2921             return new String[0];
2922         }
2923     }
2924 
2925     @Override
getTetherableWifiRegexs()2926     public String[] getTetherableWifiRegexs() {
2927         enforceTetherAccessPermission();
2928         if (isTetheringSupported()) {
2929             return mTethering.getTetherableWifiRegexs();
2930         } else {
2931             return new String[0];
2932         }
2933     }
2934 
2935     @Override
getTetherableBluetoothRegexs()2936     public String[] getTetherableBluetoothRegexs() {
2937         enforceTetherAccessPermission();
2938         if (isTetheringSupported()) {
2939             return mTethering.getTetherableBluetoothRegexs();
2940         } else {
2941             return new String[0];
2942         }
2943     }
2944 
2945     @Override
setUsbTethering(boolean enable)2946     public int setUsbTethering(boolean enable) {
2947         ConnectivityManager.enforceTetherChangePermission(mContext);
2948         if (isTetheringSupported()) {
2949             return mTethering.setUsbTethering(enable);
2950         } else {
2951             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2952         }
2953     }
2954 
2955     // TODO - move iface listing, queries, etc to new module
2956     // javadoc from interface
2957     @Override
getTetherableIfaces()2958     public String[] getTetherableIfaces() {
2959         enforceTetherAccessPermission();
2960         return mTethering.getTetherableIfaces();
2961     }
2962 
2963     @Override
getTetheredIfaces()2964     public String[] getTetheredIfaces() {
2965         enforceTetherAccessPermission();
2966         return mTethering.getTetheredIfaces();
2967     }
2968 
2969     @Override
getTetheringErroredIfaces()2970     public String[] getTetheringErroredIfaces() {
2971         enforceTetherAccessPermission();
2972         return mTethering.getErroredIfaces();
2973     }
2974 
2975     @Override
getTetheredDhcpRanges()2976     public String[] getTetheredDhcpRanges() {
2977         enforceConnectivityInternalPermission();
2978         return mTethering.getTetheredDhcpRanges();
2979     }
2980 
2981     // if ro.tether.denied = true we default to no tethering
2982     // gservices could set the secure setting to 1 though to enable it on a build where it
2983     // had previously been turned off.
2984     @Override
isTetheringSupported()2985     public boolean isTetheringSupported() {
2986         enforceTetherAccessPermission();
2987         int defaultVal = (mSystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
2988         boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
2989                 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
2990                 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
2991 
2992         // Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
2993         boolean adminUser = false;
2994         final long token = Binder.clearCallingIdentity();
2995         try {
2996             adminUser = mUserManager.isAdminUser();
2997         } finally {
2998             Binder.restoreCallingIdentity(token);
2999         }
3000 
3001         return tetherEnabledInSettings && adminUser &&
3002                mTethering.hasTetherableConfiguration();
3003     }
3004 
3005     @Override
startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi)3006     public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
3007         ConnectivityManager.enforceTetherChangePermission(mContext);
3008         if (!isTetheringSupported()) {
3009             receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
3010             return;
3011         }
3012         mTethering.startTethering(type, receiver, showProvisioningUi);
3013     }
3014 
3015     @Override
stopTethering(int type)3016     public void stopTethering(int type) {
3017         ConnectivityManager.enforceTetherChangePermission(mContext);
3018         mTethering.stopTethering(type);
3019     }
3020 
3021     // Called when we lose the default network and have no replacement yet.
3022     // This will automatically be cleared after X seconds or a new default network
3023     // becomes CONNECTED, whichever happens first.  The timer is started by the
3024     // first caller and not restarted by subsequent callers.
requestNetworkTransitionWakelock(String forWhom)3025     private void requestNetworkTransitionWakelock(String forWhom) {
3026         int serialNum = 0;
3027         synchronized (this) {
3028             if (mNetTransitionWakeLock.isHeld()) return;
3029             serialNum = ++mNetTransitionWakeLockSerialNumber;
3030             mNetTransitionWakeLock.acquire();
3031             mNetTransitionWakeLockCausedBy = forWhom;
3032         }
3033         mHandler.sendMessageDelayed(mHandler.obtainMessage(
3034                 EVENT_EXPIRE_NET_TRANSITION_WAKELOCK, serialNum, 0),
3035                 mNetTransitionWakeLockTimeout);
3036         return;
3037     }
3038 
3039     // 100 percent is full good, 0 is full bad.
3040     @Override
reportInetCondition(int networkType, int percentage)3041     public void reportInetCondition(int networkType, int percentage) {
3042         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
3043         if (nai == null) return;
3044         reportNetworkConnectivity(nai.network, percentage > 50);
3045     }
3046 
3047     @Override
reportNetworkConnectivity(Network network, boolean hasConnectivity)3048     public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
3049         enforceAccessPermission();
3050         enforceInternetPermission();
3051 
3052         // TODO: execute this logic on ConnectivityService handler.
3053         final NetworkAgentInfo nai;
3054         if (network == null) {
3055             nai = getDefaultNetwork();
3056         } else {
3057             nai = getNetworkAgentInfoForNetwork(network);
3058         }
3059         if (nai == null || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTING ||
3060             nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) {
3061             return;
3062         }
3063         // Revalidate if the app report does not match our current validated state.
3064         if (hasConnectivity == nai.lastValidated) {
3065             return;
3066         }
3067         final int uid = Binder.getCallingUid();
3068         if (DBG) {
3069             log("reportNetworkConnectivity(" + nai.network.netId + ", " + hasConnectivity +
3070                     ") by " + uid);
3071         }
3072         // Validating a network that has not yet connected could result in a call to
3073         // rematchNetworkAndRequests() which is not meant to work on such networks.
3074         if (!nai.everConnected) {
3075             return;
3076         }
3077         LinkProperties lp = getLinkProperties(nai);
3078         if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
3079             return;
3080         }
3081         nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
3082     }
3083 
getDefaultProxy()3084     private ProxyInfo getDefaultProxy() {
3085         // this information is already available as a world read/writable jvm property
3086         // so this API change wouldn't have a benifit.  It also breaks the passing
3087         // of proxy info to all the JVMs.
3088         // enforceAccessPermission();
3089         synchronized (mProxyLock) {
3090             ProxyInfo ret = mGlobalProxy;
3091             if ((ret == null) && !mDefaultProxyDisabled) ret = mDefaultProxy;
3092             return ret;
3093         }
3094     }
3095 
3096     @Override
getProxyForNetwork(Network network)3097     public ProxyInfo getProxyForNetwork(Network network) {
3098         if (network == null) return getDefaultProxy();
3099         final ProxyInfo globalProxy = getGlobalProxy();
3100         if (globalProxy != null) return globalProxy;
3101         if (!NetworkUtils.queryUserAccess(Binder.getCallingUid(), network.netId)) return null;
3102         // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
3103         // caller may not have.
3104         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3105         if (nai == null) return null;
3106         synchronized (nai) {
3107             final ProxyInfo proxyInfo = nai.linkProperties.getHttpProxy();
3108             if (proxyInfo == null) return null;
3109             return new ProxyInfo(proxyInfo);
3110         }
3111     }
3112 
3113     // Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present
3114     // (e.g. if mGlobalProxy==null fall back to network-specific proxy, if network-specific
3115     // proxy is null then there is no proxy in place).
canonicalizeProxyInfo(ProxyInfo proxy)3116     private ProxyInfo canonicalizeProxyInfo(ProxyInfo proxy) {
3117         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
3118                 && (proxy.getPacFileUrl() == null || Uri.EMPTY.equals(proxy.getPacFileUrl()))) {
3119             proxy = null;
3120         }
3121         return proxy;
3122     }
3123 
3124     // ProxyInfo equality function with a couple modifications over ProxyInfo.equals() to make it
3125     // better for determining if a new proxy broadcast is necessary:
3126     // 1. Canonicalize empty ProxyInfos to null so an empty proxy compares equal to null so as to
3127     //    avoid unnecessary broadcasts.
3128     // 2. Make sure all parts of the ProxyInfo's compare true, including the host when a PAC URL
3129     //    is in place.  This is important so legacy PAC resolver (see com.android.proxyhandler)
3130     //    changes aren't missed.  The legacy PAC resolver pretends to be a simple HTTP proxy but
3131     //    actually uses the PAC to resolve; this results in ProxyInfo's with PAC URL, host and port
3132     //    all set.
proxyInfoEqual(ProxyInfo a, ProxyInfo b)3133     private boolean proxyInfoEqual(ProxyInfo a, ProxyInfo b) {
3134         a = canonicalizeProxyInfo(a);
3135         b = canonicalizeProxyInfo(b);
3136         // ProxyInfo.equals() doesn't check hosts when PAC URLs are present, but we need to check
3137         // hosts even when PAC URLs are present to account for the legacy PAC resolver.
3138         return Objects.equals(a, b) && (a == null || Objects.equals(a.getHost(), b.getHost()));
3139     }
3140 
setGlobalProxy(ProxyInfo proxyProperties)3141     public void setGlobalProxy(ProxyInfo proxyProperties) {
3142         enforceConnectivityInternalPermission();
3143 
3144         synchronized (mProxyLock) {
3145             if (proxyProperties == mGlobalProxy) return;
3146             if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
3147             if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
3148 
3149             String host = "";
3150             int port = 0;
3151             String exclList = "";
3152             String pacFileUrl = "";
3153             if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
3154                     !Uri.EMPTY.equals(proxyProperties.getPacFileUrl()))) {
3155                 if (!proxyProperties.isValid()) {
3156                     if (DBG)
3157                         log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
3158                     return;
3159                 }
3160                 mGlobalProxy = new ProxyInfo(proxyProperties);
3161                 host = mGlobalProxy.getHost();
3162                 port = mGlobalProxy.getPort();
3163                 exclList = mGlobalProxy.getExclusionListAsString();
3164                 if (!Uri.EMPTY.equals(proxyProperties.getPacFileUrl())) {
3165                     pacFileUrl = proxyProperties.getPacFileUrl().toString();
3166                 }
3167             } else {
3168                 mGlobalProxy = null;
3169             }
3170             ContentResolver res = mContext.getContentResolver();
3171             final long token = Binder.clearCallingIdentity();
3172             try {
3173                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
3174                 Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
3175                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
3176                         exclList);
3177                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
3178             } finally {
3179                 Binder.restoreCallingIdentity(token);
3180             }
3181 
3182             if (mGlobalProxy == null) {
3183                 proxyProperties = mDefaultProxy;
3184             }
3185             sendProxyBroadcast(proxyProperties);
3186         }
3187     }
3188 
loadGlobalProxy()3189     private void loadGlobalProxy() {
3190         ContentResolver res = mContext.getContentResolver();
3191         String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
3192         int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
3193         String exclList = Settings.Global.getString(res,
3194                 Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
3195         String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
3196         if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
3197             ProxyInfo proxyProperties;
3198             if (!TextUtils.isEmpty(pacFileUrl)) {
3199                 proxyProperties = new ProxyInfo(pacFileUrl);
3200             } else {
3201                 proxyProperties = new ProxyInfo(host, port, exclList);
3202             }
3203             if (!proxyProperties.isValid()) {
3204                 if (DBG) log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
3205                 return;
3206             }
3207 
3208             synchronized (mProxyLock) {
3209                 mGlobalProxy = proxyProperties;
3210             }
3211         }
3212     }
3213 
getGlobalProxy()3214     public ProxyInfo getGlobalProxy() {
3215         // this information is already available as a world read/writable jvm property
3216         // so this API change wouldn't have a benifit.  It also breaks the passing
3217         // of proxy info to all the JVMs.
3218         // enforceAccessPermission();
3219         synchronized (mProxyLock) {
3220             return mGlobalProxy;
3221         }
3222     }
3223 
handleApplyDefaultProxy(ProxyInfo proxy)3224     private void handleApplyDefaultProxy(ProxyInfo proxy) {
3225         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
3226                 && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
3227             proxy = null;
3228         }
3229         synchronized (mProxyLock) {
3230             if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
3231             if (mDefaultProxy == proxy) return; // catches repeated nulls
3232             if (proxy != null &&  !proxy.isValid()) {
3233                 if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString());
3234                 return;
3235             }
3236 
3237             // This call could be coming from the PacManager, containing the port of the local
3238             // proxy.  If this new proxy matches the global proxy then copy this proxy to the
3239             // global (to get the correct local port), and send a broadcast.
3240             // TODO: Switch PacManager to have its own message to send back rather than
3241             // reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy.
3242             if ((mGlobalProxy != null) && (proxy != null)
3243                     && (!Uri.EMPTY.equals(proxy.getPacFileUrl()))
3244                     && proxy.getPacFileUrl().equals(mGlobalProxy.getPacFileUrl())) {
3245                 mGlobalProxy = proxy;
3246                 sendProxyBroadcast(mGlobalProxy);
3247                 return;
3248             }
3249             mDefaultProxy = proxy;
3250 
3251             if (mGlobalProxy != null) return;
3252             if (!mDefaultProxyDisabled) {
3253                 sendProxyBroadcast(proxy);
3254             }
3255         }
3256     }
3257 
3258     // If the proxy has changed from oldLp to newLp, resend proxy broadcast with default proxy.
3259     // This method gets called when any network changes proxy, but the broadcast only ever contains
3260     // the default proxy (even if it hasn't changed).
3261     // TODO: Deprecate the broadcast extras as they aren't necessarily applicable in a multi-network
3262     // world where an app might be bound to a non-default network.
updateProxy(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai)3263     private void updateProxy(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) {
3264         ProxyInfo newProxyInfo = newLp == null ? null : newLp.getHttpProxy();
3265         ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy();
3266 
3267         if (!proxyInfoEqual(newProxyInfo, oldProxyInfo)) {
3268             sendProxyBroadcast(getDefaultProxy());
3269         }
3270     }
3271 
handleDeprecatedGlobalHttpProxy()3272     private void handleDeprecatedGlobalHttpProxy() {
3273         String proxy = Settings.Global.getString(mContext.getContentResolver(),
3274                 Settings.Global.HTTP_PROXY);
3275         if (!TextUtils.isEmpty(proxy)) {
3276             String data[] = proxy.split(":");
3277             if (data.length == 0) {
3278                 return;
3279             }
3280 
3281             String proxyHost =  data[0];
3282             int proxyPort = 8080;
3283             if (data.length > 1) {
3284                 try {
3285                     proxyPort = Integer.parseInt(data[1]);
3286                 } catch (NumberFormatException e) {
3287                     return;
3288                 }
3289             }
3290             ProxyInfo p = new ProxyInfo(data[0], proxyPort, "");
3291             setGlobalProxy(p);
3292         }
3293     }
3294 
sendProxyBroadcast(ProxyInfo proxy)3295     private void sendProxyBroadcast(ProxyInfo proxy) {
3296         if (proxy == null) proxy = new ProxyInfo("", 0, "");
3297         if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
3298         if (DBG) log("sending Proxy Broadcast for " + proxy);
3299         Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
3300         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
3301             Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
3302         intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
3303         final long ident = Binder.clearCallingIdentity();
3304         try {
3305             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
3306         } finally {
3307             Binder.restoreCallingIdentity(ident);
3308         }
3309     }
3310 
3311     private static class SettingsObserver extends ContentObserver {
3312         final private HashMap<Uri, Integer> mUriEventMap;
3313         final private Context mContext;
3314         final private Handler mHandler;
3315 
SettingsObserver(Context context, Handler handler)3316         SettingsObserver(Context context, Handler handler) {
3317             super(null);
3318             mUriEventMap = new HashMap<Uri, Integer>();
3319             mContext = context;
3320             mHandler = handler;
3321         }
3322 
observe(Uri uri, int what)3323         void observe(Uri uri, int what) {
3324             mUriEventMap.put(uri, what);
3325             final ContentResolver resolver = mContext.getContentResolver();
3326             resolver.registerContentObserver(uri, false, this);
3327         }
3328 
3329         @Override
onChange(boolean selfChange)3330         public void onChange(boolean selfChange) {
3331             Slog.wtf(TAG, "Should never be reached.");
3332         }
3333 
3334         @Override
onChange(boolean selfChange, Uri uri)3335         public void onChange(boolean selfChange, Uri uri) {
3336             final Integer what = mUriEventMap.get(uri);
3337             if (what != null) {
3338                 mHandler.obtainMessage(what.intValue()).sendToTarget();
3339             } else {
3340                 loge("No matching event to send for URI=" + uri);
3341             }
3342         }
3343     }
3344 
log(String s)3345     private static void log(String s) {
3346         Slog.d(TAG, s);
3347     }
3348 
loge(String s)3349     private static void loge(String s) {
3350         Slog.e(TAG, s);
3351     }
3352 
loge(String s, Throwable t)3353     private static void loge(String s, Throwable t) {
3354         Slog.e(TAG, s, t);
3355     }
3356 
checkNotNull(T value, String message)3357     private static <T> T checkNotNull(T value, String message) {
3358         if (value == null) {
3359             throw new NullPointerException(message);
3360         }
3361         return value;
3362     }
3363 
3364     /**
3365      * Prepare for a VPN application.
3366      * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
3367      * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
3368      *
3369      * @param oldPackage Package name of the application which currently controls VPN, which will
3370      *                   be replaced. If there is no such application, this should should either be
3371      *                   {@code null} or {@link VpnConfig.LEGACY_VPN}.
3372      * @param newPackage Package name of the application which should gain control of VPN, or
3373      *                   {@code null} to disable.
3374      * @param userId User for whom to prepare the new VPN.
3375      *
3376      * @hide
3377      */
3378     @Override
prepareVpn(@ullable String oldPackage, @Nullable String newPackage, int userId)3379     public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
3380             int userId) {
3381         enforceCrossUserPermission(userId);
3382         throwIfLockdownEnabled();
3383 
3384         synchronized(mVpns) {
3385             Vpn vpn = mVpns.get(userId);
3386             if (vpn != null) {
3387                 return vpn.prepare(oldPackage, newPackage);
3388             } else {
3389                 return false;
3390             }
3391         }
3392     }
3393 
3394     /**
3395      * Set whether the VPN package has the ability to launch VPNs without user intervention.
3396      * This method is used by system-privileged apps.
3397      * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
3398      * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
3399      *
3400      * @param packageName The package for which authorization state should change.
3401      * @param userId User for whom {@code packageName} is installed.
3402      * @param authorized {@code true} if this app should be able to start a VPN connection without
3403      *                   explicit user approval, {@code false} if not.
3404      *
3405      * @hide
3406      */
3407     @Override
setVpnPackageAuthorization(String packageName, int userId, boolean authorized)3408     public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) {
3409         enforceCrossUserPermission(userId);
3410 
3411         synchronized(mVpns) {
3412             Vpn vpn = mVpns.get(userId);
3413             if (vpn != null) {
3414                 vpn.setPackageAuthorization(packageName, authorized);
3415             }
3416         }
3417     }
3418 
3419     /**
3420      * Configure a TUN interface and return its file descriptor. Parameters
3421      * are encoded and opaque to this class. This method is used by VpnBuilder
3422      * and not available in ConnectivityManager. Permissions are checked in
3423      * Vpn class.
3424      * @hide
3425      */
3426     @Override
establishVpn(VpnConfig config)3427     public ParcelFileDescriptor establishVpn(VpnConfig config) {
3428         throwIfLockdownEnabled();
3429         int user = UserHandle.getUserId(Binder.getCallingUid());
3430         synchronized(mVpns) {
3431             return mVpns.get(user).establish(config);
3432         }
3433     }
3434 
3435     /**
3436      * Start legacy VPN, controlling native daemons as needed. Creates a
3437      * secondary thread to perform connection work, returning quickly.
3438      */
3439     @Override
startLegacyVpn(VpnProfile profile)3440     public void startLegacyVpn(VpnProfile profile) {
3441         throwIfLockdownEnabled();
3442         final LinkProperties egress = getActiveLinkProperties();
3443         if (egress == null) {
3444             throw new IllegalStateException("Missing active network connection");
3445         }
3446         int user = UserHandle.getUserId(Binder.getCallingUid());
3447         synchronized(mVpns) {
3448             mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
3449         }
3450     }
3451 
3452     /**
3453      * Return the information of the ongoing legacy VPN. This method is used
3454      * by VpnSettings and not available in ConnectivityManager. Permissions
3455      * are checked in Vpn class.
3456      */
3457     @Override
getLegacyVpnInfo(int userId)3458     public LegacyVpnInfo getLegacyVpnInfo(int userId) {
3459         enforceCrossUserPermission(userId);
3460 
3461         synchronized(mVpns) {
3462             return mVpns.get(userId).getLegacyVpnInfo();
3463         }
3464     }
3465 
3466     /**
3467      * Return the information of all ongoing VPNs. This method is used by NetworkStatsService
3468      * and not available in ConnectivityManager.
3469      */
3470     @Override
getAllVpnInfo()3471     public VpnInfo[] getAllVpnInfo() {
3472         enforceConnectivityInternalPermission();
3473         if (mLockdownEnabled) {
3474             return new VpnInfo[0];
3475         }
3476 
3477         synchronized(mVpns) {
3478             List<VpnInfo> infoList = new ArrayList<>();
3479             for (int i = 0; i < mVpns.size(); i++) {
3480                 VpnInfo info = createVpnInfo(mVpns.valueAt(i));
3481                 if (info != null) {
3482                     infoList.add(info);
3483                 }
3484             }
3485             return infoList.toArray(new VpnInfo[infoList.size()]);
3486         }
3487     }
3488 
3489     /**
3490      * @return VPN information for accounting, or null if we can't retrieve all required
3491      *         information, e.g primary underlying iface.
3492      */
3493     @Nullable
createVpnInfo(Vpn vpn)3494     private VpnInfo createVpnInfo(Vpn vpn) {
3495         VpnInfo info = vpn.getVpnInfo();
3496         if (info == null) {
3497             return null;
3498         }
3499         Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
3500         // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
3501         // the underlyingNetworks list.
3502         if (underlyingNetworks == null) {
3503             NetworkAgentInfo defaultNetwork = getDefaultNetwork();
3504             if (defaultNetwork != null && defaultNetwork.linkProperties != null) {
3505                 info.primaryUnderlyingIface = getDefaultNetwork().linkProperties.getInterfaceName();
3506             }
3507         } else if (underlyingNetworks.length > 0) {
3508             LinkProperties linkProperties = getLinkProperties(underlyingNetworks[0]);
3509             if (linkProperties != null) {
3510                 info.primaryUnderlyingIface = linkProperties.getInterfaceName();
3511             }
3512         }
3513         return info.primaryUnderlyingIface == null ? null : info;
3514     }
3515 
3516     /**
3517      * Returns the information of the ongoing VPN for {@code userId}. This method is used by
3518      * VpnDialogs and not available in ConnectivityManager.
3519      * Permissions are checked in Vpn class.
3520      * @hide
3521      */
3522     @Override
getVpnConfig(int userId)3523     public VpnConfig getVpnConfig(int userId) {
3524         enforceCrossUserPermission(userId);
3525         synchronized(mVpns) {
3526             Vpn vpn = mVpns.get(userId);
3527             if (vpn != null) {
3528                 return vpn.getVpnConfig();
3529             } else {
3530                 return null;
3531             }
3532         }
3533     }
3534 
3535     @Override
updateLockdownVpn()3536     public boolean updateLockdownVpn() {
3537         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
3538             Slog.w(TAG, "Lockdown VPN only available to AID_SYSTEM");
3539             return false;
3540         }
3541 
3542         // Tear down existing lockdown if profile was removed
3543         mLockdownEnabled = LockdownVpnTracker.isEnabled();
3544         if (mLockdownEnabled) {
3545             byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
3546             if (profileTag == null) {
3547                 Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
3548                 return false;
3549             }
3550             String profileName = new String(profileTag);
3551             final VpnProfile profile = VpnProfile.decode(
3552                     profileName, mKeyStore.get(Credentials.VPN + profileName));
3553             if (profile == null) {
3554                 Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
3555                 setLockdownTracker(null);
3556                 return true;
3557             }
3558             int user = UserHandle.getUserId(Binder.getCallingUid());
3559             synchronized(mVpns) {
3560                 Vpn vpn = mVpns.get(user);
3561                 if (vpn == null) {
3562                     Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
3563                     return false;
3564                 }
3565                 setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile));
3566             }
3567         } else {
3568             setLockdownTracker(null);
3569         }
3570 
3571         return true;
3572     }
3573 
3574     /**
3575      * Internally set new {@link LockdownVpnTracker}, shutting down any existing
3576      * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
3577      */
setLockdownTracker(LockdownVpnTracker tracker)3578     private void setLockdownTracker(LockdownVpnTracker tracker) {
3579         // Shutdown any existing tracker
3580         final LockdownVpnTracker existing = mLockdownTracker;
3581         mLockdownTracker = null;
3582         if (existing != null) {
3583             existing.shutdown();
3584         }
3585 
3586         try {
3587             if (tracker != null) {
3588                 mNetd.setFirewallEnabled(true);
3589                 mNetd.setFirewallInterfaceRule("lo", true);
3590                 mLockdownTracker = tracker;
3591                 mLockdownTracker.init();
3592             } else {
3593                 mNetd.setFirewallEnabled(false);
3594             }
3595         } catch (RemoteException e) {
3596             // ignored; NMS lives inside system_server
3597         }
3598     }
3599 
throwIfLockdownEnabled()3600     private void throwIfLockdownEnabled() {
3601         if (mLockdownEnabled) {
3602             throw new IllegalStateException("Unavailable in lockdown mode");
3603         }
3604     }
3605 
3606     /**
3607      * Starts the always-on VPN {@link VpnService} for user {@param userId}, which should perform
3608      * some setup and then call {@code establish()} to connect.
3609      *
3610      * @return {@code true} if the service was started, the service was already connected, or there
3611      *         was no always-on VPN to start. {@code false} otherwise.
3612      */
startAlwaysOnVpn(int userId)3613     private boolean startAlwaysOnVpn(int userId) {
3614         synchronized (mVpns) {
3615             Vpn vpn = mVpns.get(userId);
3616             if (vpn == null) {
3617                 // Shouldn't happen as all codepaths that point here should have checked the Vpn
3618                 // exists already.
3619                 Slog.wtf(TAG, "User " + userId + " has no Vpn configuration");
3620                 return false;
3621             }
3622 
3623             return vpn.startAlwaysOnVpn();
3624         }
3625     }
3626 
3627     @Override
setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown)3628     public boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown) {
3629         enforceConnectivityInternalPermission();
3630         enforceCrossUserPermission(userId);
3631 
3632         // Can't set always-on VPN if legacy VPN is already in lockdown mode.
3633         if (LockdownVpnTracker.isEnabled()) {
3634             return false;
3635         }
3636 
3637         synchronized (mVpns) {
3638             Vpn vpn = mVpns.get(userId);
3639             if (vpn == null) {
3640                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
3641                 return false;
3642             }
3643             if (!vpn.setAlwaysOnPackage(packageName, lockdown)) {
3644                 return false;
3645             }
3646             if (!startAlwaysOnVpn(userId)) {
3647                 vpn.setAlwaysOnPackage(null, false);
3648                 return false;
3649             }
3650 
3651             vpn.saveAlwaysOnPackage();
3652         }
3653         return true;
3654     }
3655 
3656     @Override
getAlwaysOnVpnPackage(int userId)3657     public String getAlwaysOnVpnPackage(int userId) {
3658         enforceConnectivityInternalPermission();
3659         enforceCrossUserPermission(userId);
3660 
3661         synchronized (mVpns) {
3662             Vpn vpn = mVpns.get(userId);
3663             if (vpn == null) {
3664                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
3665                 return null;
3666             }
3667             return vpn.getAlwaysOnPackage();
3668         }
3669     }
3670 
3671     @Override
checkMobileProvisioning(int suggestedTimeOutMs)3672     public int checkMobileProvisioning(int suggestedTimeOutMs) {
3673         // TODO: Remove?  Any reason to trigger a provisioning check?
3674         return -1;
3675     }
3676 
3677     /** Location to an updatable file listing carrier provisioning urls.
3678      *  An example:
3679      *
3680      * <?xml version="1.0" encoding="utf-8"?>
3681      *  <provisioningUrls>
3682      *   <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&amp;iccid=%1$s&amp;imei=%2$s</provisioningUrl>
3683      *  </provisioningUrls>
3684      */
3685     private static final String PROVISIONING_URL_PATH =
3686             "/data/misc/radio/provisioning_urls.xml";
3687     private final File mProvisioningUrlFile = new File(PROVISIONING_URL_PATH);
3688 
3689     /** XML tag for root element. */
3690     private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
3691     /** XML tag for individual url */
3692     private static final String TAG_PROVISIONING_URL = "provisioningUrl";
3693     /** XML attribute for mcc */
3694     private static final String ATTR_MCC = "mcc";
3695     /** XML attribute for mnc */
3696     private static final String ATTR_MNC = "mnc";
3697 
getProvisioningUrlBaseFromFile()3698     private String getProvisioningUrlBaseFromFile() {
3699         FileReader fileReader = null;
3700         XmlPullParser parser = null;
3701         Configuration config = mContext.getResources().getConfiguration();
3702 
3703         try {
3704             fileReader = new FileReader(mProvisioningUrlFile);
3705             parser = Xml.newPullParser();
3706             parser.setInput(fileReader);
3707             XmlUtils.beginDocument(parser, TAG_PROVISIONING_URLS);
3708 
3709             while (true) {
3710                 XmlUtils.nextElement(parser);
3711 
3712                 String element = parser.getName();
3713                 if (element == null) break;
3714 
3715                 if (element.equals(TAG_PROVISIONING_URL)) {
3716                     String mcc = parser.getAttributeValue(null, ATTR_MCC);
3717                     try {
3718                         if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
3719                             String mnc = parser.getAttributeValue(null, ATTR_MNC);
3720                             if (mnc != null && Integer.parseInt(mnc) == config.mnc) {
3721                                 parser.next();
3722                                 if (parser.getEventType() == XmlPullParser.TEXT) {
3723                                     return parser.getText();
3724                                 }
3725                             }
3726                         }
3727                     } catch (NumberFormatException e) {
3728                         loge("NumberFormatException in getProvisioningUrlBaseFromFile: " + e);
3729                     }
3730                 }
3731             }
3732             return null;
3733         } catch (FileNotFoundException e) {
3734             loge("Carrier Provisioning Urls file not found");
3735         } catch (XmlPullParserException e) {
3736             loge("Xml parser exception reading Carrier Provisioning Urls file: " + e);
3737         } catch (IOException e) {
3738             loge("I/O exception reading Carrier Provisioning Urls file: " + e);
3739         } finally {
3740             if (fileReader != null) {
3741                 try {
3742                     fileReader.close();
3743                 } catch (IOException e) {}
3744             }
3745         }
3746         return null;
3747     }
3748 
3749     @Override
getMobileProvisioningUrl()3750     public String getMobileProvisioningUrl() {
3751         enforceConnectivityInternalPermission();
3752         String url = getProvisioningUrlBaseFromFile();
3753         if (TextUtils.isEmpty(url)) {
3754             url = mContext.getResources().getString(R.string.mobile_provisioning_url);
3755             log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
3756         } else {
3757             log("getMobileProvisioningUrl: mobile_provisioning_url from File =" + url);
3758         }
3759         // populate the iccid, imei and phone number in the provisioning url.
3760         if (!TextUtils.isEmpty(url)) {
3761             String phoneNumber = mTelephonyManager.getLine1Number();
3762             if (TextUtils.isEmpty(phoneNumber)) {
3763                 phoneNumber = "0000000000";
3764             }
3765             url = String.format(url,
3766                     mTelephonyManager.getSimSerialNumber() /* ICCID */,
3767                     mTelephonyManager.getDeviceId() /* IMEI */,
3768                     phoneNumber /* Phone numer */);
3769         }
3770 
3771         return url;
3772     }
3773 
3774     @Override
setProvisioningNotificationVisible(boolean visible, int networkType, String action)3775     public void setProvisioningNotificationVisible(boolean visible, int networkType,
3776             String action) {
3777         enforceConnectivityInternalPermission();
3778         final long ident = Binder.clearCallingIdentity();
3779         try {
3780             // Concatenate the range of types onto the range of NetIDs.
3781             int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
3782             mNotifier.setProvNotificationVisible(visible, id, action);
3783         } finally {
3784             Binder.restoreCallingIdentity(ident);
3785         }
3786     }
3787 
3788     @Override
setAirplaneMode(boolean enable)3789     public void setAirplaneMode(boolean enable) {
3790         enforceConnectivityInternalPermission();
3791         final long ident = Binder.clearCallingIdentity();
3792         try {
3793             final ContentResolver cr = mContext.getContentResolver();
3794             Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, enable ? 1 : 0);
3795             Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
3796             intent.putExtra("state", enable);
3797             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
3798         } finally {
3799             Binder.restoreCallingIdentity(ident);
3800         }
3801     }
3802 
onUserStart(int userId)3803     private void onUserStart(int userId) {
3804         synchronized(mVpns) {
3805             Vpn userVpn = mVpns.get(userId);
3806             if (userVpn != null) {
3807                 loge("Starting user already has a VPN");
3808                 return;
3809             }
3810             userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
3811             mVpns.put(userId, userVpn);
3812 
3813             final ContentResolver cr = mContext.getContentResolver();
3814             String alwaysOnPackage = Settings.Secure.getStringForUser(cr,
3815                     Settings.Secure.ALWAYS_ON_VPN_APP, userId);
3816             final boolean alwaysOnLockdown = Settings.Secure.getIntForUser(cr,
3817                     Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, /* default */ 0, userId) != 0;
3818             if (alwaysOnPackage != null) {
3819                 userVpn.setAlwaysOnPackage(alwaysOnPackage, alwaysOnLockdown);
3820             }
3821         }
3822         if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
3823             updateLockdownVpn();
3824         }
3825     }
3826 
onUserStop(int userId)3827     private void onUserStop(int userId) {
3828         synchronized(mVpns) {
3829             Vpn userVpn = mVpns.get(userId);
3830             if (userVpn == null) {
3831                 loge("Stopped user has no VPN");
3832                 return;
3833             }
3834             userVpn.onUserStopped();
3835             mVpns.delete(userId);
3836         }
3837     }
3838 
onUserAdded(int userId)3839     private void onUserAdded(int userId) {
3840         synchronized(mVpns) {
3841             final int vpnsSize = mVpns.size();
3842             for (int i = 0; i < vpnsSize; i++) {
3843                 Vpn vpn = mVpns.valueAt(i);
3844                 vpn.onUserAdded(userId);
3845             }
3846         }
3847     }
3848 
onUserRemoved(int userId)3849     private void onUserRemoved(int userId) {
3850         synchronized(mVpns) {
3851             final int vpnsSize = mVpns.size();
3852             for (int i = 0; i < vpnsSize; i++) {
3853                 Vpn vpn = mVpns.valueAt(i);
3854                 vpn.onUserRemoved(userId);
3855             }
3856         }
3857     }
3858 
onUserUnlocked(int userId)3859     private void onUserUnlocked(int userId) {
3860         // User present may be sent because of an unlock, which might mean an unlocked keystore.
3861         if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
3862             updateLockdownVpn();
3863         } else {
3864             startAlwaysOnVpn(userId);
3865         }
3866     }
3867 
3868     private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
3869         @Override
3870         public void onReceive(Context context, Intent intent) {
3871             final String action = intent.getAction();
3872             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
3873             if (userId == UserHandle.USER_NULL) return;
3874 
3875             if (Intent.ACTION_USER_STARTED.equals(action)) {
3876                 onUserStart(userId);
3877             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
3878                 onUserStop(userId);
3879             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
3880                 onUserAdded(userId);
3881             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
3882                 onUserRemoved(userId);
3883             } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
3884                 onUserUnlocked(userId);
3885             }
3886         }
3887     };
3888 
3889     private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
3890         @Override
3891         public void onReceive(Context context, Intent intent) {
3892             // Try creating lockdown tracker, since user present usually means
3893             // unlocked keystore.
3894             updateLockdownVpn();
3895             mContext.unregisterReceiver(this);
3896         }
3897     };
3898 
3899     private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
3900             new HashMap<Messenger, NetworkFactoryInfo>();
3901     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
3902             new HashMap<NetworkRequest, NetworkRequestInfo>();
3903 
3904     private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
3905     // Map from UID to number of NetworkRequests that UID has filed.
3906     @GuardedBy("mUidToNetworkRequestCount")
3907     private final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray();
3908 
3909     private static class NetworkFactoryInfo {
3910         public final String name;
3911         public final Messenger messenger;
3912         public final AsyncChannel asyncChannel;
3913 
NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel)3914         public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
3915             this.name = name;
3916             this.messenger = messenger;
3917             this.asyncChannel = asyncChannel;
3918         }
3919     }
3920 
ensureNetworkRequestHasType(NetworkRequest request)3921     private void ensureNetworkRequestHasType(NetworkRequest request) {
3922         if (request.type == NetworkRequest.Type.NONE) {
3923             throw new IllegalArgumentException(
3924                     "All NetworkRequests in ConnectivityService must have a type");
3925         }
3926     }
3927 
3928     /**
3929      * Tracks info about the requester.
3930      * Also used to notice when the calling process dies so we can self-expire
3931      */
3932     private class NetworkRequestInfo implements IBinder.DeathRecipient {
3933         final NetworkRequest request;
3934         final PendingIntent mPendingIntent;
3935         boolean mPendingIntentSent;
3936         private final IBinder mBinder;
3937         final int mPid;
3938         final int mUid;
3939         final Messenger messenger;
3940 
NetworkRequestInfo(NetworkRequest r, PendingIntent pi)3941         NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
3942             request = r;
3943             ensureNetworkRequestHasType(request);
3944             mPendingIntent = pi;
3945             messenger = null;
3946             mBinder = null;
3947             mPid = getCallingPid();
3948             mUid = getCallingUid();
3949             enforceRequestCountLimit();
3950         }
3951 
NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder)3952         NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder) {
3953             super();
3954             messenger = m;
3955             request = r;
3956             ensureNetworkRequestHasType(request);
3957             mBinder = binder;
3958             mPid = getCallingPid();
3959             mUid = getCallingUid();
3960             mPendingIntent = null;
3961             enforceRequestCountLimit();
3962 
3963             try {
3964                 mBinder.linkToDeath(this, 0);
3965             } catch (RemoteException e) {
3966                 binderDied();
3967             }
3968         }
3969 
enforceRequestCountLimit()3970         private void enforceRequestCountLimit() {
3971             synchronized (mUidToNetworkRequestCount) {
3972                 int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
3973                 if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) {
3974                     throw new IllegalArgumentException("Too many NetworkRequests filed");
3975                 }
3976                 mUidToNetworkRequestCount.put(mUid, networkRequests);
3977             }
3978         }
3979 
unlinkDeathRecipient()3980         void unlinkDeathRecipient() {
3981             if (mBinder != null) {
3982                 mBinder.unlinkToDeath(this, 0);
3983             }
3984         }
3985 
binderDied()3986         public void binderDied() {
3987             log("ConnectivityService NetworkRequestInfo binderDied(" +
3988                     request + ", " + mBinder + ")");
3989             releaseNetworkRequest(request);
3990         }
3991 
toString()3992         public String toString() {
3993             return "uid/pid:" + mUid + "/" + mPid + " " + request +
3994                     (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
3995         }
3996     }
3997 
ensureRequestableCapabilities(NetworkCapabilities networkCapabilities)3998     private void ensureRequestableCapabilities(NetworkCapabilities networkCapabilities) {
3999         final String badCapability = networkCapabilities.describeFirstNonRequestableCapability();
4000         if (badCapability != null) {
4001             throw new IllegalArgumentException("Cannot request network with " + badCapability);
4002         }
4003     }
4004 
getSignalStrengthThresholds(NetworkAgentInfo nai)4005     private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
4006         final SortedSet<Integer> thresholds = new TreeSet();
4007         synchronized (nai) {
4008             for (NetworkRequestInfo nri : mNetworkRequests.values()) {
4009                 if (nri.request.networkCapabilities.hasSignalStrength() &&
4010                         nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
4011                     thresholds.add(nri.request.networkCapabilities.getSignalStrength());
4012                 }
4013             }
4014         }
4015         return new ArrayList<Integer>(thresholds);
4016     }
4017 
updateSignalStrengthThresholds( NetworkAgentInfo nai, String reason, NetworkRequest request)4018     private void updateSignalStrengthThresholds(
4019             NetworkAgentInfo nai, String reason, NetworkRequest request) {
4020         ArrayList<Integer> thresholdsArray = getSignalStrengthThresholds(nai);
4021         Bundle thresholds = new Bundle();
4022         thresholds.putIntegerArrayList("thresholds", thresholdsArray);
4023 
4024         if (VDBG || (DBG && !"CONNECT".equals(reason))) {
4025             String detail;
4026             if (request != null && request.networkCapabilities.hasSignalStrength()) {
4027                 detail = reason + " " + request.networkCapabilities.getSignalStrength();
4028             } else {
4029                 detail = reason;
4030             }
4031             log(String.format("updateSignalStrengthThresholds: %s, sending %s to %s",
4032                     detail, Arrays.toString(thresholdsArray.toArray()), nai.name()));
4033         }
4034 
4035         nai.asyncChannel.sendMessage(
4036                 android.net.NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS,
4037                 0, 0, thresholds);
4038     }
4039 
4040     @Override
requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType)4041     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
4042             Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
4043         final NetworkRequest.Type type = (networkCapabilities == null)
4044                 ? NetworkRequest.Type.TRACK_DEFAULT
4045                 : NetworkRequest.Type.REQUEST;
4046         // If the requested networkCapabilities is null, take them instead from
4047         // the default network request. This allows callers to keep track of
4048         // the system default network.
4049         if (type == NetworkRequest.Type.TRACK_DEFAULT) {
4050             networkCapabilities = new NetworkCapabilities(mDefaultRequest.networkCapabilities);
4051             enforceAccessPermission();
4052         } else {
4053             networkCapabilities = new NetworkCapabilities(networkCapabilities);
4054             enforceNetworkRequestPermissions(networkCapabilities);
4055             // TODO: this is incorrect. We mark the request as metered or not depending on the state
4056             // of the app when the request is filed, but we never change the request if the app
4057             // changes network state. http://b/29964605
4058             enforceMeteredApnPolicy(networkCapabilities);
4059         }
4060         ensureRequestableCapabilities(networkCapabilities);
4061 
4062         if (timeoutMs < 0) {
4063             throw new IllegalArgumentException("Bad timeout specified");
4064         }
4065 
4066         MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
4067                 networkCapabilities.getNetworkSpecifier());
4068 
4069         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
4070                 nextNetworkRequestId(), type);
4071         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
4072         if (DBG) log("requestNetwork for " + nri);
4073 
4074         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
4075         if (timeoutMs > 0) {
4076             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
4077                     nri), timeoutMs);
4078         }
4079         return networkRequest;
4080     }
4081 
enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities)4082     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
4083         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
4084             enforceConnectivityRestrictedNetworksPermission();
4085         } else {
4086             enforceChangePermission();
4087         }
4088     }
4089 
4090     @Override
requestBandwidthUpdate(Network network)4091     public boolean requestBandwidthUpdate(Network network) {
4092         enforceAccessPermission();
4093         NetworkAgentInfo nai = null;
4094         if (network == null) {
4095             return false;
4096         }
4097         synchronized (mNetworkForNetId) {
4098             nai = mNetworkForNetId.get(network.netId);
4099         }
4100         if (nai != null) {
4101             nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
4102             return true;
4103         }
4104         return false;
4105     }
4106 
isSystem(int uid)4107     private boolean isSystem(int uid) {
4108         return uid < Process.FIRST_APPLICATION_UID;
4109     }
4110 
enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities)4111     private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
4112         final int uid = Binder.getCallingUid();
4113         if (isSystem(uid)) {
4114             // Exemption for system uid.
4115             return;
4116         }
4117         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
4118             // Policy already enforced.
4119             return;
4120         }
4121         if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
4122             // If UID is restricted, don't allow them to bring up metered APNs.
4123             networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
4124         }
4125     }
4126 
4127     @Override
pendingRequestForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation)4128     public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
4129             PendingIntent operation) {
4130         checkNotNull(operation, "PendingIntent cannot be null.");
4131         networkCapabilities = new NetworkCapabilities(networkCapabilities);
4132         enforceNetworkRequestPermissions(networkCapabilities);
4133         enforceMeteredApnPolicy(networkCapabilities);
4134         ensureRequestableCapabilities(networkCapabilities);
4135 
4136         MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
4137                 networkCapabilities.getNetworkSpecifier());
4138 
4139         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
4140                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
4141         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
4142         if (DBG) log("pendingRequest for " + nri);
4143         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
4144                 nri));
4145         return networkRequest;
4146     }
4147 
releasePendingNetworkRequestWithDelay(PendingIntent operation)4148     private void releasePendingNetworkRequestWithDelay(PendingIntent operation) {
4149         mHandler.sendMessageDelayed(
4150                 mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
4151                 getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
4152     }
4153 
4154     @Override
releasePendingNetworkRequest(PendingIntent operation)4155     public void releasePendingNetworkRequest(PendingIntent operation) {
4156         checkNotNull(operation, "PendingIntent cannot be null.");
4157         mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
4158                 getCallingUid(), 0, operation));
4159     }
4160 
4161     // In order to implement the compatibility measure for pre-M apps that call
4162     // WifiManager.enableNetwork(..., true) without also binding to that network explicitly,
4163     // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork.
4164     // This ensures it has permission to do so.
hasWifiNetworkListenPermission(NetworkCapabilities nc)4165     private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) {
4166         if (nc == null) {
4167             return false;
4168         }
4169         int[] transportTypes = nc.getTransportTypes();
4170         if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) {
4171             return false;
4172         }
4173         try {
4174             mContext.enforceCallingOrSelfPermission(
4175                     android.Manifest.permission.ACCESS_WIFI_STATE,
4176                     "ConnectivityService");
4177         } catch (SecurityException e) {
4178             return false;
4179         }
4180         return true;
4181     }
4182 
4183     @Override
listenForNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, IBinder binder)4184     public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
4185             Messenger messenger, IBinder binder) {
4186         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
4187             enforceAccessPermission();
4188         }
4189 
4190         NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
4191         if (!ConnectivityManager.checkChangePermission(mContext)) {
4192             // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
4193             // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
4194             // onLost and onAvailable callbacks when networks move in and out of the background.
4195             // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
4196             // can't request networks.
4197             nc.addCapability(NET_CAPABILITY_FOREGROUND);
4198         }
4199 
4200         MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
4201                 networkCapabilities.getNetworkSpecifier());
4202 
4203         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
4204                 NetworkRequest.Type.LISTEN);
4205         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
4206         if (VDBG) log("listenForNetwork for " + nri);
4207 
4208         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
4209         return networkRequest;
4210     }
4211 
4212     @Override
pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation)4213     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
4214             PendingIntent operation) {
4215         checkNotNull(operation, "PendingIntent cannot be null.");
4216         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
4217             enforceAccessPermission();
4218         }
4219 
4220         MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
4221                 networkCapabilities.getNetworkSpecifier());
4222 
4223         NetworkRequest networkRequest = new NetworkRequest(
4224                 new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(),
4225                 NetworkRequest.Type.LISTEN);
4226         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
4227         if (VDBG) log("pendingListenForNetwork for " + nri);
4228 
4229         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
4230     }
4231 
4232     @Override
releaseNetworkRequest(NetworkRequest networkRequest)4233     public void releaseNetworkRequest(NetworkRequest networkRequest) {
4234         ensureNetworkRequestHasType(networkRequest);
4235         mHandler.sendMessage(mHandler.obtainMessage(
4236                 EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
4237     }
4238 
4239     @Override
registerNetworkFactory(Messenger messenger, String name)4240     public void registerNetworkFactory(Messenger messenger, String name) {
4241         enforceConnectivityInternalPermission();
4242         NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
4243         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
4244     }
4245 
handleRegisterNetworkFactory(NetworkFactoryInfo nfi)4246     private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
4247         if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
4248         mNetworkFactoryInfos.put(nfi.messenger, nfi);
4249         nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
4250     }
4251 
4252     @Override
unregisterNetworkFactory(Messenger messenger)4253     public void unregisterNetworkFactory(Messenger messenger) {
4254         enforceConnectivityInternalPermission();
4255         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
4256     }
4257 
handleUnregisterNetworkFactory(Messenger messenger)4258     private void handleUnregisterNetworkFactory(Messenger messenger) {
4259         NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
4260         if (nfi == null) {
4261             loge("Failed to find Messenger in unregisterNetworkFactory");
4262             return;
4263         }
4264         if (DBG) log("unregisterNetworkFactory for " + nfi.name);
4265     }
4266 
4267     /**
4268      * NetworkAgentInfo supporting a request by requestId.
4269      * These have already been vetted (their Capabilities satisfy the request)
4270      * and the are the highest scored network available.
4271      * the are keyed off the Requests requestId.
4272      */
4273     // TODO: Yikes, this is accessed on multiple threads: add synchronization.
4274     private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =
4275             new SparseArray<NetworkAgentInfo>();
4276 
4277     // NOTE: Accessed on multiple threads, must be synchronized on itself.
4278     @GuardedBy("mNetworkForNetId")
4279     private final SparseArray<NetworkAgentInfo> mNetworkForNetId =
4280             new SparseArray<NetworkAgentInfo>();
4281     // NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
4282     // An entry is first added to mNetIdInUse, prior to mNetworkForNetId, so
4283     // there may not be a strict 1:1 correlation between the two.
4284     @GuardedBy("mNetworkForNetId")
4285     private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
4286 
4287     // NetworkAgentInfo keyed off its connecting messenger
4288     // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
4289     // NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
4290     private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =
4291             new HashMap<Messenger, NetworkAgentInfo>();
4292 
4293     @GuardedBy("mBlockedAppUids")
4294     private final HashSet<Integer> mBlockedAppUids = new HashSet();
4295 
4296     // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
4297     private final NetworkRequest mDefaultRequest;
4298 
4299     // Request used to optionally keep mobile data active even when higher
4300     // priority networks like Wi-Fi are active.
4301     private final NetworkRequest mDefaultMobileDataRequest;
4302 
getDefaultNetwork()4303     private NetworkAgentInfo getDefaultNetwork() {
4304         return mNetworkForRequestId.get(mDefaultRequest.requestId);
4305     }
4306 
isDefaultNetwork(NetworkAgentInfo nai)4307     private boolean isDefaultNetwork(NetworkAgentInfo nai) {
4308         return nai == getDefaultNetwork();
4309     }
4310 
isDefaultRequest(NetworkRequestInfo nri)4311     private boolean isDefaultRequest(NetworkRequestInfo nri) {
4312         return nri.request.requestId == mDefaultRequest.requestId;
4313     }
4314 
registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc)4315     public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
4316             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
4317             int currentScore, NetworkMisc networkMisc) {
4318         enforceConnectivityInternalPermission();
4319 
4320         // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
4321         // satisfies mDefaultRequest.
4322         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
4323                 new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
4324                 linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
4325                 mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
4326         synchronized (this) {
4327             nai.networkMonitor.systemReady = mSystemReady;
4328         }
4329         addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network,
4330                 networkInfo.getExtraInfo());
4331         if (DBG) log("registerNetworkAgent " + nai);
4332         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
4333         return nai.network.netId;
4334     }
4335 
handleRegisterNetworkAgent(NetworkAgentInfo na)4336     private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
4337         if (VDBG) log("Got NetworkAgent Messenger");
4338         mNetworkAgentInfos.put(na.messenger, na);
4339         synchronized (mNetworkForNetId) {
4340             mNetworkForNetId.put(na.network.netId, na);
4341         }
4342         na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
4343         NetworkInfo networkInfo = na.networkInfo;
4344         na.networkInfo = null;
4345         updateNetworkInfo(na, networkInfo);
4346     }
4347 
updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp)4348     private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp) {
4349         LinkProperties newLp = networkAgent.linkProperties;
4350         int netId = networkAgent.network.netId;
4351 
4352         // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before
4353         // we do anything else, make sure its LinkProperties are accurate.
4354         if (networkAgent.clatd != null) {
4355             networkAgent.clatd.fixupLinkProperties(oldLp);
4356         }
4357 
4358         updateInterfaces(newLp, oldLp, netId);
4359         updateMtu(newLp, oldLp);
4360         // TODO - figure out what to do for clat
4361 //        for (LinkProperties lp : newLp.getStackedLinks()) {
4362 //            updateMtu(lp, null);
4363 //        }
4364         updateTcpBufferSizes(networkAgent);
4365 
4366         updateRoutes(newLp, oldLp, netId);
4367         updateDnses(newLp, oldLp, netId);
4368 
4369         updateClat(newLp, oldLp, networkAgent);
4370         if (isDefaultNetwork(networkAgent)) {
4371             handleApplyDefaultProxy(newLp.getHttpProxy());
4372         } else {
4373             updateProxy(newLp, oldLp, networkAgent);
4374         }
4375         // TODO - move this check to cover the whole function
4376         if (!Objects.equals(newLp, oldLp)) {
4377             notifyIfacesChangedForNetworkStats();
4378             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
4379         }
4380 
4381         mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
4382     }
4383 
updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai)4384     private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) {
4385         final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted();
4386         final boolean shouldRunClat = Nat464Xlat.requiresClat(nai);
4387 
4388         if (!wasRunningClat && shouldRunClat) {
4389             nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai);
4390             nai.clatd.start();
4391         } else if (wasRunningClat && !shouldRunClat) {
4392             nai.clatd.stop();
4393         }
4394     }
4395 
updateInterfaces(LinkProperties newLp, LinkProperties oldLp, int netId)4396     private void updateInterfaces(LinkProperties newLp, LinkProperties oldLp, int netId) {
4397         CompareResult<String> interfaceDiff = new CompareResult<String>();
4398         if (oldLp != null) {
4399             interfaceDiff = oldLp.compareAllInterfaceNames(newLp);
4400         } else if (newLp != null) {
4401             interfaceDiff.added = newLp.getAllInterfaceNames();
4402         }
4403         for (String iface : interfaceDiff.added) {
4404             try {
4405                 if (DBG) log("Adding iface " + iface + " to network " + netId);
4406                 mNetd.addInterfaceToNetwork(iface, netId);
4407             } catch (Exception e) {
4408                 loge("Exception adding interface: " + e);
4409             }
4410         }
4411         for (String iface : interfaceDiff.removed) {
4412             try {
4413                 if (DBG) log("Removing iface " + iface + " from network " + netId);
4414                 mNetd.removeInterfaceFromNetwork(iface, netId);
4415             } catch (Exception e) {
4416                 loge("Exception removing interface: " + e);
4417             }
4418         }
4419     }
4420 
4421     /**
4422      * Have netd update routes from oldLp to newLp.
4423      * @return true if routes changed between oldLp and newLp
4424      */
updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId)4425     private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
4426         CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
4427         if (oldLp != null) {
4428             routeDiff = oldLp.compareAllRoutes(newLp);
4429         } else if (newLp != null) {
4430             routeDiff.added = newLp.getAllRoutes();
4431         }
4432 
4433         // add routes before removing old in case it helps with continuous connectivity
4434 
4435         // do this twice, adding non-nexthop routes first, then routes they are dependent on
4436         for (RouteInfo route : routeDiff.added) {
4437             if (route.hasGateway()) continue;
4438             if (VDBG) log("Adding Route [" + route + "] to network " + netId);
4439             try {
4440                 mNetd.addRoute(netId, route);
4441             } catch (Exception e) {
4442                 if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
4443                     loge("Exception in addRoute for non-gateway: " + e);
4444                 }
4445             }
4446         }
4447         for (RouteInfo route : routeDiff.added) {
4448             if (route.hasGateway() == false) continue;
4449             if (VDBG) log("Adding Route [" + route + "] to network " + netId);
4450             try {
4451                 mNetd.addRoute(netId, route);
4452             } catch (Exception e) {
4453                 if ((route.getGateway() instanceof Inet4Address) || VDBG) {
4454                     loge("Exception in addRoute for gateway: " + e);
4455                 }
4456             }
4457         }
4458 
4459         for (RouteInfo route : routeDiff.removed) {
4460             if (VDBG) log("Removing Route [" + route + "] from network " + netId);
4461             try {
4462                 mNetd.removeRoute(netId, route);
4463             } catch (Exception e) {
4464                 loge("Exception in removeRoute: " + e);
4465             }
4466         }
4467         return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
4468     }
4469 
updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId)4470     private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
4471         if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
4472             return;  // no updating necessary
4473         }
4474 
4475         Collection<InetAddress> dnses = newLp.getDnsServers();
4476         if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses);
4477         try {
4478             mNetd.setDnsConfigurationForNetwork(
4479                     netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
4480         } catch (Exception e) {
4481             loge("Exception in setDnsConfigurationForNetwork: " + e);
4482         }
4483         final NetworkAgentInfo defaultNai = getDefaultNetwork();
4484         if (defaultNai != null && defaultNai.network.netId == netId) {
4485             setDefaultDnsSystemProperties(dnses);
4486         }
4487         flushVmDnsCache();
4488     }
4489 
setDefaultDnsSystemProperties(Collection<InetAddress> dnses)4490     private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
4491         int last = 0;
4492         for (InetAddress dns : dnses) {
4493             ++last;
4494             setNetDnsProperty(last, dns.getHostAddress());
4495         }
4496         for (int i = last + 1; i <= mNumDnsEntries; ++i) {
4497             setNetDnsProperty(i, "");
4498         }
4499         mNumDnsEntries = last;
4500     }
4501 
setNetDnsProperty(int which, String value)4502     private void setNetDnsProperty(int which, String value) {
4503         final String key = "net.dns" + which;
4504         // Log and forget errors setting unsupported properties.
4505         try {
4506             mSystemProperties.set(key, value);
4507         } catch (Exception e) {
4508             Log.e(TAG, "Error setting unsupported net.dns property: ", e);
4509         }
4510     }
4511 
getNetworkPermission(NetworkCapabilities nc)4512     private String getNetworkPermission(NetworkCapabilities nc) {
4513         // TODO: make these permission strings AIDL constants instead.
4514         if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
4515             return NetworkManagementService.PERMISSION_SYSTEM;
4516         }
4517         if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) {
4518             return NetworkManagementService.PERMISSION_NETWORK;
4519         }
4520         return null;
4521     }
4522 
4523     /**
4524      * Update the NetworkCapabilities for {@code networkAgent} to {@code networkCapabilities}
4525      * augmented with any stateful capabilities implied from {@code networkAgent}
4526      * (e.g., validated status and captive portal status).
4527      *
4528      * @param oldScore score of the network before any of the changes that prompted us
4529      *                 to call this function.
4530      * @param nai the network having its capabilities updated.
4531      * @param networkCapabilities the new network capabilities.
4532      */
updateCapabilities( int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities)4533     private void updateCapabilities(
4534             int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
4535         if (nai.everConnected && !nai.networkCapabilities.equalImmutableCapabilities(
4536                 networkCapabilities)) {
4537             Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities: "
4538                     + nai.networkCapabilities + " -> " + networkCapabilities);
4539         }
4540 
4541         // Don't modify caller's NetworkCapabilities.
4542         networkCapabilities = new NetworkCapabilities(networkCapabilities);
4543         if (nai.lastValidated) {
4544             networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
4545         } else {
4546             networkCapabilities.removeCapability(NET_CAPABILITY_VALIDATED);
4547         }
4548         if (nai.lastCaptivePortalDetected) {
4549             networkCapabilities.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
4550         } else {
4551             networkCapabilities.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
4552         }
4553         if (nai.isBackgroundNetwork()) {
4554             networkCapabilities.removeCapability(NET_CAPABILITY_FOREGROUND);
4555         } else {
4556             networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
4557         }
4558 
4559         if (Objects.equals(nai.networkCapabilities, networkCapabilities)) return;
4560 
4561         final String oldPermission = getNetworkPermission(nai.networkCapabilities);
4562         final String newPermission = getNetworkPermission(networkCapabilities);
4563         if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) {
4564             try {
4565                 mNetd.setNetworkPermission(nai.network.netId, newPermission);
4566             } catch (RemoteException e) {
4567                 loge("Exception in setNetworkPermission: " + e);
4568             }
4569         }
4570 
4571         final NetworkCapabilities prevNc = nai.networkCapabilities;
4572         synchronized (nai) {
4573             nai.networkCapabilities = networkCapabilities;
4574         }
4575         if (nai.getCurrentScore() == oldScore &&
4576                 networkCapabilities.equalRequestableCapabilities(prevNc)) {
4577             // If the requestable capabilities haven't changed, and the score hasn't changed, then
4578             // the change we're processing can't affect any requests, it can only affect the listens
4579             // on this network. We might have been called by rematchNetworkAndRequests when a
4580             // network changed foreground state.
4581             processListenRequests(nai, true);
4582         } else {
4583             // If the requestable capabilities have changed or the score changed, we can't have been
4584             // called by rematchNetworkAndRequests, so it's safe to start a rematch.
4585             rematchAllNetworksAndRequests(nai, oldScore);
4586             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
4587         }
4588     }
4589 
sendUpdatedScoreToFactories(NetworkAgentInfo nai)4590     private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
4591         for (int i = 0; i < nai.numNetworkRequests(); i++) {
4592             NetworkRequest nr = nai.requestAt(i);
4593             // Don't send listening requests to factories. b/17393458
4594             if (nr.isListen()) continue;
4595             sendUpdatedScoreToFactories(nr, nai.getCurrentScore());
4596         }
4597     }
4598 
sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score)4599     private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
4600         if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
4601         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
4602             nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
4603                     networkRequest);
4604         }
4605     }
4606 
sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent, int notificationType)4607     private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
4608             int notificationType) {
4609         if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) {
4610             Intent intent = new Intent();
4611             intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network);
4612             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.request);
4613             nri.mPendingIntentSent = true;
4614             sendIntent(nri.mPendingIntent, intent);
4615         }
4616         // else not handled
4617     }
4618 
sendIntent(PendingIntent pendingIntent, Intent intent)4619     private void sendIntent(PendingIntent pendingIntent, Intent intent) {
4620         mPendingIntentWakeLock.acquire();
4621         try {
4622             if (DBG) log("Sending " + pendingIntent);
4623             pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */);
4624         } catch (PendingIntent.CanceledException e) {
4625             if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
4626             mPendingIntentWakeLock.release();
4627             releasePendingNetworkRequest(pendingIntent);
4628         }
4629         // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
4630     }
4631 
4632     @Override
onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)4633     public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
4634             String resultData, Bundle resultExtras) {
4635         if (DBG) log("Finished sending " + pendingIntent);
4636         mPendingIntentWakeLock.release();
4637         // Release with a delay so the receiving client has an opportunity to put in its
4638         // own request.
4639         releasePendingNetworkRequestWithDelay(pendingIntent);
4640     }
4641 
callCallbackForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent, int notificationType, int arg1)4642     private void callCallbackForRequest(NetworkRequestInfo nri,
4643             NetworkAgentInfo networkAgent, int notificationType, int arg1) {
4644         if (nri.messenger == null) return;  // Default request has no msgr
4645         Bundle bundle = new Bundle();
4646         bundle.putParcelable(NetworkRequest.class.getSimpleName(),
4647                 new NetworkRequest(nri.request));
4648         Message msg = Message.obtain();
4649         if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL &&
4650                 notificationType != ConnectivityManager.CALLBACK_RELEASED) {
4651             bundle.putParcelable(Network.class.getSimpleName(), networkAgent.network);
4652         }
4653         switch (notificationType) {
4654             case ConnectivityManager.CALLBACK_LOSING: {
4655                 msg.arg1 = arg1;
4656                 break;
4657             }
4658             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
4659                 bundle.putParcelable(NetworkCapabilities.class.getSimpleName(),
4660                         new NetworkCapabilities(networkAgent.networkCapabilities));
4661                 break;
4662             }
4663             case ConnectivityManager.CALLBACK_IP_CHANGED: {
4664                 bundle.putParcelable(LinkProperties.class.getSimpleName(),
4665                         new LinkProperties(networkAgent.linkProperties));
4666                 break;
4667             }
4668         }
4669         msg.what = notificationType;
4670         msg.setData(bundle);
4671         try {
4672             if (VDBG) {
4673                 log("sending notification " + notifyTypeToName(notificationType) +
4674                         " for " + nri.request);
4675             }
4676             nri.messenger.send(msg);
4677         } catch (RemoteException e) {
4678             // may occur naturally in the race of binder death.
4679             loge("RemoteException caught trying to send a callback msg for " + nri.request);
4680         }
4681     }
4682 
teardownUnneededNetwork(NetworkAgentInfo nai)4683     private void teardownUnneededNetwork(NetworkAgentInfo nai) {
4684         if (nai.numRequestNetworkRequests() != 0) {
4685             for (int i = 0; i < nai.numNetworkRequests(); i++) {
4686                 NetworkRequest nr = nai.requestAt(i);
4687                 // Ignore listening requests.
4688                 if (nr.isListen()) continue;
4689                 loge("Dead network still had at least " + nr);
4690                 break;
4691             }
4692         }
4693         nai.asyncChannel.disconnect();
4694     }
4695 
handleLingerComplete(NetworkAgentInfo oldNetwork)4696     private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
4697         if (oldNetwork == null) {
4698             loge("Unknown NetworkAgentInfo in handleLingerComplete");
4699             return;
4700         }
4701         if (DBG) log("handleLingerComplete for " + oldNetwork.name());
4702 
4703         // If we get here it means that the last linger timeout for this network expired. So there
4704         // must be no other active linger timers, and we must stop lingering.
4705         oldNetwork.clearLingerState();
4706 
4707         if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) {
4708             // Tear the network down.
4709             teardownUnneededNetwork(oldNetwork);
4710         } else {
4711             // Put the network in the background.
4712             updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork,
4713                     oldNetwork.networkCapabilities);
4714         }
4715     }
4716 
makeDefault(NetworkAgentInfo newNetwork)4717     private void makeDefault(NetworkAgentInfo newNetwork) {
4718         if (DBG) log("Switching to new default network: " + newNetwork);
4719         setupDataActivityTracking(newNetwork);
4720         try {
4721             mNetd.setDefaultNetId(newNetwork.network.netId);
4722         } catch (Exception e) {
4723             loge("Exception setting default network :" + e);
4724         }
4725         notifyLockdownVpn(newNetwork);
4726         handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
4727         updateTcpBufferSizes(newNetwork);
4728         setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
4729     }
4730 
processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged)4731     private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
4732         // For consistency with previous behaviour, send onLost callbacks before onAvailable.
4733         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
4734             NetworkRequest nr = nri.request;
4735             if (!nr.isListen()) continue;
4736             if (nai.isSatisfyingRequest(nr.requestId) && !nai.satisfies(nr)) {
4737                 nai.removeRequest(nri.request.requestId);
4738                 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
4739             }
4740         }
4741 
4742         if (capabilitiesChanged) {
4743             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
4744         }
4745 
4746         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
4747             NetworkRequest nr = nri.request;
4748             if (!nr.isListen()) continue;
4749             if (nai.satisfies(nr) && !nai.isSatisfyingRequest(nr.requestId)) {
4750                 nai.addRequest(nr);
4751                 notifyNetworkAvailable(nai, nri);
4752             }
4753         }
4754     }
4755 
4756     // Handles a network appearing or improving its score.
4757     //
4758     // - Evaluates all current NetworkRequests that can be
4759     //   satisfied by newNetwork, and reassigns to newNetwork
4760     //   any such requests for which newNetwork is the best.
4761     //
4762     // - Lingers any validated Networks that as a result are no longer
4763     //   needed. A network is needed if it is the best network for
4764     //   one or more NetworkRequests, or if it is a VPN.
4765     //
4766     // - Tears down newNetwork if it just became validated
4767     //   but turns out to be unneeded.
4768     //
4769     // - If reapUnvalidatedNetworks==REAP, tears down unvalidated
4770     //   networks that have no chance (i.e. even if validated)
4771     //   of becoming the highest scoring network.
4772     //
4773     // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
4774     // it does not remove NetworkRequests that other Networks could better satisfy.
4775     // If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
4776     // This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
4777     // as it performs better by a factor of the number of Networks.
4778     //
4779     // @param newNetwork is the network to be matched against NetworkRequests.
4780     // @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
4781     //               performed to tear down unvalidated networks that have no chance (i.e. even if
4782     //               validated) of becoming the highest scoring network.
rematchNetworkAndRequests(NetworkAgentInfo newNetwork, ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now)4783     private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
4784             ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
4785         if (!newNetwork.everConnected) return;
4786         boolean keep = newNetwork.isVPN();
4787         boolean isNewDefault = false;
4788         NetworkAgentInfo oldDefaultNetwork = null;
4789 
4790         final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
4791         final int score = newNetwork.getCurrentScore();
4792 
4793         if (VDBG) log("rematching " + newNetwork.name());
4794 
4795         // Find and migrate to this Network any NetworkRequests for
4796         // which this network is now the best.
4797         ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
4798         ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<NetworkRequestInfo>();
4799         NetworkCapabilities nc = newNetwork.networkCapabilities;
4800         if (VDBG) log(" network has: " + nc);
4801         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
4802             // Process requests in the first pass and listens in the second pass. This allows us to
4803             // change a network's capabilities depending on which requests it has. This is only
4804             // correct if the change in capabilities doesn't affect whether the network satisfies
4805             // requests or not, and doesn't affect the network's score.
4806             if (nri.request.isListen()) continue;
4807 
4808             final NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
4809             final boolean satisfies = newNetwork.satisfies(nri.request);
4810             if (newNetwork == currentNetwork && satisfies) {
4811                 if (VDBG) {
4812                     log("Network " + newNetwork.name() + " was already satisfying" +
4813                             " request " + nri.request.requestId + ". No change.");
4814                 }
4815                 keep = true;
4816                 continue;
4817             }
4818 
4819             // check if it satisfies the NetworkCapabilities
4820             if (VDBG) log("  checking if request is satisfied: " + nri.request);
4821             if (satisfies) {
4822                 // next check if it's better than any current network we're using for
4823                 // this request
4824                 if (VDBG) {
4825                     log("currentScore = " +
4826                             (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
4827                             ", newScore = " + score);
4828                 }
4829                 if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
4830                     if (VDBG) log("rematch for " + newNetwork.name());
4831                     if (currentNetwork != null) {
4832                         if (VDBG) log("   accepting network in place of " + currentNetwork.name());
4833                         currentNetwork.removeRequest(nri.request.requestId);
4834                         currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
4835                         affectedNetworks.add(currentNetwork);
4836                     } else {
4837                         if (VDBG) log("   accepting network in place of null");
4838                     }
4839                     newNetwork.unlingerRequest(nri.request);
4840                     mNetworkForRequestId.put(nri.request.requestId, newNetwork);
4841                     if (!newNetwork.addRequest(nri.request)) {
4842                         Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
4843                     }
4844                     addedRequests.add(nri);
4845                     keep = true;
4846                     // Tell NetworkFactories about the new score, so they can stop
4847                     // trying to connect if they know they cannot match it.
4848                     // TODO - this could get expensive if we have alot of requests for this
4849                     // network.  Think about if there is a way to reduce this.  Push
4850                     // netid->request mapping to each factory?
4851                     sendUpdatedScoreToFactories(nri.request, score);
4852                     if (isDefaultRequest(nri)) {
4853                         isNewDefault = true;
4854                         oldDefaultNetwork = currentNetwork;
4855                         if (currentNetwork != null) {
4856                             mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
4857                         }
4858                     }
4859                 }
4860             } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
4861                 // If "newNetwork" is listed as satisfying "nri" but no longer satisfies "nri",
4862                 // mark it as no longer satisfying "nri".  Because networks are processed by
4863                 // rematchAllNetworksAndRequests() in descending score order, "currentNetwork" will
4864                 // match "newNetwork" before this loop will encounter a "currentNetwork" with higher
4865                 // score than "newNetwork" and where "currentNetwork" no longer satisfies "nri".
4866                 // This means this code doesn't have to handle the case where "currentNetwork" no
4867                 // longer satisfies "nri" when "currentNetwork" does not equal "newNetwork".
4868                 if (DBG) {
4869                     log("Network " + newNetwork.name() + " stopped satisfying" +
4870                             " request " + nri.request.requestId);
4871                 }
4872                 newNetwork.removeRequest(nri.request.requestId);
4873                 if (currentNetwork == newNetwork) {
4874                     mNetworkForRequestId.remove(nri.request.requestId);
4875                     sendUpdatedScoreToFactories(nri.request, 0);
4876                 } else {
4877                     Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
4878                             newNetwork.name() +
4879                             " without updating mNetworkForRequestId or factories!");
4880                 }
4881                 // TODO: Technically, sending CALLBACK_LOST here is
4882                 // incorrect if there is a replacement network currently
4883                 // connected that can satisfy nri, which is a request
4884                 // (not a listen). However, the only capability that can both
4885                 // a) be requested and b) change is NET_CAPABILITY_TRUSTED,
4886                 // so this code is only incorrect for a network that loses
4887                 // the TRUSTED capability, which is a rare case.
4888                 callCallbackForRequest(nri, newNetwork, ConnectivityManager.CALLBACK_LOST, 0);
4889             }
4890         }
4891         if (isNewDefault) {
4892             // Notify system services that this network is up.
4893             makeDefault(newNetwork);
4894             // Log 0 -> X and Y -> X default network transitions, where X is the new default.
4895             logDefaultNetworkEvent(newNetwork, oldDefaultNetwork);
4896             synchronized (ConnectivityService.this) {
4897                 // have a new default network, release the transition wakelock in
4898                 // a second if it's held.  The second pause is to allow apps
4899                 // to reconnect over the new network
4900                 if (mNetTransitionWakeLock.isHeld()) {
4901                     mHandler.sendMessageDelayed(mHandler.obtainMessage(
4902                             EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
4903                             mNetTransitionWakeLockSerialNumber, 0),
4904                             1000);
4905                 }
4906             }
4907         }
4908 
4909         if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {
4910             Slog.wtf(TAG, String.format(
4911                     "BUG: %s changed requestable capabilities during rematch: %s -> %s",
4912                     nc, newNetwork.networkCapabilities));
4913         }
4914         if (newNetwork.getCurrentScore() != score) {
4915             Slog.wtf(TAG, String.format(
4916                     "BUG: %s changed score during rematch: %d -> %d",
4917                     score, newNetwork.getCurrentScore()));
4918         }
4919 
4920         // Second pass: process all listens.
4921         if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
4922             // If the network went from background to foreground or vice versa, we need to update
4923             // its foreground state. It is safe to do this after rematching the requests because
4924             // NET_CAPABILITY_FOREGROUND does not affect requests, as is not a requestable
4925             // capability and does not affect the network's score (see the Slog.wtf call above).
4926             updateCapabilities(score, newNetwork, newNetwork.networkCapabilities);
4927         } else {
4928             processListenRequests(newNetwork, false);
4929         }
4930 
4931         // do this after the default net is switched, but
4932         // before LegacyTypeTracker sends legacy broadcasts
4933         for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
4934 
4935         // Linger any networks that are no longer needed. This should be done after sending the
4936         // available callback for newNetwork.
4937         for (NetworkAgentInfo nai : affectedNetworks) {
4938             updateLingerState(nai, now);
4939         }
4940         // Possibly unlinger newNetwork. Unlingering a network does not send any callbacks so it
4941         // does not need to be done in any particular order.
4942         updateLingerState(newNetwork, now);
4943 
4944         if (isNewDefault) {
4945             // Maintain the illusion: since the legacy API only
4946             // understands one network at a time, we must pretend
4947             // that the current default network disconnected before
4948             // the new one connected.
4949             if (oldDefaultNetwork != null) {
4950                 mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(),
4951                                           oldDefaultNetwork, true);
4952             }
4953             mDefaultInetConditionPublished = newNetwork.lastValidated ? 100 : 0;
4954             mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
4955             notifyLockdownVpn(newNetwork);
4956         }
4957 
4958         if (keep) {
4959             // Notify battery stats service about this network, both the normal
4960             // interface and any stacked links.
4961             // TODO: Avoid redoing this; this must only be done once when a network comes online.
4962             try {
4963                 final IBatteryStats bs = BatteryStatsService.getService();
4964                 final int type = newNetwork.networkInfo.getType();
4965 
4966                 final String baseIface = newNetwork.linkProperties.getInterfaceName();
4967                 bs.noteNetworkInterfaceType(baseIface, type);
4968                 for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
4969                     final String stackedIface = stacked.getInterfaceName();
4970                     bs.noteNetworkInterfaceType(stackedIface, type);
4971                     NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
4972                 }
4973             } catch (RemoteException ignored) {
4974             }
4975 
4976             // This has to happen after the notifyNetworkCallbacks as that tickles each
4977             // ConnectivityManager instance so that legacy requests correctly bind dns
4978             // requests to this network.  The legacy users are listening for this bcast
4979             // and will generally do a dns request so they can ensureRouteToHost and if
4980             // they do that before the callbacks happen they'll use the default network.
4981             //
4982             // TODO: Is there still a race here? We send the broadcast
4983             // after sending the callback, but if the app can receive the
4984             // broadcast before the callback, it might still break.
4985             //
4986             // This *does* introduce a race where if the user uses the new api
4987             // (notification callbacks) and then uses the old api (getNetworkInfo(type))
4988             // they may get old info.  Reverse this after the old startUsing api is removed.
4989             // This is on top of the multiple intent sequencing referenced in the todo above.
4990             for (int i = 0; i < newNetwork.numNetworkRequests(); i++) {
4991                 NetworkRequest nr = newNetwork.requestAt(i);
4992                 if (nr.legacyType != TYPE_NONE && nr.isRequest()) {
4993                     // legacy type tracker filters out repeat adds
4994                     mLegacyTypeTracker.add(nr.legacyType, newNetwork);
4995                 }
4996             }
4997 
4998             // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above,
4999             // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest
5000             // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the
5001             // newNetwork to the tracker explicitly (it's a no-op if it has already been added).
5002             if (newNetwork.isVPN()) {
5003                 mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
5004             }
5005         }
5006         if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
5007             for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
5008                 if (unneeded(nai, UnneededFor.TEARDOWN)) {
5009                     if (nai.getLingerExpiry() > 0) {
5010                         // This network has active linger timers and no requests, but is not
5011                         // lingering. Linger it.
5012                         //
5013                         // One way (the only way?) this can happen if this network is unvalidated
5014                         // and became unneeded due to another network improving its score to the
5015                         // point where this network will no longer be able to satisfy any requests
5016                         // even if it validates.
5017                         updateLingerState(nai, now);
5018                     } else {
5019                         if (DBG) log("Reaping " + nai.name());
5020                         teardownUnneededNetwork(nai);
5021                     }
5022                 }
5023             }
5024         }
5025     }
5026 
5027     /**
5028      * Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
5029      * being disconnected.
5030      * @param changed If only one Network's score or capabilities have been modified since the last
5031      *         time this function was called, pass this Network in this argument, otherwise pass
5032      *         null.
5033      * @param oldScore If only one Network has been changed but its NetworkCapabilities have not
5034      *         changed, pass in the Network's score (from getCurrentScore()) prior to the change via
5035      *         this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if
5036      *         {@code changed} is {@code null}. This is because NetworkCapabilities influence a
5037      *         network's score.
5038      */
rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore)5039     private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
5040         // TODO: This may get slow.  The "changed" parameter is provided for future optimization
5041         // to avoid the slowness.  It is not simply enough to process just "changed", for
5042         // example in the case where "changed"'s score decreases and another network should begin
5043         // satifying a NetworkRequest that "changed" currently satisfies.
5044 
5045         // Optimization: Only reprocess "changed" if its score improved.  This is safe because it
5046         // can only add more NetworkRequests satisfied by "changed", and this is exactly what
5047         // rematchNetworkAndRequests() handles.
5048         final long now = SystemClock.elapsedRealtime();
5049         if (changed != null && oldScore < changed.getCurrentScore()) {
5050             rematchNetworkAndRequests(changed, ReapUnvalidatedNetworks.REAP, now);
5051         } else {
5052             final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(
5053                     new NetworkAgentInfo[mNetworkAgentInfos.size()]);
5054             // Rematch higher scoring networks first to prevent requests first matching a lower
5055             // scoring network and then a higher scoring network, which could produce multiple
5056             // callbacks and inadvertently unlinger networks.
5057             Arrays.sort(nais);
5058             for (NetworkAgentInfo nai : nais) {
5059                 rematchNetworkAndRequests(nai,
5060                         // Only reap the last time through the loop.  Reaping before all rematching
5061                         // is complete could incorrectly teardown a network that hasn't yet been
5062                         // rematched.
5063                         (nai != nais[nais.length-1]) ? ReapUnvalidatedNetworks.DONT_REAP
5064                                 : ReapUnvalidatedNetworks.REAP,
5065                         now);
5066             }
5067         }
5068     }
5069 
updateInetCondition(NetworkAgentInfo nai)5070     private void updateInetCondition(NetworkAgentInfo nai) {
5071         // Don't bother updating until we've graduated to validated at least once.
5072         if (!nai.everValidated) return;
5073         // For now only update icons for default connection.
5074         // TODO: Update WiFi and cellular icons separately. b/17237507
5075         if (!isDefaultNetwork(nai)) return;
5076 
5077         int newInetCondition = nai.lastValidated ? 100 : 0;
5078         // Don't repeat publish.
5079         if (newInetCondition == mDefaultInetConditionPublished) return;
5080 
5081         mDefaultInetConditionPublished = newInetCondition;
5082         sendInetConditionBroadcast(nai.networkInfo);
5083     }
5084 
notifyLockdownVpn(NetworkAgentInfo nai)5085     private void notifyLockdownVpn(NetworkAgentInfo nai) {
5086         if (mLockdownTracker != null) {
5087             if (nai != null && nai.isVPN()) {
5088                 mLockdownTracker.onVpnStateChanged(nai.networkInfo);
5089             } else {
5090                 mLockdownTracker.onNetworkInfoChanged();
5091             }
5092         }
5093     }
5094 
updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo)5095     private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
5096         final NetworkInfo.State state = newInfo.getState();
5097         NetworkInfo oldInfo = null;
5098         final int oldScore = networkAgent.getCurrentScore();
5099         synchronized (networkAgent) {
5100             oldInfo = networkAgent.networkInfo;
5101             networkAgent.networkInfo = newInfo;
5102         }
5103         notifyLockdownVpn(networkAgent);
5104 
5105         if (oldInfo != null && oldInfo.getState() == state) {
5106             if (oldInfo.isRoaming() != newInfo.isRoaming()) {
5107                 if (VDBG) log("roaming status changed, notifying NetworkStatsService");
5108                 notifyIfacesChangedForNetworkStats();
5109             } else if (VDBG) log("ignoring duplicate network state non-change");
5110             // In either case, no further work should be needed.
5111             return;
5112         }
5113         if (DBG) {
5114             log(networkAgent.name() + " EVENT_NETWORK_INFO_CHANGED, going from " +
5115                     (oldInfo == null ? "null" : oldInfo.getState()) +
5116                     " to " + state);
5117         }
5118 
5119         if (!networkAgent.created
5120                 && (state == NetworkInfo.State.CONNECTED
5121                 || (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
5122 
5123             // A network that has just connected has zero requests and is thus a foreground network.
5124             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
5125 
5126             try {
5127                 // This should never fail.  Specifying an already in use NetID will cause failure.
5128                 if (networkAgent.isVPN()) {
5129                     mNetd.createVirtualNetwork(networkAgent.network.netId,
5130                             !networkAgent.linkProperties.getDnsServers().isEmpty(),
5131                             (networkAgent.networkMisc == null ||
5132                                 !networkAgent.networkMisc.allowBypass));
5133                 } else {
5134                     mNetd.createPhysicalNetwork(networkAgent.network.netId,
5135                             getNetworkPermission(networkAgent.networkCapabilities));
5136                 }
5137             } catch (Exception e) {
5138                 loge("Error creating network " + networkAgent.network.netId + ": "
5139                         + e.getMessage());
5140                 return;
5141             }
5142             networkAgent.created = true;
5143         }
5144 
5145         if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
5146             networkAgent.everConnected = true;
5147 
5148             updateLinkProperties(networkAgent, null);
5149             notifyIfacesChangedForNetworkStats();
5150 
5151             networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
5152             scheduleUnvalidatedPrompt(networkAgent);
5153 
5154             if (networkAgent.isVPN()) {
5155                 // Temporarily disable the default proxy (not global).
5156                 synchronized (mProxyLock) {
5157                     if (!mDefaultProxyDisabled) {
5158                         mDefaultProxyDisabled = true;
5159                         if (mGlobalProxy == null && mDefaultProxy != null) {
5160                             sendProxyBroadcast(null);
5161                         }
5162                     }
5163                 }
5164                 // TODO: support proxy per network.
5165             }
5166 
5167             // Whether a particular NetworkRequest listen should cause signal strength thresholds to
5168             // be communicated to a particular NetworkAgent depends only on the network's immutable,
5169             // capabilities, so it only needs to be done once on initial connect, not every time the
5170             // network's capabilities change. Note that we do this before rematching the network,
5171             // so we could decide to tear it down immediately afterwards. That's fine though - on
5172             // disconnection NetworkAgents should stop any signal strength monitoring they have been
5173             // doing.
5174             updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
5175 
5176             // Consider network even though it is not yet validated.
5177             final long now = SystemClock.elapsedRealtime();
5178             rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
5179 
5180             // This has to happen after matching the requests, because callbacks are just requests.
5181             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
5182         } else if (state == NetworkInfo.State.DISCONNECTED) {
5183             networkAgent.asyncChannel.disconnect();
5184             if (networkAgent.isVPN()) {
5185                 synchronized (mProxyLock) {
5186                     if (mDefaultProxyDisabled) {
5187                         mDefaultProxyDisabled = false;
5188                         if (mGlobalProxy == null && mDefaultProxy != null) {
5189                             sendProxyBroadcast(mDefaultProxy);
5190                         }
5191                     }
5192                 }
5193             }
5194         } else if ((oldInfo != null && oldInfo.getState() == NetworkInfo.State.SUSPENDED) ||
5195                 state == NetworkInfo.State.SUSPENDED) {
5196             // going into or coming out of SUSPEND: rescore and notify
5197             if (networkAgent.getCurrentScore() != oldScore) {
5198                 rematchAllNetworksAndRequests(networkAgent, oldScore);
5199             }
5200             notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ?
5201                     ConnectivityManager.CALLBACK_SUSPENDED :
5202                     ConnectivityManager.CALLBACK_RESUMED));
5203             mLegacyTypeTracker.update(networkAgent);
5204         }
5205     }
5206 
updateNetworkScore(NetworkAgentInfo nai, int score)5207     private void updateNetworkScore(NetworkAgentInfo nai, int score) {
5208         if (VDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
5209         if (score < 0) {
5210             loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
5211                     ").  Bumping score to min of 0");
5212             score = 0;
5213         }
5214 
5215         final int oldScore = nai.getCurrentScore();
5216         nai.setCurrentScore(score);
5217 
5218         rematchAllNetworksAndRequests(nai, oldScore);
5219 
5220         sendUpdatedScoreToFactories(nai);
5221     }
5222 
5223     // Notify only this one new request of the current state. Transfer all the
5224     // current state by calling NetworkCapabilities and LinkProperties callbacks
5225     // so that callers can be guaranteed to have as close to atomicity in state
5226     // transfer as can be supported by this current API.
notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri)5227     protected void notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri) {
5228         mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
5229         if (nri.mPendingIntent != null) {
5230             sendPendingIntentForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE);
5231             // Attempt no subsequent state pushes where intents are involved.
5232             return;
5233         }
5234 
5235         callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, 0);
5236         // Whether a network is currently suspended is also an important
5237         // element of state to be transferred (it would not otherwise be
5238         // delivered by any currently available mechanism).
5239         if (nai.networkInfo.getState() == NetworkInfo.State.SUSPENDED) {
5240             callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_SUSPENDED, 0);
5241         }
5242         callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_CAP_CHANGED, 0);
5243         callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_IP_CHANGED, 0);
5244     }
5245 
sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type)5246     private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
5247         // The NetworkInfo we actually send out has no bearing on the real
5248         // state of affairs. For example, if the default connection is mobile,
5249         // and a request for HIPRI has just gone away, we need to pretend that
5250         // HIPRI has just disconnected. So we need to set the type to HIPRI and
5251         // the state to DISCONNECTED, even though the network is of type MOBILE
5252         // and is still connected.
5253         NetworkInfo info = new NetworkInfo(nai.networkInfo);
5254         info.setType(type);
5255         if (state != DetailedState.DISCONNECTED) {
5256             info.setDetailedState(state, null, info.getExtraInfo());
5257             sendConnectedBroadcast(info);
5258         } else {
5259             info.setDetailedState(state, info.getReason(), info.getExtraInfo());
5260             Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
5261             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
5262             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
5263             if (info.isFailover()) {
5264                 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
5265                 nai.networkInfo.setFailover(false);
5266             }
5267             if (info.getReason() != null) {
5268                 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
5269             }
5270             if (info.getExtraInfo() != null) {
5271                 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
5272             }
5273             NetworkAgentInfo newDefaultAgent = null;
5274             if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
5275                 newDefaultAgent = getDefaultNetwork();
5276                 if (newDefaultAgent != null) {
5277                     intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
5278                             newDefaultAgent.networkInfo);
5279                 } else {
5280                     intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
5281                 }
5282             }
5283             intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
5284                     mDefaultInetConditionPublished);
5285             sendStickyBroadcast(intent);
5286             if (newDefaultAgent != null) {
5287                 sendConnectedBroadcast(newDefaultAgent.networkInfo);
5288             }
5289         }
5290     }
5291 
notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1)5292     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
5293         if (VDBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
5294         for (int i = 0; i < networkAgent.numNetworkRequests(); i++) {
5295             NetworkRequest nr = networkAgent.requestAt(i);
5296             NetworkRequestInfo nri = mNetworkRequests.get(nr);
5297             if (VDBG) log(" sending notification for " + nr);
5298             // TODO: if we're in the middle of a rematch, can we send a CAP_CHANGED callback for
5299             // a network that no longer satisfies the listen?
5300             if (nri.mPendingIntent == null) {
5301                 callCallbackForRequest(nri, networkAgent, notifyType, arg1);
5302             } else {
5303                 sendPendingIntentForRequest(nri, networkAgent, notifyType);
5304             }
5305         }
5306     }
5307 
notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType)5308     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
5309         notifyNetworkCallbacks(networkAgent, notifyType, 0);
5310     }
5311 
notifyTypeToName(int notifyType)5312     private String notifyTypeToName(int notifyType) {
5313         switch (notifyType) {
5314             case ConnectivityManager.CALLBACK_PRECHECK:    return "PRECHECK";
5315             case ConnectivityManager.CALLBACK_AVAILABLE:   return "AVAILABLE";
5316             case ConnectivityManager.CALLBACK_LOSING:      return "LOSING";
5317             case ConnectivityManager.CALLBACK_LOST:        return "LOST";
5318             case ConnectivityManager.CALLBACK_UNAVAIL:     return "UNAVAILABLE";
5319             case ConnectivityManager.CALLBACK_CAP_CHANGED: return "CAP_CHANGED";
5320             case ConnectivityManager.CALLBACK_IP_CHANGED:  return "IP_CHANGED";
5321             case ConnectivityManager.CALLBACK_RELEASED:    return "RELEASED";
5322         }
5323         return "UNKNOWN";
5324     }
5325 
5326     /**
5327      * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
5328      * properties tracked by NetworkStatsService on an active iface has changed.
5329      */
notifyIfacesChangedForNetworkStats()5330     private void notifyIfacesChangedForNetworkStats() {
5331         try {
5332             mStatsService.forceUpdateIfaces();
5333         } catch (Exception ignored) {
5334         }
5335     }
5336 
5337     @Override
addVpnAddress(String address, int prefixLength)5338     public boolean addVpnAddress(String address, int prefixLength) {
5339         throwIfLockdownEnabled();
5340         int user = UserHandle.getUserId(Binder.getCallingUid());
5341         synchronized (mVpns) {
5342             return mVpns.get(user).addAddress(address, prefixLength);
5343         }
5344     }
5345 
5346     @Override
removeVpnAddress(String address, int prefixLength)5347     public boolean removeVpnAddress(String address, int prefixLength) {
5348         throwIfLockdownEnabled();
5349         int user = UserHandle.getUserId(Binder.getCallingUid());
5350         synchronized (mVpns) {
5351             return mVpns.get(user).removeAddress(address, prefixLength);
5352         }
5353     }
5354 
5355     @Override
setUnderlyingNetworksForVpn(Network[] networks)5356     public boolean setUnderlyingNetworksForVpn(Network[] networks) {
5357         throwIfLockdownEnabled();
5358         int user = UserHandle.getUserId(Binder.getCallingUid());
5359         boolean success;
5360         synchronized (mVpns) {
5361             success = mVpns.get(user).setUnderlyingNetworks(networks);
5362         }
5363         if (success) {
5364             notifyIfacesChangedForNetworkStats();
5365         }
5366         return success;
5367     }
5368 
5369     @Override
getCaptivePortalServerUrl()5370     public String getCaptivePortalServerUrl() {
5371         return NetworkMonitor.getCaptivePortalServerHttpUrl(mContext);
5372     }
5373 
5374     @Override
startNattKeepalive(Network network, int intervalSeconds, Messenger messenger, IBinder binder, String srcAddr, int srcPort, String dstAddr)5375     public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger,
5376             IBinder binder, String srcAddr, int srcPort, String dstAddr) {
5377         enforceKeepalivePermission();
5378         mKeepaliveTracker.startNattKeepalive(
5379                 getNetworkAgentInfoForNetwork(network),
5380                 intervalSeconds, messenger, binder,
5381                 srcAddr, srcPort, dstAddr, ConnectivityManager.PacketKeepalive.NATT_PORT);
5382     }
5383 
5384     @Override
stopKeepalive(Network network, int slot)5385     public void stopKeepalive(Network network, int slot) {
5386         mHandler.sendMessage(mHandler.obtainMessage(
5387                 NetworkAgent.CMD_STOP_PACKET_KEEPALIVE, slot, PacketKeepalive.SUCCESS, network));
5388     }
5389 
5390     @Override
factoryReset()5391     public void factoryReset() {
5392         enforceConnectivityInternalPermission();
5393 
5394         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
5395             return;
5396         }
5397 
5398         final int userId = UserHandle.getCallingUserId();
5399 
5400         // Turn airplane mode off
5401         setAirplaneMode(false);
5402 
5403         if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
5404             // Untether
5405             for (String tether : getTetheredIfaces()) {
5406                 untether(tether);
5407             }
5408         }
5409 
5410         if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
5411             // Remove always-on package
5412             synchronized (mVpns) {
5413                 final String alwaysOnPackage = getAlwaysOnVpnPackage(userId);
5414                 if (alwaysOnPackage != null) {
5415                     setAlwaysOnVpnPackage(userId, null, false);
5416                     setVpnPackageAuthorization(alwaysOnPackage, userId, false);
5417                 }
5418             }
5419 
5420             // Turn Always-on VPN off
5421             if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
5422                 final long ident = Binder.clearCallingIdentity();
5423                 try {
5424                     mKeyStore.delete(Credentials.LOCKDOWN_VPN);
5425                     mLockdownEnabled = false;
5426                     setLockdownTracker(null);
5427                 } finally {
5428                     Binder.restoreCallingIdentity(ident);
5429                 }
5430             }
5431 
5432             // Turn VPN off
5433             VpnConfig vpnConfig = getVpnConfig(userId);
5434             if (vpnConfig != null) {
5435                 if (vpnConfig.legacy) {
5436                     prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
5437                 } else {
5438                     // Prevent this app (packagename = vpnConfig.user) from initiating VPN connections
5439                     // in the future without user intervention.
5440                     setVpnPackageAuthorization(vpnConfig.user, userId, false);
5441 
5442                     prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
5443                 }
5444             }
5445         }
5446 
5447         Settings.Global.putString(mContext.getContentResolver(),
5448                 Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
5449     }
5450 
5451     @VisibleForTesting
createNetworkMonitor(Context context, Handler handler, NetworkAgentInfo nai, NetworkRequest defaultRequest)5452     public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
5453             NetworkAgentInfo nai, NetworkRequest defaultRequest) {
5454         return new NetworkMonitor(context, handler, nai, defaultRequest);
5455     }
5456 
5457     @VisibleForTesting
createMultinetworkPolicyTracker(Context c, Handler h, Runnable r)5458     MultinetworkPolicyTracker createMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
5459         return new MultinetworkPolicyTracker(c, h, r);
5460     }
5461 
5462     @VisibleForTesting
makeWakeupMessage(Context c, Handler h, String s, int cmd, Object obj)5463     public WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int cmd, Object obj) {
5464         return new WakeupMessage(c, h, s, cmd, 0, 0, obj);
5465     }
5466 
logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai)5467     private void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
5468         int newNetid = NETID_UNSET;
5469         int prevNetid = NETID_UNSET;
5470         int[] transports = new int[0];
5471         boolean hadIPv4 = false;
5472         boolean hadIPv6 = false;
5473 
5474         if (newNai != null) {
5475             newNetid = newNai.network.netId;
5476             transports = newNai.networkCapabilities.getTransportTypes();
5477         }
5478         if (prevNai != null) {
5479             prevNetid = prevNai.network.netId;
5480             final LinkProperties lp = prevNai.linkProperties;
5481             hadIPv4 = lp.hasIPv4Address() && lp.hasIPv4DefaultRoute();
5482             hadIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute();
5483         }
5484 
5485         mMetricsLog.log(new DefaultNetworkEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6));
5486     }
5487 
logNetworkEvent(NetworkAgentInfo nai, int evtype)5488     private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
5489         mMetricsLog.log(new NetworkEvent(nai.network.netId, evtype));
5490     }
5491 }
5492