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