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