OSDN Git Service

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