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