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