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