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