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