Add mobile data on/off switch.

bug:2251458
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index badb767..c76aca1 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -332,10 +332,10 @@
 
     /**
      * Sets the value of the setting for background data usage.
-     * 
+     *
      * @param allowBackgroundData Whether an application should use data while
      *            it is in the background.
-     *            
+     *
      * @attr ref android.Manifest.permission#CHANGE_BACKGROUND_DATA_SETTING
      * @see #getBackgroundDataSetting()
      * @hide
@@ -346,7 +346,35 @@
         } catch (RemoteException e) {
         }
     }
-    
+
+    /**
+     * Gets the value of the setting for enabling Mobile data.
+     *
+     * @return Whether mobile data is enabled.
+     * @hide
+     */
+    public boolean getMobileDataEnabled() {
+        try {
+            return mService.getMobileDataEnabled();
+        } catch (RemoteException e) {
+            return true;
+        }
+    }
+
+    /**
+     * Sets the persisted value for enabling/disabling Mobile data.
+     *
+     * @param allowMobileData Whether the mobile data connection should be
+     *            used or not.
+     * @hide
+     */
+    public void setMobileDataEnabled(boolean enabled) {
+        try {
+            mService.setMobileDataEnabled(enabled);
+        } catch (RemoteException e) {
+        }
+    }
+
     /**
      * Don't allow use of default constructor.
      */
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 508e9c3..2514693 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -51,6 +51,10 @@
 
     void setBackgroundDataSetting(boolean allowBackgroundData);
 
+    boolean getMobileDataEnabled();
+
+    void setMobileDataEnabled(boolean enabled);
+
     boolean tether(String iface);
 
     boolean untether(String iface);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 108246d..df685ab 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -289,6 +289,7 @@
          * the number of different network types is not going
          * to change very often.
          */
+        boolean noMobileData = !getMobileDataEnabled();
         for (int netType : mPriorityList) {
             switch (mNetAttributes[netType].mRadio) {
             case ConnectivityManager.TYPE_WIFI:
@@ -306,6 +307,10 @@
                 mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler,
                     netType, mNetAttributes[netType].mName);
                 mNetTrackers[netType].startMonitoring();
+                if (noMobileData) {
+                    if (DBG) Log.d(TAG, "tearing down Mobile networks due to setting");
+                    mNetTrackers[netType].teardown();
+                }
                 break;
             default:
                 Log.e(TAG, "Trying to create a DataStateTracker for an unknown radio type " +
@@ -530,6 +535,10 @@
         // TODO - move this into the MobileDataStateTracker
         int usedNetworkType = networkType;
         if(networkType == ConnectivityManager.TYPE_MOBILE) {
+            if (!getMobileDataEnabled()) {
+                if (DBG) Log.d(TAG, "requested special network with data disabled - rejected");
+                return Phone.APN_TYPE_NOT_AVAILABLE;
+            }
             if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
                 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
             } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
@@ -767,6 +776,46 @@
         mContext.sendBroadcast(broadcast);
     }
 
+    /**
+     * @see ConnectivityManager#getMobileDataEnabled()
+     */
+    public boolean getMobileDataEnabled() {
+        enforceAccessPermission();
+        boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.MOBILE_DATA, 1) == 1;
+        if (DBG) Log.d(TAG, "getMobileDataEnabled returning " + retVal);
+        return retVal;
+    }
+
+    /**
+     * @see ConnectivityManager#setMobileDataEnabled(boolean)
+     */
+    public synchronized void setMobileDataEnabled(boolean enabled) {
+        enforceChangePermission();
+        if (DBG) Log.d(TAG, "setMobileDataEnabled(" + enabled + ")");
+
+        if (getMobileDataEnabled() == enabled) return;
+
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
+
+        if (enabled) {
+            if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
+                if (DBG) Log.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
+                mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
+            }
+        } else {
+            for (NetworkStateTracker nt : mNetTrackers) {
+                if (nt == null) continue;
+                int netType = nt.getNetworkInfo().getType();
+                if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) {
+                    if (DBG) Log.d(TAG, "tearing down " + nt);
+                    nt.teardown();
+                }
+            }
+        }
+    }
+
     private int getNumConnectedNetworks() {
         int numConnectedNets = 0;