ConnectivityService.java revision a10a3ad35afc0b2a97cd72afceebd8e3db9b7db4
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.net.ConnectivityManager.CONNECTIVITY_ACTION;
21import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
22import static android.net.ConnectivityManager.isNetworkTypeValid;
23import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
24import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
25
26import android.bluetooth.BluetoothTetheringDataTracker;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.pm.PackageManager;
31import android.database.ContentObserver;
32import android.net.ConnectivityManager;
33import android.net.DummyDataStateTracker;
34import android.net.EthernetDataTracker;
35import android.net.IConnectivityManager;
36import android.net.INetworkPolicyListener;
37import android.net.INetworkPolicyManager;
38import android.net.LinkAddress;
39import android.net.LinkProperties;
40import android.net.LinkProperties.CompareResult;
41import android.net.MobileDataStateTracker;
42import android.net.NetworkConfig;
43import android.net.NetworkInfo;
44import android.net.NetworkInfo.DetailedState;
45import android.net.NetworkQuotaInfo;
46import android.net.NetworkState;
47import android.net.NetworkStateTracker;
48import android.net.NetworkUtils;
49import android.net.Proxy;
50import android.net.ProxyProperties;
51import android.net.RouteInfo;
52import android.net.wifi.WifiStateTracker;
53import android.os.Binder;
54import android.os.FileUtils;
55import android.os.Handler;
56import android.os.HandlerThread;
57import android.os.IBinder;
58import android.os.INetworkManagementService;
59import android.os.Looper;
60import android.os.Message;
61import android.os.ParcelFileDescriptor;
62import android.os.PowerManager;
63import android.os.RemoteException;
64import android.os.ServiceManager;
65import android.os.SystemProperties;
66import android.provider.Settings;
67import android.text.TextUtils;
68import android.util.EventLog;
69import android.util.Slog;
70import android.util.SparseIntArray;
71
72import com.android.internal.net.LegacyVpnInfo;
73import com.android.internal.net.VpnConfig;
74import com.android.internal.telephony.Phone;
75import com.android.server.connectivity.Tethering;
76import com.android.server.connectivity.Vpn;
77import com.google.android.collect.Lists;
78import com.google.android.collect.Sets;
79
80import java.io.FileDescriptor;
81import java.io.IOException;
82import java.io.PrintWriter;
83import java.net.Inet4Address;
84import java.net.Inet6Address;
85import java.net.InetAddress;
86import java.net.UnknownHostException;
87import java.util.ArrayList;
88import java.util.Arrays;
89import java.util.Collection;
90import java.util.GregorianCalendar;
91import java.util.HashSet;
92import java.util.List;
93
94/**
95 * @hide
96 */
97public class ConnectivityService extends IConnectivityManager.Stub {
98
99    private static final boolean DBG = true;
100    private static final boolean VDBG = true;
101    private static final String TAG = "ConnectivityService";
102
103    private static final boolean LOGD_RULES = false;
104
105    // how long to wait before switching back to a radio's default network
106    private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
107    // system property that can override the above value
108    private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
109            "android.telephony.apn-restore";
110
111    // used in recursive route setting to add gateways for the host for which
112    // a host route was requested.
113    private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
114
115    private Tethering mTethering;
116    private boolean mTetheringConfigValid = false;
117
118    private Vpn mVpn;
119
120    /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
121    private Object mRulesLock = new Object();
122    /** Currently active network rules by UID. */
123    private SparseIntArray mUidRules = new SparseIntArray();
124    /** Set of ifaces that are costly. */
125    private HashSet<String> mMeteredIfaces = Sets.newHashSet();
126
127    /**
128     * Sometimes we want to refer to the individual network state
129     * trackers separately, and sometimes we just want to treat them
130     * abstractly.
131     */
132    private NetworkStateTracker mNetTrackers[];
133
134    /**
135     * The link properties that define the current links
136     */
137    private LinkProperties mCurrentLinkProperties[];
138
139    /**
140     * A per Net list of the PID's that requested access to the net
141     * used both as a refcount and for per-PID DNS selection
142     */
143    private List mNetRequestersPids[];
144
145    // priority order of the nettrackers
146    // (excluding dynamically set mNetworkPreference)
147    // TODO - move mNetworkTypePreference into this
148    private int[] mPriorityList;
149
150    private Context mContext;
151    private int mNetworkPreference;
152    private int mActiveDefaultNetwork = -1;
153    // 0 is full bad, 100 is full good
154    private int mDefaultInetCondition = 0;
155    private int mDefaultInetConditionPublished = 0;
156    private boolean mInetConditionChangeInFlight = false;
157    private int mDefaultConnectionSequence = 0;
158
159    private Object mDnsLock = new Object();
160    private int mNumDnsEntries;
161    private boolean mDnsOverridden = false;
162
163    private boolean mTestMode;
164    private static ConnectivityService sServiceInstance;
165
166    private INetworkManagementService mNetd;
167    private INetworkPolicyManager mPolicyManager;
168
169    private static final int ENABLED  = 1;
170    private static final int DISABLED = 0;
171
172    // Share the event space with NetworkStateTracker (which can't see this
173    // internal class but sends us events).  If you change these, change
174    // NetworkStateTracker.java too.
175    private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
176    private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
177
178    /**
179     * used internally as a delayed event to make us switch back to the
180     * default network
181     */
182    private static final int EVENT_RESTORE_DEFAULT_NETWORK =
183            MAX_NETWORK_STATE_TRACKER_EVENT + 1;
184
185    /**
186     * used internally to change our mobile data enabled flag
187     */
188    private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
189            MAX_NETWORK_STATE_TRACKER_EVENT + 2;
190
191    /**
192     * used internally to change our network preference setting
193     * arg1 = networkType to prefer
194     */
195    private static final int EVENT_SET_NETWORK_PREFERENCE =
196            MAX_NETWORK_STATE_TRACKER_EVENT + 3;
197
198    /**
199     * used internally to synchronize inet condition reports
200     * arg1 = networkType
201     * arg2 = condition (0 bad, 100 good)
202     */
203    private static final int EVENT_INET_CONDITION_CHANGE =
204            MAX_NETWORK_STATE_TRACKER_EVENT + 4;
205
206    /**
207     * used internally to mark the end of inet condition hold periods
208     * arg1 = networkType
209     */
210    private static final int EVENT_INET_CONDITION_HOLD_END =
211            MAX_NETWORK_STATE_TRACKER_EVENT + 5;
212
213    /**
214     * used internally to set enable/disable cellular data
215     * arg1 = ENBALED or DISABLED
216     */
217    private static final int EVENT_SET_MOBILE_DATA =
218            MAX_NETWORK_STATE_TRACKER_EVENT + 7;
219
220    /**
221     * used internally to clear a wakelock when transitioning
222     * from one net to another
223     */
224    private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
225            MAX_NETWORK_STATE_TRACKER_EVENT + 8;
226
227    /**
228     * used internally to reload global proxy settings
229     */
230    private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
231            MAX_NETWORK_STATE_TRACKER_EVENT + 9;
232
233    /**
234     * used internally to set external dependency met/unmet
235     * arg1 = ENABLED (met) or DISABLED (unmet)
236     * arg2 = NetworkType
237     */
238    private static final int EVENT_SET_DEPENDENCY_MET =
239            MAX_NETWORK_STATE_TRACKER_EVENT + 10;
240
241    /**
242     * used internally to restore DNS properties back to the
243     * default network
244     */
245    private static final int EVENT_RESTORE_DNS =
246            MAX_NETWORK_STATE_TRACKER_EVENT + 11;
247
248    /**
249     * used internally to send a sticky broadcast delayed.
250     */
251    private static final int EVENT_SEND_STICKY_BROADCAST_INTENT =
252            MAX_NETWORK_STATE_TRACKER_EVENT + 12;
253
254    /**
255     * Used internally to
256     * {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
257     */
258    private static final int EVENT_SET_POLICY_DATA_ENABLE = MAX_NETWORK_STATE_TRACKER_EVENT + 13;
259
260    private Handler mHandler;
261
262    // list of DeathRecipients used to make sure features are turned off when
263    // a process dies
264    private List<FeatureUser> mFeatureUsers;
265
266    private boolean mSystemReady;
267    private Intent mInitialBroadcast;
268
269    private PowerManager.WakeLock mNetTransitionWakeLock;
270    private String mNetTransitionWakeLockCausedBy = "";
271    private int mNetTransitionWakeLockSerialNumber;
272    private int mNetTransitionWakeLockTimeout;
273
274    private InetAddress mDefaultDns;
275
276    // this collection is used to refcount the added routes - if there are none left
277    // it's time to remove the route from the route table
278    private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
279
280    // used in DBG mode to track inet condition reports
281    private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
282    private ArrayList mInetLog;
283
284    // track the current default http proxy - tell the world if we get a new one (real change)
285    private ProxyProperties mDefaultProxy = null;
286    // track the global proxy.
287    private ProxyProperties mGlobalProxy = null;
288    private final Object mGlobalProxyLock = new Object();
289
290    private SettingsObserver mSettingsObserver;
291
292    NetworkConfig[] mNetConfigs;
293    int mNetworksDefined;
294
295    private static class RadioAttributes {
296        public int mSimultaneity;
297        public int mType;
298        public RadioAttributes(String init) {
299            String fragments[] = init.split(",");
300            mType = Integer.parseInt(fragments[0]);
301            mSimultaneity = Integer.parseInt(fragments[1]);
302        }
303    }
304    RadioAttributes[] mRadioAttributes;
305
306    // the set of network types that can only be enabled by system/sig apps
307    List mProtectedNetworks;
308
309    public ConnectivityService(
310            Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
311        if (DBG) log("ConnectivityService starting up");
312
313        HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
314        handlerThread.start();
315        mHandler = new MyHandler(handlerThread.getLooper());
316
317        // setup our unique device name
318        if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
319            String id = Settings.Secure.getString(context.getContentResolver(),
320                    Settings.Secure.ANDROID_ID);
321            if (id != null && id.length() > 0) {
322                String name = new String("android-").concat(id);
323                SystemProperties.set("net.hostname", name);
324            }
325        }
326
327        // read our default dns server ip
328        String dns = Settings.Secure.getString(context.getContentResolver(),
329                Settings.Secure.DEFAULT_DNS_SERVER);
330        if (dns == null || dns.length() == 0) {
331            dns = context.getResources().getString(
332                    com.android.internal.R.string.config_default_dns_server);
333        }
334        try {
335            mDefaultDns = NetworkUtils.numericToInetAddress(dns);
336        } catch (IllegalArgumentException e) {
337            loge("Error setting defaultDns using " + dns);
338        }
339
340        mContext = checkNotNull(context, "missing Context");
341        mNetd = checkNotNull(netd, "missing INetworkManagementService");
342        mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
343
344        try {
345            mPolicyManager.registerListener(mPolicyListener);
346        } catch (RemoteException e) {
347            // ouch, no rules updates means some processes may never get network
348            loge("unable to register INetworkPolicyListener" + e.toString());
349        }
350
351        final PowerManager powerManager = (PowerManager) context.getSystemService(
352                Context.POWER_SERVICE);
353        mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
354        mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
355                com.android.internal.R.integer.config_networkTransitionTimeout);
356
357        mNetTrackers = new NetworkStateTracker[
358                ConnectivityManager.MAX_NETWORK_TYPE+1];
359        mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
360
361        mNetworkPreference = getPersistedNetworkPreference();
362
363        mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
364        mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
365
366        // Load device network attributes from resources
367        String[] raStrings = context.getResources().getStringArray(
368                com.android.internal.R.array.radioAttributes);
369        for (String raString : raStrings) {
370            RadioAttributes r = new RadioAttributes(raString);
371            if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
372                loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
373                continue;
374            }
375            if (mRadioAttributes[r.mType] != null) {
376                loge("Error in radioAttributes - ignoring attempt to redefine type " +
377                        r.mType);
378                continue;
379            }
380            mRadioAttributes[r.mType] = r;
381        }
382
383        String[] naStrings = context.getResources().getStringArray(
384                com.android.internal.R.array.networkAttributes);
385        for (String naString : naStrings) {
386            try {
387                NetworkConfig n = new NetworkConfig(naString);
388                if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
389                    loge("Error in networkAttributes - ignoring attempt to define type " +
390                            n.type);
391                    continue;
392                }
393                if (mNetConfigs[n.type] != null) {
394                    loge("Error in networkAttributes - ignoring attempt to redefine type " +
395                            n.type);
396                    continue;
397                }
398                if (mRadioAttributes[n.radio] == null) {
399                    loge("Error in networkAttributes - ignoring attempt to use undefined " +
400                            "radio " + n.radio + " in network type " + n.type);
401                    continue;
402                }
403                mNetConfigs[n.type] = n;
404                mNetworksDefined++;
405            } catch(Exception e) {
406                // ignore it - leave the entry null
407            }
408        }
409
410        mProtectedNetworks = new ArrayList<Integer>();
411        int[] protectedNetworks = context.getResources().getIntArray(
412                com.android.internal.R.array.config_protectedNetworks);
413        for (int p : protectedNetworks) {
414            if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
415                mProtectedNetworks.add(p);
416            } else {
417                if (DBG) loge("Ignoring protectedNetwork " + p);
418            }
419        }
420
421        // high priority first
422        mPriorityList = new int[mNetworksDefined];
423        {
424            int insertionPoint = mNetworksDefined-1;
425            int currentLowest = 0;
426            int nextLowest = 0;
427            while (insertionPoint > -1) {
428                for (NetworkConfig na : mNetConfigs) {
429                    if (na == null) continue;
430                    if (na.priority < currentLowest) continue;
431                    if (na.priority > currentLowest) {
432                        if (na.priority < nextLowest || nextLowest == 0) {
433                            nextLowest = na.priority;
434                        }
435                        continue;
436                    }
437                    mPriorityList[insertionPoint--] = na.type;
438                }
439                currentLowest = nextLowest;
440                nextLowest = 0;
441            }
442        }
443
444        mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
445        for (int i : mPriorityList) {
446            mNetRequestersPids[i] = new ArrayList();
447        }
448
449        mFeatureUsers = new ArrayList<FeatureUser>();
450
451        mNumDnsEntries = 0;
452
453        mTestMode = SystemProperties.get("cm.test.mode").equals("true")
454                && SystemProperties.get("ro.build.type").equals("eng");
455        /*
456         * Create the network state trackers for Wi-Fi and mobile
457         * data. Maybe this could be done with a factory class,
458         * but it's not clear that it's worth it, given that
459         * the number of different network types is not going
460         * to change very often.
461         */
462        for (int netType : mPriorityList) {
463            switch (mNetConfigs[netType].radio) {
464            case ConnectivityManager.TYPE_WIFI:
465                mNetTrackers[netType] = new WifiStateTracker(netType,
466                        mNetConfigs[netType].name);
467                mNetTrackers[netType].startMonitoring(context, mHandler);
468               break;
469            case ConnectivityManager.TYPE_MOBILE:
470                mNetTrackers[netType] = new MobileDataStateTracker(netType,
471                        mNetConfigs[netType].name);
472                mNetTrackers[netType].startMonitoring(context, mHandler);
473                break;
474            case ConnectivityManager.TYPE_DUMMY:
475                mNetTrackers[netType] = new DummyDataStateTracker(netType,
476                        mNetConfigs[netType].name);
477                mNetTrackers[netType].startMonitoring(context, mHandler);
478                break;
479            case ConnectivityManager.TYPE_BLUETOOTH:
480                mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
481                mNetTrackers[netType].startMonitoring(context, mHandler);
482                break;
483            case ConnectivityManager.TYPE_ETHERNET:
484                mNetTrackers[netType] = EthernetDataTracker.getInstance();
485                mNetTrackers[netType].startMonitoring(context, mHandler);
486                break;
487            default:
488                loge("Trying to create a DataStateTracker for an unknown radio type " +
489                        mNetConfigs[netType].radio);
490                continue;
491            }
492            mCurrentLinkProperties[netType] = null;
493            if (mNetConfigs[netType].isDefault()) mNetTrackers[netType].reconnect();
494        }
495
496        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
497        INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
498
499        mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
500        mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
501                                  mTethering.getTetherableWifiRegexs().length != 0 ||
502                                  mTethering.getTetherableBluetoothRegexs().length != 0) &&
503                                 mTethering.getUpstreamIfaceTypes().length != 0);
504
505        mVpn = new Vpn(mContext, new VpnCallback());
506
507        try {
508            nmService.registerObserver(mTethering);
509            nmService.registerObserver(mVpn);
510        } catch (RemoteException e) {
511            loge("Error registering observer :" + e);
512        }
513
514        if (DBG) {
515            mInetLog = new ArrayList();
516        }
517
518        mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
519        mSettingsObserver.observe(mContext);
520
521        loadGlobalProxy();
522    }
523
524    /**
525     * Sets the preferred network.
526     * @param preference the new preference
527     */
528    public void setNetworkPreference(int preference) {
529        enforceChangePermission();
530
531        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
532    }
533
534    public int getNetworkPreference() {
535        enforceAccessPermission();
536        int preference;
537        synchronized(this) {
538            preference = mNetworkPreference;
539        }
540        return preference;
541    }
542
543    private void handleSetNetworkPreference(int preference) {
544        if (ConnectivityManager.isNetworkTypeValid(preference) &&
545                mNetConfigs[preference] != null &&
546                mNetConfigs[preference].isDefault()) {
547            if (mNetworkPreference != preference) {
548                final ContentResolver cr = mContext.getContentResolver();
549                Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
550                synchronized(this) {
551                    mNetworkPreference = preference;
552                }
553                enforcePreference();
554            }
555        }
556    }
557
558    private int getConnectivityChangeDelay() {
559        final ContentResolver cr = mContext.getContentResolver();
560
561        /** Check system properties for the default value then use secure settings value, if any. */
562        int defaultDelay = SystemProperties.getInt(
563                "conn." + Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
564                Settings.Secure.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
565        return Settings.Secure.getInt(cr, Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
566                defaultDelay);
567    }
568
569    private int getPersistedNetworkPreference() {
570        final ContentResolver cr = mContext.getContentResolver();
571
572        final int networkPrefSetting = Settings.Secure
573                .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
574        if (networkPrefSetting != -1) {
575            return networkPrefSetting;
576        }
577
578        return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
579    }
580
581    /**
582     * Make the state of network connectivity conform to the preference settings
583     * In this method, we only tear down a non-preferred network. Establishing
584     * a connection to the preferred network is taken care of when we handle
585     * the disconnect event from the non-preferred network
586     * (see {@link #handleDisconnect(NetworkInfo)}).
587     */
588    private void enforcePreference() {
589        if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
590            return;
591
592        if (!mNetTrackers[mNetworkPreference].isAvailable())
593            return;
594
595        for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
596            if (t != mNetworkPreference && mNetTrackers[t] != null &&
597                    mNetTrackers[t].getNetworkInfo().isConnected()) {
598                if (DBG) {
599                    log("tearing down " + mNetTrackers[t].getNetworkInfo() +
600                            " in enforcePreference");
601                }
602                teardown(mNetTrackers[t]);
603            }
604        }
605    }
606
607    private boolean teardown(NetworkStateTracker netTracker) {
608        if (netTracker.teardown()) {
609            netTracker.setTeardownRequested(true);
610            return true;
611        } else {
612            return false;
613        }
614    }
615
616    /**
617     * Check if UID should be blocked from using the network represented by the
618     * given {@link NetworkStateTracker}.
619     */
620    private boolean isNetworkBlocked(NetworkStateTracker tracker, int uid) {
621        final String iface = tracker.getLinkProperties().getInterfaceName();
622
623        final boolean networkCostly;
624        final int uidRules;
625        synchronized (mRulesLock) {
626            networkCostly = mMeteredIfaces.contains(iface);
627            uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
628        }
629
630        if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) {
631            return true;
632        }
633
634        // no restrictive rules; network is visible
635        return false;
636    }
637
638    /**
639     * Return a filtered {@link NetworkInfo}, potentially marked
640     * {@link DetailedState#BLOCKED} based on
641     * {@link #isNetworkBlocked(NetworkStateTracker, int)}.
642     */
643    private NetworkInfo getFilteredNetworkInfo(NetworkStateTracker tracker, int uid) {
644        NetworkInfo info = tracker.getNetworkInfo();
645        if (isNetworkBlocked(tracker, uid)) {
646            // network is blocked; clone and override state
647            info = new NetworkInfo(info);
648            info.setDetailedState(DetailedState.BLOCKED, null, null);
649        }
650        return info;
651    }
652
653    /**
654     * Return NetworkInfo for the active (i.e., connected) network interface.
655     * It is assumed that at most one network is active at a time. If more
656     * than one is active, it is indeterminate which will be returned.
657     * @return the info for the active network, or {@code null} if none is
658     * active
659     */
660    @Override
661    public NetworkInfo getActiveNetworkInfo() {
662        enforceAccessPermission();
663        final int uid = Binder.getCallingUid();
664        return getNetworkInfo(mActiveDefaultNetwork, uid);
665    }
666
667    @Override
668    public NetworkInfo getActiveNetworkInfoForUid(int uid) {
669        enforceConnectivityInternalPermission();
670        return getNetworkInfo(mActiveDefaultNetwork, uid);
671    }
672
673    @Override
674    public NetworkInfo getNetworkInfo(int networkType) {
675        enforceAccessPermission();
676        final int uid = Binder.getCallingUid();
677        return getNetworkInfo(networkType, uid);
678    }
679
680    private NetworkInfo getNetworkInfo(int networkType, int uid) {
681        NetworkInfo info = null;
682        if (isNetworkTypeValid(networkType)) {
683            final NetworkStateTracker tracker = mNetTrackers[networkType];
684            if (tracker != null) {
685                info = getFilteredNetworkInfo(tracker, uid);
686            }
687        }
688        return info;
689    }
690
691    @Override
692    public NetworkInfo[] getAllNetworkInfo() {
693        enforceAccessPermission();
694        final int uid = Binder.getCallingUid();
695        final ArrayList<NetworkInfo> result = Lists.newArrayList();
696        synchronized (mRulesLock) {
697            for (NetworkStateTracker tracker : mNetTrackers) {
698                if (tracker != null) {
699                    result.add(getFilteredNetworkInfo(tracker, uid));
700                }
701            }
702        }
703        return result.toArray(new NetworkInfo[result.size()]);
704    }
705
706    @Override
707    public boolean isNetworkSupported(int networkType) {
708        enforceAccessPermission();
709        return (isNetworkTypeValid(networkType) && (mNetTrackers[networkType] != null));
710    }
711
712    /**
713     * Return LinkProperties for the active (i.e., connected) default
714     * network interface.  It is assumed that at most one default network
715     * is active at a time. If more than one is active, it is indeterminate
716     * which will be returned.
717     * @return the ip properties for the active network, or {@code null} if
718     * none is active
719     */
720    @Override
721    public LinkProperties getActiveLinkProperties() {
722        return getLinkProperties(mActiveDefaultNetwork);
723    }
724
725    @Override
726    public LinkProperties getLinkProperties(int networkType) {
727        enforceAccessPermission();
728        if (isNetworkTypeValid(networkType)) {
729            final NetworkStateTracker tracker = mNetTrackers[networkType];
730            if (tracker != null) {
731                return tracker.getLinkProperties();
732            }
733        }
734        return null;
735    }
736
737    @Override
738    public NetworkState[] getAllNetworkState() {
739        enforceAccessPermission();
740        final int uid = Binder.getCallingUid();
741        final ArrayList<NetworkState> result = Lists.newArrayList();
742        synchronized (mRulesLock) {
743            for (NetworkStateTracker tracker : mNetTrackers) {
744                if (tracker != null) {
745                    final NetworkInfo info = getFilteredNetworkInfo(tracker, uid);
746                    result.add(new NetworkState(
747                            info, tracker.getLinkProperties(), tracker.getLinkCapabilities()));
748                }
749            }
750        }
751        return result.toArray(new NetworkState[result.size()]);
752    }
753
754    private NetworkState getNetworkStateUnchecked(int networkType) {
755        if (isNetworkTypeValid(networkType)) {
756            final NetworkStateTracker tracker = mNetTrackers[networkType];
757            if (tracker != null) {
758                return new NetworkState(tracker.getNetworkInfo(), tracker.getLinkProperties(),
759                        tracker.getLinkCapabilities());
760            }
761        }
762        return null;
763    }
764
765    @Override
766    public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
767        enforceAccessPermission();
768        final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
769        if (state != null) {
770            try {
771                return mPolicyManager.getNetworkQuotaInfo(state);
772            } catch (RemoteException e) {
773            }
774        }
775        return null;
776    }
777
778    public boolean setRadios(boolean turnOn) {
779        boolean result = true;
780        enforceChangePermission();
781        for (NetworkStateTracker t : mNetTrackers) {
782            if (t != null) result = t.setRadio(turnOn) && result;
783        }
784        return result;
785    }
786
787    public boolean setRadio(int netType, boolean turnOn) {
788        enforceChangePermission();
789        if (!ConnectivityManager.isNetworkTypeValid(netType)) {
790            return false;
791        }
792        NetworkStateTracker tracker = mNetTrackers[netType];
793        return tracker != null && tracker.setRadio(turnOn);
794    }
795
796    /**
797     * Used to notice when the calling process dies so we can self-expire
798     *
799     * Also used to know if the process has cleaned up after itself when
800     * our auto-expire timer goes off.  The timer has a link to an object.
801     *
802     */
803    private class FeatureUser implements IBinder.DeathRecipient {
804        int mNetworkType;
805        String mFeature;
806        IBinder mBinder;
807        int mPid;
808        int mUid;
809        long mCreateTime;
810
811        FeatureUser(int type, String feature, IBinder binder) {
812            super();
813            mNetworkType = type;
814            mFeature = feature;
815            mBinder = binder;
816            mPid = getCallingPid();
817            mUid = getCallingUid();
818            mCreateTime = System.currentTimeMillis();
819
820            try {
821                mBinder.linkToDeath(this, 0);
822            } catch (RemoteException e) {
823                binderDied();
824            }
825        }
826
827        void unlinkDeathRecipient() {
828            mBinder.unlinkToDeath(this, 0);
829        }
830
831        public void binderDied() {
832            log("ConnectivityService FeatureUser binderDied(" +
833                    mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
834                    (System.currentTimeMillis() - mCreateTime) + " mSec ago");
835            stopUsingNetworkFeature(this, false);
836        }
837
838        public void expire() {
839            if (VDBG) {
840                log("ConnectivityService FeatureUser expire(" +
841                        mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
842                        (System.currentTimeMillis() - mCreateTime) + " mSec ago");
843            }
844            stopUsingNetworkFeature(this, false);
845        }
846
847        public boolean isSameUser(FeatureUser u) {
848            if (u == null) return false;
849
850            return isSameUser(u.mPid, u.mUid, u.mNetworkType, u.mFeature);
851        }
852
853        public boolean isSameUser(int pid, int uid, int networkType, String feature) {
854            if ((mPid == pid) && (mUid == uid) && (mNetworkType == networkType) &&
855                TextUtils.equals(mFeature, feature)) {
856                return true;
857            }
858            return false;
859        }
860
861        public String toString() {
862            return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
863                    (System.currentTimeMillis() - mCreateTime) + " mSec ago";
864        }
865    }
866
867    // javadoc from interface
868    public int startUsingNetworkFeature(int networkType, String feature,
869            IBinder binder) {
870        if (DBG) {
871            log("startUsingNetworkFeature for net " + networkType + ": " + feature);
872        }
873        enforceChangePermission();
874        if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
875                mNetConfigs[networkType] == null) {
876            return Phone.APN_REQUEST_FAILED;
877        }
878
879        FeatureUser f = new FeatureUser(networkType, feature, binder);
880
881        // TODO - move this into individual networktrackers
882        int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
883
884        if (mProtectedNetworks.contains(usedNetworkType)) {
885            enforceConnectivityInternalPermission();
886        }
887
888        NetworkStateTracker network = mNetTrackers[usedNetworkType];
889        if (network != null) {
890            Integer currentPid = new Integer(getCallingPid());
891            if (usedNetworkType != networkType) {
892                NetworkInfo ni = network.getNetworkInfo();
893
894                if (ni.isAvailable() == false) {
895                    if (DBG) log("special network not available");
896                    if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
897                        return Phone.APN_TYPE_NOT_AVAILABLE;
898                    } else {
899                        // else make the attempt anyway - probably giving REQUEST_STARTED below
900                    }
901                }
902
903                int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
904
905                synchronized(this) {
906                    boolean addToList = true;
907                    if (restoreTimer < 0) {
908                        // In case there is no timer is specified for the feature,
909                        // make sure we don't add duplicate entry with the same request.
910                        for (FeatureUser u : mFeatureUsers) {
911                            if (u.isSameUser(f)) {
912                                // Duplicate user is found. Do not add.
913                                addToList = false;
914                                break;
915                            }
916                        }
917                    }
918
919                    if (addToList) mFeatureUsers.add(f);
920                    if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
921                        // this gets used for per-pid dns when connected
922                        mNetRequestersPids[usedNetworkType].add(currentPid);
923                    }
924                }
925
926                if (restoreTimer >= 0) {
927                    mHandler.sendMessageDelayed(
928                            mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
929                }
930
931                if ((ni.isConnectedOrConnecting() == true) &&
932                        !network.isTeardownRequested()) {
933                    if (ni.isConnected() == true) {
934                        // add the pid-specific dns
935                        handleDnsConfigurationChange(usedNetworkType);
936                        if (DBG) log("special network already active");
937                        return Phone.APN_ALREADY_ACTIVE;
938                    }
939                    if (DBG) log("special network already connecting");
940                    return Phone.APN_REQUEST_STARTED;
941                }
942
943                // check if the radio in play can make another contact
944                // assume if cannot for now
945
946                if (DBG) log("reconnecting to special network");
947                network.reconnect();
948                return Phone.APN_REQUEST_STARTED;
949            } else {
950                // need to remember this unsupported request so we respond appropriately on stop
951                synchronized(this) {
952                    mFeatureUsers.add(f);
953                    if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
954                        // this gets used for per-pid dns when connected
955                        mNetRequestersPids[usedNetworkType].add(currentPid);
956                    }
957                }
958                return -1;
959            }
960        }
961        return Phone.APN_TYPE_NOT_AVAILABLE;
962    }
963
964    // javadoc from interface
965    public int stopUsingNetworkFeature(int networkType, String feature) {
966        enforceChangePermission();
967
968        int pid = getCallingPid();
969        int uid = getCallingUid();
970
971        FeatureUser u = null;
972        boolean found = false;
973
974        synchronized(this) {
975            for (FeatureUser x : mFeatureUsers) {
976                if (x.isSameUser(pid, uid, networkType, feature)) {
977                    u = x;
978                    found = true;
979                    break;
980                }
981            }
982        }
983        if (found && u != null) {
984            // stop regardless of how many other time this proc had called start
985            return stopUsingNetworkFeature(u, true);
986        } else {
987            // none found!
988            if (VDBG) log("ignoring stopUsingNetworkFeature - not a live request");
989            return 1;
990        }
991    }
992
993    private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
994        int networkType = u.mNetworkType;
995        String feature = u.mFeature;
996        int pid = u.mPid;
997        int uid = u.mUid;
998
999        NetworkStateTracker tracker = null;
1000        boolean callTeardown = false;  // used to carry our decision outside of sync block
1001
1002        if (DBG) {
1003            log("stopUsingNetworkFeature for net " + networkType +
1004                    ": " + feature);
1005        }
1006
1007        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
1008            return -1;
1009        }
1010
1011        // need to link the mFeatureUsers list with the mNetRequestersPids state in this
1012        // sync block
1013        synchronized(this) {
1014            // check if this process still has an outstanding start request
1015            if (!mFeatureUsers.contains(u)) {
1016                if (DBG) log("ignoring - this process has no outstanding requests");
1017                return 1;
1018            }
1019            u.unlinkDeathRecipient();
1020            mFeatureUsers.remove(mFeatureUsers.indexOf(u));
1021            // If we care about duplicate requests, check for that here.
1022            //
1023            // This is done to support the extension of a request - the app
1024            // can request we start the network feature again and renew the
1025            // auto-shutoff delay.  Normal "stop" calls from the app though
1026            // do not pay attention to duplicate requests - in effect the
1027            // API does not refcount and a single stop will counter multiple starts.
1028            if (ignoreDups == false) {
1029                for (FeatureUser x : mFeatureUsers) {
1030                    if (x.isSameUser(u)) {
1031                        if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
1032                        return 1;
1033                    }
1034                }
1035            }
1036
1037            // TODO - move to individual network trackers
1038            int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
1039
1040            tracker =  mNetTrackers[usedNetworkType];
1041            if (tracker == null) {
1042                if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
1043                return -1;
1044            }
1045            if (usedNetworkType != networkType) {
1046                Integer currentPid = new Integer(pid);
1047                mNetRequestersPids[usedNetworkType].remove(currentPid);
1048                reassessPidDns(pid, true);
1049                if (mNetRequestersPids[usedNetworkType].size() != 0) {
1050                    if (DBG) log("not tearing down special network - " +
1051                           "others still using it");
1052                    return 1;
1053                }
1054                callTeardown = true;
1055            } else {
1056                if (DBG) log("not a known feature - dropping");
1057            }
1058        }
1059        if (DBG) log("Doing network teardown");
1060        if (callTeardown) {
1061            tracker.teardown();
1062            return 1;
1063        } else {
1064            return -1;
1065        }
1066    }
1067
1068    /**
1069     * @deprecated use requestRouteToHostAddress instead
1070     *
1071     * Ensure that a network route exists to deliver traffic to the specified
1072     * host via the specified network interface.
1073     * @param networkType the type of the network over which traffic to the
1074     * specified host is to be routed
1075     * @param hostAddress the IP address of the host to which the route is
1076     * desired
1077     * @return {@code true} on success, {@code false} on failure
1078     */
1079    public boolean requestRouteToHost(int networkType, int hostAddress) {
1080        InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
1081
1082        if (inetAddress == null) {
1083            return false;
1084        }
1085
1086        return requestRouteToHostAddress(networkType, inetAddress.getAddress());
1087    }
1088
1089    /**
1090     * Ensure that a network route exists to deliver traffic to the specified
1091     * host via the specified network interface.
1092     * @param networkType the type of the network over which traffic to the
1093     * specified host is to be routed
1094     * @param hostAddress the IP address of the host to which the route is
1095     * desired
1096     * @return {@code true} on success, {@code false} on failure
1097     */
1098    public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
1099        enforceChangePermission();
1100        if (mProtectedNetworks.contains(networkType)) {
1101            enforceConnectivityInternalPermission();
1102        }
1103
1104        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
1105            return false;
1106        }
1107        NetworkStateTracker tracker = mNetTrackers[networkType];
1108
1109        if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
1110                tracker.isTeardownRequested()) {
1111            if (VDBG) {
1112                log("requestRouteToHostAddress on down network " +
1113                           "(" + networkType + ") - dropped");
1114            }
1115            return false;
1116        }
1117        try {
1118            InetAddress addr = InetAddress.getByAddress(hostAddress);
1119            LinkProperties lp = tracker.getLinkProperties();
1120            return addRouteToAddress(lp, addr);
1121        } catch (UnknownHostException e) {}
1122        return false;
1123    }
1124
1125    private boolean addRoute(LinkProperties p, RouteInfo r) {
1126        return modifyRoute(p.getInterfaceName(), p, r, 0, true);
1127    }
1128
1129    private boolean removeRoute(LinkProperties p, RouteInfo r) {
1130        return modifyRoute(p.getInterfaceName(), p, r, 0, false);
1131    }
1132
1133    private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
1134        return modifyRouteToAddress(lp, addr, true);
1135    }
1136
1137    private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
1138        return modifyRouteToAddress(lp, addr, false);
1139    }
1140
1141    private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) {
1142        RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
1143        if (bestRoute == null) {
1144            bestRoute = RouteInfo.makeHostRoute(addr);
1145        } else {
1146            if (bestRoute.getGateway().equals(addr)) {
1147                // if there is no better route, add the implied hostroute for our gateway
1148                bestRoute = RouteInfo.makeHostRoute(addr);
1149            } else {
1150                // if we will connect to this through another route, add a direct route
1151                // to it's gateway
1152                bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
1153            }
1154        }
1155        return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd);
1156    }
1157
1158    private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
1159            boolean doAdd) {
1160        if ((ifaceName == null) || (lp == null) || (r == null)) return false;
1161
1162        if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
1163            loge("Error adding route - too much recursion");
1164            return false;
1165        }
1166
1167        if (r.isHostRoute() == false) {
1168            RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway());
1169            if (bestRoute != null) {
1170                if (bestRoute.getGateway().equals(r.getGateway())) {
1171                    // if there is no better route, add the implied hostroute for our gateway
1172                    bestRoute = RouteInfo.makeHostRoute(r.getGateway());
1173                } else {
1174                    // if we will connect to our gateway through another route, add a direct
1175                    // route to it's gateway
1176                    bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
1177                }
1178                modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd);
1179            }
1180        }
1181        if (doAdd) {
1182            if (VDBG) log("Adding " + r + " for interface " + ifaceName);
1183            mAddedRoutes.add(r);
1184            try {
1185                mNetd.addRoute(ifaceName, r);
1186            } catch (Exception e) {
1187                // never crash - catch them all
1188                if (VDBG) loge("Exception trying to add a route: " + e);
1189                return false;
1190            }
1191        } else {
1192            // if we remove this one and there are no more like it, then refcount==0 and
1193            // we can remove it from the table
1194            mAddedRoutes.remove(r);
1195            if (mAddedRoutes.contains(r) == false) {
1196                if (VDBG) log("Removing " + r + " for interface " + ifaceName);
1197                try {
1198                    mNetd.removeRoute(ifaceName, r);
1199                } catch (Exception e) {
1200                    // never crash - catch them all
1201                    if (VDBG) loge("Exception trying to remove a route: " + e);
1202                    return false;
1203                }
1204            } else {
1205                if (VDBG) log("not removing " + r + " as it's still in use");
1206            }
1207        }
1208        return true;
1209    }
1210
1211    /**
1212     * @see ConnectivityManager#getMobileDataEnabled()
1213     */
1214    public boolean getMobileDataEnabled() {
1215        // TODO: This detail should probably be in DataConnectionTracker's
1216        //       which is where we store the value and maybe make this
1217        //       asynchronous.
1218        enforceAccessPermission();
1219        boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1220                Settings.Secure.MOBILE_DATA, 1) == 1;
1221        if (VDBG) log("getMobileDataEnabled returning " + retVal);
1222        return retVal;
1223    }
1224
1225    public void setDataDependency(int networkType, boolean met) {
1226        enforceConnectivityInternalPermission();
1227
1228        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1229                (met ? ENABLED : DISABLED), networkType));
1230    }
1231
1232    private void handleSetDependencyMet(int networkType, boolean met) {
1233        if (mNetTrackers[networkType] != null) {
1234            if (DBG) {
1235                log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1236            }
1237            mNetTrackers[networkType].setDependencyMet(met);
1238        }
1239    }
1240
1241    private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
1242        @Override
1243        public void onUidRulesChanged(int uid, int uidRules) {
1244            // only someone like NPMS should only be calling us
1245            mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1246
1247            if (LOGD_RULES) {
1248                log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
1249            }
1250
1251            synchronized (mRulesLock) {
1252                // skip update when we've already applied rules
1253                final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
1254                if (oldRules == uidRules) return;
1255
1256                mUidRules.put(uid, uidRules);
1257            }
1258
1259            // TODO: dispatch into NMS to push rules towards kernel module
1260            // TODO: notify UID when it has requested targeted updates
1261        }
1262
1263        @Override
1264        public void onMeteredIfacesChanged(String[] meteredIfaces) {
1265            // only someone like NPMS should only be calling us
1266            mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1267
1268            if (LOGD_RULES) {
1269                log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
1270            }
1271
1272            synchronized (mRulesLock) {
1273                mMeteredIfaces.clear();
1274                for (String iface : meteredIfaces) {
1275                    mMeteredIfaces.add(iface);
1276                }
1277            }
1278        }
1279    };
1280
1281    /**
1282     * @see ConnectivityManager#setMobileDataEnabled(boolean)
1283     */
1284    public void setMobileDataEnabled(boolean enabled) {
1285        enforceChangePermission();
1286        if (DBG) log("setMobileDataEnabled(" + enabled + ")");
1287
1288        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
1289                (enabled ? ENABLED : DISABLED), 0));
1290    }
1291
1292    private void handleSetMobileData(boolean enabled) {
1293        if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
1294            if (VDBG) {
1295                log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
1296            }
1297            mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled);
1298        }
1299    }
1300
1301    @Override
1302    public void setPolicyDataEnable(int networkType, boolean enabled) {
1303        // only someone like NPMS should only be calling us
1304        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1305
1306        mHandler.sendMessage(mHandler.obtainMessage(
1307                EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED)));
1308    }
1309
1310    private void handleSetPolicyDataEnable(int networkType, boolean enabled) {
1311        if (isNetworkTypeValid(networkType)) {
1312            final NetworkStateTracker tracker = mNetTrackers[networkType];
1313            if (tracker != null) {
1314                tracker.setPolicyDataEnable(enabled);
1315            }
1316        }
1317    }
1318
1319    private void enforceAccessPermission() {
1320        mContext.enforceCallingOrSelfPermission(
1321                android.Manifest.permission.ACCESS_NETWORK_STATE,
1322                "ConnectivityService");
1323    }
1324
1325    private void enforceChangePermission() {
1326        mContext.enforceCallingOrSelfPermission(
1327                android.Manifest.permission.CHANGE_NETWORK_STATE,
1328                "ConnectivityService");
1329    }
1330
1331    // TODO Make this a special check when it goes public
1332    private void enforceTetherChangePermission() {
1333        mContext.enforceCallingOrSelfPermission(
1334                android.Manifest.permission.CHANGE_NETWORK_STATE,
1335                "ConnectivityService");
1336    }
1337
1338    private void enforceTetherAccessPermission() {
1339        mContext.enforceCallingOrSelfPermission(
1340                android.Manifest.permission.ACCESS_NETWORK_STATE,
1341                "ConnectivityService");
1342    }
1343
1344    private void enforceConnectivityInternalPermission() {
1345        mContext.enforceCallingOrSelfPermission(
1346                android.Manifest.permission.CONNECTIVITY_INTERNAL,
1347                "ConnectivityService");
1348    }
1349
1350    /**
1351     * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1352     * network, we ignore it. If it is for the active network, we send out a
1353     * broadcast. But first, we check whether it might be possible to connect
1354     * to a different network.
1355     * @param info the {@code NetworkInfo} for the network
1356     */
1357    private void handleDisconnect(NetworkInfo info) {
1358
1359        int prevNetType = info.getType();
1360
1361        mNetTrackers[prevNetType].setTeardownRequested(false);
1362        /*
1363         * If the disconnected network is not the active one, then don't report
1364         * this as a loss of connectivity. What probably happened is that we're
1365         * getting the disconnect for a network that we explicitly disabled
1366         * in accordance with network preference policies.
1367         */
1368        if (!mNetConfigs[prevNetType].isDefault()) {
1369            List pids = mNetRequestersPids[prevNetType];
1370            for (int i = 0; i<pids.size(); i++) {
1371                Integer pid = (Integer)pids.get(i);
1372                // will remove them because the net's no longer connected
1373                // need to do this now as only now do we know the pids and
1374                // can properly null things that are no longer referenced.
1375                reassessPidDns(pid.intValue(), false);
1376            }
1377        }
1378
1379        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1380        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1381        if (info.isFailover()) {
1382            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1383            info.setFailover(false);
1384        }
1385        if (info.getReason() != null) {
1386            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1387        }
1388        if (info.getExtraInfo() != null) {
1389            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1390                    info.getExtraInfo());
1391        }
1392
1393        if (mNetConfigs[prevNetType].isDefault()) {
1394            tryFailover(prevNetType);
1395            if (mActiveDefaultNetwork != -1) {
1396                NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
1397                intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1398            } else {
1399                mDefaultInetConditionPublished = 0; // we're not connected anymore
1400                intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1401            }
1402        }
1403        intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
1404
1405        // Reset interface if no other connections are using the same interface
1406        boolean doReset = true;
1407        LinkProperties linkProperties = mNetTrackers[prevNetType].getLinkProperties();
1408        if (linkProperties != null) {
1409            String oldIface = linkProperties.getInterfaceName();
1410            if (TextUtils.isEmpty(oldIface) == false) {
1411                for (NetworkStateTracker networkStateTracker : mNetTrackers) {
1412                    if (networkStateTracker == null) continue;
1413                    NetworkInfo networkInfo = networkStateTracker.getNetworkInfo();
1414                    if (networkInfo.isConnected() && networkInfo.getType() != prevNetType) {
1415                        LinkProperties l = networkStateTracker.getLinkProperties();
1416                        if (l == null) continue;
1417                        if (oldIface.equals(l.getInterfaceName())) {
1418                            doReset = false;
1419                            break;
1420                        }
1421                    }
1422                }
1423            }
1424        }
1425
1426        // do this before we broadcast the change
1427        handleConnectivityChange(prevNetType, doReset);
1428
1429        final Intent immediateIntent = new Intent(intent);
1430        immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
1431        sendStickyBroadcast(immediateIntent);
1432        sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
1433        /*
1434         * If the failover network is already connected, then immediately send
1435         * out a followup broadcast indicating successful failover
1436         */
1437        if (mActiveDefaultNetwork != -1) {
1438            sendConnectedBroadcastDelayed(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(),
1439                    getConnectivityChangeDelay());
1440        }
1441    }
1442
1443    private void tryFailover(int prevNetType) {
1444        /*
1445         * If this is a default network, check if other defaults are available.
1446         * Try to reconnect on all available and let them hash it out when
1447         * more than one connects.
1448         */
1449        if (mNetConfigs[prevNetType].isDefault()) {
1450            if (mActiveDefaultNetwork == prevNetType) {
1451                mActiveDefaultNetwork = -1;
1452            }
1453
1454            // don't signal a reconnect for anything lower or equal priority than our
1455            // current connected default
1456            // TODO - don't filter by priority now - nice optimization but risky
1457//            int currentPriority = -1;
1458//            if (mActiveDefaultNetwork != -1) {
1459//                currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
1460//            }
1461            for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
1462                if (checkType == prevNetType) continue;
1463                if (mNetConfigs[checkType] == null) continue;
1464                if (!mNetConfigs[checkType].isDefault()) continue;
1465
1466// Enabling the isAvailable() optimization caused mobile to not get
1467// selected if it was in the middle of error handling. Specifically
1468// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1469// would not be available and we wouldn't get connected to anything.
1470// So removing the isAvailable() optimization below for now. TODO: This
1471// optimization should work and we need to investigate why it doesn't work.
1472// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1473// complete before it is really complete.
1474//                if (!mNetTrackers[checkType].isAvailable()) continue;
1475
1476//                if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
1477
1478                NetworkStateTracker checkTracker = mNetTrackers[checkType];
1479                NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1480                if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1481                    checkInfo.setFailover(true);
1482                    checkTracker.reconnect();
1483                }
1484                if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
1485            }
1486        }
1487    }
1488
1489    private void sendConnectedBroadcast(NetworkInfo info) {
1490        sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
1491        sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
1492    }
1493
1494    private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
1495        sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
1496        sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs);
1497    }
1498
1499    private void sendInetConditionBroadcast(NetworkInfo info) {
1500        sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1501    }
1502
1503    private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
1504        Intent intent = new Intent(bcastType);
1505        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1506        if (info.isFailover()) {
1507            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1508            info.setFailover(false);
1509        }
1510        if (info.getReason() != null) {
1511            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1512        }
1513        if (info.getExtraInfo() != null) {
1514            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1515                    info.getExtraInfo());
1516        }
1517        intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
1518        return intent;
1519    }
1520
1521    private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1522        sendStickyBroadcast(makeGeneralIntent(info, bcastType));
1523    }
1524
1525    private void sendGeneralBroadcastDelayed(NetworkInfo info, String bcastType, int delayMs) {
1526        sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
1527    }
1528
1529    /**
1530     * Called when an attempt to fail over to another network has failed.
1531     * @param info the {@link NetworkInfo} for the failed network
1532     */
1533    private void handleConnectionFailure(NetworkInfo info) {
1534        mNetTrackers[info.getType()].setTeardownRequested(false);
1535
1536        String reason = info.getReason();
1537        String extraInfo = info.getExtraInfo();
1538
1539        String reasonText;
1540        if (reason == null) {
1541            reasonText = ".";
1542        } else {
1543            reasonText = " (" + reason + ").";
1544        }
1545        loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
1546
1547        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1548        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1549        if (getActiveNetworkInfo() == null) {
1550            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1551        }
1552        if (reason != null) {
1553            intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1554        }
1555        if (extraInfo != null) {
1556            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1557        }
1558        if (info.isFailover()) {
1559            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1560            info.setFailover(false);
1561        }
1562
1563        if (mNetConfigs[info.getType()].isDefault()) {
1564            tryFailover(info.getType());
1565            if (mActiveDefaultNetwork != -1) {
1566                NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
1567                intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1568            } else {
1569                mDefaultInetConditionPublished = 0;
1570                intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1571            }
1572        }
1573
1574        intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
1575
1576        final Intent immediateIntent = new Intent(intent);
1577        immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
1578        sendStickyBroadcast(immediateIntent);
1579        sendStickyBroadcast(intent);
1580        /*
1581         * If the failover network is already connected, then immediately send
1582         * out a followup broadcast indicating successful failover
1583         */
1584        if (mActiveDefaultNetwork != -1) {
1585            sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
1586        }
1587    }
1588
1589    private void sendStickyBroadcast(Intent intent) {
1590        synchronized(this) {
1591            if (!mSystemReady) {
1592                mInitialBroadcast = new Intent(intent);
1593            }
1594            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1595            if (DBG) {
1596                log("sendStickyBroadcast: action=" + intent.getAction());
1597            }
1598
1599            mContext.sendStickyBroadcast(intent);
1600        }
1601    }
1602
1603    private void sendStickyBroadcastDelayed(Intent intent, int delayMs) {
1604        if (delayMs <= 0) {
1605            sendStickyBroadcast(intent);
1606        } else {
1607            if (DBG) {
1608                log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action="
1609                        + intent.getAction());
1610            }
1611            mHandler.sendMessageDelayed(mHandler.obtainMessage(
1612                    EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
1613        }
1614    }
1615
1616    void systemReady() {
1617        synchronized(this) {
1618            mSystemReady = true;
1619            if (mInitialBroadcast != null) {
1620                mContext.sendStickyBroadcast(mInitialBroadcast);
1621                mInitialBroadcast = null;
1622            }
1623        }
1624        // load the global proxy at startup
1625        mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
1626    }
1627
1628    private void handleConnect(NetworkInfo info) {
1629        int type = info.getType();
1630
1631        // snapshot isFailover, because sendConnectedBroadcast() resets it
1632        boolean isFailover = info.isFailover();
1633        NetworkStateTracker thisNet = mNetTrackers[type];
1634
1635        // if this is a default net and other default is running
1636        // kill the one not preferred
1637        if (mNetConfigs[type].isDefault()) {
1638            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1639                if ((type != mNetworkPreference &&
1640                        mNetConfigs[mActiveDefaultNetwork].priority >
1641                        mNetConfigs[type].priority) ||
1642                        mNetworkPreference == mActiveDefaultNetwork) {
1643                        // don't accept this one
1644                        if (VDBG) {
1645                            log("Not broadcasting CONNECT_ACTION " +
1646                                "to torn down network " + info.getTypeName());
1647                        }
1648                        teardown(thisNet);
1649                        return;
1650                } else {
1651                    // tear down the other
1652                    NetworkStateTracker otherNet =
1653                            mNetTrackers[mActiveDefaultNetwork];
1654                    if (DBG) {
1655                        log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
1656                            " teardown");
1657                    }
1658                    if (!teardown(otherNet)) {
1659                        loge("Network declined teardown request");
1660                        teardown(thisNet);
1661                        return;
1662                    }
1663                }
1664            }
1665            synchronized (ConnectivityService.this) {
1666                // have a new default network, release the transition wakelock in a second
1667                // if it's held.  The second pause is to allow apps to reconnect over the
1668                // new network
1669                if (mNetTransitionWakeLock.isHeld()) {
1670                    mHandler.sendMessageDelayed(mHandler.obtainMessage(
1671                            EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
1672                            mNetTransitionWakeLockSerialNumber, 0),
1673                            1000);
1674                }
1675            }
1676            mActiveDefaultNetwork = type;
1677            // this will cause us to come up initially as unconnected and switching
1678            // to connected after our normal pause unless somebody reports us as reall
1679            // disconnected
1680            mDefaultInetConditionPublished = 0;
1681            mDefaultConnectionSequence++;
1682            mInetConditionChangeInFlight = false;
1683            // Don't do this - if we never sign in stay, grey
1684            //reportNetworkCondition(mActiveDefaultNetwork, 100);
1685        }
1686        thisNet.setTeardownRequested(false);
1687        updateNetworkSettings(thisNet);
1688        handleConnectivityChange(type, false);
1689        sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
1690    }
1691
1692    /**
1693     * After a change in the connectivity state of a network. We're mainly
1694     * concerned with making sure that the list of DNS servers is set up
1695     * according to which networks are connected, and ensuring that the
1696     * right routing table entries exist.
1697     */
1698    private void handleConnectivityChange(int netType, boolean doReset) {
1699        int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
1700
1701        /*
1702         * If a non-default network is enabled, add the host routes that
1703         * will allow it's DNS servers to be accessed.
1704         */
1705        handleDnsConfigurationChange(netType);
1706
1707        LinkProperties curLp = mCurrentLinkProperties[netType];
1708        LinkProperties newLp = null;
1709
1710        if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
1711            newLp = mNetTrackers[netType].getLinkProperties();
1712            if (VDBG) {
1713                log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
1714                        " doReset=" + doReset + " resetMask=" + resetMask +
1715                        "\n   curLp=" + curLp +
1716                        "\n   newLp=" + newLp);
1717            }
1718
1719            if (curLp != null) {
1720                if (curLp.isIdenticalInterfaceName(newLp)) {
1721                    CompareResult<LinkAddress> car = curLp.compareAddresses(newLp);
1722                    if ((car.removed.size() != 0) || (car.added.size() != 0)) {
1723                        for (LinkAddress linkAddr : car.removed) {
1724                            if (linkAddr.getAddress() instanceof Inet4Address) {
1725                                resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES;
1726                            }
1727                            if (linkAddr.getAddress() instanceof Inet6Address) {
1728                                resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES;
1729                            }
1730                        }
1731                        if (DBG) {
1732                            log("handleConnectivityChange: addresses changed" +
1733                                    " linkProperty[" + netType + "]:" + " resetMask=" + resetMask +
1734                                    "\n   car=" + car);
1735                        }
1736                    } else {
1737                        if (DBG) {
1738                            log("handleConnectivityChange: address are the same reset per doReset" +
1739                                   " linkProperty[" + netType + "]:" +
1740                                   " resetMask=" + resetMask);
1741                        }
1742                    }
1743                } else {
1744                    resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
1745                    if (DBG) {
1746                        log("handleConnectivityChange: interface not not equivalent reset both" +
1747                                " linkProperty[" + netType + "]:" +
1748                                " resetMask=" + resetMask);
1749                    }
1750                }
1751            }
1752            if (mNetConfigs[netType].isDefault()) {
1753                handleApplyDefaultProxy(netType);
1754            }
1755        } else {
1756            if (VDBG) {
1757                log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
1758                        " doReset=" + doReset + " resetMask=" + resetMask +
1759                        "\n  curLp=" + curLp +
1760                        "\n  newLp= null");
1761            }
1762        }
1763        mCurrentLinkProperties[netType] = newLp;
1764        boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
1765
1766        if (resetMask != 0 || resetDns) {
1767            LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
1768            if (linkProperties != null) {
1769                String iface = linkProperties.getInterfaceName();
1770                if (TextUtils.isEmpty(iface) == false) {
1771                    if (resetMask != 0) {
1772                        if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
1773                        NetworkUtils.resetConnections(iface, resetMask);
1774
1775                        // Tell VPN the interface is down. It is a temporary
1776                        // but effective fix to make VPN aware of the change.
1777                        if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
1778                            mVpn.interfaceStatusChanged(iface, false);
1779                        }
1780                    }
1781                    if (resetDns) {
1782                        if (DBG) log("resetting DNS cache for " + iface);
1783                        try {
1784                            mNetd.flushInterfaceDnsCache(iface);
1785                        } catch (Exception e) {
1786                            // never crash - catch them all
1787                            loge("Exception resetting dns cache: " + e);
1788                        }
1789                    }
1790                }
1791            }
1792        }
1793
1794        // TODO: Temporary notifying upstread change to Tethering.
1795        //       @see bug/4455071
1796        /** Notify TetheringService if interface name has been changed. */
1797        if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
1798                             Phone.REASON_LINK_PROPERTIES_CHANGED)) {
1799            if (isTetheringSupported()) {
1800                mTethering.handleTetherIfaceChange();
1801            }
1802        }
1803    }
1804
1805    /**
1806     * Add and remove routes using the old properties (null if not previously connected),
1807     * new properties (null if becoming disconnected).  May even be double null, which
1808     * is a noop.
1809     * Uses isLinkDefault to determine if default routes should be set or conversely if
1810     * host routes should be set to the dns servers
1811     * returns a boolean indicating the routes changed
1812     */
1813    private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
1814            boolean isLinkDefault) {
1815        Collection<RouteInfo> routesToAdd = null;
1816        CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>();
1817        CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
1818        if (curLp != null) {
1819            // check for the delta between the current set and the new
1820            routeDiff = curLp.compareRoutes(newLp);
1821            dnsDiff = curLp.compareDnses(newLp);
1822        } else if (newLp != null) {
1823            routeDiff.added = newLp.getRoutes();
1824            dnsDiff.added = newLp.getDnses();
1825        }
1826
1827        boolean routesChanged = (routeDiff.removed.size() != 0 || routeDiff.added.size() != 0);
1828
1829        for (RouteInfo r : routeDiff.removed) {
1830            if (isLinkDefault || ! r.isDefaultRoute()) {
1831                removeRoute(curLp, r);
1832            }
1833        }
1834
1835        for (RouteInfo r :  routeDiff.added) {
1836            if (isLinkDefault || ! r.isDefaultRoute()) {
1837                addRoute(newLp, r);
1838            } else {
1839                // many radios add a default route even when we don't want one.
1840                // remove the default route unless somebody else has asked for it
1841                String ifaceName = newLp.getInterfaceName();
1842                if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) {
1843                    if (DBG) log("Removing " + r + " for interface " + ifaceName);
1844                    try {
1845                        mNetd.removeRoute(ifaceName, r);
1846                    } catch (Exception e) {
1847                        // never crash - catch them all
1848                        loge("Exception trying to remove a route: " + e);
1849                    }
1850                }
1851            }
1852        }
1853
1854        if (!isLinkDefault) {
1855            // handle DNS routes
1856            if (routesChanged) {
1857                // routes changed - remove all old dns entries and add new
1858                if (curLp != null) {
1859                    for (InetAddress oldDns : curLp.getDnses()) {
1860                        removeRouteToAddress(curLp, oldDns);
1861                    }
1862                }
1863                if (newLp != null) {
1864                    for (InetAddress newDns : newLp.getDnses()) {
1865                        addRouteToAddress(newLp, newDns);
1866                    }
1867                }
1868            } else {
1869                // no change in routes, check for change in dns themselves
1870                for (InetAddress oldDns : dnsDiff.removed) {
1871                    removeRouteToAddress(curLp, oldDns);
1872                }
1873                for (InetAddress newDns : dnsDiff.added) {
1874                    addRouteToAddress(newLp, newDns);
1875                }
1876            }
1877        }
1878        return routesChanged;
1879    }
1880
1881
1882   /**
1883     * Reads the network specific TCP buffer sizes from SystemProperties
1884     * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
1885     * wide use
1886     */
1887   public void updateNetworkSettings(NetworkStateTracker nt) {
1888        String key = nt.getTcpBufferSizesPropName();
1889        String bufferSizes = SystemProperties.get(key);
1890
1891        if (bufferSizes.length() == 0) {
1892            if (VDBG) log(key + " not found in system properties. Using defaults");
1893
1894            // Setting to default values so we won't be stuck to previous values
1895            key = "net.tcp.buffersize.default";
1896            bufferSizes = SystemProperties.get(key);
1897        }
1898
1899        // Set values in kernel
1900        if (bufferSizes.length() != 0) {
1901            if (VDBG) {
1902                log("Setting TCP values: [" + bufferSizes
1903                        + "] which comes from [" + key + "]");
1904            }
1905            setBufferSize(bufferSizes);
1906        }
1907    }
1908
1909   /**
1910     * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
1911     * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
1912     *
1913     * @param bufferSizes in the format of "readMin, readInitial, readMax,
1914     *        writeMin, writeInitial, writeMax"
1915     */
1916    private void setBufferSize(String bufferSizes) {
1917        try {
1918            String[] values = bufferSizes.split(",");
1919
1920            if (values.length == 6) {
1921              final String prefix = "/sys/kernel/ipv4/tcp_";
1922                FileUtils.stringToFile(prefix + "rmem_min", values[0]);
1923                FileUtils.stringToFile(prefix + "rmem_def", values[1]);
1924                FileUtils.stringToFile(prefix + "rmem_max", values[2]);
1925                FileUtils.stringToFile(prefix + "wmem_min", values[3]);
1926                FileUtils.stringToFile(prefix + "wmem_def", values[4]);
1927                FileUtils.stringToFile(prefix + "wmem_max", values[5]);
1928            } else {
1929                loge("Invalid buffersize string: " + bufferSizes);
1930            }
1931        } catch (IOException e) {
1932            loge("Can't set tcp buffer sizes:" + e);
1933        }
1934    }
1935
1936    /**
1937     * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1938     * on the highest priority active net which this process requested.
1939     * If there aren't any, clear it out
1940     */
1941    private void reassessPidDns(int myPid, boolean doBump)
1942    {
1943        if (VDBG) log("reassessPidDns for pid " + myPid);
1944        for(int i : mPriorityList) {
1945            if (mNetConfigs[i].isDefault()) {
1946                continue;
1947            }
1948            NetworkStateTracker nt = mNetTrackers[i];
1949            if (nt.getNetworkInfo().isConnected() &&
1950                    !nt.isTeardownRequested()) {
1951                LinkProperties p = nt.getLinkProperties();
1952                if (p == null) continue;
1953                List pids = mNetRequestersPids[i];
1954                for (int j=0; j<pids.size(); j++) {
1955                    Integer pid = (Integer)pids.get(j);
1956                    if (pid.intValue() == myPid) {
1957                        Collection<InetAddress> dnses = p.getDnses();
1958                        writePidDns(dnses, myPid);
1959                        if (doBump) {
1960                            bumpDns();
1961                        }
1962                        return;
1963                    }
1964                }
1965           }
1966        }
1967        // nothing found - delete
1968        for (int i = 1; ; i++) {
1969            String prop = "net.dns" + i + "." + myPid;
1970            if (SystemProperties.get(prop).length() == 0) {
1971                if (doBump) {
1972                    bumpDns();
1973                }
1974                return;
1975            }
1976            SystemProperties.set(prop, "");
1977        }
1978    }
1979
1980    // return true if results in a change
1981    private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
1982        int j = 1;
1983        boolean changed = false;
1984        for (InetAddress dns : dnses) {
1985            String dnsString = dns.getHostAddress();
1986            if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
1987                changed = true;
1988                SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
1989            }
1990        }
1991        return changed;
1992    }
1993
1994    private void bumpDns() {
1995        /*
1996         * Bump the property that tells the name resolver library to reread
1997         * the DNS server list from the properties.
1998         */
1999        String propVal = SystemProperties.get("net.dnschange");
2000        int n = 0;
2001        if (propVal.length() != 0) {
2002            try {
2003                n = Integer.parseInt(propVal);
2004            } catch (NumberFormatException e) {}
2005        }
2006        SystemProperties.set("net.dnschange", "" + (n+1));
2007        /*
2008         * Tell the VMs to toss their DNS caches
2009         */
2010        Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
2011        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
2012        /*
2013         * Connectivity events can happen before boot has completed ...
2014         */
2015        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2016        mContext.sendBroadcast(intent);
2017    }
2018
2019    // Caller must grab mDnsLock.
2020    private boolean updateDns(String network, String iface,
2021            Collection<InetAddress> dnses, String domains) {
2022        boolean changed = false;
2023        int last = 0;
2024        if (dnses.size() == 0 && mDefaultDns != null) {
2025            ++last;
2026            String value = mDefaultDns.getHostAddress();
2027            if (!value.equals(SystemProperties.get("net.dns1"))) {
2028                if (DBG) {
2029                    loge("no dns provided for " + network + " - using " + value);
2030                }
2031                changed = true;
2032                SystemProperties.set("net.dns1", value);
2033            }
2034        } else {
2035            for (InetAddress dns : dnses) {
2036                ++last;
2037                String key = "net.dns" + last;
2038                String value = dns.getHostAddress();
2039                if (!changed && value.equals(SystemProperties.get(key))) {
2040                    continue;
2041                }
2042                if (VDBG) {
2043                    log("adding dns " + value + " for " + network);
2044                }
2045                changed = true;
2046                SystemProperties.set(key, value);
2047            }
2048        }
2049        for (int i = last + 1; i <= mNumDnsEntries; ++i) {
2050            String key = "net.dns" + i;
2051            if (VDBG) log("erasing " + key);
2052            changed = true;
2053            SystemProperties.set(key, "");
2054        }
2055        mNumDnsEntries = last;
2056
2057        if (changed) {
2058            try {
2059                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
2060                mNetd.setDefaultInterfaceForDns(iface);
2061            } catch (Exception e) {
2062                loge("exception setting default dns interface: " + e);
2063            }
2064        }
2065        if (!domains.equals(SystemProperties.get("net.dns.search"))) {
2066            SystemProperties.set("net.dns.search", domains);
2067            changed = true;
2068        }
2069        return changed;
2070    }
2071
2072    private void handleDnsConfigurationChange(int netType) {
2073        // add default net's dns entries
2074        NetworkStateTracker nt = mNetTrackers[netType];
2075        if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
2076            LinkProperties p = nt.getLinkProperties();
2077            if (p == null) return;
2078            Collection<InetAddress> dnses = p.getDnses();
2079            boolean changed = false;
2080            if (mNetConfigs[netType].isDefault()) {
2081                String network = nt.getNetworkInfo().getTypeName();
2082                synchronized (mDnsLock) {
2083                    if (!mDnsOverridden) {
2084                        changed = updateDns(network, p.getInterfaceName(), dnses, "");
2085                    }
2086                }
2087            } else {
2088                try {
2089                    mNetd.setDnsServersForInterface(p.getInterfaceName(),
2090                            NetworkUtils.makeStrings(dnses));
2091                } catch (Exception e) {
2092                    loge("exception setting dns servers: " + e);
2093                }
2094                // set per-pid dns for attached secondary nets
2095                List pids = mNetRequestersPids[netType];
2096                for (int y=0; y< pids.size(); y++) {
2097                    Integer pid = (Integer)pids.get(y);
2098                    changed = writePidDns(dnses, pid.intValue());
2099                }
2100            }
2101            if (changed) bumpDns();
2102        }
2103    }
2104
2105    private int getRestoreDefaultNetworkDelay(int networkType) {
2106        String restoreDefaultNetworkDelayStr = SystemProperties.get(
2107                NETWORK_RESTORE_DELAY_PROP_NAME);
2108        if(restoreDefaultNetworkDelayStr != null &&
2109                restoreDefaultNetworkDelayStr.length() != 0) {
2110            try {
2111                return Integer.valueOf(restoreDefaultNetworkDelayStr);
2112            } catch (NumberFormatException e) {
2113            }
2114        }
2115        // if the system property isn't set, use the value for the apn type
2116        int ret = RESTORE_DEFAULT_NETWORK_DELAY;
2117
2118        if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
2119                (mNetConfigs[networkType] != null)) {
2120            ret = mNetConfigs[networkType].restoreTime;
2121        }
2122        return ret;
2123    }
2124
2125    @Override
2126    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2127        if (mContext.checkCallingOrSelfPermission(
2128                android.Manifest.permission.DUMP)
2129                != PackageManager.PERMISSION_GRANTED) {
2130            pw.println("Permission Denial: can't dump ConnectivityService " +
2131                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
2132                    Binder.getCallingUid());
2133            return;
2134        }
2135        pw.println();
2136        for (NetworkStateTracker nst : mNetTrackers) {
2137            if (nst != null) {
2138                if (nst.getNetworkInfo().isConnected()) {
2139                    pw.println("Active network: " + nst.getNetworkInfo().
2140                            getTypeName());
2141                }
2142                pw.println(nst.getNetworkInfo());
2143                pw.println(nst);
2144                pw.println();
2145            }
2146        }
2147
2148        pw.println("Network Requester Pids:");
2149        for (int net : mPriorityList) {
2150            String pidString = net + ": ";
2151            for (Object pid : mNetRequestersPids[net]) {
2152                pidString = pidString + pid.toString() + ", ";
2153            }
2154            pw.println(pidString);
2155        }
2156        pw.println();
2157
2158        pw.println("FeatureUsers:");
2159        for (Object requester : mFeatureUsers) {
2160            pw.println(requester.toString());
2161        }
2162        pw.println();
2163
2164        synchronized (this) {
2165            pw.println("NetworkTranstionWakeLock is currently " +
2166                    (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
2167            pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
2168        }
2169        pw.println();
2170
2171        mTethering.dump(fd, pw, args);
2172
2173        if (mInetLog != null) {
2174            pw.println();
2175            pw.println("Inet condition reports:");
2176            for(int i = 0; i < mInetLog.size(); i++) {
2177                pw.println(mInetLog.get(i));
2178            }
2179        }
2180    }
2181
2182    // must be stateless - things change under us.
2183    private class MyHandler extends Handler {
2184        public MyHandler(Looper looper) {
2185            super(looper);
2186        }
2187
2188        @Override
2189        public void handleMessage(Message msg) {
2190            NetworkInfo info;
2191            switch (msg.what) {
2192                case NetworkStateTracker.EVENT_STATE_CHANGED:
2193                    info = (NetworkInfo) msg.obj;
2194                    int type = info.getType();
2195                    NetworkInfo.State state = info.getState();
2196
2197                    if (DBG) log("ConnectivityChange for " +
2198                            info.getTypeName() + ": " +
2199                            state + "/" + info.getDetailedState());
2200
2201                    // Connectivity state changed:
2202                    // [31-13] Reserved for future use
2203                    // [12-9] Network subtype (for mobile network, as defined
2204                    //         by TelephonyManager)
2205                    // [8-3] Detailed state ordinal (as defined by
2206                    //         NetworkInfo.DetailedState)
2207                    // [2-0] Network type (as defined by ConnectivityManager)
2208                    int eventLogParam = (info.getType() & 0x7) |
2209                            ((info.getDetailedState().ordinal() & 0x3f) << 3) |
2210                            (info.getSubtype() << 9);
2211                    EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
2212                            eventLogParam);
2213
2214                    if (info.getDetailedState() ==
2215                            NetworkInfo.DetailedState.FAILED) {
2216                        handleConnectionFailure(info);
2217                    } else if (state == NetworkInfo.State.DISCONNECTED) {
2218                        handleDisconnect(info);
2219                    } else if (state == NetworkInfo.State.SUSPENDED) {
2220                        // TODO: need to think this over.
2221                        // the logic here is, handle SUSPENDED the same as
2222                        // DISCONNECTED. The only difference being we are
2223                        // broadcasting an intent with NetworkInfo that's
2224                        // suspended. This allows the applications an
2225                        // opportunity to handle DISCONNECTED and SUSPENDED
2226                        // differently, or not.
2227                        handleDisconnect(info);
2228                    } else if (state == NetworkInfo.State.CONNECTED) {
2229                        handleConnect(info);
2230                    }
2231                    break;
2232                case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
2233                    info = (NetworkInfo) msg.obj;
2234                    // TODO: Temporary allowing network configuration
2235                    //       change not resetting sockets.
2236                    //       @see bug/4455071
2237                    handleConnectivityChange(info.getType(), false);
2238                    break;
2239                case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
2240                    String causedBy = null;
2241                    synchronized (ConnectivityService.this) {
2242                        if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
2243                                mNetTransitionWakeLock.isHeld()) {
2244                            mNetTransitionWakeLock.release();
2245                            causedBy = mNetTransitionWakeLockCausedBy;
2246                        }
2247                    }
2248                    if (causedBy != null) {
2249                        log("NetTransition Wakelock for " + causedBy + " released by timeout");
2250                    }
2251                    break;
2252                case EVENT_RESTORE_DEFAULT_NETWORK:
2253                    FeatureUser u = (FeatureUser)msg.obj;
2254                    u.expire();
2255                    break;
2256                case EVENT_INET_CONDITION_CHANGE:
2257                {
2258                    int netType = msg.arg1;
2259                    int condition = msg.arg2;
2260                    handleInetConditionChange(netType, condition);
2261                    break;
2262                }
2263                case EVENT_INET_CONDITION_HOLD_END:
2264                {
2265                    int netType = msg.arg1;
2266                    int sequence = msg.arg2;
2267                    handleInetConditionHoldEnd(netType, sequence);
2268                    break;
2269                }
2270                case EVENT_SET_NETWORK_PREFERENCE:
2271                {
2272                    int preference = msg.arg1;
2273                    handleSetNetworkPreference(preference);
2274                    break;
2275                }
2276                case EVENT_SET_MOBILE_DATA:
2277                {
2278                    boolean enabled = (msg.arg1 == ENABLED);
2279                    handleSetMobileData(enabled);
2280                    break;
2281                }
2282                case EVENT_APPLY_GLOBAL_HTTP_PROXY:
2283                {
2284                    handleDeprecatedGlobalHttpProxy();
2285                    break;
2286                }
2287                case EVENT_SET_DEPENDENCY_MET:
2288                {
2289                    boolean met = (msg.arg1 == ENABLED);
2290                    handleSetDependencyMet(msg.arg2, met);
2291                    break;
2292                }
2293                case EVENT_RESTORE_DNS:
2294                {
2295                    if (mActiveDefaultNetwork != -1) {
2296                        handleDnsConfigurationChange(mActiveDefaultNetwork);
2297                    }
2298                    break;
2299                }
2300                case EVENT_SEND_STICKY_BROADCAST_INTENT:
2301                {
2302                    Intent intent = (Intent)msg.obj;
2303                    sendStickyBroadcast(intent);
2304                    break;
2305                }
2306                case EVENT_SET_POLICY_DATA_ENABLE: {
2307                    final int networkType = msg.arg1;
2308                    final boolean enabled = msg.arg2 == ENABLED;
2309                    handleSetPolicyDataEnable(networkType, enabled);
2310                }
2311            }
2312        }
2313    }
2314
2315    // javadoc from interface
2316    public int tether(String iface) {
2317        enforceTetherChangePermission();
2318
2319        if (isTetheringSupported()) {
2320            return mTethering.tether(iface);
2321        } else {
2322            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2323        }
2324    }
2325
2326    // javadoc from interface
2327    public int untether(String iface) {
2328        enforceTetherChangePermission();
2329
2330        if (isTetheringSupported()) {
2331            return mTethering.untether(iface);
2332        } else {
2333            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2334        }
2335    }
2336
2337    // javadoc from interface
2338    public int getLastTetherError(String iface) {
2339        enforceTetherAccessPermission();
2340
2341        if (isTetheringSupported()) {
2342            return mTethering.getLastTetherError(iface);
2343        } else {
2344            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2345        }
2346    }
2347
2348    // TODO - proper iface API for selection by property, inspection, etc
2349    public String[] getTetherableUsbRegexs() {
2350        enforceTetherAccessPermission();
2351        if (isTetheringSupported()) {
2352            return mTethering.getTetherableUsbRegexs();
2353        } else {
2354            return new String[0];
2355        }
2356    }
2357
2358    public String[] getTetherableWifiRegexs() {
2359        enforceTetherAccessPermission();
2360        if (isTetheringSupported()) {
2361            return mTethering.getTetherableWifiRegexs();
2362        } else {
2363            return new String[0];
2364        }
2365    }
2366
2367    public String[] getTetherableBluetoothRegexs() {
2368        enforceTetherAccessPermission();
2369        if (isTetheringSupported()) {
2370            return mTethering.getTetherableBluetoothRegexs();
2371        } else {
2372            return new String[0];
2373        }
2374    }
2375
2376    public int setUsbTethering(boolean enable) {
2377        enforceTetherAccessPermission();
2378        if (isTetheringSupported()) {
2379            return mTethering.setUsbTethering(enable);
2380        } else {
2381            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2382        }
2383    }
2384
2385    // TODO - move iface listing, queries, etc to new module
2386    // javadoc from interface
2387    public String[] getTetherableIfaces() {
2388        enforceTetherAccessPermission();
2389        return mTethering.getTetherableIfaces();
2390    }
2391
2392    public String[] getTetheredIfaces() {
2393        enforceTetherAccessPermission();
2394        return mTethering.getTetheredIfaces();
2395    }
2396
2397    @Override
2398    public String[] getTetheredIfacePairs() {
2399        enforceTetherAccessPermission();
2400        return mTethering.getTetheredIfacePairs();
2401    }
2402
2403    public String[] getTetheringErroredIfaces() {
2404        enforceTetherAccessPermission();
2405        return mTethering.getErroredIfaces();
2406    }
2407
2408    // if ro.tether.denied = true we default to no tethering
2409    // gservices could set the secure setting to 1 though to enable it on a build where it
2410    // had previously been turned off.
2411    public boolean isTetheringSupported() {
2412        enforceTetherAccessPermission();
2413        int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
2414        boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
2415                Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
2416        return tetherEnabledInSettings && mTetheringConfigValid;
2417    }
2418
2419    // An API NetworkStateTrackers can call when they lose their network.
2420    // This will automatically be cleared after X seconds or a network becomes CONNECTED,
2421    // whichever happens first.  The timer is started by the first caller and not
2422    // restarted by subsequent callers.
2423    public void requestNetworkTransitionWakelock(String forWhom) {
2424        enforceConnectivityInternalPermission();
2425        synchronized (this) {
2426            if (mNetTransitionWakeLock.isHeld()) return;
2427            mNetTransitionWakeLockSerialNumber++;
2428            mNetTransitionWakeLock.acquire();
2429            mNetTransitionWakeLockCausedBy = forWhom;
2430        }
2431        mHandler.sendMessageDelayed(mHandler.obtainMessage(
2432                EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
2433                mNetTransitionWakeLockSerialNumber, 0),
2434                mNetTransitionWakeLockTimeout);
2435        return;
2436    }
2437
2438    // 100 percent is full good, 0 is full bad.
2439    public void reportInetCondition(int networkType, int percentage) {
2440        if (VDBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
2441        mContext.enforceCallingOrSelfPermission(
2442                android.Manifest.permission.STATUS_BAR,
2443                "ConnectivityService");
2444
2445        if (DBG) {
2446            int pid = getCallingPid();
2447            int uid = getCallingUid();
2448            String s = pid + "(" + uid + ") reports inet is " +
2449                (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
2450                "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
2451            mInetLog.add(s);
2452            while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
2453                mInetLog.remove(0);
2454            }
2455        }
2456        mHandler.sendMessage(mHandler.obtainMessage(
2457            EVENT_INET_CONDITION_CHANGE, networkType, percentage));
2458    }
2459
2460    private void handleInetConditionChange(int netType, int condition) {
2461        if (DBG) {
2462            log("Inet connectivity change, net=" +
2463                    netType + ", condition=" + condition +
2464                    ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
2465        }
2466        if (mActiveDefaultNetwork == -1) {
2467            if (DBG) log("no active default network - aborting");
2468            return;
2469        }
2470        if (mActiveDefaultNetwork != netType) {
2471            if (DBG) log("given net not default - aborting");
2472            return;
2473        }
2474        mDefaultInetCondition = condition;
2475        int delay;
2476        if (mInetConditionChangeInFlight == false) {
2477            if (VDBG) log("starting a change hold");
2478            // setup a new hold to debounce this
2479            if (mDefaultInetCondition > 50) {
2480                delay = Settings.Secure.getInt(mContext.getContentResolver(),
2481                        Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
2482            } else {
2483                delay = Settings.Secure.getInt(mContext.getContentResolver(),
2484                Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
2485            }
2486            mInetConditionChangeInFlight = true;
2487            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
2488                    mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
2489        } else {
2490            // we've set the new condition, when this hold ends that will get
2491            // picked up
2492            if (VDBG) log("currently in hold - not setting new end evt");
2493        }
2494    }
2495
2496    private void handleInetConditionHoldEnd(int netType, int sequence) {
2497        if (VDBG) {
2498            log("Inet hold end, net=" + netType +
2499                    ", condition =" + mDefaultInetCondition +
2500                    ", published condition =" + mDefaultInetConditionPublished);
2501        }
2502        mInetConditionChangeInFlight = false;
2503
2504        if (mActiveDefaultNetwork == -1) {
2505            if (DBG) log("no active default network - aborting");
2506            return;
2507        }
2508        if (mDefaultConnectionSequence != sequence) {
2509            if (DBG) log("event hold for obsolete network - aborting");
2510            return;
2511        }
2512        // TODO: Figure out why this optimization sometimes causes a
2513        //       change in mDefaultInetCondition to be missed and the
2514        //       UI to not be updated.
2515        //if (mDefaultInetConditionPublished == mDefaultInetCondition) {
2516        //    if (DBG) log("no change in condition - aborting");
2517        //    return;
2518        //}
2519        NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
2520        if (networkInfo.isConnected() == false) {
2521            if (DBG) log("default network not connected - aborting");
2522            return;
2523        }
2524        mDefaultInetConditionPublished = mDefaultInetCondition;
2525        sendInetConditionBroadcast(networkInfo);
2526        return;
2527    }
2528
2529    public synchronized ProxyProperties getProxy() {
2530        if (mGlobalProxy != null) return mGlobalProxy;
2531        if (mDefaultProxy != null) return mDefaultProxy;
2532        return null;
2533    }
2534
2535    public void setGlobalProxy(ProxyProperties proxyProperties) {
2536        enforceChangePermission();
2537        synchronized (mGlobalProxyLock) {
2538            if (proxyProperties == mGlobalProxy) return;
2539            if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2540            if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2541
2542            String host = "";
2543            int port = 0;
2544            String exclList = "";
2545            if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
2546                mGlobalProxy = new ProxyProperties(proxyProperties);
2547                host = mGlobalProxy.getHost();
2548                port = mGlobalProxy.getPort();
2549                exclList = mGlobalProxy.getExclusionList();
2550            } else {
2551                mGlobalProxy = null;
2552            }
2553            ContentResolver res = mContext.getContentResolver();
2554            Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
2555            Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
2556            Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
2557                    exclList);
2558        }
2559
2560        if (mGlobalProxy == null) {
2561            proxyProperties = mDefaultProxy;
2562        }
2563        sendProxyBroadcast(proxyProperties);
2564    }
2565
2566    private void loadGlobalProxy() {
2567        ContentResolver res = mContext.getContentResolver();
2568        String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
2569        int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
2570        String exclList = Settings.Secure.getString(res,
2571                Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2572        if (!TextUtils.isEmpty(host)) {
2573            ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
2574            synchronized (mGlobalProxyLock) {
2575                mGlobalProxy = proxyProperties;
2576            }
2577        }
2578    }
2579
2580    public ProxyProperties getGlobalProxy() {
2581        synchronized (mGlobalProxyLock) {
2582            return mGlobalProxy;
2583        }
2584    }
2585
2586    private void handleApplyDefaultProxy(int type) {
2587        // check if new default - push it out to all VM if so
2588        ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
2589        synchronized (this) {
2590            if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2591            if (mDefaultProxy == proxy) return;
2592            if (proxy != null && !TextUtils.isEmpty(proxy.getHost())) {
2593                mDefaultProxy = proxy;
2594            } else {
2595                mDefaultProxy = null;
2596            }
2597        }
2598        if (VDBG) log("changing default proxy to " + proxy);
2599        if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
2600        if (mGlobalProxy != null) return;
2601        sendProxyBroadcast(proxy);
2602    }
2603
2604    private void handleDeprecatedGlobalHttpProxy() {
2605        String proxy = Settings.Secure.getString(mContext.getContentResolver(),
2606                Settings.Secure.HTTP_PROXY);
2607        if (!TextUtils.isEmpty(proxy)) {
2608            String data[] = proxy.split(":");
2609            String proxyHost =  data[0];
2610            int proxyPort = 8080;
2611            if (data.length > 1) {
2612                try {
2613                    proxyPort = Integer.parseInt(data[1]);
2614                } catch (NumberFormatException e) {
2615                    return;
2616                }
2617            }
2618            ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
2619            setGlobalProxy(p);
2620        }
2621    }
2622
2623    private void sendProxyBroadcast(ProxyProperties proxy) {
2624        if (proxy == null) proxy = new ProxyProperties("", 0, "");
2625        if (DBG) log("sending Proxy Broadcast for " + proxy);
2626        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
2627        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2628            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2629        intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
2630        mContext.sendStickyBroadcast(intent);
2631    }
2632
2633    private static class SettingsObserver extends ContentObserver {
2634        private int mWhat;
2635        private Handler mHandler;
2636        SettingsObserver(Handler handler, int what) {
2637            super(handler);
2638            mHandler = handler;
2639            mWhat = what;
2640        }
2641
2642        void observe(Context context) {
2643            ContentResolver resolver = context.getContentResolver();
2644            resolver.registerContentObserver(Settings.Secure.getUriFor(
2645                    Settings.Secure.HTTP_PROXY), false, this);
2646        }
2647
2648        @Override
2649        public void onChange(boolean selfChange) {
2650            mHandler.obtainMessage(mWhat).sendToTarget();
2651        }
2652    }
2653
2654    private void log(String s) {
2655        Slog.d(TAG, s);
2656    }
2657
2658    private void loge(String s) {
2659        Slog.e(TAG, s);
2660    }
2661
2662    int convertFeatureToNetworkType(int networkType, String feature) {
2663        int usedNetworkType = networkType;
2664
2665        if(networkType == ConnectivityManager.TYPE_MOBILE) {
2666            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
2667                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
2668            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
2669                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
2670            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
2671                    TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
2672                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
2673            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
2674                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
2675            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
2676                usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA;
2677            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
2678                usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS;
2679            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
2680                usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS;
2681            } else {
2682                Slog.e(TAG, "Can't match any mobile netTracker!");
2683            }
2684        } else if (networkType == ConnectivityManager.TYPE_WIFI) {
2685            if (TextUtils.equals(feature, "p2p")) {
2686                usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P;
2687            } else {
2688                Slog.e(TAG, "Can't match any wifi netTracker!");
2689            }
2690        } else {
2691            Slog.e(TAG, "Unexpected network type");
2692        }
2693        return usedNetworkType;
2694    }
2695
2696    private static <T> T checkNotNull(T value, String message) {
2697        if (value == null) {
2698            throw new NullPointerException(message);
2699        }
2700        return value;
2701    }
2702
2703    /**
2704     * Protect a socket from VPN routing rules. This method is used by
2705     * VpnBuilder and not available in ConnectivityManager. Permissions
2706     * are checked in Vpn class.
2707     * @hide
2708     */
2709    @Override
2710    public boolean protectVpn(ParcelFileDescriptor socket) {
2711        try {
2712            int type = mActiveDefaultNetwork;
2713            if (ConnectivityManager.isNetworkTypeValid(type)) {
2714                mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName());
2715                return true;
2716            }
2717        } catch (Exception e) {
2718            // ignore
2719        } finally {
2720            try {
2721                socket.close();
2722            } catch (Exception e) {
2723                // ignore
2724            }
2725        }
2726        return false;
2727    }
2728
2729    /**
2730     * Prepare for a VPN application. This method is used by VpnDialogs
2731     * and not available in ConnectivityManager. Permissions are checked
2732     * in Vpn class.
2733     * @hide
2734     */
2735    @Override
2736    public boolean prepareVpn(String oldPackage, String newPackage) {
2737        return mVpn.prepare(oldPackage, newPackage);
2738    }
2739
2740    /**
2741     * Configure a TUN interface and return its file descriptor. Parameters
2742     * are encoded and opaque to this class. This method is used by VpnBuilder
2743     * and not available in ConnectivityManager. Permissions are checked in
2744     * Vpn class.
2745     * @hide
2746     */
2747    @Override
2748    public ParcelFileDescriptor establishVpn(VpnConfig config) {
2749        return mVpn.establish(config);
2750    }
2751
2752    /**
2753     * Start legacy VPN and return an intent to VpnDialogs. This method is
2754     * used by VpnSettings and not available in ConnectivityManager.
2755     * Permissions are checked in Vpn class.
2756     * @hide
2757     */
2758    @Override
2759    public void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
2760        mVpn.startLegacyVpn(config, racoon, mtpd);
2761    }
2762
2763    /**
2764     * Return the information of the ongoing legacy VPN. This method is used
2765     * by VpnSettings and not available in ConnectivityManager. Permissions
2766     * are checked in Vpn class.
2767     * @hide
2768     */
2769    @Override
2770    public LegacyVpnInfo getLegacyVpnInfo() {
2771        return mVpn.getLegacyVpnInfo();
2772    }
2773
2774    /**
2775     * Callback for VPN subsystem. Currently VPN is not adapted to the service
2776     * through NetworkStateTracker since it works differently. For example, it
2777     * needs to override DNS servers but never takes the default routes. It
2778     * relies on another data network, and it could keep existing connections
2779     * alive after reconnecting, switching between networks, or even resuming
2780     * from deep sleep. Calls from applications should be done synchronously
2781     * to avoid race conditions. As these are all hidden APIs, refactoring can
2782     * be done whenever a better abstraction is developed.
2783     */
2784    public class VpnCallback {
2785
2786        private VpnCallback() {
2787        }
2788
2789        public void override(List<String> dnsServers, List<String> searchDomains) {
2790            if (dnsServers == null) {
2791                restore();
2792                return;
2793            }
2794
2795            // Convert DNS servers into addresses.
2796            List<InetAddress> addresses = new ArrayList<InetAddress>();
2797            for (String address : dnsServers) {
2798                // Double check the addresses and remove invalid ones.
2799                try {
2800                    addresses.add(InetAddress.parseNumericAddress(address));
2801                } catch (Exception e) {
2802                    // ignore
2803                }
2804            }
2805            if (addresses.isEmpty()) {
2806                restore();
2807                return;
2808            }
2809
2810            // Concatenate search domains into a string.
2811            StringBuilder buffer = new StringBuilder();
2812            if (searchDomains != null) {
2813                for (String domain : searchDomains) {
2814                    buffer.append(domain).append(' ');
2815                }
2816            }
2817            String domains = buffer.toString().trim();
2818
2819            // Apply DNS changes.
2820            boolean changed = false;
2821            synchronized (mDnsLock) {
2822                changed = updateDns("VPN", "VPN", addresses, domains);
2823                mDnsOverridden = true;
2824            }
2825            if (changed) {
2826                bumpDns();
2827            }
2828
2829            // TODO: temporarily remove http proxy?
2830        }
2831
2832        public void restore() {
2833            synchronized (mDnsLock) {
2834                if (!mDnsOverridden) {
2835                    return;
2836                }
2837                mDnsOverridden = false;
2838            }
2839            mHandler.sendEmptyMessage(EVENT_RESTORE_DNS);
2840        }
2841    }
2842}
2843