OSDN Git Service

Merge "Make reportInetCondition revalidate if the report differs from our state"...
[android-x86/frameworks-base.git] / services / core / java / com / android / server / ConnectivityService.java
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.MANAGE_NETWORK_POLICY;
20 import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
21 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
22 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
23 import static android.net.ConnectivityManager.TYPE_NONE;
24 import static android.net.ConnectivityManager.TYPE_VPN;
25 import static android.net.ConnectivityManager.getNetworkTypeName;
26 import static android.net.ConnectivityManager.isNetworkTypeValid;
27 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
28 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
29
30 import android.app.AlarmManager;
31 import android.app.Notification;
32 import android.app.NotificationManager;
33 import android.app.PendingIntent;
34 import android.content.BroadcastReceiver;
35 import android.content.ContentResolver;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.IntentFilter;
39 import android.content.pm.PackageManager;
40 import android.content.res.Configuration;
41 import android.content.res.Resources;
42 import android.database.ContentObserver;
43 import android.net.ConnectivityManager;
44 import android.net.IConnectivityManager;
45 import android.net.INetworkManagementEventObserver;
46 import android.net.INetworkPolicyListener;
47 import android.net.INetworkPolicyManager;
48 import android.net.INetworkStatsService;
49 import android.net.LinkProperties;
50 import android.net.LinkProperties.CompareResult;
51 import android.net.MobileDataStateTracker;
52 import android.net.Network;
53 import android.net.NetworkAgent;
54 import android.net.NetworkCapabilities;
55 import android.net.NetworkConfig;
56 import android.net.NetworkInfo;
57 import android.net.NetworkInfo.DetailedState;
58 import android.net.NetworkMisc;
59 import android.net.NetworkQuotaInfo;
60 import android.net.NetworkRequest;
61 import android.net.NetworkState;
62 import android.net.NetworkStateTracker;
63 import android.net.NetworkUtils;
64 import android.net.Proxy;
65 import android.net.ProxyInfo;
66 import android.net.RouteInfo;
67 import android.net.SamplingDataTracker;
68 import android.net.UidRange;
69 import android.net.Uri;
70 import android.os.Binder;
71 import android.os.Bundle;
72 import android.os.FileUtils;
73 import android.os.Handler;
74 import android.os.HandlerThread;
75 import android.os.IBinder;
76 import android.os.INetworkManagementService;
77 import android.os.Looper;
78 import android.os.Message;
79 import android.os.Messenger;
80 import android.os.ParcelFileDescriptor;
81 import android.os.PowerManager;
82 import android.os.Process;
83 import android.os.RemoteException;
84 import android.os.SystemClock;
85 import android.os.SystemProperties;
86 import android.os.UserHandle;
87 import android.os.UserManager;
88 import android.provider.Settings;
89 import android.security.Credentials;
90 import android.security.KeyStore;
91 import android.telephony.TelephonyManager;
92 import android.text.TextUtils;
93 import android.util.Slog;
94 import android.util.SparseArray;
95 import android.util.SparseIntArray;
96 import android.util.Xml;
97
98 import com.android.internal.R;
99 import com.android.internal.annotations.GuardedBy;
100 import com.android.internal.app.IBatteryStats;
101 import com.android.internal.net.LegacyVpnInfo;
102 import com.android.internal.net.NetworkStatsFactory;
103 import com.android.internal.net.VpnConfig;
104 import com.android.internal.net.VpnProfile;
105 import com.android.internal.telephony.DctConstants;
106 import com.android.internal.util.AsyncChannel;
107 import com.android.internal.util.IndentingPrintWriter;
108 import com.android.internal.util.XmlUtils;
109 import com.android.server.am.BatteryStatsService;
110 import com.android.server.connectivity.DataConnectionStats;
111 import com.android.server.connectivity.Nat464Xlat;
112 import com.android.server.connectivity.NetworkAgentInfo;
113 import com.android.server.connectivity.NetworkMonitor;
114 import com.android.server.connectivity.PacManager;
115 import com.android.server.connectivity.PermissionMonitor;
116 import com.android.server.connectivity.Tethering;
117 import com.android.server.connectivity.Vpn;
118 import com.android.server.net.BaseNetworkObserver;
119 import com.android.server.net.LockdownVpnTracker;
120 import com.google.android.collect.Lists;
121 import com.google.android.collect.Sets;
122
123 import org.xmlpull.v1.XmlPullParser;
124 import org.xmlpull.v1.XmlPullParserException;
125
126 import java.io.File;
127 import java.io.FileDescriptor;
128 import java.io.FileNotFoundException;
129 import java.io.FileReader;
130 import java.io.IOException;
131 import java.io.PrintWriter;
132 import java.net.Inet4Address;
133 import java.net.InetAddress;
134 import java.net.UnknownHostException;
135 import java.util.ArrayList;
136 import java.util.Arrays;
137 import java.util.Collection;
138 import java.util.HashMap;
139 import java.util.HashSet;
140 import java.util.Iterator;
141 import java.util.List;
142 import java.util.Map;
143 import java.util.Objects;
144 import java.util.concurrent.atomic.AtomicInteger;
145
146 /**
147  * @hide
148  */
149 public class ConnectivityService extends IConnectivityManager.Stub
150         implements PendingIntent.OnFinished {
151     private static final String TAG = "ConnectivityService";
152
153     private static final boolean DBG = true;
154     private static final boolean VDBG = false;
155
156     // network sampling debugging
157     private static final boolean SAMPLE_DBG = false;
158
159     private static final boolean LOGD_RULES = false;
160
161     // TODO: create better separation between radio types and network types
162
163     // how long to wait before switching back to a radio's default network
164     private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
165     // system property that can override the above value
166     private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
167             "android.telephony.apn-restore";
168
169     // Default value if FAIL_FAST_TIME_MS is not set
170     private static final int DEFAULT_FAIL_FAST_TIME_MS = 1 * 60 * 1000;
171     // system property that can override DEFAULT_FAIL_FAST_TIME_MS
172     private static final String FAIL_FAST_TIME_MS =
173             "persist.radio.fail_fast_time_ms";
174
175     private static final String ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED =
176             "android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED";
177
178     private static final int SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE = 0;
179
180     // How long to delay to removal of a pending intent based request.
181     // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
182     private final int mReleasePendingIntentDelayMs;
183
184     private PendingIntent mSampleIntervalElapsedIntent;
185
186     // Set network sampling interval at 12 minutes, this way, even if the timers get
187     // aggregated, it will fire at around 15 minutes, which should allow us to
188     // aggregate this timer with other timers (specially the socket keep alive timers)
189     private static final int DEFAULT_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 12 * 60);
190
191     // start network sampling a minute after booting ...
192     private static final int DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 60);
193
194     AlarmManager mAlarmManager;
195
196     private Tethering mTethering;
197
198     private final PermissionMonitor mPermissionMonitor;
199
200     private KeyStore mKeyStore;
201
202     @GuardedBy("mVpns")
203     private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
204
205     private boolean mLockdownEnabled;
206     private LockdownVpnTracker mLockdownTracker;
207
208     /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
209     private Object mRulesLock = new Object();
210     /** Currently active network rules by UID. */
211     private SparseIntArray mUidRules = new SparseIntArray();
212     /** Set of ifaces that are costly. */
213     private HashSet<String> mMeteredIfaces = Sets.newHashSet();
214
215     /**
216      * Sometimes we want to refer to the individual network state
217      * trackers separately, and sometimes we just want to treat them
218      * abstractly.
219      */
220     private NetworkStateTracker mNetTrackers[];
221
222     private Context mContext;
223     private int mNetworkPreference;
224     // 0 is full bad, 100 is full good
225     private int mDefaultInetConditionPublished = 0;
226
227     private Object mDnsLock = new Object();
228     private int mNumDnsEntries;
229
230     private boolean mTestMode;
231     private static ConnectivityService sServiceInstance;
232
233     private INetworkManagementService mNetd;
234     private INetworkStatsService mStatsService;
235     private INetworkPolicyManager mPolicyManager;
236
237     private String mCurrentTcpBufferSizes;
238
239     private static final int ENABLED  = 1;
240     private static final int DISABLED = 0;
241
242     // Arguments to rematchNetworkAndRequests()
243     private enum NascentState {
244         // Indicates a network was just validated for the first time.  If the network is found to
245         // be unwanted (i.e. not satisfy any NetworkRequests) it is torn down.
246         JUST_VALIDATED,
247         // Indicates a network was not validated for the first time immediately prior to this call.
248         NOT_JUST_VALIDATED
249     };
250     private enum ReapUnvalidatedNetworks {
251         // Tear down unvalidated networks that have no chance (i.e. even if validated) of becoming
252         // the highest scoring network satisfying a NetworkRequest.  This should be passed when it's
253         // known that there may be unvalidated networks that could potentially be reaped, and when
254         // all networks have been rematched against all NetworkRequests.
255         REAP,
256         // Don't reap unvalidated networks.  This should be passed when it's known that there are
257         // no unvalidated networks that could potentially be reaped, and when some networks have
258         // not yet been rematched against all NetworkRequests.
259         DONT_REAP
260     };
261
262     /**
263      * used internally to change our mobile data enabled flag
264      */
265     private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
266
267     /**
268      * used internally to clear a wakelock when transitioning
269      * from one net to another.  Clear happens when we get a new
270      * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
271      * after a timeout if no network is found (typically 1 min).
272      */
273     private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
274
275     /**
276      * used internally to reload global proxy settings
277      */
278     private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
279
280     /**
281      * used internally to set external dependency met/unmet
282      * arg1 = ENABLED (met) or DISABLED (unmet)
283      * arg2 = NetworkType
284      */
285     private static final int EVENT_SET_DEPENDENCY_MET = 10;
286
287     /**
288      * used internally to send a sticky broadcast delayed.
289      */
290     private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11;
291
292     /**
293      * Used internally to disable fail fast of mobile data
294      */
295     private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 14;
296
297     /**
298      * used internally to indicate that data sampling interval is up
299      */
300     private static final int EVENT_SAMPLE_INTERVAL_ELAPSED = 15;
301
302     /**
303      * PAC manager has received new port.
304      */
305     private static final int EVENT_PROXY_HAS_CHANGED = 16;
306
307     /**
308      * used internally when registering NetworkFactories
309      * obj = NetworkFactoryInfo
310      */
311     private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
312
313     /**
314      * used internally when registering NetworkAgents
315      * obj = Messenger
316      */
317     private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
318
319     /**
320      * used to add a network request
321      * includes a NetworkRequestInfo
322      */
323     private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
324
325     /**
326      * indicates a timeout period is over - check if we had a network yet or not
327      * and if not, call the timeout calback (but leave the request live until they
328      * cancel it.
329      * includes a NetworkRequestInfo
330      */
331     private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;
332
333     /**
334      * used to add a network listener - no request
335      * includes a NetworkRequestInfo
336      */
337     private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
338
339     /**
340      * used to remove a network request, either a listener or a real request
341      * arg1 = UID of caller
342      * obj  = NetworkRequest
343      */
344     private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
345
346     /**
347      * used internally when registering NetworkFactories
348      * obj = Messenger
349      */
350     private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
351
352     /**
353      * used internally to expire a wakelock when transitioning
354      * from one net to another.  Expire happens when we fail to find
355      * a new network (typically after 1 minute) -
356      * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found
357      * a replacement network.
358      */
359     private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
360
361     /**
362      * Used internally to indicate the system is ready.
363      */
364     private static final int EVENT_SYSTEM_READY = 25;
365
366     /**
367      * used to add a network request with a pending intent
368      * includes a NetworkRequestInfo
369      */
370     private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
371
372     /**
373      * used to remove a pending intent and its associated network request.
374      * arg1 = UID of caller
375      * obj  = PendingIntent
376      */
377     private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
378
379
380     /** Handler used for internal events. */
381     final private InternalHandler mHandler;
382     /** Handler used for incoming {@link NetworkStateTracker} events. */
383     final private NetworkStateTrackerHandler mTrackerHandler;
384
385     private boolean mSystemReady;
386     private Intent mInitialBroadcast;
387
388     private PowerManager.WakeLock mNetTransitionWakeLock;
389     private String mNetTransitionWakeLockCausedBy = "";
390     private int mNetTransitionWakeLockSerialNumber;
391     private int mNetTransitionWakeLockTimeout;
392     private final PowerManager.WakeLock mPendingIntentWakeLock;
393
394     private InetAddress mDefaultDns;
395
396     // used in DBG mode to track inet condition reports
397     private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
398     private ArrayList mInetLog;
399
400     // track the current default http proxy - tell the world if we get a new one (real change)
401     private volatile ProxyInfo mDefaultProxy = null;
402     private Object mProxyLock = new Object();
403     private boolean mDefaultProxyDisabled = false;
404
405     // track the global proxy.
406     private ProxyInfo mGlobalProxy = null;
407
408     private PacManager mPacManager = null;
409
410     private SettingsObserver mSettingsObserver;
411
412     private UserManager mUserManager;
413
414     NetworkConfig[] mNetConfigs;
415     int mNetworksDefined;
416
417     // the set of network types that can only be enabled by system/sig apps
418     List mProtectedNetworks;
419
420     private DataConnectionStats mDataConnectionStats;
421
422     private AtomicInteger mEnableFailFastMobileDataTag = new AtomicInteger(0);
423
424     TelephonyManager mTelephonyManager;
425
426     // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
427     private final static int MIN_NET_ID = 100; // some reserved marks
428     private final static int MAX_NET_ID = 65535;
429     private int mNextNetId = MIN_NET_ID;
430
431     // sequence number of NetworkRequests
432     private int mNextNetworkRequestId = 1;
433
434     /**
435      * Implements support for the legacy "one network per network type" model.
436      *
437      * We used to have a static array of NetworkStateTrackers, one for each
438      * network type, but that doesn't work any more now that we can have,
439      * for example, more that one wifi network. This class stores all the
440      * NetworkAgentInfo objects that support a given type, but the legacy
441      * API will only see the first one.
442      *
443      * It serves two main purposes:
444      *
445      * 1. Provide information about "the network for a given type" (since this
446      *    API only supports one).
447      * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
448      *    the first network for a given type changes, or if the default network
449      *    changes.
450      */
451     private class LegacyTypeTracker {
452
453         private static final boolean DBG = true;
454         private static final boolean VDBG = false;
455         private static final String TAG = "CSLegacyTypeTracker";
456
457         /**
458          * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
459          * Each list holds references to all NetworkAgentInfos that are used to
460          * satisfy requests for that network type.
461          *
462          * This array is built out at startup such that an unsupported network
463          * doesn't get an ArrayList instance, making this a tristate:
464          * unsupported, supported but not active and active.
465          *
466          * The actual lists are populated when we scan the network types that
467          * are supported on this device.
468          */
469         private ArrayList<NetworkAgentInfo> mTypeLists[];
470
471         public LegacyTypeTracker() {
472             mTypeLists = (ArrayList<NetworkAgentInfo>[])
473                     new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
474         }
475
476         public void addSupportedType(int type) {
477             if (mTypeLists[type] != null) {
478                 throw new IllegalStateException(
479                         "legacy list for type " + type + "already initialized");
480             }
481             mTypeLists[type] = new ArrayList<NetworkAgentInfo>();
482         }
483
484         public boolean isTypeSupported(int type) {
485             return isNetworkTypeValid(type) && mTypeLists[type] != null;
486         }
487
488         public NetworkAgentInfo getNetworkForType(int type) {
489             if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
490                 return mTypeLists[type].get(0);
491             } else {
492                 return null;
493             }
494         }
495
496         private void maybeLogBroadcast(NetworkAgentInfo nai, boolean connected, int type) {
497             if (DBG) {
498                 log("Sending " + (connected ? "connected" : "disconnected") +
499                         " broadcast for type " + type + " " + nai.name() +
500                         " isDefaultNetwork=" + isDefaultNetwork(nai));
501             }
502         }
503
504         /** Adds the given network to the specified legacy type list. */
505         public void add(int type, NetworkAgentInfo nai) {
506             if (!isTypeSupported(type)) {
507                 return;  // Invalid network type.
508             }
509             if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
510
511             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
512             if (list.contains(nai)) {
513                 loge("Attempting to register duplicate agent for type " + type + ": " + nai);
514                 return;
515             }
516
517             list.add(nai);
518
519             // Send a broadcast if this is the first network of its type or if it's the default.
520             if (list.size() == 1 || isDefaultNetwork(nai)) {
521                 maybeLogBroadcast(nai, true, type);
522                 sendLegacyNetworkBroadcast(nai, true, type);
523             }
524         }
525
526         /** Removes the given network from the specified legacy type list. */
527         public void remove(int type, NetworkAgentInfo nai) {
528             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
529             if (list == null || list.isEmpty()) {
530                 return;
531             }
532
533             boolean wasFirstNetwork = list.get(0).equals(nai);
534
535             if (!list.remove(nai)) {
536                 return;
537             }
538
539             if (wasFirstNetwork || isDefaultNetwork(nai)) {
540                 maybeLogBroadcast(nai, false, type);
541                 sendLegacyNetworkBroadcast(nai, false, type);
542             }
543
544             if (!list.isEmpty() && wasFirstNetwork) {
545                 if (DBG) log("Other network available for type " + type +
546                               ", sending connected broadcast");
547                 maybeLogBroadcast(list.get(0), false, type);
548                 sendLegacyNetworkBroadcast(list.get(0), false, type);
549             }
550         }
551
552         /** Removes the given network from all legacy type lists. */
553         public void remove(NetworkAgentInfo nai) {
554             if (VDBG) log("Removing agent " + nai);
555             for (int type = 0; type < mTypeLists.length; type++) {
556                 remove(type, nai);
557             }
558         }
559
560         private String naiToString(NetworkAgentInfo nai) {
561             String name = (nai != null) ? nai.name() : "null";
562             String state = (nai.networkInfo != null) ?
563                     nai.networkInfo.getState() + "/" + nai.networkInfo.getDetailedState() :
564                     "???/???";
565             return name + " " + state;
566         }
567
568         public void dump(IndentingPrintWriter pw) {
569             for (int type = 0; type < mTypeLists.length; type++) {
570                 if (mTypeLists[type] == null) continue;
571                 pw.print(type + " ");
572                 pw.increaseIndent();
573                 if (mTypeLists[type].size() == 0) pw.println("none");
574                 for (NetworkAgentInfo nai : mTypeLists[type]) {
575                     pw.println(naiToString(nai));
576                 }
577                 pw.decreaseIndent();
578             }
579         }
580
581         // This class needs its own log method because it has a different TAG.
582         private void log(String s) {
583             Slog.d(TAG, s);
584         }
585
586     }
587     private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
588
589     public ConnectivityService(Context context, INetworkManagementService netManager,
590             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
591         if (DBG) log("ConnectivityService starting up");
592
593         NetworkCapabilities netCap = new NetworkCapabilities();
594         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
595         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
596         mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
597         NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
598                 NetworkRequestInfo.REQUEST);
599         mNetworkRequests.put(mDefaultRequest, nri);
600
601         HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
602         handlerThread.start();
603         mHandler = new InternalHandler(handlerThread.getLooper());
604         mTrackerHandler = new NetworkStateTrackerHandler(handlerThread.getLooper());
605
606         // setup our unique device name
607         if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
608             String id = Settings.Secure.getString(context.getContentResolver(),
609                     Settings.Secure.ANDROID_ID);
610             if (id != null && id.length() > 0) {
611                 String name = new String("android-").concat(id);
612                 SystemProperties.set("net.hostname", name);
613             }
614         }
615
616         // read our default dns server ip
617         String dns = Settings.Global.getString(context.getContentResolver(),
618                 Settings.Global.DEFAULT_DNS_SERVER);
619         if (dns == null || dns.length() == 0) {
620             dns = context.getResources().getString(
621                     com.android.internal.R.string.config_default_dns_server);
622         }
623         try {
624             mDefaultDns = NetworkUtils.numericToInetAddress(dns);
625         } catch (IllegalArgumentException e) {
626             loge("Error setting defaultDns using " + dns);
627         }
628
629         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
630                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
631
632         mContext = checkNotNull(context, "missing Context");
633         mNetd = checkNotNull(netManager, "missing INetworkManagementService");
634         mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
635         mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
636         mKeyStore = KeyStore.getInstance();
637         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
638
639         try {
640             mPolicyManager.registerListener(mPolicyListener);
641         } catch (RemoteException e) {
642             // ouch, no rules updates means some processes may never get network
643             loge("unable to register INetworkPolicyListener" + e.toString());
644         }
645
646         final PowerManager powerManager = (PowerManager) context.getSystemService(
647                 Context.POWER_SERVICE);
648         mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
649         mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
650                 com.android.internal.R.integer.config_networkTransitionTimeout);
651         mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
652
653         mNetTrackers = new NetworkStateTracker[
654                 ConnectivityManager.MAX_NETWORK_TYPE+1];
655
656         mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
657
658         // TODO: What is the "correct" way to do determine if this is a wifi only device?
659         boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);
660         log("wifiOnly=" + wifiOnly);
661         String[] naStrings = context.getResources().getStringArray(
662                 com.android.internal.R.array.networkAttributes);
663         for (String naString : naStrings) {
664             try {
665                 NetworkConfig n = new NetworkConfig(naString);
666                 if (VDBG) log("naString=" + naString + " config=" + n);
667                 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
668                     loge("Error in networkAttributes - ignoring attempt to define type " +
669                             n.type);
670                     continue;
671                 }
672                 if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
673                     log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
674                             n.type);
675                     continue;
676                 }
677                 if (mNetConfigs[n.type] != null) {
678                     loge("Error in networkAttributes - ignoring attempt to redefine type " +
679                             n.type);
680                     continue;
681                 }
682                 mLegacyTypeTracker.addSupportedType(n.type);
683
684                 mNetConfigs[n.type] = n;
685                 mNetworksDefined++;
686             } catch(Exception e) {
687                 // ignore it - leave the entry null
688             }
689         }
690
691         // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
692         if (mNetConfigs[TYPE_VPN] == null) {
693             // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
694             // don't need to add TYPE_VPN to mNetConfigs.
695             mLegacyTypeTracker.addSupportedType(TYPE_VPN);
696             mNetworksDefined++;  // used only in the log() statement below.
697         }
698
699         if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
700
701         mProtectedNetworks = new ArrayList<Integer>();
702         int[] protectedNetworks = context.getResources().getIntArray(
703                 com.android.internal.R.array.config_protectedNetworks);
704         for (int p : protectedNetworks) {
705             if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
706                 mProtectedNetworks.add(p);
707             } else {
708                 if (DBG) loge("Ignoring protectedNetwork " + p);
709             }
710         }
711
712         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
713                 && SystemProperties.get("ro.build.type").equals("eng");
714
715         mTethering = new Tethering(mContext, mNetd, statsService, mHandler.getLooper());
716
717         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
718
719         //set up the listener for user state for creating user VPNs
720         IntentFilter intentFilter = new IntentFilter();
721         intentFilter.addAction(Intent.ACTION_USER_STARTING);
722         intentFilter.addAction(Intent.ACTION_USER_STOPPING);
723         mContext.registerReceiverAsUser(
724                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
725
726         try {
727             mNetd.registerObserver(mTethering);
728             mNetd.registerObserver(mDataActivityObserver);
729         } catch (RemoteException e) {
730             loge("Error registering observer :" + e);
731         }
732
733         if (DBG) {
734             mInetLog = new ArrayList();
735         }
736
737         mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
738         mSettingsObserver.observe(mContext);
739
740         mDataConnectionStats = new DataConnectionStats(mContext);
741         mDataConnectionStats.startMonitoring();
742
743         mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
744
745         IntentFilter filter = new IntentFilter();
746         filter.addAction(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED);
747         mContext.registerReceiver(
748                 new BroadcastReceiver() {
749                     @Override
750                     public void onReceive(Context context, Intent intent) {
751                         String action = intent.getAction();
752                         if (action.equals(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED)) {
753                             mHandler.sendMessage(mHandler.obtainMessage
754                                     (EVENT_SAMPLE_INTERVAL_ELAPSED));
755                         }
756                     }
757                 },
758                 new IntentFilter(filter));
759
760         mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
761
762         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
763     }
764
765     private synchronized int nextNetworkRequestId() {
766         return mNextNetworkRequestId++;
767     }
768
769     private void assignNextNetId(NetworkAgentInfo nai) {
770         synchronized (mNetworkForNetId) {
771             for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
772                 int netId = mNextNetId;
773                 if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
774                 // Make sure NetID unused.  http://b/16815182
775                 if (mNetworkForNetId.get(netId) == null) {
776                     nai.network = new Network(netId);
777                     mNetworkForNetId.put(netId, nai);
778                     return;
779                 }
780             }
781         }
782         throw new IllegalStateException("No free netIds");
783     }
784
785     private boolean teardown(NetworkStateTracker netTracker) {
786         if (netTracker.teardown()) {
787             netTracker.setTeardownRequested(true);
788             return true;
789         } else {
790             return false;
791         }
792     }
793
794     private NetworkState getFilteredNetworkState(int networkType, int uid) {
795         NetworkInfo info = null;
796         LinkProperties lp = null;
797         NetworkCapabilities nc = null;
798         Network network = null;
799         String subscriberId = null;
800
801         if (mLegacyTypeTracker.isTypeSupported(networkType)) {
802             NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
803             if (nai != null) {
804                 synchronized (nai) {
805                     info = new NetworkInfo(nai.networkInfo);
806                     lp = new LinkProperties(nai.linkProperties);
807                     nc = new NetworkCapabilities(nai.networkCapabilities);
808                     network = new Network(nai.network);
809                     subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
810                 }
811                 info.setType(networkType);
812             } else {
813                 info = new NetworkInfo(networkType, 0, getNetworkTypeName(networkType), "");
814                 info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
815                 info.setIsAvailable(true);
816                 lp = new LinkProperties();
817                 nc = new NetworkCapabilities();
818                 network = null;
819             }
820             info = getFilteredNetworkInfo(info, lp, uid);
821         }
822
823         return new NetworkState(info, lp, nc, network, subscriberId, null);
824     }
825
826     private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
827         if (network == null) {
828             return null;
829         }
830         synchronized (mNetworkForNetId) {
831             return mNetworkForNetId.get(network.netId);
832         }
833     };
834
835     private Network[] getVpnUnderlyingNetworks(int uid) {
836         if (!mLockdownEnabled) {
837             int user = UserHandle.getUserId(uid);
838             synchronized (mVpns) {
839                 Vpn vpn = mVpns.get(user);
840                 if (vpn != null && vpn.appliesToUid(uid)) {
841                     return vpn.getUnderlyingNetworks();
842                 }
843             }
844         }
845         return null;
846     }
847
848     private NetworkState getUnfilteredActiveNetworkState(int uid) {
849         NetworkInfo info = null;
850         LinkProperties lp = null;
851         NetworkCapabilities nc = null;
852         Network network = null;
853         String subscriberId = null;
854
855         NetworkAgentInfo nai = mNetworkForRequestId.get(mDefaultRequest.requestId);
856
857         final Network[] networks = getVpnUnderlyingNetworks(uid);
858         if (networks != null) {
859             // getUnderlyingNetworks() returns:
860             // null => there was no VPN, or the VPN didn't specify anything, so we use the default.
861             // empty array => the VPN explicitly said "no default network".
862             // non-empty array => the VPN specified one or more default networks; we use the
863             //                    first one.
864             if (networks.length > 0) {
865                 nai = getNetworkAgentInfoForNetwork(networks[0]);
866             } else {
867                 nai = null;
868             }
869         }
870
871         if (nai != null) {
872             synchronized (nai) {
873                 info = new NetworkInfo(nai.networkInfo);
874                 lp = new LinkProperties(nai.linkProperties);
875                 nc = new NetworkCapabilities(nai.networkCapabilities);
876                 network = new Network(nai.network);
877                 subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
878             }
879         }
880
881         return new NetworkState(info, lp, nc, network, subscriberId, null);
882     }
883
884     /**
885      * Check if UID should be blocked from using the network with the given LinkProperties.
886      */
887     private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid) {
888         final boolean networkCostly;
889         final int uidRules;
890
891         final String iface = (lp == null ? "" : lp.getInterfaceName());
892         synchronized (mRulesLock) {
893             networkCostly = mMeteredIfaces.contains(iface);
894             uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
895         }
896
897         if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) {
898             return true;
899         }
900
901         // no restrictive rules; network is visible
902         return false;
903     }
904
905     /**
906      * Return a filtered {@link NetworkInfo}, potentially marked
907      * {@link DetailedState#BLOCKED} based on
908      * {@link #isNetworkWithLinkPropertiesBlocked}.
909      */
910     private NetworkInfo getFilteredNetworkInfo(NetworkInfo info, LinkProperties lp, int uid) {
911         if (info != null && isNetworkWithLinkPropertiesBlocked(lp, uid)) {
912             // network is blocked; clone and override state
913             info = new NetworkInfo(info);
914             info.setDetailedState(DetailedState.BLOCKED, null, null);
915             if (DBG) {
916                 log("returning Blocked NetworkInfo for ifname=" +
917                         lp.getInterfaceName() + ", uid=" + uid);
918             }
919         }
920         if (info != null && mLockdownTracker != null) {
921             info = mLockdownTracker.augmentNetworkInfo(info);
922             if (DBG) log("returning Locked NetworkInfo");
923         }
924         return info;
925     }
926
927     /**
928      * Return NetworkInfo for the active (i.e., connected) network interface.
929      * It is assumed that at most one network is active at a time. If more
930      * than one is active, it is indeterminate which will be returned.
931      * @return the info for the active network, or {@code null} if none is
932      * active
933      */
934     @Override
935     public NetworkInfo getActiveNetworkInfo() {
936         enforceAccessPermission();
937         final int uid = Binder.getCallingUid();
938         NetworkState state = getUnfilteredActiveNetworkState(uid);
939         return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
940     }
941
942     /**
943      * Find the first Provisioning network.
944      *
945      * @return NetworkInfo or null if none.
946      */
947     private NetworkInfo getProvisioningNetworkInfo() {
948         enforceAccessPermission();
949
950         // Find the first Provisioning Network
951         NetworkInfo provNi = null;
952         for (NetworkInfo ni : getAllNetworkInfo()) {
953             if (ni.isConnectedToProvisioningNetwork()) {
954                 provNi = ni;
955                 break;
956             }
957         }
958         if (DBG) log("getProvisioningNetworkInfo: X provNi=" + provNi);
959         return provNi;
960     }
961
962     /**
963      * Find the first Provisioning network or the ActiveDefaultNetwork
964      * if there is no Provisioning network
965      *
966      * @return NetworkInfo or null if none.
967      */
968     @Override
969     public NetworkInfo getProvisioningOrActiveNetworkInfo() {
970         enforceAccessPermission();
971
972         NetworkInfo provNi = getProvisioningNetworkInfo();
973         if (provNi == null) {
974             provNi = getActiveNetworkInfo();
975         }
976         if (DBG) log("getProvisioningOrActiveNetworkInfo: X provNi=" + provNi);
977         return provNi;
978     }
979
980     public NetworkInfo getActiveNetworkInfoUnfiltered() {
981         enforceAccessPermission();
982         final int uid = Binder.getCallingUid();
983         NetworkState state = getUnfilteredActiveNetworkState(uid);
984         return state.networkInfo;
985     }
986
987     @Override
988     public NetworkInfo getActiveNetworkInfoForUid(int uid) {
989         enforceConnectivityInternalPermission();
990         NetworkState state = getUnfilteredActiveNetworkState(uid);
991         return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
992     }
993
994     @Override
995     public NetworkInfo getNetworkInfo(int networkType) {
996         enforceAccessPermission();
997         final int uid = Binder.getCallingUid();
998         if (getVpnUnderlyingNetworks(uid) != null) {
999             // A VPN is active, so we may need to return one of its underlying networks. This
1000             // information is not available in LegacyTypeTracker, so we have to get it from
1001             // getUnfilteredActiveNetworkState.
1002             NetworkState state = getUnfilteredActiveNetworkState(uid);
1003             if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
1004                 return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
1005             }
1006         }
1007         NetworkState state = getFilteredNetworkState(networkType, uid);
1008         return state.networkInfo;
1009     }
1010
1011     @Override
1012     public NetworkInfo getNetworkInfoForNetwork(Network network) {
1013         enforceAccessPermission();
1014         final int uid = Binder.getCallingUid();
1015         NetworkInfo info = null;
1016         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1017         if (nai != null) {
1018             synchronized (nai) {
1019                 info = new NetworkInfo(nai.networkInfo);
1020                 info = getFilteredNetworkInfo(info, nai.linkProperties, uid);
1021             }
1022         }
1023         return info;
1024     }
1025
1026     @Override
1027     public NetworkInfo[] getAllNetworkInfo() {
1028         enforceAccessPermission();
1029         final ArrayList<NetworkInfo> result = Lists.newArrayList();
1030         for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
1031                 networkType++) {
1032             NetworkInfo info = getNetworkInfo(networkType);
1033             if (info != null) {
1034                 result.add(info);
1035             }
1036         }
1037         return result.toArray(new NetworkInfo[result.size()]);
1038     }
1039
1040     @Override
1041     public Network getNetworkForType(int networkType) {
1042         enforceAccessPermission();
1043         final int uid = Binder.getCallingUid();
1044         NetworkState state = getFilteredNetworkState(networkType, uid);
1045         if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid)) {
1046             return state.network;
1047         }
1048         return null;
1049     }
1050
1051     @Override
1052     public Network[] getAllNetworks() {
1053         enforceAccessPermission();
1054         final ArrayList<Network> result = new ArrayList();
1055         synchronized (mNetworkForNetId) {
1056             for (int i = 0; i < mNetworkForNetId.size(); i++) {
1057                 result.add(new Network(mNetworkForNetId.valueAt(i).network));
1058             }
1059         }
1060         return result.toArray(new Network[result.size()]);
1061     }
1062
1063     private NetworkCapabilities getNetworkCapabilitiesAndValidation(NetworkAgentInfo nai) {
1064         if (nai != null) {
1065             synchronized (nai) {
1066                 if (nai.created) {
1067                     NetworkCapabilities nc = new NetworkCapabilities(nai.networkCapabilities);
1068                     if (nai.lastValidated) {
1069                         nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
1070                     } else {
1071                         nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
1072                     }
1073                     return nc;
1074                 }
1075             }
1076         }
1077         return null;
1078     }
1079
1080     @Override
1081     public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
1082         // The basic principle is: if an app's traffic could possibly go over a
1083         // network, without the app doing anything multinetwork-specific,
1084         // (hence, by "default"), then include that network's capabilities in
1085         // the array.
1086         //
1087         // In the normal case, app traffic only goes over the system's default
1088         // network connection, so that's the only network returned.
1089         //
1090         // With a VPN in force, some app traffic may go into the VPN, and thus
1091         // over whatever underlying networks the VPN specifies, while other app
1092         // traffic may go over the system default network (e.g.: a split-tunnel
1093         // VPN, or an app disallowed by the VPN), so the set of networks
1094         // returned includes the VPN's underlying networks and the system
1095         // default.
1096         enforceAccessPermission();
1097
1098         HashMap<Network, NetworkCapabilities> result = new HashMap<Network, NetworkCapabilities>();
1099
1100         NetworkAgentInfo nai = getDefaultNetwork();
1101         NetworkCapabilities nc = getNetworkCapabilitiesAndValidation(getDefaultNetwork());
1102         if (nc != null) {
1103             result.put(nai.network, nc);
1104         }
1105
1106         if (!mLockdownEnabled) {
1107             synchronized (mVpns) {
1108                 Vpn vpn = mVpns.get(userId);
1109                 if (vpn != null) {
1110                     Network[] networks = vpn.getUnderlyingNetworks();
1111                     if (networks != null) {
1112                         for (Network network : networks) {
1113                             nai = getNetworkAgentInfoForNetwork(network);
1114                             nc = getNetworkCapabilitiesAndValidation(nai);
1115                             if (nc != null) {
1116                                 result.put(nai.network, nc);
1117                             }
1118                         }
1119                     }
1120                 }
1121             }
1122         }
1123
1124         NetworkCapabilities[] out = new NetworkCapabilities[result.size()];
1125         out = result.values().toArray(out);
1126         return out;
1127     }
1128
1129     @Override
1130     public boolean isNetworkSupported(int networkType) {
1131         enforceAccessPermission();
1132         return mLegacyTypeTracker.isTypeSupported(networkType);
1133     }
1134
1135     /**
1136      * Return LinkProperties for the active (i.e., connected) default
1137      * network interface.  It is assumed that at most one default network
1138      * is active at a time. If more than one is active, it is indeterminate
1139      * which will be returned.
1140      * @return the ip properties for the active network, or {@code null} if
1141      * none is active
1142      */
1143     @Override
1144     public LinkProperties getActiveLinkProperties() {
1145         enforceAccessPermission();
1146         final int uid = Binder.getCallingUid();
1147         NetworkState state = getUnfilteredActiveNetworkState(uid);
1148         return state.linkProperties;
1149     }
1150
1151     @Override
1152     public LinkProperties getLinkPropertiesForType(int networkType) {
1153         enforceAccessPermission();
1154         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1155         if (nai != null) {
1156             synchronized (nai) {
1157                 return new LinkProperties(nai.linkProperties);
1158             }
1159         }
1160         return null;
1161     }
1162
1163     // TODO - this should be ALL networks
1164     @Override
1165     public LinkProperties getLinkProperties(Network network) {
1166         enforceAccessPermission();
1167         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1168         if (nai != null) {
1169             synchronized (nai) {
1170                 return new LinkProperties(nai.linkProperties);
1171             }
1172         }
1173         return null;
1174     }
1175
1176     @Override
1177     public NetworkCapabilities getNetworkCapabilities(Network network) {
1178         enforceAccessPermission();
1179         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1180         if (nai != null) {
1181             synchronized (nai) {
1182                 return new NetworkCapabilities(nai.networkCapabilities);
1183             }
1184         }
1185         return null;
1186     }
1187
1188     @Override
1189     public NetworkState[] getAllNetworkState() {
1190         // Require internal since we're handing out IMSI details
1191         enforceConnectivityInternalPermission();
1192
1193         final ArrayList<NetworkState> result = Lists.newArrayList();
1194         for (Network network : getAllNetworks()) {
1195             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1196             if (nai != null) {
1197                 synchronized (nai) {
1198                     final String subscriberId = (nai.networkMisc != null)
1199                             ? nai.networkMisc.subscriberId : null;
1200                     result.add(new NetworkState(nai.networkInfo, nai.linkProperties,
1201                             nai.networkCapabilities, network, subscriberId, null));
1202                 }
1203             }
1204         }
1205         return result.toArray(new NetworkState[result.size()]);
1206     }
1207
1208     @Override
1209     public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
1210         enforceAccessPermission();
1211         final int uid = Binder.getCallingUid();
1212         final long token = Binder.clearCallingIdentity();
1213         try {
1214             final NetworkState state = getUnfilteredActiveNetworkState(uid);
1215             if (state.networkInfo != null) {
1216                 try {
1217                     return mPolicyManager.getNetworkQuotaInfo(state);
1218                 } catch (RemoteException e) {
1219                 }
1220             }
1221             return null;
1222         } finally {
1223             Binder.restoreCallingIdentity(token);
1224         }
1225     }
1226
1227     @Override
1228     public boolean isActiveNetworkMetered() {
1229         enforceAccessPermission();
1230         final int uid = Binder.getCallingUid();
1231         final long token = Binder.clearCallingIdentity();
1232         try {
1233             return isActiveNetworkMeteredUnchecked(uid);
1234         } finally {
1235             Binder.restoreCallingIdentity(token);
1236         }
1237     }
1238
1239     private boolean isActiveNetworkMeteredUnchecked(int uid) {
1240         final NetworkState state = getUnfilteredActiveNetworkState(uid);
1241         if (state.networkInfo != null) {
1242             try {
1243                 return mPolicyManager.isNetworkMetered(state);
1244             } catch (RemoteException e) {
1245             }
1246         }
1247         return false;
1248     }
1249
1250     private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
1251         @Override
1252         public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
1253             int deviceType = Integer.parseInt(label);
1254             sendDataActivityBroadcast(deviceType, active, tsNanos);
1255         }
1256     };
1257
1258     /**
1259      * Ensure that a network route exists to deliver traffic to the specified
1260      * host via the specified network interface.
1261      * @param networkType the type of the network over which traffic to the
1262      * specified host is to be routed
1263      * @param hostAddress the IP address of the host to which the route is
1264      * desired
1265      * @return {@code true} on success, {@code false} on failure
1266      */
1267     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
1268         enforceChangePermission();
1269         if (mProtectedNetworks.contains(networkType)) {
1270             enforceConnectivityInternalPermission();
1271         }
1272
1273         InetAddress addr;
1274         try {
1275             addr = InetAddress.getByAddress(hostAddress);
1276         } catch (UnknownHostException e) {
1277             if (DBG) log("requestRouteToHostAddress got " + e.toString());
1278             return false;
1279         }
1280
1281         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
1282             if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
1283             return false;
1284         }
1285
1286         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1287         if (nai == null) {
1288             if (mLegacyTypeTracker.isTypeSupported(networkType) == false) {
1289                 if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType);
1290             } else {
1291                 if (DBG) log("requestRouteToHostAddress on down network: " + networkType);
1292             }
1293             return false;
1294         }
1295
1296         DetailedState netState;
1297         synchronized (nai) {
1298             netState = nai.networkInfo.getDetailedState();
1299         }
1300
1301         if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) {
1302             if (VDBG) {
1303                 log("requestRouteToHostAddress on down network "
1304                         + "(" + networkType + ") - dropped"
1305                         + " netState=" + netState);
1306             }
1307             return false;
1308         }
1309
1310         final int uid = Binder.getCallingUid();
1311         final long token = Binder.clearCallingIdentity();
1312         try {
1313             LinkProperties lp;
1314             int netId;
1315             synchronized (nai) {
1316                 lp = nai.linkProperties;
1317                 netId = nai.network.netId;
1318             }
1319             boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
1320             if (DBG) log("requestRouteToHostAddress ok=" + ok);
1321             return ok;
1322         } finally {
1323             Binder.restoreCallingIdentity(token);
1324         }
1325     }
1326
1327     private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) {
1328         RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
1329         if (bestRoute == null) {
1330             bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
1331         } else {
1332             String iface = bestRoute.getInterface();
1333             if (bestRoute.getGateway().equals(addr)) {
1334                 // if there is no better route, add the implied hostroute for our gateway
1335                 bestRoute = RouteInfo.makeHostRoute(addr, iface);
1336             } else {
1337                 // if we will connect to this through another route, add a direct route
1338                 // to it's gateway
1339                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
1340             }
1341         }
1342         if (DBG) log("Adding " + bestRoute + " for interface " + bestRoute.getInterface());
1343         try {
1344             mNetd.addLegacyRouteForNetId(netId, bestRoute, uid);
1345         } catch (Exception e) {
1346             // never crash - catch them all
1347             if (DBG) loge("Exception trying to add a route: " + e);
1348             return false;
1349         }
1350         return true;
1351     }
1352
1353     public void setDataDependency(int networkType, boolean met) {
1354         enforceConnectivityInternalPermission();
1355
1356         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1357                 (met ? ENABLED : DISABLED), networkType));
1358     }
1359
1360     private void handleSetDependencyMet(int networkType, boolean met) {
1361         if (mNetTrackers[networkType] != null) {
1362             if (DBG) {
1363                 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1364             }
1365             mNetTrackers[networkType].setDependencyMet(met);
1366         }
1367     }
1368
1369     private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
1370         @Override
1371         public void onUidRulesChanged(int uid, int uidRules) {
1372             // caller is NPMS, since we only register with them
1373             if (LOGD_RULES) {
1374                 log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
1375             }
1376
1377             synchronized (mRulesLock) {
1378                 // skip update when we've already applied rules
1379                 final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
1380                 if (oldRules == uidRules) return;
1381
1382                 mUidRules.put(uid, uidRules);
1383             }
1384
1385             // TODO: notify UID when it has requested targeted updates
1386         }
1387
1388         @Override
1389         public void onMeteredIfacesChanged(String[] meteredIfaces) {
1390             // caller is NPMS, since we only register with them
1391             if (LOGD_RULES) {
1392                 log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
1393             }
1394
1395             synchronized (mRulesLock) {
1396                 mMeteredIfaces.clear();
1397                 for (String iface : meteredIfaces) {
1398                     mMeteredIfaces.add(iface);
1399                 }
1400             }
1401         }
1402
1403         @Override
1404         public void onRestrictBackgroundChanged(boolean restrictBackground) {
1405             // caller is NPMS, since we only register with them
1406             if (LOGD_RULES) {
1407                 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
1408             }
1409
1410             // kick off connectivity change broadcast for active network, since
1411             // global background policy change is radical.
1412             // TODO: Dead code; remove.
1413             //
1414             // final int networkType = mActiveDefaultNetwork;
1415             // if (isNetworkTypeValid(networkType)) {
1416             //     final NetworkStateTracker tracker = mNetTrackers[networkType];
1417             //     if (tracker != null) {
1418             //         final NetworkInfo info = tracker.getNetworkInfo();
1419             //         if (info != null && info.isConnected()) {
1420             //             sendConnectedBroadcast(info);
1421             //         }
1422             //     }
1423             // }
1424         }
1425     };
1426
1427     private void enforceInternetPermission() {
1428         mContext.enforceCallingOrSelfPermission(
1429                 android.Manifest.permission.INTERNET,
1430                 "ConnectivityService");
1431     }
1432
1433     private void enforceAccessPermission() {
1434         mContext.enforceCallingOrSelfPermission(
1435                 android.Manifest.permission.ACCESS_NETWORK_STATE,
1436                 "ConnectivityService");
1437     }
1438
1439     private void enforceChangePermission() {
1440         mContext.enforceCallingOrSelfPermission(
1441                 android.Manifest.permission.CHANGE_NETWORK_STATE,
1442                 "ConnectivityService");
1443     }
1444
1445     private void enforceTetherAccessPermission() {
1446         mContext.enforceCallingOrSelfPermission(
1447                 android.Manifest.permission.ACCESS_NETWORK_STATE,
1448                 "ConnectivityService");
1449     }
1450
1451     private void enforceConnectivityInternalPermission() {
1452         mContext.enforceCallingOrSelfPermission(
1453                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1454                 "ConnectivityService");
1455     }
1456
1457     public void sendConnectedBroadcast(NetworkInfo info) {
1458         enforceConnectivityInternalPermission();
1459         sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
1460         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
1461     }
1462
1463     private void sendInetConditionBroadcast(NetworkInfo info) {
1464         sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1465     }
1466
1467     private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
1468         if (mLockdownTracker != null) {
1469             info = mLockdownTracker.augmentNetworkInfo(info);
1470         }
1471
1472         Intent intent = new Intent(bcastType);
1473         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
1474         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
1475         if (info.isFailover()) {
1476             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1477             info.setFailover(false);
1478         }
1479         if (info.getReason() != null) {
1480             intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1481         }
1482         if (info.getExtraInfo() != null) {
1483             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1484                     info.getExtraInfo());
1485         }
1486         intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
1487         return intent;
1488     }
1489
1490     private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1491         sendStickyBroadcast(makeGeneralIntent(info, bcastType));
1492     }
1493
1494     private void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) {
1495         Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
1496         intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
1497         intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
1498         intent.putExtra(ConnectivityManager.EXTRA_REALTIME_NS, tsNanos);
1499         final long ident = Binder.clearCallingIdentity();
1500         try {
1501             mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
1502                     RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null);
1503         } finally {
1504             Binder.restoreCallingIdentity(ident);
1505         }
1506     }
1507
1508     private void sendStickyBroadcast(Intent intent) {
1509         synchronized(this) {
1510             if (!mSystemReady) {
1511                 mInitialBroadcast = new Intent(intent);
1512             }
1513             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1514             if (DBG) {
1515                 log("sendStickyBroadcast: action=" + intent.getAction());
1516             }
1517
1518             final long ident = Binder.clearCallingIdentity();
1519             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
1520                 final IBatteryStats bs = BatteryStatsService.getService();
1521                 try {
1522                     NetworkInfo ni = intent.getParcelableExtra(
1523                             ConnectivityManager.EXTRA_NETWORK_INFO);
1524                     bs.noteConnectivityChanged(intent.getIntExtra(
1525                             ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE),
1526                             ni != null ? ni.getState().toString() : "?");
1527                 } catch (RemoteException e) {
1528                 }
1529             }
1530             try {
1531                 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1532             } finally {
1533                 Binder.restoreCallingIdentity(ident);
1534             }
1535         }
1536     }
1537
1538     void systemReady() {
1539         // start network sampling ..
1540         Intent intent = new Intent(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED);
1541         intent.setPackage(mContext.getPackageName());
1542
1543         mSampleIntervalElapsedIntent = PendingIntent.getBroadcast(mContext,
1544                 SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE, intent, 0);
1545         setAlarm(DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS * 1000, mSampleIntervalElapsedIntent);
1546
1547         loadGlobalProxy();
1548
1549         synchronized(this) {
1550             mSystemReady = true;
1551             if (mInitialBroadcast != null) {
1552                 mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
1553                 mInitialBroadcast = null;
1554             }
1555         }
1556         // load the global proxy at startup
1557         mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
1558
1559         // Try bringing up tracker, but if KeyStore isn't ready yet, wait
1560         // for user to unlock device.
1561         if (!updateLockdownVpn()) {
1562             final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
1563             mContext.registerReceiver(mUserPresentReceiver, filter);
1564         }
1565
1566         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
1567
1568         mPermissionMonitor.startMonitoring();
1569     }
1570
1571     private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
1572         @Override
1573         public void onReceive(Context context, Intent intent) {
1574             // Try creating lockdown tracker, since user present usually means
1575             // unlocked keystore.
1576             if (updateLockdownVpn()) {
1577                 mContext.unregisterReceiver(this);
1578             }
1579         }
1580     };
1581
1582     /** @hide */
1583     @Override
1584     public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
1585         enforceConnectivityInternalPermission();
1586         if (DBG) log("captivePortalCheckCompleted: ni=" + info + " captive=" + isCaptivePortal);
1587 //        mNetTrackers[info.getType()].captivePortalCheckCompleted(isCaptivePortal);
1588     }
1589
1590     /**
1591      * Setup data activity tracking for the given network.
1592      *
1593      * Every {@code setupDataActivityTracking} should be paired with a
1594      * {@link #removeDataActivityTracking} for cleanup.
1595      */
1596     private void setupDataActivityTracking(NetworkAgentInfo networkAgent) {
1597         final String iface = networkAgent.linkProperties.getInterfaceName();
1598
1599         final int timeout;
1600         int type = ConnectivityManager.TYPE_NONE;
1601
1602         if (networkAgent.networkCapabilities.hasTransport(
1603                 NetworkCapabilities.TRANSPORT_CELLULAR)) {
1604             timeout = Settings.Global.getInt(mContext.getContentResolver(),
1605                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
1606                                              5);
1607             type = ConnectivityManager.TYPE_MOBILE;
1608         } else if (networkAgent.networkCapabilities.hasTransport(
1609                 NetworkCapabilities.TRANSPORT_WIFI)) {
1610             timeout = Settings.Global.getInt(mContext.getContentResolver(),
1611                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
1612                                              0);
1613             type = ConnectivityManager.TYPE_WIFI;
1614         } else {
1615             // do not track any other networks
1616             timeout = 0;
1617         }
1618
1619         if (timeout > 0 && iface != null && type != ConnectivityManager.TYPE_NONE) {
1620             try {
1621                 mNetd.addIdleTimer(iface, timeout, type);
1622             } catch (Exception e) {
1623                 // You shall not crash!
1624                 loge("Exception in setupDataActivityTracking " + e);
1625             }
1626         }
1627     }
1628
1629     /**
1630      * Remove data activity tracking when network disconnects.
1631      */
1632     private void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
1633         final String iface = networkAgent.linkProperties.getInterfaceName();
1634         final NetworkCapabilities caps = networkAgent.networkCapabilities;
1635
1636         if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
1637                               caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
1638             try {
1639                 // the call fails silently if no idletimer setup for this interface
1640                 mNetd.removeIdleTimer(iface);
1641             } catch (Exception e) {
1642                 loge("Exception in removeDataActivityTracking " + e);
1643             }
1644         }
1645     }
1646
1647     /**
1648      * Reads the network specific MTU size from reources.
1649      * and set it on it's iface.
1650      */
1651     private void updateMtu(LinkProperties newLp, LinkProperties oldLp) {
1652         final String iface = newLp.getInterfaceName();
1653         final int mtu = newLp.getMtu();
1654         if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
1655             if (VDBG) log("identical MTU - not setting");
1656             return;
1657         }
1658
1659         if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) {
1660             loge("Unexpected mtu value: " + mtu + ", " + iface);
1661             return;
1662         }
1663
1664         // Cannot set MTU without interface name
1665         if (TextUtils.isEmpty(iface)) {
1666             loge("Setting MTU size with null iface.");
1667             return;
1668         }
1669
1670         try {
1671             if (DBG) log("Setting MTU size: " + iface + ", " + mtu);
1672             mNetd.setMtu(iface, mtu);
1673         } catch (Exception e) {
1674             Slog.e(TAG, "exception in setMtu()" + e);
1675         }
1676     }
1677
1678     private static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
1679
1680     private void updateTcpBufferSizes(NetworkAgentInfo nai) {
1681         if (isDefaultNetwork(nai) == false) {
1682             return;
1683         }
1684
1685         String tcpBufferSizes = nai.linkProperties.getTcpBufferSizes();
1686         String[] values = null;
1687         if (tcpBufferSizes != null) {
1688             values = tcpBufferSizes.split(",");
1689         }
1690
1691         if (values == null || values.length != 6) {
1692             if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
1693             tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES;
1694             values = tcpBufferSizes.split(",");
1695         }
1696
1697         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
1698
1699         try {
1700             if (DBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
1701
1702             final String prefix = "/sys/kernel/ipv4/tcp_";
1703             FileUtils.stringToFile(prefix + "rmem_min", values[0]);
1704             FileUtils.stringToFile(prefix + "rmem_def", values[1]);
1705             FileUtils.stringToFile(prefix + "rmem_max", values[2]);
1706             FileUtils.stringToFile(prefix + "wmem_min", values[3]);
1707             FileUtils.stringToFile(prefix + "wmem_def", values[4]);
1708             FileUtils.stringToFile(prefix + "wmem_max", values[5]);
1709             mCurrentTcpBufferSizes = tcpBufferSizes;
1710         } catch (IOException e) {
1711             loge("Can't set TCP buffer sizes:" + e);
1712         }
1713
1714         final String defaultRwndKey = "net.tcp.default_init_rwnd";
1715         int defaultRwndValue = SystemProperties.getInt(defaultRwndKey, 0);
1716         Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
1717             Settings.Global.TCP_DEFAULT_INIT_RWND, defaultRwndValue);
1718         final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
1719         if (rwndValue != 0) {
1720             SystemProperties.set(sysctlKey, rwndValue.toString());
1721         }
1722     }
1723
1724     private void flushVmDnsCache() {
1725         /*
1726          * Tell the VMs to toss their DNS caches
1727          */
1728         Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
1729         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
1730         /*
1731          * Connectivity events can happen before boot has completed ...
1732          */
1733         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1734         final long ident = Binder.clearCallingIdentity();
1735         try {
1736             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1737         } finally {
1738             Binder.restoreCallingIdentity(ident);
1739         }
1740     }
1741
1742     @Override
1743     public int getRestoreDefaultNetworkDelay(int networkType) {
1744         String restoreDefaultNetworkDelayStr = SystemProperties.get(
1745                 NETWORK_RESTORE_DELAY_PROP_NAME);
1746         if(restoreDefaultNetworkDelayStr != null &&
1747                 restoreDefaultNetworkDelayStr.length() != 0) {
1748             try {
1749                 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1750             } catch (NumberFormatException e) {
1751             }
1752         }
1753         // if the system property isn't set, use the value for the apn type
1754         int ret = RESTORE_DEFAULT_NETWORK_DELAY;
1755
1756         if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
1757                 (mNetConfigs[networkType] != null)) {
1758             ret = mNetConfigs[networkType].restoreTime;
1759         }
1760         return ret;
1761     }
1762
1763     @Override
1764     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1765         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
1766         if (mContext.checkCallingOrSelfPermission(
1767                 android.Manifest.permission.DUMP)
1768                 != PackageManager.PERMISSION_GRANTED) {
1769             pw.println("Permission Denial: can't dump ConnectivityService " +
1770                     "from from pid=" + Binder.getCallingPid() + ", uid=" +
1771                     Binder.getCallingUid());
1772             return;
1773         }
1774
1775         pw.println("NetworkFactories for:");
1776         pw.increaseIndent();
1777         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
1778             pw.println(nfi.name);
1779         }
1780         pw.decreaseIndent();
1781         pw.println();
1782
1783         NetworkAgentInfo defaultNai = mNetworkForRequestId.get(mDefaultRequest.requestId);
1784         pw.print("Active default network: ");
1785         if (defaultNai == null) {
1786             pw.println("none");
1787         } else {
1788             pw.println(defaultNai.network.netId);
1789         }
1790         pw.println();
1791
1792         pw.println("Current Networks:");
1793         pw.increaseIndent();
1794         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
1795             pw.println(nai.toString());
1796             pw.increaseIndent();
1797             pw.println("Requests:");
1798             pw.increaseIndent();
1799             for (int i = 0; i < nai.networkRequests.size(); i++) {
1800                 pw.println(nai.networkRequests.valueAt(i).toString());
1801             }
1802             pw.decreaseIndent();
1803             pw.println("Lingered:");
1804             pw.increaseIndent();
1805             for (NetworkRequest nr : nai.networkLingered) pw.println(nr.toString());
1806             pw.decreaseIndent();
1807             pw.decreaseIndent();
1808         }
1809         pw.decreaseIndent();
1810         pw.println();
1811
1812         pw.println("Network Requests:");
1813         pw.increaseIndent();
1814         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
1815             pw.println(nri.toString());
1816         }
1817         pw.println();
1818         pw.decreaseIndent();
1819
1820         pw.println("mLegacyTypeTracker:");
1821         pw.increaseIndent();
1822         mLegacyTypeTracker.dump(pw);
1823         pw.decreaseIndent();
1824         pw.println();
1825
1826         synchronized (this) {
1827             pw.println("NetworkTransitionWakeLock is currently " +
1828                     (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
1829             pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
1830         }
1831         pw.println();
1832
1833         mTethering.dump(fd, pw, args);
1834
1835         if (mInetLog != null) {
1836             pw.println();
1837             pw.println("Inet condition reports:");
1838             pw.increaseIndent();
1839             for(int i = 0; i < mInetLog.size(); i++) {
1840                 pw.println(mInetLog.get(i));
1841             }
1842             pw.decreaseIndent();
1843         }
1844     }
1845
1846     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, String msg) {
1847         if (nai.network == null) return false;
1848         final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
1849         if (officialNai != null && officialNai.equals(nai)) return true;
1850         if (officialNai != null || VDBG) {
1851             loge(msg + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
1852                 " - " + nai);
1853         }
1854         return false;
1855     }
1856
1857     private boolean isRequest(NetworkRequest request) {
1858         return mNetworkRequests.get(request).isRequest;
1859     }
1860
1861     // must be stateless - things change under us.
1862     private class NetworkStateTrackerHandler extends Handler {
1863         public NetworkStateTrackerHandler(Looper looper) {
1864             super(looper);
1865         }
1866
1867         @Override
1868         public void handleMessage(Message msg) {
1869             NetworkInfo info;
1870             switch (msg.what) {
1871                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
1872                     handleAsyncChannelHalfConnect(msg);
1873                     break;
1874                 }
1875                 case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
1876                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1877                     if (nai != null) nai.asyncChannel.disconnect();
1878                     break;
1879                 }
1880                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
1881                     handleAsyncChannelDisconnected(msg);
1882                     break;
1883                 }
1884                 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
1885                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1886                     if (nai == null) {
1887                         loge("EVENT_NETWORK_CAPABILITIES_CHANGED from unknown NetworkAgent");
1888                     } else {
1889                         updateCapabilities(nai, (NetworkCapabilities)msg.obj);
1890                     }
1891                     break;
1892                 }
1893                 case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
1894                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1895                     if (nai == null) {
1896                         loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
1897                     } else {
1898                         if (VDBG) {
1899                             log("Update of LinkProperties for " + nai.name() +
1900                                     "; created=" + nai.created);
1901                         }
1902                         LinkProperties oldLp = nai.linkProperties;
1903                         synchronized (nai) {
1904                             nai.linkProperties = (LinkProperties)msg.obj;
1905                         }
1906                         if (nai.created) updateLinkProperties(nai, oldLp);
1907                     }
1908                     break;
1909                 }
1910                 case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
1911                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1912                     if (nai == null) {
1913                         loge("EVENT_NETWORK_INFO_CHANGED from unknown NetworkAgent");
1914                         break;
1915                     }
1916                     info = (NetworkInfo) msg.obj;
1917                     updateNetworkInfo(nai, info);
1918                     break;
1919                 }
1920                 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
1921                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1922                     if (nai == null) {
1923                         loge("EVENT_NETWORK_SCORE_CHANGED from unknown NetworkAgent");
1924                         break;
1925                     }
1926                     Integer score = (Integer) msg.obj;
1927                     if (score != null) updateNetworkScore(nai, score.intValue());
1928                     break;
1929                 }
1930                 case NetworkAgent.EVENT_UID_RANGES_ADDED: {
1931                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1932                     if (nai == null) {
1933                         loge("EVENT_UID_RANGES_ADDED from unknown NetworkAgent");
1934                         break;
1935                     }
1936                     try {
1937                         mNetd.addVpnUidRanges(nai.network.netId, (UidRange[])msg.obj);
1938                     } catch (Exception e) {
1939                         // Never crash!
1940                         loge("Exception in addVpnUidRanges: " + e);
1941                     }
1942                     break;
1943                 }
1944                 case NetworkAgent.EVENT_UID_RANGES_REMOVED: {
1945                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1946                     if (nai == null) {
1947                         loge("EVENT_UID_RANGES_REMOVED from unknown NetworkAgent");
1948                         break;
1949                     }
1950                     try {
1951                         mNetd.removeVpnUidRanges(nai.network.netId, (UidRange[])msg.obj);
1952                     } catch (Exception e) {
1953                         // Never crash!
1954                         loge("Exception in removeVpnUidRanges: " + e);
1955                     }
1956                     break;
1957                 }
1958                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
1959                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
1960                     if (nai == null) {
1961                         loge("EVENT_SET_EXPLICITLY_SELECTED from unknown NetworkAgent");
1962                         break;
1963                     }
1964                     if (nai.created && !nai.networkMisc.explicitlySelected) {
1965                         loge("ERROR: created network explicitly selected.");
1966                     }
1967                     nai.networkMisc.explicitlySelected = true;
1968                     break;
1969                 }
1970                 case NetworkMonitor.EVENT_NETWORK_TESTED: {
1971                     NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
1972                     if (isLiveNetworkAgent(nai, "EVENT_NETWORK_VALIDATED")) {
1973                         boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
1974                         nai.lastValidated = valid;
1975                         if (valid) {
1976                             if (DBG) log("Validated " + nai.name());
1977                             if (!nai.everValidated) {
1978                                 nai.everValidated = true;
1979                                 rematchNetworkAndRequests(nai, NascentState.JUST_VALIDATED,
1980                                     ReapUnvalidatedNetworks.REAP);
1981                                 // If score has changed, rebroadcast to NetworkFactories. b/17726566
1982                                 sendUpdatedScoreToFactories(nai);
1983                             }
1984                         }
1985                         updateInetCondition(nai);
1986                         // Let the NetworkAgent know the state of its network
1987                         nai.asyncChannel.sendMessage(
1988                                 android.net.NetworkAgent.CMD_REPORT_NETWORK_STATUS,
1989                                 (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
1990                                 0, null);
1991                     }
1992                     break;
1993                 }
1994                 case NetworkMonitor.EVENT_NETWORK_LINGER_COMPLETE: {
1995                     NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
1996                     if (isLiveNetworkAgent(nai, "EVENT_NETWORK_LINGER_COMPLETE")) {
1997                         handleLingerComplete(nai);
1998                     }
1999                     break;
2000                 }
2001                 case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
2002                     if (msg.arg1 == 0) {
2003                         setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null);
2004                     } else {
2005                         NetworkAgentInfo nai = null;
2006                         synchronized (mNetworkForNetId) {
2007                             nai = mNetworkForNetId.get(msg.arg2);
2008                         }
2009                         if (nai == null) {
2010                             loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
2011                             break;
2012                         }
2013                         setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(),
2014                                 nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj);
2015                     }
2016                     break;
2017                 }
2018                 case NetworkStateTracker.EVENT_STATE_CHANGED: {
2019                     info = (NetworkInfo) msg.obj;
2020                     NetworkInfo.State state = info.getState();
2021
2022                     if (VDBG || (state == NetworkInfo.State.CONNECTED) ||
2023                             (state == NetworkInfo.State.DISCONNECTED) ||
2024                             (state == NetworkInfo.State.SUSPENDED)) {
2025                         log("ConnectivityChange for " +
2026                             info.getTypeName() + ": " +
2027                             state + "/" + info.getDetailedState());
2028                     }
2029
2030                     EventLogTags.writeConnectivityStateChanged(
2031                             info.getType(), info.getSubtype(), info.getDetailedState().ordinal());
2032
2033                     if (info.isConnectedToProvisioningNetwork()) {
2034                         /**
2035                          * TODO: Create ConnectivityManager.TYPE_MOBILE_PROVISIONING
2036                          * for now its an in between network, its a network that
2037                          * is actually a default network but we don't want it to be
2038                          * announced as such to keep background applications from
2039                          * trying to use it. It turns out that some still try so we
2040                          * take the additional step of clearing any default routes
2041                          * to the link that may have incorrectly setup by the lower
2042                          * levels.
2043                          */
2044                         LinkProperties lp = getLinkPropertiesForType(info.getType());
2045                         if (DBG) {
2046                             log("EVENT_STATE_CHANGED: connected to provisioning network, lp=" + lp);
2047                         }
2048
2049                         // Clear any default routes setup by the radio so
2050                         // any activity by applications trying to use this
2051                         // connection will fail until the provisioning network
2052                         // is enabled.
2053                         /*
2054                         for (RouteInfo r : lp.getRoutes()) {
2055                             removeRoute(lp, r, TO_DEFAULT_TABLE,
2056                                         mNetTrackers[info.getType()].getNetwork().netId);
2057                         }
2058                         */
2059                     } else if (state == NetworkInfo.State.DISCONNECTED) {
2060                     } else if (state == NetworkInfo.State.SUSPENDED) {
2061                     } else if (state == NetworkInfo.State.CONNECTED) {
2062                     //    handleConnect(info);
2063                     }
2064                     notifyLockdownVpn(null);
2065                     break;
2066                 }
2067                 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
2068                     info = (NetworkInfo) msg.obj;
2069                     // TODO: Temporary allowing network configuration
2070                     //       change not resetting sockets.
2071                     //       @see bug/4455071
2072                     /*
2073                     handleConnectivityChange(info.getType(), mCurrentLinkProperties[info.getType()],
2074                             false);
2075                     */
2076                     break;
2077                 }
2078             }
2079         }
2080     }
2081
2082     // Cancel any lingering so the linger timeout doesn't teardown a network.
2083     // This should be called when a network begins satisfying a NetworkRequest.
2084     // Note: depending on what state the NetworkMonitor is in (e.g.,
2085     // if it's awaiting captive portal login, or if validation failed), this
2086     // may trigger a re-evaluation of the network.
2087     private void unlinger(NetworkAgentInfo nai) {
2088         if (VDBG) log("Canceling linger of " + nai.name());
2089         // If network has never been validated, it cannot have been lingered, so don't bother
2090         // needlessly triggering a re-evaluation.
2091         if (!nai.everValidated) return;
2092         nai.networkLingered.clear();
2093         nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
2094     }
2095
2096     private void handleAsyncChannelHalfConnect(Message msg) {
2097         AsyncChannel ac = (AsyncChannel) msg.obj;
2098         if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
2099             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
2100                 if (VDBG) log("NetworkFactory connected");
2101                 // A network factory has connected.  Send it all current NetworkRequests.
2102                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
2103                     if (nri.isRequest == false) continue;
2104                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
2105                     ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
2106                             (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
2107                 }
2108             } else {
2109                 loge("Error connecting NetworkFactory");
2110                 mNetworkFactoryInfos.remove(msg.obj);
2111             }
2112         } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
2113             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
2114                 if (VDBG) log("NetworkAgent connected");
2115                 // A network agent has requested a connection.  Establish the connection.
2116                 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
2117                         sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
2118             } else {
2119                 loge("Error connecting NetworkAgent");
2120                 NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
2121                 if (nai != null) {
2122                     synchronized (mNetworkForNetId) {
2123                         mNetworkForNetId.remove(nai.network.netId);
2124                     }
2125                     // Just in case.
2126                     mLegacyTypeTracker.remove(nai);
2127                 }
2128             }
2129         }
2130     }
2131
2132     private void handleAsyncChannelDisconnected(Message msg) {
2133         NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2134         if (nai != null) {
2135             if (DBG) {
2136                 log(nai.name() + " got DISCONNECTED, was satisfying " + nai.networkRequests.size());
2137             }
2138             // A network agent has disconnected.
2139             if (nai.created) {
2140                 // Tell netd to clean up the configuration for this network
2141                 // (routing rules, DNS, etc).
2142                 try {
2143                     mNetd.removeNetwork(nai.network.netId);
2144                 } catch (Exception e) {
2145                     loge("Exception removing network: " + e);
2146                 }
2147             }
2148             // TODO - if we move the logic to the network agent (have them disconnect
2149             // because they lost all their requests or because their score isn't good)
2150             // then they would disconnect organically, report their new state and then
2151             // disconnect the channel.
2152             if (nai.networkInfo.isConnected()) {
2153                 nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
2154                         null, null);
2155             }
2156             if (isDefaultNetwork(nai)) {
2157                 mDefaultInetConditionPublished = 0;
2158             }
2159             notifyIfacesChanged();
2160             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
2161             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
2162             mNetworkAgentInfos.remove(msg.replyTo);
2163             updateClat(null, nai.linkProperties, nai);
2164             mLegacyTypeTracker.remove(nai);
2165             synchronized (mNetworkForNetId) {
2166                 mNetworkForNetId.remove(nai.network.netId);
2167             }
2168             // Since we've lost the network, go through all the requests that
2169             // it was satisfying and see if any other factory can satisfy them.
2170             // TODO: This logic may be better replaced with a call to rematchAllNetworksAndRequests
2171             final ArrayList<NetworkAgentInfo> toActivate = new ArrayList<NetworkAgentInfo>();
2172             for (int i = 0; i < nai.networkRequests.size(); i++) {
2173                 NetworkRequest request = nai.networkRequests.valueAt(i);
2174                 NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
2175                 if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
2176                     if (DBG) {
2177                         log("Checking for replacement network to handle request " + request );
2178                     }
2179                     mNetworkForRequestId.remove(request.requestId);
2180                     sendUpdatedScoreToFactories(request, 0);
2181                     NetworkAgentInfo alternative = null;
2182                     for (NetworkAgentInfo existing : mNetworkAgentInfos.values()) {
2183                         if (existing.satisfies(request) &&
2184                                 (alternative == null ||
2185                                  alternative.getCurrentScore() < existing.getCurrentScore())) {
2186                             alternative = existing;
2187                         }
2188                     }
2189                     if (alternative != null) {
2190                         if (DBG) log(" found replacement in " + alternative.name());
2191                         if (!toActivate.contains(alternative)) {
2192                             toActivate.add(alternative);
2193                         }
2194                     }
2195                 }
2196             }
2197             if (nai.networkRequests.get(mDefaultRequest.requestId) != null) {
2198                 removeDataActivityTracking(nai);
2199                 notifyLockdownVpn(nai);
2200                 requestNetworkTransitionWakelock(nai.name());
2201             }
2202             for (NetworkAgentInfo networkToActivate : toActivate) {
2203                 unlinger(networkToActivate);
2204                 rematchNetworkAndRequests(networkToActivate, NascentState.NOT_JUST_VALIDATED,
2205                         ReapUnvalidatedNetworks.DONT_REAP);
2206             }
2207         }
2208     }
2209
2210     // If this method proves to be too slow then we can maintain a separate
2211     // pendingIntent => NetworkRequestInfo map.
2212     // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
2213     private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
2214         Intent intent = pendingIntent.getIntent();
2215         for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
2216             PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
2217             if (existingPendingIntent != null &&
2218                     existingPendingIntent.getIntent().filterEquals(intent)) {
2219                 return entry.getValue();
2220             }
2221         }
2222         return null;
2223     }
2224
2225     private void handleRegisterNetworkRequestWithIntent(Message msg) {
2226         final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
2227
2228         NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
2229         if (existingRequest != null) { // remove the existing request.
2230             if (DBG) log("Replacing " + existingRequest.request + " with "
2231                     + nri.request + " because their intents matched.");
2232             handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
2233         }
2234         handleRegisterNetworkRequest(msg);
2235     }
2236
2237     private void handleRegisterNetworkRequest(Message msg) {
2238         final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
2239
2240         mNetworkRequests.put(nri.request, nri);
2241
2242         // TODO: This logic may be better replaced with a call to rematchNetworkAndRequests
2243
2244         // Check for the best currently alive network that satisfies this request
2245         NetworkAgentInfo bestNetwork = null;
2246         for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
2247             if (DBG) log("handleRegisterNetworkRequest checking " + network.name());
2248             if (network.satisfies(nri.request)) {
2249                 if (DBG) log("apparently satisfied.  currentScore=" + network.getCurrentScore());
2250                 if (!nri.isRequest) {
2251                     // Not setting bestNetwork here as a listening NetworkRequest may be
2252                     // satisfied by multiple Networks.  Instead the request is added to
2253                     // each satisfying Network and notified about each.
2254                     network.addRequest(nri.request);
2255                     notifyNetworkCallback(network, nri);
2256                 } else if (bestNetwork == null ||
2257                         bestNetwork.getCurrentScore() < network.getCurrentScore()) {
2258                     bestNetwork = network;
2259                 }
2260             }
2261         }
2262         if (bestNetwork != null) {
2263             if (DBG) log("using " + bestNetwork.name());
2264             unlinger(bestNetwork);
2265             bestNetwork.addRequest(nri.request);
2266             mNetworkForRequestId.put(nri.request.requestId, bestNetwork);
2267             notifyNetworkCallback(bestNetwork, nri);
2268             if (nri.request.legacyType != TYPE_NONE) {
2269                 mLegacyTypeTracker.add(nri.request.legacyType, bestNetwork);
2270             }
2271         }
2272
2273         if (nri.isRequest) {
2274             if (DBG) log("sending new NetworkRequest to factories");
2275             final int score = bestNetwork == null ? 0 : bestNetwork.getCurrentScore();
2276             for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
2277                 nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
2278                         0, nri.request);
2279             }
2280         }
2281     }
2282
2283     private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
2284             int callingUid) {
2285         NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
2286         if (nri != null) {
2287             handleReleaseNetworkRequest(nri.request, callingUid);
2288         }
2289     }
2290
2291     // Is nai unneeded by all NetworkRequests (and should be disconnected)?
2292     // For validated Networks this is simply whether it is satsifying any NetworkRequests.
2293     // For unvalidated Networks this is whether it is satsifying any NetworkRequests or
2294     // were it to become validated, would it have a chance of satisfying any NetworkRequests.
2295     private boolean unneeded(NetworkAgentInfo nai) {
2296         if (!nai.created || nai.isVPN()) return false;
2297         boolean unneeded = true;
2298         if (nai.everValidated) {
2299             for (int i = 0; i < nai.networkRequests.size() && unneeded; i++) {
2300                 final NetworkRequest nr = nai.networkRequests.valueAt(i);
2301                 try {
2302                     if (isRequest(nr)) unneeded = false;
2303                 } catch (Exception e) {
2304                     loge("Request " + nr + " not found in mNetworkRequests.");
2305                     loge("  it came from request list  of " + nai.name());
2306                 }
2307             }
2308         } else {
2309             for (NetworkRequestInfo nri : mNetworkRequests.values()) {
2310                 // If this Network is already the highest scoring Network for a request, or if
2311                 // there is hope for it to become one if it validated, then it is needed.
2312                 if (nri.isRequest && nai.satisfies(nri.request) &&
2313                         (nai.networkRequests.get(nri.request.requestId) != null ||
2314                         // Note that this catches two important cases:
2315                         // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
2316                         //    is currently satisfying the request.  This is desirable when
2317                         //    cellular ends up validating but WiFi does not.
2318                         // 2. Unvalidated WiFi will not be reaped when validated cellular
2319                         //    is currently satsifying the request.  This is desirable when
2320                         //    WiFi ends up validating and out scoring cellular.
2321                         mNetworkForRequestId.get(nri.request.requestId).getCurrentScore() <
2322                                 nai.getCurrentScoreAsValidated())) {
2323                     unneeded = false;
2324                     break;
2325                 }
2326             }
2327         }
2328         return unneeded;
2329     }
2330
2331     private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
2332         NetworkRequestInfo nri = mNetworkRequests.get(request);
2333         if (nri != null) {
2334             if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
2335                 if (DBG) log("Attempt to release unowned NetworkRequest " + request);
2336                 return;
2337             }
2338             if (DBG) log("releasing NetworkRequest " + request);
2339             nri.unlinkDeathRecipient();
2340             mNetworkRequests.remove(request);
2341             if (nri.isRequest) {
2342                 // Find all networks that are satisfying this request and remove the request
2343                 // from their request lists.
2344                 // TODO - it's my understanding that for a request there is only a single
2345                 // network satisfying it, so this loop is wasteful
2346                 boolean wasKept = false;
2347                 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2348                     if (nai.networkRequests.get(nri.request.requestId) != null) {
2349                         nai.networkRequests.remove(nri.request.requestId);
2350                         if (DBG) {
2351                             log(" Removing from current network " + nai.name() +
2352                                     ", leaving " + nai.networkRequests.size() +
2353                                     " requests.");
2354                         }
2355                         if (unneeded(nai)) {
2356                             if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
2357                             teardownUnneededNetwork(nai);
2358                         } else {
2359                             // suspect there should only be one pass through here
2360                             // but if any were kept do the check below
2361                             wasKept |= true;
2362                         }
2363                     }
2364                 }
2365
2366                 NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
2367                 if (nai != null) {
2368                     mNetworkForRequestId.remove(nri.request.requestId);
2369                 }
2370                 // Maintain the illusion.  When this request arrived, we might have pretended
2371                 // that a network connected to serve it, even though the network was already
2372                 // connected.  Now that this request has gone away, we might have to pretend
2373                 // that the network disconnected.  LegacyTypeTracker will generate that
2374                 // phantom disconnect for this type.
2375                 if (nri.request.legacyType != TYPE_NONE && nai != null) {
2376                     boolean doRemove = true;
2377                     if (wasKept) {
2378                         // check if any of the remaining requests for this network are for the
2379                         // same legacy type - if so, don't remove the nai
2380                         for (int i = 0; i < nai.networkRequests.size(); i++) {
2381                             NetworkRequest otherRequest = nai.networkRequests.valueAt(i);
2382                             if (otherRequest.legacyType == nri.request.legacyType &&
2383                                     isRequest(otherRequest)) {
2384                                 if (DBG) log(" still have other legacy request - leaving");
2385                                 doRemove = false;
2386                             }
2387                         }
2388                     }
2389
2390                     if (doRemove) {
2391                         mLegacyTypeTracker.remove(nri.request.legacyType, nai);
2392                     }
2393                 }
2394
2395                 for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
2396                     nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
2397                             nri.request);
2398                 }
2399             } else {
2400                 // listens don't have a singular affectedNetwork.  Check all networks to see
2401                 // if this listen request applies and remove it.
2402                 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2403                     nai.networkRequests.remove(nri.request.requestId);
2404                 }
2405             }
2406             callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED);
2407         }
2408     }
2409
2410     private class InternalHandler extends Handler {
2411         public InternalHandler(Looper looper) {
2412             super(looper);
2413         }
2414
2415         @Override
2416         public void handleMessage(Message msg) {
2417             switch (msg.what) {
2418                 case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
2419                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
2420                     String causedBy = null;
2421                     synchronized (ConnectivityService.this) {
2422                         if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
2423                                 mNetTransitionWakeLock.isHeld()) {
2424                             mNetTransitionWakeLock.release();
2425                             causedBy = mNetTransitionWakeLockCausedBy;
2426                         } else {
2427                             break;
2428                         }
2429                     }
2430                     if (msg.what == EVENT_EXPIRE_NET_TRANSITION_WAKELOCK) {
2431                         log("Failed to find a new network - expiring NetTransition Wakelock");
2432                     } else {
2433                         log("NetTransition Wakelock (" + (causedBy == null ? "unknown" : causedBy) +
2434                                 " cleared because we found a replacement network");
2435                     }
2436                     break;
2437                 }
2438                 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
2439                     handleDeprecatedGlobalHttpProxy();
2440                     break;
2441                 }
2442                 case EVENT_SET_DEPENDENCY_MET: {
2443                     boolean met = (msg.arg1 == ENABLED);
2444                     handleSetDependencyMet(msg.arg2, met);
2445                     break;
2446                 }
2447                 case EVENT_SEND_STICKY_BROADCAST_INTENT: {
2448                     Intent intent = (Intent)msg.obj;
2449                     sendStickyBroadcast(intent);
2450                     break;
2451                 }
2452                 case EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: {
2453                     int tag = mEnableFailFastMobileDataTag.get();
2454                     if (msg.arg1 == tag) {
2455                         MobileDataStateTracker mobileDst =
2456                             (MobileDataStateTracker) mNetTrackers[ConnectivityManager.TYPE_MOBILE];
2457                         if (mobileDst != null) {
2458                             mobileDst.setEnableFailFastMobileData(msg.arg2);
2459                         }
2460                     } else {
2461                         log("EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: stale arg1:" + msg.arg1
2462                                 + " != tag:" + tag);
2463                     }
2464                     break;
2465                 }
2466                 case EVENT_SAMPLE_INTERVAL_ELAPSED: {
2467                     handleNetworkSamplingTimeout();
2468                     break;
2469                 }
2470                 case EVENT_PROXY_HAS_CHANGED: {
2471                     handleApplyDefaultProxy((ProxyInfo)msg.obj);
2472                     break;
2473                 }
2474                 case EVENT_REGISTER_NETWORK_FACTORY: {
2475                     handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
2476                     break;
2477                 }
2478                 case EVENT_UNREGISTER_NETWORK_FACTORY: {
2479                     handleUnregisterNetworkFactory((Messenger)msg.obj);
2480                     break;
2481                 }
2482                 case EVENT_REGISTER_NETWORK_AGENT: {
2483                     handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
2484                     break;
2485                 }
2486                 case EVENT_REGISTER_NETWORK_REQUEST:
2487                 case EVENT_REGISTER_NETWORK_LISTENER: {
2488                     handleRegisterNetworkRequest(msg);
2489                     break;
2490                 }
2491                 case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: {
2492                     handleRegisterNetworkRequestWithIntent(msg);
2493                     break;
2494                 }
2495                 case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
2496                     handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
2497                     break;
2498                 }
2499                 case EVENT_RELEASE_NETWORK_REQUEST: {
2500                     handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
2501                     break;
2502                 }
2503                 case EVENT_SYSTEM_READY: {
2504                     for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2505                         nai.networkMonitor.systemReady = true;
2506                     }
2507                     break;
2508                 }
2509             }
2510         }
2511     }
2512
2513     // javadoc from interface
2514     public int tether(String iface) {
2515         ConnectivityManager.enforceTetherChangePermission(mContext);
2516         if (isTetheringSupported()) {
2517             return mTethering.tether(iface);
2518         } else {
2519             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2520         }
2521     }
2522
2523     // javadoc from interface
2524     public int untether(String iface) {
2525         ConnectivityManager.enforceTetherChangePermission(mContext);
2526
2527         if (isTetheringSupported()) {
2528             return mTethering.untether(iface);
2529         } else {
2530             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2531         }
2532     }
2533
2534     // javadoc from interface
2535     public int getLastTetherError(String iface) {
2536         enforceTetherAccessPermission();
2537
2538         if (isTetheringSupported()) {
2539             return mTethering.getLastTetherError(iface);
2540         } else {
2541             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2542         }
2543     }
2544
2545     // TODO - proper iface API for selection by property, inspection, etc
2546     public String[] getTetherableUsbRegexs() {
2547         enforceTetherAccessPermission();
2548         if (isTetheringSupported()) {
2549             return mTethering.getTetherableUsbRegexs();
2550         } else {
2551             return new String[0];
2552         }
2553     }
2554
2555     public String[] getTetherableWifiRegexs() {
2556         enforceTetherAccessPermission();
2557         if (isTetheringSupported()) {
2558             return mTethering.getTetherableWifiRegexs();
2559         } else {
2560             return new String[0];
2561         }
2562     }
2563
2564     public String[] getTetherableBluetoothRegexs() {
2565         enforceTetherAccessPermission();
2566         if (isTetheringSupported()) {
2567             return mTethering.getTetherableBluetoothRegexs();
2568         } else {
2569             return new String[0];
2570         }
2571     }
2572
2573     public int setUsbTethering(boolean enable) {
2574         ConnectivityManager.enforceTetherChangePermission(mContext);
2575         if (isTetheringSupported()) {
2576             return mTethering.setUsbTethering(enable);
2577         } else {
2578             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2579         }
2580     }
2581
2582     // TODO - move iface listing, queries, etc to new module
2583     // javadoc from interface
2584     public String[] getTetherableIfaces() {
2585         enforceTetherAccessPermission();
2586         return mTethering.getTetherableIfaces();
2587     }
2588
2589     public String[] getTetheredIfaces() {
2590         enforceTetherAccessPermission();
2591         return mTethering.getTetheredIfaces();
2592     }
2593
2594     public String[] getTetheringErroredIfaces() {
2595         enforceTetherAccessPermission();
2596         return mTethering.getErroredIfaces();
2597     }
2598
2599     public String[] getTetheredDhcpRanges() {
2600         enforceConnectivityInternalPermission();
2601         return mTethering.getTetheredDhcpRanges();
2602     }
2603
2604     // if ro.tether.denied = true we default to no tethering
2605     // gservices could set the secure setting to 1 though to enable it on a build where it
2606     // had previously been turned off.
2607     public boolean isTetheringSupported() {
2608         enforceTetherAccessPermission();
2609         int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
2610         boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
2611                 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
2612                 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
2613         return tetherEnabledInSettings && ((mTethering.getTetherableUsbRegexs().length != 0 ||
2614                 mTethering.getTetherableWifiRegexs().length != 0 ||
2615                 mTethering.getTetherableBluetoothRegexs().length != 0) &&
2616                 mTethering.getUpstreamIfaceTypes().length != 0);
2617     }
2618
2619     // Called when we lose the default network and have no replacement yet.
2620     // This will automatically be cleared after X seconds or a new default network
2621     // becomes CONNECTED, whichever happens first.  The timer is started by the
2622     // first caller and not restarted by subsequent callers.
2623     private void requestNetworkTransitionWakelock(String forWhom) {
2624         int serialNum = 0;
2625         synchronized (this) {
2626             if (mNetTransitionWakeLock.isHeld()) return;
2627             serialNum = ++mNetTransitionWakeLockSerialNumber;
2628             mNetTransitionWakeLock.acquire();
2629             mNetTransitionWakeLockCausedBy = forWhom;
2630         }
2631         mHandler.sendMessageDelayed(mHandler.obtainMessage(
2632                 EVENT_EXPIRE_NET_TRANSITION_WAKELOCK, serialNum, 0),
2633                 mNetTransitionWakeLockTimeout);
2634         return;
2635     }
2636
2637     // 100 percent is full good, 0 is full bad.
2638     public void reportInetCondition(int networkType, int percentage) {
2639         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
2640         if (nai == null) return;
2641         boolean isGood = percentage > 50;
2642         // Revalidate if the app report does not match our current validated state.
2643         if (isGood != nai.lastValidated) {
2644             // Make the message logged by reportBadNetwork below less confusing.
2645             if (DBG && isGood) log("reportInetCondition: type=" + networkType + " ok, revalidate");
2646             reportBadNetwork(nai.network);
2647         }
2648     }
2649
2650     public void reportBadNetwork(Network network) {
2651         enforceAccessPermission();
2652         enforceInternetPermission();
2653
2654         if (network == null) return;
2655
2656         final int uid = Binder.getCallingUid();
2657         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
2658         if (nai == null) return;
2659         if (DBG) log("reportBadNetwork(" + nai.name() + ") by " + uid);
2660         synchronized (nai) {
2661             // Validating an uncreated network could result in a call to rematchNetworkAndRequests()
2662             // which isn't meant to work on uncreated networks.
2663             if (!nai.created) return;
2664
2665             if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid)) return;
2666
2667             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
2668         }
2669     }
2670
2671     public ProxyInfo getDefaultProxy() {
2672         // this information is already available as a world read/writable jvm property
2673         // so this API change wouldn't have a benifit.  It also breaks the passing
2674         // of proxy info to all the JVMs.
2675         // enforceAccessPermission();
2676         synchronized (mProxyLock) {
2677             ProxyInfo ret = mGlobalProxy;
2678             if ((ret == null) && !mDefaultProxyDisabled) ret = mDefaultProxy;
2679             return ret;
2680         }
2681     }
2682
2683     // Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present
2684     // (e.g. if mGlobalProxy==null fall back to network-specific proxy, if network-specific
2685     // proxy is null then there is no proxy in place).
2686     private ProxyInfo canonicalizeProxyInfo(ProxyInfo proxy) {
2687         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
2688                 && (proxy.getPacFileUrl() == null || Uri.EMPTY.equals(proxy.getPacFileUrl()))) {
2689             proxy = null;
2690         }
2691         return proxy;
2692     }
2693
2694     // ProxyInfo equality function with a couple modifications over ProxyInfo.equals() to make it
2695     // better for determining if a new proxy broadcast is necessary:
2696     // 1. Canonicalize empty ProxyInfos to null so an empty proxy compares equal to null so as to
2697     //    avoid unnecessary broadcasts.
2698     // 2. Make sure all parts of the ProxyInfo's compare true, including the host when a PAC URL
2699     //    is in place.  This is important so legacy PAC resolver (see com.android.proxyhandler)
2700     //    changes aren't missed.  The legacy PAC resolver pretends to be a simple HTTP proxy but
2701     //    actually uses the PAC to resolve; this results in ProxyInfo's with PAC URL, host and port
2702     //    all set.
2703     private boolean proxyInfoEqual(ProxyInfo a, ProxyInfo b) {
2704         a = canonicalizeProxyInfo(a);
2705         b = canonicalizeProxyInfo(b);
2706         // ProxyInfo.equals() doesn't check hosts when PAC URLs are present, but we need to check
2707         // hosts even when PAC URLs are present to account for the legacy PAC resolver.
2708         return Objects.equals(a, b) && (a == null || Objects.equals(a.getHost(), b.getHost()));
2709     }
2710
2711     public void setGlobalProxy(ProxyInfo proxyProperties) {
2712         enforceConnectivityInternalPermission();
2713
2714         synchronized (mProxyLock) {
2715             if (proxyProperties == mGlobalProxy) return;
2716             if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2717             if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2718
2719             String host = "";
2720             int port = 0;
2721             String exclList = "";
2722             String pacFileUrl = "";
2723             if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
2724                     !Uri.EMPTY.equals(proxyProperties.getPacFileUrl()))) {
2725                 if (!proxyProperties.isValid()) {
2726                     if (DBG)
2727                         log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
2728                     return;
2729                 }
2730                 mGlobalProxy = new ProxyInfo(proxyProperties);
2731                 host = mGlobalProxy.getHost();
2732                 port = mGlobalProxy.getPort();
2733                 exclList = mGlobalProxy.getExclusionListAsString();
2734                 if (!Uri.EMPTY.equals(proxyProperties.getPacFileUrl())) {
2735                     pacFileUrl = proxyProperties.getPacFileUrl().toString();
2736                 }
2737             } else {
2738                 mGlobalProxy = null;
2739             }
2740             ContentResolver res = mContext.getContentResolver();
2741             final long token = Binder.clearCallingIdentity();
2742             try {
2743                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
2744                 Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
2745                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
2746                         exclList);
2747                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
2748             } finally {
2749                 Binder.restoreCallingIdentity(token);
2750             }
2751
2752             if (mGlobalProxy == null) {
2753                 proxyProperties = mDefaultProxy;
2754             }
2755             sendProxyBroadcast(proxyProperties);
2756         }
2757     }
2758
2759     private void loadGlobalProxy() {
2760         ContentResolver res = mContext.getContentResolver();
2761         String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
2762         int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
2763         String exclList = Settings.Global.getString(res,
2764                 Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2765         String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
2766         if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
2767             ProxyInfo proxyProperties;
2768             if (!TextUtils.isEmpty(pacFileUrl)) {
2769                 proxyProperties = new ProxyInfo(pacFileUrl);
2770             } else {
2771                 proxyProperties = new ProxyInfo(host, port, exclList);
2772             }
2773             if (!proxyProperties.isValid()) {
2774                 if (DBG) log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
2775                 return;
2776             }
2777
2778             synchronized (mProxyLock) {
2779                 mGlobalProxy = proxyProperties;
2780             }
2781         }
2782     }
2783
2784     public ProxyInfo getGlobalProxy() {
2785         // this information is already available as a world read/writable jvm property
2786         // so this API change wouldn't have a benifit.  It also breaks the passing
2787         // of proxy info to all the JVMs.
2788         // enforceAccessPermission();
2789         synchronized (mProxyLock) {
2790             return mGlobalProxy;
2791         }
2792     }
2793
2794     private void handleApplyDefaultProxy(ProxyInfo proxy) {
2795         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
2796                 && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
2797             proxy = null;
2798         }
2799         synchronized (mProxyLock) {
2800             if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2801             if (mDefaultProxy == proxy) return; // catches repeated nulls
2802             if (proxy != null &&  !proxy.isValid()) {
2803                 if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString());
2804                 return;
2805             }
2806
2807             // This call could be coming from the PacManager, containing the port of the local
2808             // proxy.  If this new proxy matches the global proxy then copy this proxy to the
2809             // global (to get the correct local port), and send a broadcast.
2810             // TODO: Switch PacManager to have its own message to send back rather than
2811             // reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy.
2812             if ((mGlobalProxy != null) && (proxy != null)
2813                     && (!Uri.EMPTY.equals(proxy.getPacFileUrl()))
2814                     && proxy.getPacFileUrl().equals(mGlobalProxy.getPacFileUrl())) {
2815                 mGlobalProxy = proxy;
2816                 sendProxyBroadcast(mGlobalProxy);
2817                 return;
2818             }
2819             mDefaultProxy = proxy;
2820
2821             if (mGlobalProxy != null) return;
2822             if (!mDefaultProxyDisabled) {
2823                 sendProxyBroadcast(proxy);
2824             }
2825         }
2826     }
2827
2828     // If the proxy has changed from oldLp to newLp, resend proxy broadcast with default proxy.
2829     // This method gets called when any network changes proxy, but the broadcast only ever contains
2830     // the default proxy (even if it hasn't changed).
2831     // TODO: Deprecate the broadcast extras as they aren't necessarily applicable in a multi-network
2832     // world where an app might be bound to a non-default network.
2833     private void updateProxy(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) {
2834         ProxyInfo newProxyInfo = newLp == null ? null : newLp.getHttpProxy();
2835         ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy();
2836
2837         if (!proxyInfoEqual(newProxyInfo, oldProxyInfo)) {
2838             sendProxyBroadcast(getDefaultProxy());
2839         }
2840     }
2841
2842     private void handleDeprecatedGlobalHttpProxy() {
2843         String proxy = Settings.Global.getString(mContext.getContentResolver(),
2844                 Settings.Global.HTTP_PROXY);
2845         if (!TextUtils.isEmpty(proxy)) {
2846             String data[] = proxy.split(":");
2847             if (data.length == 0) {
2848                 return;
2849             }
2850
2851             String proxyHost =  data[0];
2852             int proxyPort = 8080;
2853             if (data.length > 1) {
2854                 try {
2855                     proxyPort = Integer.parseInt(data[1]);
2856                 } catch (NumberFormatException e) {
2857                     return;
2858                 }
2859             }
2860             ProxyInfo p = new ProxyInfo(data[0], proxyPort, "");
2861             setGlobalProxy(p);
2862         }
2863     }
2864
2865     private void sendProxyBroadcast(ProxyInfo proxy) {
2866         if (proxy == null) proxy = new ProxyInfo("", 0, "");
2867         if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
2868         if (DBG) log("sending Proxy Broadcast for " + proxy);
2869         Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
2870         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2871             Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2872         intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
2873         final long ident = Binder.clearCallingIdentity();
2874         try {
2875             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2876         } finally {
2877             Binder.restoreCallingIdentity(ident);
2878         }
2879     }
2880
2881     private static class SettingsObserver extends ContentObserver {
2882         private int mWhat;
2883         private Handler mHandler;
2884         SettingsObserver(Handler handler, int what) {
2885             super(handler);
2886             mHandler = handler;
2887             mWhat = what;
2888         }
2889
2890         void observe(Context context) {
2891             ContentResolver resolver = context.getContentResolver();
2892             resolver.registerContentObserver(Settings.Global.getUriFor(
2893                     Settings.Global.HTTP_PROXY), false, this);
2894         }
2895
2896         @Override
2897         public void onChange(boolean selfChange) {
2898             mHandler.obtainMessage(mWhat).sendToTarget();
2899         }
2900     }
2901
2902     private static void log(String s) {
2903         Slog.d(TAG, s);
2904     }
2905
2906     private static void loge(String s) {
2907         Slog.e(TAG, s);
2908     }
2909
2910     private static <T> T checkNotNull(T value, String message) {
2911         if (value == null) {
2912             throw new NullPointerException(message);
2913         }
2914         return value;
2915     }
2916
2917     /**
2918      * Prepare for a VPN application.
2919      * Permissions are checked in Vpn class.
2920      * @hide
2921      */
2922     @Override
2923     public boolean prepareVpn(String oldPackage, String newPackage) {
2924         throwIfLockdownEnabled();
2925         int user = UserHandle.getUserId(Binder.getCallingUid());
2926         synchronized(mVpns) {
2927             return mVpns.get(user).prepare(oldPackage, newPackage);
2928         }
2929     }
2930
2931     /**
2932      * Set whether the current VPN package has the ability to launch VPNs without
2933      * user intervention. This method is used by system-privileged apps.
2934      * Permissions are checked in Vpn class.
2935      * @hide
2936      */
2937     @Override
2938     public void setVpnPackageAuthorization(boolean authorized) {
2939         int user = UserHandle.getUserId(Binder.getCallingUid());
2940         synchronized(mVpns) {
2941             mVpns.get(user).setPackageAuthorization(authorized);
2942         }
2943     }
2944
2945     /**
2946      * Configure a TUN interface and return its file descriptor. Parameters
2947      * are encoded and opaque to this class. This method is used by VpnBuilder
2948      * and not available in ConnectivityManager. Permissions are checked in
2949      * Vpn class.
2950      * @hide
2951      */
2952     @Override
2953     public ParcelFileDescriptor establishVpn(VpnConfig config) {
2954         throwIfLockdownEnabled();
2955         int user = UserHandle.getUserId(Binder.getCallingUid());
2956         synchronized(mVpns) {
2957             return mVpns.get(user).establish(config);
2958         }
2959     }
2960
2961     /**
2962      * Start legacy VPN, controlling native daemons as needed. Creates a
2963      * secondary thread to perform connection work, returning quickly.
2964      */
2965     @Override
2966     public void startLegacyVpn(VpnProfile profile) {
2967         throwIfLockdownEnabled();
2968         final LinkProperties egress = getActiveLinkProperties();
2969         if (egress == null) {
2970             throw new IllegalStateException("Missing active network connection");
2971         }
2972         int user = UserHandle.getUserId(Binder.getCallingUid());
2973         synchronized(mVpns) {
2974             mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
2975         }
2976     }
2977
2978     /**
2979      * Return the information of the ongoing legacy VPN. This method is used
2980      * by VpnSettings and not available in ConnectivityManager. Permissions
2981      * are checked in Vpn class.
2982      * @hide
2983      */
2984     @Override
2985     public LegacyVpnInfo getLegacyVpnInfo() {
2986         throwIfLockdownEnabled();
2987         int user = UserHandle.getUserId(Binder.getCallingUid());
2988         synchronized(mVpns) {
2989             return mVpns.get(user).getLegacyVpnInfo();
2990         }
2991     }
2992
2993     /**
2994      * Returns the information of the ongoing VPN. This method is used by VpnDialogs and
2995      * not available in ConnectivityManager.
2996      * Permissions are checked in Vpn class.
2997      * @hide
2998      */
2999     @Override
3000     public VpnConfig getVpnConfig() {
3001         int user = UserHandle.getUserId(Binder.getCallingUid());
3002         synchronized(mVpns) {
3003             return mVpns.get(user).getVpnConfig();
3004         }
3005     }
3006
3007     @Override
3008     public boolean updateLockdownVpn() {
3009         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
3010             Slog.w(TAG, "Lockdown VPN only available to AID_SYSTEM");
3011             return false;
3012         }
3013
3014         // Tear down existing lockdown if profile was removed
3015         mLockdownEnabled = LockdownVpnTracker.isEnabled();
3016         if (mLockdownEnabled) {
3017             if (!mKeyStore.isUnlocked()) {
3018                 Slog.w(TAG, "KeyStore locked; unable to create LockdownTracker");
3019                 return false;
3020             }
3021
3022             final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN));
3023             final VpnProfile profile = VpnProfile.decode(
3024                     profileName, mKeyStore.get(Credentials.VPN + profileName));
3025             int user = UserHandle.getUserId(Binder.getCallingUid());
3026             synchronized(mVpns) {
3027                 setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user),
3028                             profile));
3029             }
3030         } else {
3031             setLockdownTracker(null);
3032         }
3033
3034         return true;
3035     }
3036
3037     /**
3038      * Internally set new {@link LockdownVpnTracker}, shutting down any existing
3039      * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
3040      */
3041     private void setLockdownTracker(LockdownVpnTracker tracker) {
3042         // Shutdown any existing tracker
3043         final LockdownVpnTracker existing = mLockdownTracker;
3044         mLockdownTracker = null;
3045         if (existing != null) {
3046             existing.shutdown();
3047         }
3048
3049         try {
3050             if (tracker != null) {
3051                 mNetd.setFirewallEnabled(true);
3052                 mNetd.setFirewallInterfaceRule("lo", true);
3053                 mLockdownTracker = tracker;
3054                 mLockdownTracker.init();
3055             } else {
3056                 mNetd.setFirewallEnabled(false);
3057             }
3058         } catch (RemoteException e) {
3059             // ignored; NMS lives inside system_server
3060         }
3061     }
3062
3063     private void throwIfLockdownEnabled() {
3064         if (mLockdownEnabled) {
3065             throw new IllegalStateException("Unavailable in lockdown mode");
3066         }
3067     }
3068
3069     public void supplyMessenger(int networkType, Messenger messenger) {
3070         enforceConnectivityInternalPermission();
3071
3072         if (isNetworkTypeValid(networkType) && mNetTrackers[networkType] != null) {
3073             mNetTrackers[networkType].supplyMessenger(messenger);
3074         }
3075     }
3076
3077     public int findConnectionTypeForIface(String iface) {
3078         enforceConnectivityInternalPermission();
3079
3080         if (TextUtils.isEmpty(iface)) return ConnectivityManager.TYPE_NONE;
3081
3082         synchronized(mNetworkForNetId) {
3083             for (int i = 0; i < mNetworkForNetId.size(); i++) {
3084                 NetworkAgentInfo nai = mNetworkForNetId.valueAt(i);
3085                 LinkProperties lp = nai.linkProperties;
3086                 if (lp != null && iface.equals(lp.getInterfaceName()) && nai.networkInfo != null) {
3087                     return nai.networkInfo.getType();
3088                 }
3089             }
3090         }
3091         return ConnectivityManager.TYPE_NONE;
3092     }
3093
3094     /**
3095      * Have mobile data fail fast if enabled.
3096      *
3097      * @param enabled DctConstants.ENABLED/DISABLED
3098      */
3099     private void setEnableFailFastMobileData(int enabled) {
3100         int tag;
3101
3102         if (enabled == DctConstants.ENABLED) {
3103             tag = mEnableFailFastMobileDataTag.incrementAndGet();
3104         } else {
3105             tag = mEnableFailFastMobileDataTag.get();
3106         }
3107         mHandler.sendMessage(mHandler.obtainMessage(EVENT_ENABLE_FAIL_FAST_MOBILE_DATA, tag,
3108                          enabled));
3109     }
3110
3111     @Override
3112     public int checkMobileProvisioning(int suggestedTimeOutMs) {
3113         // TODO: Remove?  Any reason to trigger a provisioning check?
3114         return -1;
3115     }
3116
3117     private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
3118     private volatile boolean mIsNotificationVisible = false;
3119
3120     private void setProvNotificationVisible(boolean visible, int networkType, String action) {
3121         if (DBG) {
3122             log("setProvNotificationVisible: E visible=" + visible + " networkType=" + networkType
3123                 + " action=" + action);
3124         }
3125         Intent intent = new Intent(action);
3126         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
3127         // Concatenate the range of types onto the range of NetIDs.
3128         int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
3129         setProvNotificationVisibleIntent(visible, id, networkType, null, pendingIntent);
3130     }
3131
3132     /**
3133      * Show or hide network provisioning notificaitons.
3134      *
3135      * @param id an identifier that uniquely identifies this notification.  This must match
3136      *         between show and hide calls.  We use the NetID value but for legacy callers
3137      *         we concatenate the range of types with the range of NetIDs.
3138      */
3139     private void setProvNotificationVisibleIntent(boolean visible, int id, int networkType,
3140             String extraInfo, PendingIntent intent) {
3141         if (DBG) {
3142             log("setProvNotificationVisibleIntent: E visible=" + visible + " networkType=" +
3143                 networkType + " extraInfo=" + extraInfo);
3144         }
3145
3146         Resources r = Resources.getSystem();
3147         NotificationManager notificationManager = (NotificationManager) mContext
3148             .getSystemService(Context.NOTIFICATION_SERVICE);
3149
3150         if (visible) {
3151             CharSequence title;
3152             CharSequence details;
3153             int icon;
3154             Notification notification = new Notification();
3155             switch (networkType) {
3156                 case ConnectivityManager.TYPE_WIFI:
3157                     title = r.getString(R.string.wifi_available_sign_in, 0);
3158                     details = r.getString(R.string.network_available_sign_in_detailed,
3159                             extraInfo);
3160                     icon = R.drawable.stat_notify_wifi_in_range;
3161                     break;
3162                 case ConnectivityManager.TYPE_MOBILE:
3163                 case ConnectivityManager.TYPE_MOBILE_HIPRI:
3164                     title = r.getString(R.string.network_available_sign_in, 0);
3165                     // TODO: Change this to pull from NetworkInfo once a printable
3166                     // name has been added to it
3167                     details = mTelephonyManager.getNetworkOperatorName();
3168                     icon = R.drawable.stat_notify_rssi_in_range;
3169                     break;
3170                 default:
3171                     title = r.getString(R.string.network_available_sign_in, 0);
3172                     details = r.getString(R.string.network_available_sign_in_detailed,
3173                             extraInfo);
3174                     icon = R.drawable.stat_notify_rssi_in_range;
3175                     break;
3176             }
3177
3178             notification.when = 0;
3179             notification.icon = icon;
3180             notification.flags = Notification.FLAG_AUTO_CANCEL;
3181             notification.tickerText = title;
3182             notification.color = mContext.getResources().getColor(
3183                     com.android.internal.R.color.system_notification_accent_color);
3184             notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
3185             notification.contentIntent = intent;
3186
3187             try {
3188                 notificationManager.notify(NOTIFICATION_ID, id, notification);
3189             } catch (NullPointerException npe) {
3190                 loge("setNotificaitionVisible: visible notificationManager npe=" + npe);
3191                 npe.printStackTrace();
3192             }
3193         } else {
3194             try {
3195                 notificationManager.cancel(NOTIFICATION_ID, id);
3196             } catch (NullPointerException npe) {
3197                 loge("setNotificaitionVisible: cancel notificationManager npe=" + npe);
3198                 npe.printStackTrace();
3199             }
3200         }
3201         mIsNotificationVisible = visible;
3202     }
3203
3204     /** Location to an updatable file listing carrier provisioning urls.
3205      *  An example:
3206      *
3207      * <?xml version="1.0" encoding="utf-8"?>
3208      *  <provisioningUrls>
3209      *   <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&amp;iccid=%1$s&amp;imei=%2$s</provisioningUrl>
3210      *   <redirectedUrl mcc="310" mnc="4">http://www.google.com</redirectedUrl>
3211      *  </provisioningUrls>
3212      */
3213     private static final String PROVISIONING_URL_PATH =
3214             "/data/misc/radio/provisioning_urls.xml";
3215     private final File mProvisioningUrlFile = new File(PROVISIONING_URL_PATH);
3216
3217     /** XML tag for root element. */
3218     private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
3219     /** XML tag for individual url */
3220     private static final String TAG_PROVISIONING_URL = "provisioningUrl";
3221     /** XML tag for redirected url */
3222     private static final String TAG_REDIRECTED_URL = "redirectedUrl";
3223     /** XML attribute for mcc */
3224     private static final String ATTR_MCC = "mcc";
3225     /** XML attribute for mnc */
3226     private static final String ATTR_MNC = "mnc";
3227
3228     private static final int REDIRECTED_PROVISIONING = 1;
3229     private static final int PROVISIONING = 2;
3230
3231     private String getProvisioningUrlBaseFromFile(int type) {
3232         FileReader fileReader = null;
3233         XmlPullParser parser = null;
3234         Configuration config = mContext.getResources().getConfiguration();
3235         String tagType;
3236
3237         switch (type) {
3238             case PROVISIONING:
3239                 tagType = TAG_PROVISIONING_URL;
3240                 break;
3241             case REDIRECTED_PROVISIONING:
3242                 tagType = TAG_REDIRECTED_URL;
3243                 break;
3244             default:
3245                 throw new RuntimeException("getProvisioningUrlBaseFromFile: Unexpected parameter " +
3246                         type);
3247         }
3248
3249         try {
3250             fileReader = new FileReader(mProvisioningUrlFile);
3251             parser = Xml.newPullParser();
3252             parser.setInput(fileReader);
3253             XmlUtils.beginDocument(parser, TAG_PROVISIONING_URLS);
3254
3255             while (true) {
3256                 XmlUtils.nextElement(parser);
3257
3258                 String element = parser.getName();
3259                 if (element == null) break;
3260
3261                 if (element.equals(tagType)) {
3262                     String mcc = parser.getAttributeValue(null, ATTR_MCC);
3263                     try {
3264                         if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
3265                             String mnc = parser.getAttributeValue(null, ATTR_MNC);
3266                             if (mnc != null && Integer.parseInt(mnc) == config.mnc) {
3267                                 parser.next();
3268                                 if (parser.getEventType() == XmlPullParser.TEXT) {
3269                                     return parser.getText();
3270                                 }
3271                             }
3272                         }
3273                     } catch (NumberFormatException e) {
3274                         loge("NumberFormatException in getProvisioningUrlBaseFromFile: " + e);
3275                     }
3276                 }
3277             }
3278             return null;
3279         } catch (FileNotFoundException e) {
3280             loge("Carrier Provisioning Urls file not found");
3281         } catch (XmlPullParserException e) {
3282             loge("Xml parser exception reading Carrier Provisioning Urls file: " + e);
3283         } catch (IOException e) {
3284             loge("I/O exception reading Carrier Provisioning Urls file: " + e);
3285         } finally {
3286             if (fileReader != null) {
3287                 try {
3288                     fileReader.close();
3289                 } catch (IOException e) {}
3290             }
3291         }
3292         return null;
3293     }
3294
3295     @Override
3296     public String getMobileRedirectedProvisioningUrl() {
3297         enforceConnectivityInternalPermission();
3298         String url = getProvisioningUrlBaseFromFile(REDIRECTED_PROVISIONING);
3299         if (TextUtils.isEmpty(url)) {
3300             url = mContext.getResources().getString(R.string.mobile_redirected_provisioning_url);
3301         }
3302         return url;
3303     }
3304
3305     @Override
3306     public String getMobileProvisioningUrl() {
3307         enforceConnectivityInternalPermission();
3308         String url = getProvisioningUrlBaseFromFile(PROVISIONING);
3309         if (TextUtils.isEmpty(url)) {
3310             url = mContext.getResources().getString(R.string.mobile_provisioning_url);
3311             log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
3312         } else {
3313             log("getMobileProvisioningUrl: mobile_provisioning_url from File =" + url);
3314         }
3315         // populate the iccid, imei and phone number in the provisioning url.
3316         if (!TextUtils.isEmpty(url)) {
3317             String phoneNumber = mTelephonyManager.getLine1Number();
3318             if (TextUtils.isEmpty(phoneNumber)) {
3319                 phoneNumber = "0000000000";
3320             }
3321             url = String.format(url,
3322                     mTelephonyManager.getSimSerialNumber() /* ICCID */,
3323                     mTelephonyManager.getDeviceId() /* IMEI */,
3324                     phoneNumber /* Phone numer */);
3325         }
3326
3327         return url;
3328     }
3329
3330     @Override
3331     public void setProvisioningNotificationVisible(boolean visible, int networkType,
3332             String action) {
3333         enforceConnectivityInternalPermission();
3334         final long ident = Binder.clearCallingIdentity();
3335         try {
3336             setProvNotificationVisible(visible, networkType, action);
3337         } finally {
3338             Binder.restoreCallingIdentity(ident);
3339         }
3340     }
3341
3342     @Override
3343     public void setAirplaneMode(boolean enable) {
3344         enforceConnectivityInternalPermission();
3345         final long ident = Binder.clearCallingIdentity();
3346         try {
3347             final ContentResolver cr = mContext.getContentResolver();
3348             Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, enable ? 1 : 0);
3349             Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
3350             intent.putExtra("state", enable);
3351             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
3352         } finally {
3353             Binder.restoreCallingIdentity(ident);
3354         }
3355     }
3356
3357     private void onUserStart(int userId) {
3358         synchronized(mVpns) {
3359             Vpn userVpn = mVpns.get(userId);
3360             if (userVpn != null) {
3361                 loge("Starting user already has a VPN");
3362                 return;
3363             }
3364             userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, this, userId);
3365             mVpns.put(userId, userVpn);
3366         }
3367     }
3368
3369     private void onUserStop(int userId) {
3370         synchronized(mVpns) {
3371             Vpn userVpn = mVpns.get(userId);
3372             if (userVpn == null) {
3373                 loge("Stopping user has no VPN");
3374                 return;
3375             }
3376             mVpns.delete(userId);
3377         }
3378     }
3379
3380     private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
3381         @Override
3382         public void onReceive(Context context, Intent intent) {
3383             final String action = intent.getAction();
3384             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
3385             if (userId == UserHandle.USER_NULL) return;
3386
3387             if (Intent.ACTION_USER_STARTING.equals(action)) {
3388                 onUserStart(userId);
3389             } else if (Intent.ACTION_USER_STOPPING.equals(action)) {
3390                 onUserStop(userId);
3391             }
3392         }
3393     };
3394
3395     /* Infrastructure for network sampling */
3396
3397     private void handleNetworkSamplingTimeout() {
3398
3399         if (SAMPLE_DBG) log("Sampling interval elapsed, updating statistics ..");
3400
3401         // initialize list of interfaces ..
3402         Map<String, SamplingDataTracker.SamplingSnapshot> mapIfaceToSample =
3403                 new HashMap<String, SamplingDataTracker.SamplingSnapshot>();
3404         for (NetworkStateTracker tracker : mNetTrackers) {
3405             if (tracker != null) {
3406                 String ifaceName = tracker.getNetworkInterfaceName();
3407                 if (ifaceName != null) {
3408                     mapIfaceToSample.put(ifaceName, null);
3409                 }
3410             }
3411         }
3412
3413         // Read samples for all interfaces
3414         SamplingDataTracker.getSamplingSnapshots(mapIfaceToSample);
3415
3416         // process samples for all networks
3417         for (NetworkStateTracker tracker : mNetTrackers) {
3418             if (tracker != null) {
3419                 String ifaceName = tracker.getNetworkInterfaceName();
3420                 SamplingDataTracker.SamplingSnapshot ss = mapIfaceToSample.get(ifaceName);
3421                 if (ss != null) {
3422                     // end the previous sampling cycle
3423                     tracker.stopSampling(ss);
3424                     // start a new sampling cycle ..
3425                     tracker.startSampling(ss);
3426                 }
3427             }
3428         }
3429
3430         if (SAMPLE_DBG) log("Done.");
3431
3432         int samplingIntervalInSeconds = Settings.Global.getInt(mContext.getContentResolver(),
3433                 Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
3434                 DEFAULT_SAMPLING_INTERVAL_IN_SECONDS);
3435
3436         if (SAMPLE_DBG) {
3437             log("Setting timer for " + String.valueOf(samplingIntervalInSeconds) + "seconds");
3438         }
3439
3440         setAlarm(samplingIntervalInSeconds * 1000, mSampleIntervalElapsedIntent);
3441     }
3442
3443     /**
3444      * Sets a network sampling alarm.
3445      */
3446     void setAlarm(int timeoutInMilliseconds, PendingIntent intent) {
3447         long wakeupTime = SystemClock.elapsedRealtime() + timeoutInMilliseconds;
3448         int alarmType;
3449         if (Resources.getSystem().getBoolean(
3450                 R.bool.config_networkSamplingWakesDevice)) {
3451             alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
3452         } else {
3453             alarmType = AlarmManager.ELAPSED_REALTIME;
3454         }
3455         mAlarmManager.set(alarmType, wakeupTime, intent);
3456     }
3457
3458     private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
3459             new HashMap<Messenger, NetworkFactoryInfo>();
3460     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
3461             new HashMap<NetworkRequest, NetworkRequestInfo>();
3462
3463     private static class NetworkFactoryInfo {
3464         public final String name;
3465         public final Messenger messenger;
3466         public final AsyncChannel asyncChannel;
3467
3468         public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
3469             this.name = name;
3470             this.messenger = messenger;
3471             this.asyncChannel = asyncChannel;
3472         }
3473     }
3474
3475     /**
3476      * Tracks info about the requester.
3477      * Also used to notice when the calling process dies so we can self-expire
3478      */
3479     private class NetworkRequestInfo implements IBinder.DeathRecipient {
3480         static final boolean REQUEST = true;
3481         static final boolean LISTEN = false;
3482
3483         final NetworkRequest request;
3484         final PendingIntent mPendingIntent;
3485         boolean mPendingIntentSent;
3486         private final IBinder mBinder;
3487         final int mPid;
3488         final int mUid;
3489         final Messenger messenger;
3490         final boolean isRequest;
3491
3492         NetworkRequestInfo(NetworkRequest r, PendingIntent pi, boolean isRequest) {
3493             request = r;
3494             mPendingIntent = pi;
3495             messenger = null;
3496             mBinder = null;
3497             mPid = getCallingPid();
3498             mUid = getCallingUid();
3499             this.isRequest = isRequest;
3500         }
3501
3502         NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) {
3503             super();
3504             messenger = m;
3505             request = r;
3506             mBinder = binder;
3507             mPid = getCallingPid();
3508             mUid = getCallingUid();
3509             this.isRequest = isRequest;
3510             mPendingIntent = null;
3511
3512             try {
3513                 mBinder.linkToDeath(this, 0);
3514             } catch (RemoteException e) {
3515                 binderDied();
3516             }
3517         }
3518
3519         void unlinkDeathRecipient() {
3520             if (mBinder != null) {
3521                 mBinder.unlinkToDeath(this, 0);
3522             }
3523         }
3524
3525         public void binderDied() {
3526             log("ConnectivityService NetworkRequestInfo binderDied(" +
3527                     request + ", " + mBinder + ")");
3528             releaseNetworkRequest(request);
3529         }
3530
3531         public String toString() {
3532             return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
3533                     mPid + " for " + request +
3534                     (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
3535         }
3536     }
3537
3538     @Override
3539     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
3540             Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
3541         networkCapabilities = new NetworkCapabilities(networkCapabilities);
3542         enforceNetworkRequestPermissions(networkCapabilities);
3543         enforceMeteredApnPolicy(networkCapabilities);
3544
3545         if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
3546             throw new IllegalArgumentException("Bad timeout specified");
3547         }
3548
3549         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
3550                 nextNetworkRequestId());
3551         if (DBG) log("requestNetwork for " + networkRequest);
3552         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
3553                 NetworkRequestInfo.REQUEST);
3554
3555         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
3556         if (timeoutMs > 0) {
3557             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
3558                     nri), timeoutMs);
3559         }
3560         return networkRequest;
3561     }
3562
3563     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
3564         if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
3565                 == false) {
3566             enforceConnectivityInternalPermission();
3567         } else {
3568             enforceChangePermission();
3569         }
3570     }
3571
3572     private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
3573         // if UID is restricted, don't allow them to bring up metered APNs
3574         if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
3575                 == false) {
3576             final int uidRules;
3577             final int uid = Binder.getCallingUid();
3578             synchronized(mRulesLock) {
3579                 uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
3580             }
3581             if ((uidRules & RULE_REJECT_METERED) != 0) {
3582                 // we could silently fail or we can filter the available nets to only give
3583                 // them those they have access to.  Chose the more useful
3584                 networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3585             }
3586         }
3587     }
3588
3589     @Override
3590     public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
3591             PendingIntent operation) {
3592         checkNotNull(operation, "PendingIntent cannot be null.");
3593         networkCapabilities = new NetworkCapabilities(networkCapabilities);
3594         enforceNetworkRequestPermissions(networkCapabilities);
3595         enforceMeteredApnPolicy(networkCapabilities);
3596
3597         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
3598                 nextNetworkRequestId());
3599         if (DBG) log("pendingRequest for " + networkRequest + " to trigger " + operation);
3600         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
3601                 NetworkRequestInfo.REQUEST);
3602         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
3603                 nri));
3604         return networkRequest;
3605     }
3606
3607     private void releasePendingNetworkRequestWithDelay(PendingIntent operation) {
3608         mHandler.sendMessageDelayed(
3609                 mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
3610                 getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
3611     }
3612
3613     @Override
3614     public void releasePendingNetworkRequest(PendingIntent operation) {
3615         mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
3616                 getCallingUid(), 0, operation));
3617     }
3618
3619     @Override
3620     public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
3621             Messenger messenger, IBinder binder) {
3622         enforceAccessPermission();
3623
3624         NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
3625                 networkCapabilities), TYPE_NONE, nextNetworkRequestId());
3626         if (DBG) log("listenForNetwork for " + networkRequest);
3627         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
3628                 NetworkRequestInfo.LISTEN);
3629
3630         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
3631         return networkRequest;
3632     }
3633
3634     @Override
3635     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
3636             PendingIntent operation) {
3637     }
3638
3639     @Override
3640     public void releaseNetworkRequest(NetworkRequest networkRequest) {
3641         mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(),
3642                 0, networkRequest));
3643     }
3644
3645     @Override
3646     public void registerNetworkFactory(Messenger messenger, String name) {
3647         enforceConnectivityInternalPermission();
3648         NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
3649         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
3650     }
3651
3652     private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
3653         if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
3654         mNetworkFactoryInfos.put(nfi.messenger, nfi);
3655         nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
3656     }
3657
3658     @Override
3659     public void unregisterNetworkFactory(Messenger messenger) {
3660         enforceConnectivityInternalPermission();
3661         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
3662     }
3663
3664     private void handleUnregisterNetworkFactory(Messenger messenger) {
3665         NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
3666         if (nfi == null) {
3667             loge("Failed to find Messenger in unregisterNetworkFactory");
3668             return;
3669         }
3670         if (DBG) log("unregisterNetworkFactory for " + nfi.name);
3671     }
3672
3673     /**
3674      * NetworkAgentInfo supporting a request by requestId.
3675      * These have already been vetted (their Capabilities satisfy the request)
3676      * and the are the highest scored network available.
3677      * the are keyed off the Requests requestId.
3678      */
3679     private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =
3680             new SparseArray<NetworkAgentInfo>();
3681
3682     private final SparseArray<NetworkAgentInfo> mNetworkForNetId =
3683             new SparseArray<NetworkAgentInfo>();
3684
3685     // NetworkAgentInfo keyed off its connecting messenger
3686     // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
3687     private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =
3688             new HashMap<Messenger, NetworkAgentInfo>();
3689
3690     // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
3691     private final NetworkRequest mDefaultRequest;
3692
3693     private NetworkAgentInfo getDefaultNetwork() {
3694         return mNetworkForRequestId.get(mDefaultRequest.requestId);
3695     }
3696
3697     private boolean isDefaultNetwork(NetworkAgentInfo nai) {
3698         return nai == getDefaultNetwork();
3699     }
3700
3701     public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
3702             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
3703             int currentScore, NetworkMisc networkMisc) {
3704         enforceConnectivityInternalPermission();
3705
3706         // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
3707         // satisfies mDefaultRequest.
3708         NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
3709             new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
3710             new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,
3711             new NetworkMisc(networkMisc), mDefaultRequest);
3712         synchronized (this) {
3713             nai.networkMonitor.systemReady = mSystemReady;
3714         }
3715         if (DBG) log("registerNetworkAgent " + nai);
3716         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
3717     }
3718
3719     private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
3720         if (VDBG) log("Got NetworkAgent Messenger");
3721         mNetworkAgentInfos.put(na.messenger, na);
3722         assignNextNetId(na);
3723         na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
3724         NetworkInfo networkInfo = na.networkInfo;
3725         na.networkInfo = null;
3726         updateNetworkInfo(na, networkInfo);
3727     }
3728
3729     private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp) {
3730         LinkProperties newLp = networkAgent.linkProperties;
3731         int netId = networkAgent.network.netId;
3732
3733         // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before
3734         // we do anything else, make sure its LinkProperties are accurate.
3735         if (networkAgent.clatd != null) {
3736             networkAgent.clatd.fixupLinkProperties(oldLp);
3737         }
3738
3739         updateInterfaces(newLp, oldLp, netId);
3740         updateMtu(newLp, oldLp);
3741         // TODO - figure out what to do for clat
3742 //        for (LinkProperties lp : newLp.getStackedLinks()) {
3743 //            updateMtu(lp, null);
3744 //        }
3745         updateTcpBufferSizes(networkAgent);
3746
3747         // TODO: deprecate and remove mDefaultDns when we can do so safely.
3748         // For now, use it only when the network has Internet access. http://b/18327075
3749         final boolean useDefaultDns = networkAgent.networkCapabilities.hasCapability(
3750                 NetworkCapabilities.NET_CAPABILITY_INTERNET);
3751         final boolean flushDns = updateRoutes(newLp, oldLp, netId);
3752         updateDnses(newLp, oldLp, netId, flushDns, useDefaultDns);
3753
3754         updateClat(newLp, oldLp, networkAgent);
3755         if (isDefaultNetwork(networkAgent)) {
3756             handleApplyDefaultProxy(newLp.getHttpProxy());
3757         } else {
3758             updateProxy(newLp, oldLp, networkAgent);
3759         }
3760         // TODO - move this check to cover the whole function
3761         if (!Objects.equals(newLp, oldLp)) {
3762             notifyIfacesChanged();
3763             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
3764         }
3765     }
3766
3767     private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) {
3768         final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted();
3769         final boolean shouldRunClat = Nat464Xlat.requiresClat(nai);
3770
3771         if (!wasRunningClat && shouldRunClat) {
3772             nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai);
3773             nai.clatd.start();
3774         } else if (wasRunningClat && !shouldRunClat) {
3775             nai.clatd.stop();
3776         }
3777     }
3778
3779     private void updateInterfaces(LinkProperties newLp, LinkProperties oldLp, int netId) {
3780         CompareResult<String> interfaceDiff = new CompareResult<String>();
3781         if (oldLp != null) {
3782             interfaceDiff = oldLp.compareAllInterfaceNames(newLp);
3783         } else if (newLp != null) {
3784             interfaceDiff.added = newLp.getAllInterfaceNames();
3785         }
3786         for (String iface : interfaceDiff.added) {
3787             try {
3788                 if (DBG) log("Adding iface " + iface + " to network " + netId);
3789                 mNetd.addInterfaceToNetwork(iface, netId);
3790             } catch (Exception e) {
3791                 loge("Exception adding interface: " + e);
3792             }
3793         }
3794         for (String iface : interfaceDiff.removed) {
3795             try {
3796                 if (DBG) log("Removing iface " + iface + " from network " + netId);
3797                 mNetd.removeInterfaceFromNetwork(iface, netId);
3798             } catch (Exception e) {
3799                 loge("Exception removing interface: " + e);
3800             }
3801         }
3802     }
3803
3804     /**
3805      * Have netd update routes from oldLp to newLp.
3806      * @return true if routes changed between oldLp and newLp
3807      */
3808     private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
3809         CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
3810         if (oldLp != null) {
3811             routeDiff = oldLp.compareAllRoutes(newLp);
3812         } else if (newLp != null) {
3813             routeDiff.added = newLp.getAllRoutes();
3814         }
3815
3816         // add routes before removing old in case it helps with continuous connectivity
3817
3818         // do this twice, adding non-nexthop routes first, then routes they are dependent on
3819         for (RouteInfo route : routeDiff.added) {
3820             if (route.hasGateway()) continue;
3821             if (DBG) log("Adding Route [" + route + "] to network " + netId);
3822             try {
3823                 mNetd.addRoute(netId, route);
3824             } catch (Exception e) {
3825                 if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
3826                     loge("Exception in addRoute for non-gateway: " + e);
3827                 }
3828             }
3829         }
3830         for (RouteInfo route : routeDiff.added) {
3831             if (route.hasGateway() == false) continue;
3832             if (DBG) log("Adding Route [" + route + "] to network " + netId);
3833             try {
3834                 mNetd.addRoute(netId, route);
3835             } catch (Exception e) {
3836                 if ((route.getGateway() instanceof Inet4Address) || VDBG) {
3837                     loge("Exception in addRoute for gateway: " + e);
3838                 }
3839             }
3840         }
3841
3842         for (RouteInfo route : routeDiff.removed) {
3843             if (DBG) log("Removing Route [" + route + "] from network " + netId);
3844             try {
3845                 mNetd.removeRoute(netId, route);
3846             } catch (Exception e) {
3847                 loge("Exception in removeRoute: " + e);
3848             }
3849         }
3850         return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
3851     }
3852     private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId,
3853                              boolean flush, boolean useDefaultDns) {
3854         if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
3855             Collection<InetAddress> dnses = newLp.getDnsServers();
3856             if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) {
3857                 dnses = new ArrayList();
3858                 dnses.add(mDefaultDns);
3859                 if (DBG) {
3860                     loge("no dns provided for netId " + netId + ", so using defaults");
3861                 }
3862             }
3863             if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
3864             try {
3865                 mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses),
3866                     newLp.getDomains());
3867             } catch (Exception e) {
3868                 loge("Exception in setDnsServersForNetwork: " + e);
3869             }
3870             NetworkAgentInfo defaultNai = mNetworkForRequestId.get(mDefaultRequest.requestId);
3871             if (defaultNai != null && defaultNai.network.netId == netId) {
3872                 setDefaultDnsSystemProperties(dnses);
3873             }
3874             flushVmDnsCache();
3875         } else if (flush) {
3876             try {
3877                 mNetd.flushNetworkDnsCache(netId);
3878             } catch (Exception e) {
3879                 loge("Exception in flushNetworkDnsCache: " + e);
3880             }
3881             flushVmDnsCache();
3882         }
3883     }
3884
3885     private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
3886         int last = 0;
3887         for (InetAddress dns : dnses) {
3888             ++last;
3889             String key = "net.dns" + last;
3890             String value = dns.getHostAddress();
3891             SystemProperties.set(key, value);
3892         }
3893         for (int i = last + 1; i <= mNumDnsEntries; ++i) {
3894             String key = "net.dns" + i;
3895             SystemProperties.set(key, "");
3896         }
3897         mNumDnsEntries = last;
3898     }
3899
3900     private void updateCapabilities(NetworkAgentInfo networkAgent,
3901             NetworkCapabilities networkCapabilities) {
3902         if (!Objects.equals(networkAgent.networkCapabilities, networkCapabilities)) {
3903             synchronized (networkAgent) {
3904                 networkAgent.networkCapabilities = networkCapabilities;
3905             }
3906             rematchAllNetworksAndRequests(networkAgent, networkAgent.getCurrentScore());
3907             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_CAP_CHANGED);
3908         }
3909     }
3910
3911     private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
3912         for (int i = 0; i < nai.networkRequests.size(); i++) {
3913             NetworkRequest nr = nai.networkRequests.valueAt(i);
3914             // Don't send listening requests to factories. b/17393458
3915             if (!isRequest(nr)) continue;
3916             sendUpdatedScoreToFactories(nr, nai.getCurrentScore());
3917         }
3918     }
3919
3920     private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
3921         if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
3922         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
3923             nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
3924                     networkRequest);
3925         }
3926     }
3927
3928     private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
3929             int notificationType) {
3930         if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) {
3931             Intent intent = new Intent();
3932             intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network);
3933             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.request);
3934             nri.mPendingIntentSent = true;
3935             sendIntent(nri.mPendingIntent, intent);
3936         }
3937         // else not handled
3938     }
3939
3940     private void sendIntent(PendingIntent pendingIntent, Intent intent) {
3941         mPendingIntentWakeLock.acquire();
3942         try {
3943             if (DBG) log("Sending " + pendingIntent);
3944             pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */);
3945         } catch (PendingIntent.CanceledException e) {
3946             if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
3947             mPendingIntentWakeLock.release();
3948             releasePendingNetworkRequest(pendingIntent);
3949         }
3950         // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
3951     }
3952
3953     @Override
3954     public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
3955             String resultData, Bundle resultExtras) {
3956         if (DBG) log("Finished sending " + pendingIntent);
3957         mPendingIntentWakeLock.release();
3958         // Release with a delay so the receiving client has an opportunity to put in its
3959         // own request.
3960         releasePendingNetworkRequestWithDelay(pendingIntent);
3961     }
3962
3963     private void callCallbackForRequest(NetworkRequestInfo nri,
3964             NetworkAgentInfo networkAgent, int notificationType) {
3965         if (nri.messenger == null) return;  // Default request has no msgr
3966         Bundle bundle = new Bundle();
3967         bundle.putParcelable(NetworkRequest.class.getSimpleName(),
3968                 new NetworkRequest(nri.request));
3969         Message msg = Message.obtain();
3970         if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL &&
3971                 notificationType != ConnectivityManager.CALLBACK_RELEASED) {
3972             bundle.putParcelable(Network.class.getSimpleName(), networkAgent.network);
3973         }
3974         switch (notificationType) {
3975             case ConnectivityManager.CALLBACK_LOSING: {
3976                 msg.arg1 = 30 * 1000; // TODO - read this from NetworkMonitor
3977                 break;
3978             }
3979             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
3980                 bundle.putParcelable(NetworkCapabilities.class.getSimpleName(),
3981                         new NetworkCapabilities(networkAgent.networkCapabilities));
3982                 break;
3983             }
3984             case ConnectivityManager.CALLBACK_IP_CHANGED: {
3985                 bundle.putParcelable(LinkProperties.class.getSimpleName(),
3986                         new LinkProperties(networkAgent.linkProperties));
3987                 break;
3988             }
3989         }
3990         msg.what = notificationType;
3991         msg.setData(bundle);
3992         try {
3993             if (VDBG) {
3994                 log("sending notification " + notifyTypeToName(notificationType) +
3995                         " for " + nri.request);
3996             }
3997             nri.messenger.send(msg);
3998         } catch (RemoteException e) {
3999             // may occur naturally in the race of binder death.
4000             loge("RemoteException caught trying to send a callback msg for " + nri.request);
4001         }
4002     }
4003
4004     private void teardownUnneededNetwork(NetworkAgentInfo nai) {
4005         for (int i = 0; i < nai.networkRequests.size(); i++) {
4006             NetworkRequest nr = nai.networkRequests.valueAt(i);
4007             // Ignore listening requests.
4008             if (!isRequest(nr)) continue;
4009             loge("Dead network still had at least " + nr);
4010             break;
4011         }
4012         nai.asyncChannel.disconnect();
4013     }
4014
4015     private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
4016         if (oldNetwork == null) {
4017             loge("Unknown NetworkAgentInfo in handleLingerComplete");
4018             return;
4019         }
4020         if (DBG) log("handleLingerComplete for " + oldNetwork.name());
4021         teardownUnneededNetwork(oldNetwork);
4022     }
4023
4024     private void makeDefault(NetworkAgentInfo newNetwork) {
4025         if (DBG) log("Switching to new default network: " + newNetwork);
4026         setupDataActivityTracking(newNetwork);
4027         try {
4028             mNetd.setDefaultNetId(newNetwork.network.netId);
4029         } catch (Exception e) {
4030             loge("Exception setting default network :" + e);
4031         }
4032         notifyLockdownVpn(newNetwork);
4033         handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
4034         updateTcpBufferSizes(newNetwork);
4035         setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
4036     }
4037
4038     // Handles a network appearing or improving its score.
4039     //
4040     // - Evaluates all current NetworkRequests that can be
4041     //   satisfied by newNetwork, and reassigns to newNetwork
4042     //   any such requests for which newNetwork is the best.
4043     //
4044     // - Lingers any validated Networks that as a result are no longer
4045     //   needed. A network is needed if it is the best network for
4046     //   one or more NetworkRequests, or if it is a VPN.
4047     //
4048     // - Tears down newNetwork if it just became validated
4049     //   (i.e. nascent==JUST_VALIDATED) but turns out to be unneeded.
4050     //
4051     // - If reapUnvalidatedNetworks==REAP, tears down unvalidated
4052     //   networks that have no chance (i.e. even if validated)
4053     //   of becoming the highest scoring network.
4054     //
4055     // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
4056     // it does not remove NetworkRequests that other Networks could better satisfy.
4057     // If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
4058     // This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
4059     // as it performs better by a factor of the number of Networks.
4060     //
4061     // @param newNetwork is the network to be matched against NetworkRequests.
4062     // @param nascent indicates if newNetwork just became validated, in which case it should be
4063     //               torn down if unneeded.
4064     // @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
4065     //               performed to tear down unvalidated networks that have no chance (i.e. even if
4066     //               validated) of becoming the highest scoring network.
4067     private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, NascentState nascent,
4068             ReapUnvalidatedNetworks reapUnvalidatedNetworks) {
4069         if (!newNetwork.created) return;
4070         if (nascent == NascentState.JUST_VALIDATED && !newNetwork.everValidated) {
4071             loge("ERROR: nascent network not validated.");
4072         }
4073         boolean keep = newNetwork.isVPN();
4074         boolean isNewDefault = false;
4075         NetworkAgentInfo oldDefaultNetwork = null;
4076         if (DBG) log("rematching " + newNetwork.name());
4077         // Find and migrate to this Network any NetworkRequests for
4078         // which this network is now the best.
4079         ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
4080         if (VDBG) log(" network has: " + newNetwork.networkCapabilities);
4081         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
4082             NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
4083             if (newNetwork == currentNetwork) {
4084                 if (DBG) {
4085                     log("Network " + newNetwork.name() + " was already satisfying" +
4086                             " request " + nri.request.requestId + ". No change.");
4087                 }
4088                 keep = true;
4089                 continue;
4090             }
4091
4092             // check if it satisfies the NetworkCapabilities
4093             if (VDBG) log("  checking if request is satisfied: " + nri.request);
4094             if (newNetwork.satisfies(nri.request)) {
4095                 if (!nri.isRequest) {
4096                     // This is not a request, it's a callback listener.
4097                     // Add it to newNetwork regardless of score.
4098                     newNetwork.addRequest(nri.request);
4099                     continue;
4100                 }
4101
4102                 // next check if it's better than any current network we're using for
4103                 // this request
4104                 if (VDBG) {
4105                     log("currentScore = " +
4106                             (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
4107                             ", newScore = " + newNetwork.getCurrentScore());
4108                 }
4109                 if (currentNetwork == null ||
4110                         currentNetwork.getCurrentScore() < newNetwork.getCurrentScore()) {
4111                     if (currentNetwork != null) {
4112                         if (DBG) log("   accepting network in place of " + currentNetwork.name());
4113                         currentNetwork.networkRequests.remove(nri.request.requestId);
4114                         currentNetwork.networkLingered.add(nri.request);
4115                         affectedNetworks.add(currentNetwork);
4116                     } else {
4117                         if (DBG) log("   accepting network in place of null");
4118                     }
4119                     unlinger(newNetwork);
4120                     mNetworkForRequestId.put(nri.request.requestId, newNetwork);
4121                     newNetwork.addRequest(nri.request);
4122                     keep = true;
4123                     // Tell NetworkFactories about the new score, so they can stop
4124                     // trying to connect if they know they cannot match it.
4125                     // TODO - this could get expensive if we have alot of requests for this
4126                     // network.  Think about if there is a way to reduce this.  Push
4127                     // netid->request mapping to each factory?
4128                     sendUpdatedScoreToFactories(nri.request, newNetwork.getCurrentScore());
4129                     if (mDefaultRequest.requestId == nri.request.requestId) {
4130                         isNewDefault = true;
4131                         oldDefaultNetwork = currentNetwork;
4132                     }
4133                 }
4134             }
4135         }
4136         // Linger any networks that are no longer needed.
4137         for (NetworkAgentInfo nai : affectedNetworks) {
4138             if (nai.everValidated && unneeded(nai)) {
4139                 nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_LINGER);
4140                 notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING);
4141             } else {
4142                 unlinger(nai);
4143             }
4144         }
4145         if (keep) {
4146             if (isNewDefault) {
4147                 // Notify system services that this network is up.
4148                 makeDefault(newNetwork);
4149                 synchronized (ConnectivityService.this) {
4150                     // have a new default network, release the transition wakelock in
4151                     // a second if it's held.  The second pause is to allow apps
4152                     // to reconnect over the new network
4153                     if (mNetTransitionWakeLock.isHeld()) {
4154                         mHandler.sendMessageDelayed(mHandler.obtainMessage(
4155                                 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
4156                                 mNetTransitionWakeLockSerialNumber, 0),
4157                                 1000);
4158                     }
4159                 }
4160             }
4161
4162             // do this after the default net is switched, but
4163             // before LegacyTypeTracker sends legacy broadcasts
4164             notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE);
4165
4166             if (isNewDefault) {
4167                 // Maintain the illusion: since the legacy API only
4168                 // understands one network at a time, we must pretend
4169                 // that the current default network disconnected before
4170                 // the new one connected.
4171                 if (oldDefaultNetwork != null) {
4172                     mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(),
4173                                               oldDefaultNetwork);
4174                 }
4175                 mDefaultInetConditionPublished = newNetwork.everValidated ? 100 : 0;
4176                 mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
4177                 notifyLockdownVpn(newNetwork);
4178             }
4179
4180             // Notify battery stats service about this network, both the normal
4181             // interface and any stacked links.
4182             // TODO: Avoid redoing this; this must only be done once when a network comes online.
4183             try {
4184                 final IBatteryStats bs = BatteryStatsService.getService();
4185                 final int type = newNetwork.networkInfo.getType();
4186
4187                 final String baseIface = newNetwork.linkProperties.getInterfaceName();
4188                 bs.noteNetworkInterfaceType(baseIface, type);
4189                 for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
4190                     final String stackedIface = stacked.getInterfaceName();
4191                     bs.noteNetworkInterfaceType(stackedIface, type);
4192                     NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
4193                 }
4194             } catch (RemoteException ignored) {
4195             }
4196
4197             // This has to happen after the notifyNetworkCallbacks as that tickles each
4198             // ConnectivityManager instance so that legacy requests correctly bind dns
4199             // requests to this network.  The legacy users are listening for this bcast
4200             // and will generally do a dns request so they can ensureRouteToHost and if
4201             // they do that before the callbacks happen they'll use the default network.
4202             //
4203             // TODO: Is there still a race here? We send the broadcast
4204             // after sending the callback, but if the app can receive the
4205             // broadcast before the callback, it might still break.
4206             //
4207             // This *does* introduce a race where if the user uses the new api
4208             // (notification callbacks) and then uses the old api (getNetworkInfo(type))
4209             // they may get old info.  Reverse this after the old startUsing api is removed.
4210             // This is on top of the multiple intent sequencing referenced in the todo above.
4211             for (int i = 0; i < newNetwork.networkRequests.size(); i++) {
4212                 NetworkRequest nr = newNetwork.networkRequests.valueAt(i);
4213                 if (nr.legacyType != TYPE_NONE && isRequest(nr)) {
4214                     // legacy type tracker filters out repeat adds
4215                     mLegacyTypeTracker.add(nr.legacyType, newNetwork);
4216                 }
4217             }
4218
4219             // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above,
4220             // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest
4221             // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the
4222             // newNetwork to the tracker explicitly (it's a no-op if it has already been added).
4223             if (newNetwork.isVPN()) {
4224                 mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
4225             }
4226         } else if (nascent == NascentState.JUST_VALIDATED) {
4227             // Only tear down newly validated networks here.  Leave unvalidated to either become
4228             // validated (and get evaluated against peers, one losing here), or get reaped (see
4229             // reapUnvalidatedNetworks) if they have no chance of becoming the highest scoring
4230             // network.  Networks that have been up for a while and are validated should be torn
4231             // down via the lingering process so communication on that network is given time to
4232             // wrap up.
4233             if (DBG) log("Validated network turns out to be unwanted.  Tear it down.");
4234             teardownUnneededNetwork(newNetwork);
4235         }
4236         if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
4237             for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
4238                 if (!nai.everValidated && unneeded(nai)) {
4239                     if (DBG) log("Reaping " + nai.name());
4240                     teardownUnneededNetwork(nai);
4241                 }
4242             }
4243         }
4244     }
4245
4246     // Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
4247     // being disconnected.
4248     // If only one Network's score or capabilities have been modified since the last time
4249     // this function was called, pass this Network in via the "changed" arugment, otherwise
4250     // pass null.
4251     // If only one Network has been changed but its NetworkCapabilities have not changed,
4252     // pass in the Network's score (from getCurrentScore()) prior to the change via
4253     // "oldScore", otherwise pass changed.getCurrentScore() or 0 if "changed" is null.
4254     private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
4255         // TODO: This may get slow.  The "changed" parameter is provided for future optimization
4256         // to avoid the slowness.  It is not simply enough to process just "changed", for
4257         // example in the case where "changed"'s score decreases and another network should begin
4258         // satifying a NetworkRequest that "changed" currently satisfies.
4259
4260         // Optimization: Only reprocess "changed" if its score improved.  This is safe because it
4261         // can only add more NetworkRequests satisfied by "changed", and this is exactly what
4262         // rematchNetworkAndRequests() handles.
4263         if (changed != null && oldScore < changed.getCurrentScore()) {
4264             rematchNetworkAndRequests(changed, NascentState.NOT_JUST_VALIDATED,
4265                     ReapUnvalidatedNetworks.REAP);
4266         } else {
4267             for (Iterator i = mNetworkAgentInfos.values().iterator(); i.hasNext(); ) {
4268                 rematchNetworkAndRequests((NetworkAgentInfo)i.next(),
4269                         NascentState.NOT_JUST_VALIDATED,
4270                         // Only reap the last time through the loop.  Reaping before all rematching
4271                         // is complete could incorrectly teardown a network that hasn't yet been
4272                         // rematched.
4273                         i.hasNext() ? ReapUnvalidatedNetworks.DONT_REAP
4274                                 : ReapUnvalidatedNetworks.REAP);
4275             }
4276         }
4277     }
4278
4279     private void updateInetCondition(NetworkAgentInfo nai) {
4280         // Don't bother updating until we've graduated to validated at least once.
4281         if (!nai.everValidated) return;
4282         // For now only update icons for default connection.
4283         // TODO: Update WiFi and cellular icons separately. b/17237507
4284         if (!isDefaultNetwork(nai)) return;
4285
4286         int newInetCondition = nai.lastValidated ? 100 : 0;
4287         // Don't repeat publish.
4288         if (newInetCondition == mDefaultInetConditionPublished) return;
4289
4290         mDefaultInetConditionPublished = newInetCondition;
4291         sendInetConditionBroadcast(nai.networkInfo);
4292     }
4293
4294     private void notifyLockdownVpn(NetworkAgentInfo nai) {
4295         if (mLockdownTracker != null) {
4296             if (nai != null && nai.isVPN()) {
4297                 mLockdownTracker.onVpnStateChanged(nai.networkInfo);
4298             } else {
4299                 mLockdownTracker.onNetworkInfoChanged();
4300             }
4301         }
4302     }
4303
4304     private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
4305         NetworkInfo.State state = newInfo.getState();
4306         NetworkInfo oldInfo = null;
4307         synchronized (networkAgent) {
4308             oldInfo = networkAgent.networkInfo;
4309             networkAgent.networkInfo = newInfo;
4310         }
4311         notifyLockdownVpn(networkAgent);
4312
4313         if (oldInfo != null && oldInfo.getState() == state) {
4314             if (VDBG) log("ignoring duplicate network state non-change");
4315             return;
4316         }
4317         if (DBG) {
4318             log(networkAgent.name() + " EVENT_NETWORK_INFO_CHANGED, going from " +
4319                     (oldInfo == null ? "null" : oldInfo.getState()) +
4320                     " to " + state);
4321         }
4322
4323         if (state == NetworkInfo.State.CONNECTED && !networkAgent.created) {
4324             try {
4325                 // This should never fail.  Specifying an already in use NetID will cause failure.
4326                 if (networkAgent.isVPN()) {
4327                     mNetd.createVirtualNetwork(networkAgent.network.netId,
4328                             !networkAgent.linkProperties.getDnsServers().isEmpty(),
4329                             (networkAgent.networkMisc == null ||
4330                                 !networkAgent.networkMisc.allowBypass));
4331                 } else {
4332                     mNetd.createPhysicalNetwork(networkAgent.network.netId);
4333                 }
4334             } catch (Exception e) {
4335                 loge("Error creating network " + networkAgent.network.netId + ": "
4336                         + e.getMessage());
4337                 return;
4338             }
4339             networkAgent.created = true;
4340             updateLinkProperties(networkAgent, null);
4341             notifyIfacesChanged();
4342             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
4343             networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
4344             if (networkAgent.isVPN()) {
4345                 // Temporarily disable the default proxy (not global).
4346                 synchronized (mProxyLock) {
4347                     if (!mDefaultProxyDisabled) {
4348                         mDefaultProxyDisabled = true;
4349                         if (mGlobalProxy == null && mDefaultProxy != null) {
4350                             sendProxyBroadcast(null);
4351                         }
4352                     }
4353                 }
4354                 // TODO: support proxy per network.
4355             }
4356             // Consider network even though it is not yet validated.
4357             rematchNetworkAndRequests(networkAgent, NascentState.NOT_JUST_VALIDATED,
4358                     ReapUnvalidatedNetworks.REAP);
4359         } else if (state == NetworkInfo.State.DISCONNECTED ||
4360                 state == NetworkInfo.State.SUSPENDED) {
4361             networkAgent.asyncChannel.disconnect();
4362             if (networkAgent.isVPN()) {
4363                 synchronized (mProxyLock) {
4364                     if (mDefaultProxyDisabled) {
4365                         mDefaultProxyDisabled = false;
4366                         if (mGlobalProxy == null && mDefaultProxy != null) {
4367                             sendProxyBroadcast(mDefaultProxy);
4368                         }
4369                     }
4370                 }
4371             }
4372         }
4373     }
4374
4375     private void updateNetworkScore(NetworkAgentInfo nai, int score) {
4376         if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
4377         if (score < 0) {
4378             loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
4379                     ").  Bumping score to min of 0");
4380             score = 0;
4381         }
4382
4383         final int oldScore = nai.getCurrentScore();
4384         nai.setCurrentScore(score);
4385
4386         rematchAllNetworksAndRequests(nai, oldScore);
4387
4388         sendUpdatedScoreToFactories(nai);
4389     }
4390
4391     // notify only this one new request of the current state
4392     protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) {
4393         int notifyType = ConnectivityManager.CALLBACK_AVAILABLE;
4394         // TODO - read state from monitor to decide what to send.
4395 //        if (nai.networkMonitor.isLingering()) {
4396 //            notifyType = NetworkCallbacks.LOSING;
4397 //        } else if (nai.networkMonitor.isEvaluating()) {
4398 //            notifyType = NetworkCallbacks.callCallbackForRequest(request, nai, notifyType);
4399 //        }
4400         if (nri.mPendingIntent == null) {
4401             callCallbackForRequest(nri, nai, notifyType);
4402         } else {
4403             sendPendingIntentForRequest(nri, nai, notifyType);
4404         }
4405     }
4406
4407     private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) {
4408         // The NetworkInfo we actually send out has no bearing on the real
4409         // state of affairs. For example, if the default connection is mobile,
4410         // and a request for HIPRI has just gone away, we need to pretend that
4411         // HIPRI has just disconnected. So we need to set the type to HIPRI and
4412         // the state to DISCONNECTED, even though the network is of type MOBILE
4413         // and is still connected.
4414         NetworkInfo info = new NetworkInfo(nai.networkInfo);
4415         info.setType(type);
4416         if (connected) {
4417             info.setDetailedState(DetailedState.CONNECTED, null, info.getExtraInfo());
4418             sendConnectedBroadcast(info);
4419         } else {
4420             info.setDetailedState(DetailedState.DISCONNECTED, null, info.getExtraInfo());
4421             Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
4422             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
4423             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
4424             if (info.isFailover()) {
4425                 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
4426                 nai.networkInfo.setFailover(false);
4427             }
4428             if (info.getReason() != null) {
4429                 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
4430             }
4431             if (info.getExtraInfo() != null) {
4432                 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
4433             }
4434             NetworkAgentInfo newDefaultAgent = null;
4435             if (nai.networkRequests.get(mDefaultRequest.requestId) != null) {
4436                 newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId);
4437                 if (newDefaultAgent != null) {
4438                     intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
4439                             newDefaultAgent.networkInfo);
4440                 } else {
4441                     intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
4442                 }
4443             }
4444             intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
4445                     mDefaultInetConditionPublished);
4446             final Intent immediateIntent = new Intent(intent);
4447             immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
4448             sendStickyBroadcast(immediateIntent);
4449             sendStickyBroadcast(intent);
4450             if (newDefaultAgent != null) {
4451                 sendConnectedBroadcast(newDefaultAgent.networkInfo);
4452             }
4453         }
4454     }
4455
4456     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
4457         if (DBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
4458         for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
4459             NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
4460             NetworkRequestInfo nri = mNetworkRequests.get(nr);
4461             if (VDBG) log(" sending notification for " + nr);
4462             if (nri.mPendingIntent == null) {
4463                 callCallbackForRequest(nri, networkAgent, notifyType);
4464             } else {
4465                 sendPendingIntentForRequest(nri, networkAgent, notifyType);
4466             }
4467         }
4468     }
4469
4470     private String notifyTypeToName(int notifyType) {
4471         switch (notifyType) {
4472             case ConnectivityManager.CALLBACK_PRECHECK:    return "PRECHECK";
4473             case ConnectivityManager.CALLBACK_AVAILABLE:   return "AVAILABLE";
4474             case ConnectivityManager.CALLBACK_LOSING:      return "LOSING";
4475             case ConnectivityManager.CALLBACK_LOST:        return "LOST";
4476             case ConnectivityManager.CALLBACK_UNAVAIL:     return "UNAVAILABLE";
4477             case ConnectivityManager.CALLBACK_CAP_CHANGED: return "CAP_CHANGED";
4478             case ConnectivityManager.CALLBACK_IP_CHANGED:  return "IP_CHANGED";
4479             case ConnectivityManager.CALLBACK_RELEASED:    return "RELEASED";
4480         }
4481         return "UNKNOWN";
4482     }
4483
4484     /**
4485      * Notify other system services that set of active ifaces has changed.
4486      */
4487     private void notifyIfacesChanged() {
4488         try {
4489             mStatsService.forceUpdateIfaces();
4490         } catch (Exception ignored) {
4491         }
4492     }
4493
4494     @Override
4495     public boolean addVpnAddress(String address, int prefixLength) {
4496         throwIfLockdownEnabled();
4497         int user = UserHandle.getUserId(Binder.getCallingUid());
4498         synchronized (mVpns) {
4499             return mVpns.get(user).addAddress(address, prefixLength);
4500         }
4501     }
4502
4503     @Override
4504     public boolean removeVpnAddress(String address, int prefixLength) {
4505         throwIfLockdownEnabled();
4506         int user = UserHandle.getUserId(Binder.getCallingUid());
4507         synchronized (mVpns) {
4508             return mVpns.get(user).removeAddress(address, prefixLength);
4509         }
4510     }
4511
4512     @Override
4513     public boolean setUnderlyingNetworksForVpn(Network[] networks) {
4514         throwIfLockdownEnabled();
4515         int user = UserHandle.getUserId(Binder.getCallingUid());
4516         synchronized (mVpns) {
4517             return mVpns.get(user).setUnderlyingNetworks(networks);
4518         }
4519     }
4520 }