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