Merge "Create new isNetworkSupported API"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3441217..530122c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -814,4 +814,22 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * Returns true if the hardware supports the given network type
+     * else it returns false.  This doesn't indicate we have coverage
+     * or are authorized onto a network, just whether or not the
+     * hardware supports it.  For example a gsm phone without a sim
+     * should still return true for mobile data, but a wifi only tablet
+     * would return false.
+     * @param networkType The nework type we'd like to check
+     * @return true if supported, else false
+     * @hide
+     */
+    public boolean isNetworkSupported(int networkType) {
+        try {
+            return mService.isNetworkSupported(networkType);
+        } catch (RemoteException e) {}
+        return false;
+    }
 }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index c9553c0..eef658e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -43,6 +43,8 @@
     NetworkInfo getNetworkInfo(int networkType);
     NetworkInfo[] getAllNetworkInfo();
 
+    boolean isNetworkSupported(int networkType);
+
     LinkProperties getActiveLinkProperties();
     LinkProperties getLinkProperties(int networkType);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 60dfdac..3c85814 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -130,6 +130,8 @@
     int mLastDataTypeIconId = -1;
     String mLastLabel = "";
 
+    private boolean mHasMobileDataFeature;
+
     boolean mDataAndWifiStacked = false;
 
     // yuck -- stop doing this here and put it in the framework
@@ -147,6 +149,10 @@
     public NetworkController(Context context) {
         mContext = context;
 
+        ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        mHasMobileDataFeature = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
         // set up the default wifi icon, used when no radios have ever appeared
         updateWifiIcons();
 
@@ -229,7 +235,7 @@
                 mWifiIconId,
                 mWifiActivityIconId);
         cluster.setMobileDataIndicators(
-                hasMobileDataFeature(),
+                mHasMobileDataFeature,
                 mPhoneSignalIconId,
                 mMobileActivityIconId,
                 mDataTypeIconId);
@@ -376,12 +382,6 @@
         }
     }
 
-    private boolean hasMobileDataFeature() {
-        // XXX: HAX: replace when a more reliable method is available
-        return (! "wifi-only".equals(SystemProperties.get("ro.carrier")));
-    }
-
-
     private void updateAirplaneMode() {
         mAirplaneMode = (Settings.System.getInt(mContext.getContentResolver(),
             Settings.System.AIRPLANE_MODE_ON, 0) == 1);
@@ -828,8 +828,8 @@
             label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
             // On devices without mobile radios, we want to show the wifi icon
             combinedSignalIconId =
-                hasMobileDataFeature() ? mDataSignalIconId : mWifiIconId;
-            mContentDescriptionCombinedSignal = hasMobileDataFeature()
+                mHasMobileDataFeature ? mDataSignalIconId : mWifiIconId;
+            mContentDescriptionCombinedSignal = mHasMobileDataFeature
                 ? mContentDescriptionDataType : mContentDescriptionWifi;
             mDataTypeIconId = 0;
         }
@@ -866,7 +866,7 @@
                         mWifiIconId,
                         mWifiActivityIconId);
                 cluster.setMobileDataIndicators(
-                        hasMobileDataFeature(),
+                        mHasMobileDataFeature,
                         mPhoneSignalIconId,
                         mMobileActivityIconId,
                         mDataTypeIconId);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3815c3b..2348d76 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -703,6 +703,12 @@
         return result.toArray(new NetworkInfo[result.size()]);
     }
 
+    @Override
+    public boolean isNetworkSupported(int networkType) {
+        enforceAccessPermission();
+        return (isNetworkTypeValid(networkType) && (mNetTrackers[networkType] != null));
+    }
+
     /**
      * Return LinkProperties for the active (i.e., connected) default
      * network interface.  It is assumed that at most one default network
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d0e8b5e..2714fc5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -350,7 +350,6 @@
                 Slog.i(TAG, "Wi-Fi Service");
                 wifi = new WifiService(context);
                 ServiceManager.addService(Context.WIFI_SERVICE, wifi);
-                wifi.checkAndStartWifi();
             } catch (Throwable e) {
                 reportWtf("starting Wi-Fi Service", e);
             }
@@ -361,6 +360,7 @@
                 ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
                 networkStats.bindConnectivityManager(connectivity);
                 networkPolicy.bindConnectivityManager(connectivity);
+                wifi.checkAndStartWifi();
                 wifiP2p.connectivityServiceReady();
             } catch (Throwable e) {
                 reportWtf("starting Connectivity Service", e);
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 3e13a86..bd35058 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -29,6 +29,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ConnectivityManager;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.os.AsyncResult;
@@ -230,8 +231,6 @@
 
     Object     mLastNITZTimeInfo;
 
-    private static final String WIFI_ONLY_CARRIER = "wifi-only";
-
     //***** Events
 
     static final int EVENT_SEND                 = 1;
@@ -626,10 +625,9 @@
         Looper looper = mSenderThread.getLooper();
         mSender = new RILSender(looper);
 
-        // TODO: Provide a common API for determining if a
-        // device is wifi-only. bug: 3480713
-        String carrier = SystemProperties.get("ro.carrier");
-        if (WIFI_ONLY_CARRIER.equals(carrier)) {
+        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        if (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
             riljLog("Not starting RILReceiver: wifi-only");
         } else {
             riljLog("Starting RILReceiver");
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 274edae..c52142d 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -36,6 +36,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.util.Slog;
+import android.util.Log;
 
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
@@ -174,7 +175,7 @@
      * It triggers a disableNetwork call if a DNS check fails.
      */
     public boolean mDisableAPNextFailure = false;
-    private ConnectivityManager mConnectivityManager;
+    private static boolean sWifiOnly = false;
     private boolean mNotificationShown;
     public boolean mHasConnectedWifiManager = false;
 
@@ -219,9 +220,14 @@
 
     public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) {
         ContentResolver contentResolver = context.getContentResolver();
+
+        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false);
+
         // Disable for wifi only devices.
         if (Settings.Secure.getString(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON) == null &&
-                "wifi-only".equals(SystemProperties.get("ro.carrier"))) {
+                sWifiOnly) {
             putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, false);
         }
         WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
@@ -508,22 +514,6 @@
         }
     }
 
-    /**
-     * @return true if there is definitely no mobile data (we'll be less aggressive)
-     */
-    private boolean hasNoMobileData() {
-        if (mConnectivityManager == null) {
-            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
-                    Context.CONNECTIVITY_SERVICE);
-        }
-        NetworkInfo mobileNetInfo = mConnectivityManager.getNetworkInfo(
-                ConnectivityManager.TYPE_MOBILE);
-        if (mobileNetInfo == null || !mobileNetInfo.isAvailable()) {
-            return true;
-        }
-        return false;
-    }
-
     class DefaultState extends State {
         @Override
         public boolean processMessage(Message msg) {
@@ -941,7 +931,7 @@
 
             if (mDisableAPNextFailure || mNumCheckFailures >= mBssids.size()
                     || mNumCheckFailures >= mMaxSsidBlacklists) {
-                if (hasNoMobileData()) {
+                if (sWifiOnly) {
                     Slog.w(WWSM_TAG, "Would disable bad network, but device has no mobile data!" +
                             "  Going idle...");
                     // This state should be called idle -- will be changing flow.