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