merge in klp-release history after reset to klp-dev
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3874369..4cf38b6 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1426,9 +1426,9 @@
      * get the information about a specific network link
      * @hide
      */
-    public LinkInfo getLinkInfo(int networkType) {
+    public LinkQualityInfo getLinkQualityInfo(int networkType) {
         try {
-            LinkInfo li = mService.getLinkInfo(networkType);
+            LinkQualityInfo li = mService.getLinkQualityInfo(networkType);
             return li;
         } catch (RemoteException e) {
             return null;
@@ -1439,9 +1439,9 @@
      * get the information of currently active network link
      * @hide
      */
-    public LinkInfo getActiveLinkInfo() {
+    public LinkQualityInfo getActiveLinkQualityInfo() {
         try {
-            LinkInfo li = mService.getActiveLinkInfo();
+            LinkQualityInfo li = mService.getActiveLinkQualityInfo();
             return li;
         } catch (RemoteException e) {
             return null;
@@ -1452,9 +1452,9 @@
      * get the information of all network links
      * @hide
      */
-    public LinkInfo[] getAllLinkInfo() {
+    public LinkQualityInfo[] getAllLinkQualityInfo() {
         try {
-            LinkInfo[] li = mService.getAllLinkInfo();
+            LinkQualityInfo[] li = mService.getAllLinkQualityInfo();
             return li;
         } catch (RemoteException e) {
             return null;
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index c07e900..a6f10ec 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -16,7 +16,7 @@
 
 package android.net;
 
-import android.net.LinkInfo;
+import android.net.LinkQualityInfo;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.net.NetworkQuotaInfo;
@@ -149,11 +149,11 @@
 
     String getMobileRedirectedProvisioningUrl();
 
-    LinkInfo getLinkInfo(int networkType);
+    LinkQualityInfo getLinkQualityInfo(int networkType);
 
-    LinkInfo getActiveLinkInfo();
+    LinkQualityInfo getActiveLinkQualityInfo();
 
-    LinkInfo[] getAllLinkInfo();
+    LinkQualityInfo[] getAllLinkQualityInfo();
 
     void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url);
 }
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 1f73c4a..b4d07a1 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -66,6 +66,7 @@
     private String mDomains;
     private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
     private ProxyProperties mHttpProxy;
+    private int mMtu;
 
     // Stores the properties of links that are "stacked" above this link.
     // Indexed by interface name to allow modification and to prevent duplicates being added.
@@ -104,6 +105,7 @@
             for (LinkProperties l: source.mStackedLinks.values()) {
                 addStackedLink(l);
             }
+            setMtu(source.getMtu());
         }
     }
 
@@ -197,6 +199,16 @@
         return addresses;
     }
 
+    /**
+     * Replaces the LinkAddresses on this link with the given collection of addresses.
+     */
+    public void setLinkAddresses(Collection<LinkAddress> addresses) {
+        mLinkAddresses.clear();
+        for (LinkAddress address: addresses) {
+            addLinkAddress(address);
+        }
+    }
+
     public void addDns(InetAddress dns) {
         if (dns != null) mDnses.add(dns);
     }
@@ -213,6 +225,14 @@
         mDomains = domains;
     }
 
+    public void setMtu(int mtu) {
+        mMtu = mtu;
+    }
+
+    public int getMtu() {
+        return mMtu;
+    }
+
     private RouteInfo routeWithInterface(RouteInfo route) {
         return new RouteInfo(
             route.getDestination(),
@@ -312,6 +332,7 @@
         mRoutes.clear();
         mHttpProxy = null;
         mStackedLinks.clear();
+        mMtu = 0;
     }
 
     /**
@@ -336,6 +357,8 @@
 
         String domainName = "Domains: " + mDomains;
 
+        String mtu = "MTU: " + mMtu;
+
         String routes = " Routes: [";
         for (RouteInfo route : mRoutes) routes += route.toString() + ",";
         routes += "] ";
@@ -349,7 +372,8 @@
             }
             stacked += "] ";
         }
-        return "{" + ifaceName + linkAddresses + routes + dns + domainName + proxy + stacked + "}";
+        return "{" + ifaceName + linkAddresses + routes + dns + domainName + mtu
+            + proxy + stacked + "}";
     }
 
     /**
@@ -464,6 +488,16 @@
         return true;
     }
 
+    /**
+     * Compares this {@code LinkProperties} MTU against the target
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     */
+    public boolean isIdenticalMtu(LinkProperties target) {
+        return getMtu() == target.getMtu();
+    }
+
     @Override
     /**
      * Compares this {@code LinkProperties} instance against the target
@@ -495,7 +529,8 @@
                 isIdenticalDnses(target) &&
                 isIdenticalRoutes(target) &&
                 isIdenticalHttpProxy(target) &&
-                isIdenticalStackedLinks(target);
+                isIdenticalStackedLinks(target) &&
+                isIdenticalMtu(target);
     }
 
     /**
@@ -597,7 +632,8 @@
                 + ((null == mDomains) ? 0 : mDomains.hashCode())
                 + mRoutes.size() * 41
                 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
-                + mStackedLinks.hashCode() * 47);
+                + mStackedLinks.hashCode() * 47)
+                + mMtu * 51;
     }
 
     /**
@@ -615,7 +651,7 @@
             dest.writeByteArray(d.getAddress());
         }
         dest.writeString(mDomains);
-
+        dest.writeInt(mMtu);
         dest.writeInt(mRoutes.size());
         for(RouteInfo route : mRoutes) {
             dest.writeParcelable(route, flags);
@@ -654,6 +690,7 @@
                     } catch (UnknownHostException e) { }
                 }
                 netProp.setDomains(in.readString());
+                netProp.setMtu(in.readInt());
                 addressCount = in.readInt();
                 for (int i=0; i<addressCount; i++) {
                     netProp.addRoute((RouteInfo)in.readParcelable(null));
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index dabc73a..4d2a70d 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -83,13 +83,7 @@
         /** Link has poor connectivity. */
         VERIFYING_POOR_LINK,
         /** Checking if network is a captive portal */
-        CAPTIVE_PORTAL_CHECK,
-        /**
-         * Network is connected to provisioning network
-         * TODO: Probably not needed when we add TYPE_PROVISIONING_NETWORK
-         * @hide
-         */
-        CONNECTED_TO_PROVISIONING_NETWORK
+        CAPTIVE_PORTAL_CHECK
     }
 
     /**
@@ -114,7 +108,6 @@
         stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
         stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
         stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
-        stateMap.put(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, State.CONNECTED);
     }
 
     private int mNetworkType;
@@ -127,6 +120,8 @@
     private String mExtraInfo;
     private boolean mIsFailover;
     private boolean mIsRoaming;
+    private boolean mIsConnectedToProvisioningNetwork;
+
     /**
      * Indicates whether network connectivity is possible:
      */
@@ -155,6 +150,7 @@
         mState = State.UNKNOWN;
         mIsAvailable = false; // until we're told otherwise, assume unavailable
         mIsRoaming = false;
+        mIsConnectedToProvisioningNetwork = false;
     }
 
     /** {@hide} */
@@ -171,6 +167,7 @@
             mIsFailover = source.mIsFailover;
             mIsRoaming = source.mIsRoaming;
             mIsAvailable = source.mIsAvailable;
+            mIsConnectedToProvisioningNetwork = source.mIsConnectedToProvisioningNetwork;
         }
     }
 
@@ -329,6 +326,22 @@
         }
     }
 
+    /** {@hide} */
+    @VisibleForTesting
+    public boolean isConnectedToProvisioningNetwork() {
+        synchronized (this) {
+            return mIsConnectedToProvisioningNetwork;
+        }
+    }
+
+    /** {@hide} */
+    @VisibleForTesting
+    public void setIsConnectedToProvisioningNetwork(boolean val) {
+        synchronized (this) {
+            mIsConnectedToProvisioningNetwork = val;
+        }
+    }
+
     /**
      * Reports the current coarse-grained state of the network.
      * @return the coarse-grained state
@@ -412,7 +425,9 @@
             append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo).
             append(", roaming: ").append(mIsRoaming).
             append(", failover: ").append(mIsFailover).
-            append(", isAvailable: ").append(mIsAvailable);
+            append(", isAvailable: ").append(mIsAvailable).
+            append(", isConnectedToProvisioningNetwork: ").
+                    append(mIsConnectedToProvisioningNetwork);
             return builder.toString();
         }
     }
@@ -440,6 +455,7 @@
             dest.writeInt(mIsFailover ? 1 : 0);
             dest.writeInt(mIsAvailable ? 1 : 0);
             dest.writeInt(mIsRoaming ? 1 : 0);
+            dest.writeInt(mIsConnectedToProvisioningNetwork ? 1 : 0);
             dest.writeString(mReason);
             dest.writeString(mExtraInfo);
         }
@@ -462,6 +478,7 @@
                 netInfo.mIsFailover = in.readInt() != 0;
                 netInfo.mIsAvailable = in.readInt() != 0;
                 netInfo.mIsRoaming = in.readInt() != 0;
+                netInfo.mIsConnectedToProvisioningNetwork = in.readInt() != 0;
                 netInfo.mReason = in.readString();
                 netInfo.mExtraInfo = in.readString();
                 return netInfo;
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index a570802..e63f6b0 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -33,6 +33,7 @@
     private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
     private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
     private static String NAME = "qmi0";
+    private static int MTU = 1500;
 
     private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
     private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
@@ -57,6 +58,9 @@
         assertTrue(source.isIdenticalStackedLinks(target));
         assertTrue(target.isIdenticalStackedLinks(source));
 
+        assertTrue(source.isIdenticalMtu(target));
+        assertTrue(target.isIdenticalMtu(source));
+
         // Check result of equals().
         assertTrue(source.equals(target));
         assertTrue(target.equals(source));
@@ -88,6 +92,7 @@
             // set 2 gateways
             source.addRoute(new RouteInfo(GATEWAY1));
             source.addRoute(new RouteInfo(GATEWAY2));
+            source.setMtu(MTU);
 
             LinkProperties target = new LinkProperties();
 
@@ -99,6 +104,7 @@
             target.addDns(DNS2);
             target.addRoute(new RouteInfo(GATEWAY1));
             target.addRoute(new RouteInfo(GATEWAY2));
+            target.setMtu(MTU);
 
             assertLinkPropertiesEqual(source, target);
 
@@ -111,6 +117,7 @@
             target.addDns(DNS2);
             target.addRoute(new RouteInfo(GATEWAY1));
             target.addRoute(new RouteInfo(GATEWAY2));
+            target.setMtu(MTU);
             assertFalse(source.equals(target));
 
             target.clear();
@@ -123,6 +130,7 @@
             target.addDns(DNS2);
             target.addRoute(new RouteInfo(GATEWAY1));
             target.addRoute(new RouteInfo(GATEWAY2));
+            target.setMtu(MTU);
             assertFalse(source.equals(target));
 
             target.clear();
@@ -134,6 +142,7 @@
             target.addDns(DNS2);
             target.addRoute(new RouteInfo(GATEWAY1));
             target.addRoute(new RouteInfo(GATEWAY2));
+            target.setMtu(MTU);
             assertFalse(source.equals(target));
 
             target.clear();
@@ -145,6 +154,19 @@
             // change gateway
             target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
             target.addRoute(new RouteInfo(GATEWAY2));
+            target.setMtu(MTU);
+            assertFalse(source.equals(target));
+
+            target.clear();
+            target.setInterfaceName(NAME);
+            target.addLinkAddress(LINKADDRV4);
+            target.addLinkAddress(LINKADDRV6);
+            target.addDns(DNS1);
+            target.addDns(DNS2);
+            target.addRoute(new RouteInfo(GATEWAY1));
+            target.addRoute(new RouteInfo(GATEWAY2));
+            // change mtu
+            target.setMtu(1440);
             assertFalse(source.equals(target));
 
         } catch (Exception e) {
@@ -167,6 +189,7 @@
             // set 2 gateways
             source.addRoute(new RouteInfo(GATEWAY1));
             source.addRoute(new RouteInfo(GATEWAY2));
+            source.setMtu(MTU);
 
             LinkProperties target = new LinkProperties();
             // Exchange order
@@ -177,6 +200,7 @@
             target.addDns(DNS1);
             target.addRoute(new RouteInfo(GATEWAY2));
             target.addRoute(new RouteInfo(GATEWAY1));
+            target.setMtu(MTU);
 
             assertLinkPropertiesEqual(source, target);
         } catch (Exception e) {
@@ -363,4 +387,19 @@
         assertFalse(lp.hasIPv4Address());
         assertFalse(lp.removeLinkAddress(LINKADDRV4));
     }
+
+    @SmallTest
+    public void testSetLinkAddresses() {
+        LinkProperties lp = new LinkProperties();
+        lp.addLinkAddress(LINKADDRV4);
+        lp.addLinkAddress(LINKADDRV6);
+
+        LinkProperties lp2 = new LinkProperties();
+        lp2.addLinkAddress(LINKADDRV6);
+
+        assertFalse(lp.equals(lp2));
+
+        lp2.setLinkAddresses(lp.getLinkAddresses());
+        assertTrue(lp.equals(lp));
+    }
 }
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 9c14654..02a78de 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -58,7 +58,7 @@
 import android.net.INetworkStatsService;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
-import android.net.LinkInfo;
+import android.net.LinkQualityInfo;
 import android.net.LinkProperties.CompareResult;
 import android.net.MobileDataStateTracker;
 import android.net.NetworkConfig;
@@ -184,7 +184,7 @@
     private static final String ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED =
             "android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED";
 
-    private static final int SAMPLE_INTERVAL_ELAPSED_REQURST_CODE = 0;
+    private static final int SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE = 0;
 
     private PendingIntent mSampleIntervalElapsedIntent;
 
@@ -661,7 +661,7 @@
         // start network sampling ..
         Intent intent = new Intent(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED, null);
         mSampleIntervalElapsedIntent = PendingIntent.getBroadcast(mContext,
-                SAMPLE_INTERVAL_ELAPSED_REQURST_CODE, intent, 0);
+                SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE, intent, 0);
 
         mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
         setAlarm(DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS * 1000, mSampleIntervalElapsedIntent);
@@ -965,8 +965,7 @@
         // Find the first Provisioning Network
         NetworkInfo provNi = null;
         for (NetworkInfo ni : getAllNetworkInfo()) {
-            if (ni.getDetailedState()
-                    == NetworkInfo.DetailedState.CONNECTED_TO_PROVISIONING_NETWORK) {
+            if (ni.isConnectedToProvisioningNetwork()) {
                 provNi = ni;
                 break;
             }
@@ -2300,6 +2299,7 @@
         }
         thisNet.setTeardownRequested(false);
         updateNetworkSettings(thisNet);
+        updateMtuSizeSettings(thisNet);
         handleConnectivityChange(newNetType, false);
         sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
 
@@ -2637,6 +2637,26 @@
         return routesChanged;
     }
 
+   /**
+     * Reads the network specific MTU size from reources.
+     * and set it on it's iface.
+     */
+   private void updateMtuSizeSettings(NetworkStateTracker nt) {
+       final String iface = nt.getLinkProperties().getInterfaceName();
+       final int mtu = nt.getLinkProperties().getMtu();
+
+       if (mtu < 68 || mtu > 10000) {
+           loge("Unexpected mtu value: " + nt);
+           return;
+       }
+
+       try {
+           if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
+           mNetd.setMtu(iface, mtu);
+       } catch (Exception e) {
+           Slog.e(TAG, "exception in setMtu()" + e);
+       }
+   }
 
     /**
      * Reads the network specific TCP buffer sizes from SystemProperties
@@ -2919,7 +2939,8 @@
                     NetworkInfo.State state = info.getState();
 
                     if (VDBG || (state == NetworkInfo.State.CONNECTED) ||
-                            (state == NetworkInfo.State.DISCONNECTED)) {
+                            (state == NetworkInfo.State.DISCONNECTED) ||
+                            (state == NetworkInfo.State.SUSPENDED)) {
                         log("ConnectivityChange for " +
                             info.getTypeName() + ": " +
                             state + "/" + info.getDetailedState());
@@ -2934,7 +2955,8 @@
                     if (ConnectivityManager.isNetworkTypeMobile(info.getType())
                             && (0 != Settings.Global.getInt(mContext.getContentResolver(),
                                         Settings.Global.DEVICE_PROVISIONED, 0))
-                            && (state == NetworkInfo.State.CONNECTED)) {
+                            && ((state == NetworkInfo.State.CONNECTED)
+                                    || info.isConnectedToProvisioningNetwork())) {
                         checkMobileProvisioning(CheckMp.MAX_TIMEOUT_MS);
                     }
 
@@ -2947,8 +2969,7 @@
                     } else if (info.getDetailedState() ==
                             DetailedState.CAPTIVE_PORTAL_CHECK) {
                         handleCaptivePortalTrackerCheck(info);
-                    } else if (info.getDetailedState() ==
-                            DetailedState.CONNECTED_TO_PROVISIONING_NETWORK) {
+                    } else if (info.isConnectedToProvisioningNetwork()) {
                         /**
                          * TODO: Create ConnectivityManager.TYPE_MOBILE_PROVISIONING
                          * for now its an in between network, its a network that
@@ -3017,7 +3038,7 @@
         public void handleMessage(Message msg) {
             NetworkInfo info;
             switch (msg.what) {
-                case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
+                case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
                     String causedBy = null;
                     synchronized (ConnectivityService.this) {
                         if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
@@ -3030,49 +3051,44 @@
                         log("NetTransition Wakelock for " + causedBy + " released by timeout");
                     }
                     break;
-                case EVENT_RESTORE_DEFAULT_NETWORK:
+                }
+                case EVENT_RESTORE_DEFAULT_NETWORK: {
                     FeatureUser u = (FeatureUser)msg.obj;
                     u.expire();
                     break;
-                case EVENT_INET_CONDITION_CHANGE:
-                {
+                }
+                case EVENT_INET_CONDITION_CHANGE: {
                     int netType = msg.arg1;
                     int condition = msg.arg2;
                     handleInetConditionChange(netType, condition);
                     break;
                 }
-                case EVENT_INET_CONDITION_HOLD_END:
-                {
+                case EVENT_INET_CONDITION_HOLD_END: {
                     int netType = msg.arg1;
                     int sequence = msg.arg2;
                     handleInetConditionHoldEnd(netType, sequence);
                     break;
                 }
-                case EVENT_SET_NETWORK_PREFERENCE:
-                {
+                case EVENT_SET_NETWORK_PREFERENCE: {
                     int preference = msg.arg1;
                     handleSetNetworkPreference(preference);
                     break;
                 }
-                case EVENT_SET_MOBILE_DATA:
-                {
+                case EVENT_SET_MOBILE_DATA: {
                     boolean enabled = (msg.arg1 == ENABLED);
                     handleSetMobileData(enabled);
                     break;
                 }
-                case EVENT_APPLY_GLOBAL_HTTP_PROXY:
-                {
+                case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
                     handleDeprecatedGlobalHttpProxy();
                     break;
                 }
-                case EVENT_SET_DEPENDENCY_MET:
-                {
+                case EVENT_SET_DEPENDENCY_MET: {
                     boolean met = (msg.arg1 == ENABLED);
                     handleSetDependencyMet(msg.arg2, met);
                     break;
                 }
-                case EVENT_SEND_STICKY_BROADCAST_INTENT:
-                {
+                case EVENT_SEND_STICKY_BROADCAST_INTENT: {
                     Intent intent = (Intent)msg.obj;
                     sendStickyBroadcast(intent);
                     break;
@@ -3101,10 +3117,12 @@
                         log("EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: stale arg1:" + msg.arg1
                                 + " != tag:" + tag);
                     }
+                    break;
                 }
-                case EVENT_SAMPLE_INTERVAL_ELAPSED:
+                case EVENT_SAMPLE_INTERVAL_ELAPSED: {
                     handleNetworkSamplingTimeout();
                     break;
+                }
             }
         }
     }
@@ -3911,39 +3929,41 @@
 
     /**
      * No connection was possible to the network.
+     * This is NOT a warm sim.
      */
-    public static final int CMP_RESULT_CODE_NO_CONNECTION = 0;
+    private static final int CMP_RESULT_CODE_NO_CONNECTION = 0;
 
     /**
      * A connection was made to the internet, all is well.
+     * This is NOT a warm sim.
      */
-    public static final int CMP_RESULT_CODE_CONNECTABLE = 1;
-
-    /**
-     * A connection was made but there was a redirection, we appear to be in walled garden.
-     * This is an indication of a warm sim on a mobile network.
-     */
-    public static final int CMP_RESULT_CODE_REDIRECTED = 2;
+    private static final int CMP_RESULT_CODE_CONNECTABLE = 1;
 
     /**
      * A connection was made but no dns server was available to resolve a name to address.
-     * This is an indication of a warm sim on a mobile network.
+     * This is NOT a warm sim since provisioning network is supported.
      */
-    public static final int CMP_RESULT_CODE_NO_DNS = 3;
+    private static final int CMP_RESULT_CODE_NO_DNS = 2;
 
     /**
      * A connection was made but could not open a TCP connection.
-     * This is an indication of a warm sim on a mobile network.
+     * This is NOT a warm sim since provisioning network is supported.
      */
-    public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4;
+    private static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 3;
+
+    /**
+     * A connection was made but there was a redirection, we appear to be in walled garden.
+     * This is an indication of a warm sim on a mobile network such as T-Mobile.
+     */
+    private static final int CMP_RESULT_CODE_REDIRECTED = 4;
 
     /**
      * The mobile network is a provisioning network.
-     * This is an indication of a warm sim on a mobile network.
+     * This is an indication of a warm sim on a mobile network such as AT&T.
      */
-    public static final int CMP_RESULT_CODE_PROVISIONING_NETWORK = 5;
+    private static final int CMP_RESULT_CODE_PROVISIONING_NETWORK = 5;
 
-    AtomicBoolean mIsCheckingMobileProvisioning = new AtomicBoolean(false);
+    private AtomicBoolean mIsCheckingMobileProvisioning = new AtomicBoolean(false);
 
     @Override
     public int checkMobileProvisioning(int suggestedTimeOutMs) {
@@ -4018,7 +4038,9 @@
                             mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI].getNetworkInfo();
                     switch(result) {
                         case CMP_RESULT_CODE_CONNECTABLE:
-                        case CMP_RESULT_CODE_NO_CONNECTION: {
+                        case CMP_RESULT_CODE_NO_CONNECTION:
+                        case CMP_RESULT_CODE_NO_DNS:
+                        case CMP_RESULT_CODE_NO_TCP_CONNECTION: {
                             if (DBG) log("CheckMp.onComplete: ignore, connected or no connection");
                             break;
                         }
@@ -4037,8 +4059,7 @@
                             }
                             break;
                         }
-                        case CMP_RESULT_CODE_NO_DNS:
-                        case CMP_RESULT_CODE_NO_TCP_CONNECTION: {
+                        case CMP_RESULT_CODE_PROVISIONING_NETWORK: {
                             String url = getMobileProvisioningUrl();
                             if (TextUtils.isEmpty(url) == false) {
                                 if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), url=" + url);
@@ -4204,8 +4225,8 @@
                         MobileDataStateTracker mdst = (MobileDataStateTracker)
                                 mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
                         if (mdst.isProvisioningNetwork()) {
-                            if (DBG) log("isMobileOk: isProvisioningNetwork is true, no TCP conn");
-                            result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
+                            if (DBG) log("isMobileOk: isProvisioningNetwork is true");
+                            result = CMP_RESULT_CODE_PROVISIONING_NETWORK;
                             return result;
                         } else {
                             if (DBG) log("isMobileOk: isProvisioningNetwork is false, continue");
@@ -4285,25 +4306,37 @@
                                 urlConn.setAllowUserInteraction(false);
                                 urlConn.setRequestProperty("Connection", "close");
                                 int responseCode = urlConn.getResponseCode();
-                                if (responseCode == 204) {
-                                    result = CMP_RESULT_CODE_CONNECTABLE;
-                                } else {
-                                    result = CMP_RESULT_CODE_REDIRECTED;
-                                }
-                                log("isMobileOk: connected responseCode=" + responseCode);
+
+                                // For debug display the headers
+                                Map<String, List<String>> headers = urlConn.getHeaderFields();
+                                log("isMobileOk: headers=" + headers);
+
+                                // Close the connection
                                 urlConn.disconnect();
                                 urlConn = null;
-                                return result;
+
+                                if (responseCode == 204) {
+                                    // Return
+                                    log("isMobileOk: expected responseCode=" + responseCode);
+                                    result = CMP_RESULT_CODE_CONNECTABLE;
+                                    return result;
+                                } else {
+                                    // Retry to be sure this was redirected, we've gotten
+                                    // occasions where a server returned 200 even though
+                                    // the device didn't have a "warm" sim.
+                                    log("isMobileOk: not expected responseCode=" + responseCode);
+                                    result = CMP_RESULT_CODE_REDIRECTED;
+                                }
                             } catch (Exception e) {
                                 log("isMobileOk: HttpURLConnection Exception e=" + e);
+                                result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
                                 if (urlConn != null) {
                                     urlConn.disconnect();
                                     urlConn = null;
                                 }
                             }
                         }
-                        result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
-                        log("isMobileOk: loops|timed out");
+                        log("isMobileOk: loops|timed out result=" + result);
                         return result;
                     } catch (Exception e) {
                         log("isMobileOk: Exception e=" + e);
@@ -4418,8 +4451,7 @@
         // If provisioning network handle as a special case,
         // otherwise launch browser with the intent directly.
         NetworkInfo ni = getProvisioningNetworkInfo();
-        if ((ni != null) && ni.getDetailedState() ==
-                    NetworkInfo.DetailedState.CONNECTED_TO_PROVISIONING_NETWORK) {
+        if ((ni != null) && ni.isConnectedToProvisioningNetwork()) {
             if (DBG) log("handleMobileProvisioningAction: on provisioning network");
             MobileDataStateTracker mdst = (MobileDataStateTracker)
                     mNetTrackers[ConnectivityManager.TYPE_MOBILE];
@@ -4689,39 +4721,39 @@
     };
 
     @Override
-    public LinkInfo getLinkInfo(int networkType) {
+    public LinkQualityInfo getLinkQualityInfo(int networkType) {
         enforceAccessPermission();
         if (isNetworkTypeValid(networkType)) {
-            return mNetTrackers[networkType].getLinkInfo();
+            return mNetTrackers[networkType].getLinkQualityInfo();
         } else {
             return null;
         }
     }
 
     @Override
-    public LinkInfo getActiveLinkInfo() {
+    public LinkQualityInfo getActiveLinkQualityInfo() {
         enforceAccessPermission();
         if (isNetworkTypeValid(mActiveDefaultNetwork)) {
-            return mNetTrackers[mActiveDefaultNetwork].getLinkInfo();
+            return mNetTrackers[mActiveDefaultNetwork].getLinkQualityInfo();
         } else {
             return null;
         }
     }
 
     @Override
-    public LinkInfo[] getAllLinkInfo() {
+    public LinkQualityInfo[] getAllLinkQualityInfo() {
         enforceAccessPermission();
-        final ArrayList<LinkInfo> result = Lists.newArrayList();
+        final ArrayList<LinkQualityInfo> result = Lists.newArrayList();
         for (NetworkStateTracker tracker : mNetTrackers) {
             if (tracker != null) {
-                LinkInfo li = tracker.getLinkInfo();
+                LinkQualityInfo li = tracker.getLinkQualityInfo();
                 if (li != null) {
                     result.add(li);
                 }
             }
         }
 
-        return result.toArray(new LinkInfo[result.size()]);
+        return result.toArray(new LinkQualityInfo[result.size()]);
     }
 
     /* Infrastructure for network sampling */
@@ -4775,4 +4807,3 @@
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime, intent);
     }
 }
-