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