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