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