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