Handle data warning/limit notification actions.

Respond to user interaction with data warning/limit notifications
shown by NetworkPolicyManager.  Show correct tab for the template that
triggered notification.  When data is disabled, prompt user with
dialog and option to re-enable.

Change-Id: I73aeecc0e840fffa2b4cdb90af269115ed0ab56c
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8f86002..25eced1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1133,7 +1133,12 @@
                 android:label="@string/data_usage_summary_title">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-                <action android:name="android.intent.action.DATA_USAGE_SUMMARY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <!-- actions from NetworkPolicyManager notifications -->
+                <action android:name="android.intent.action.DATA_USAGE_WARNING" />
+                <action android:name="android.intent.action.DATA_USAGE_LIMIT" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1cc955c..cc4061c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3415,11 +3415,22 @@
 
     <!-- Title of dialog shown before user limits data usage. [CHAR LIMIT=48] -->
     <string name="data_usage_limit_dialog_title">Limiting data usage</string>
-    <!-- First paragraph of dialog shown before user limits mobile data usage. [CHAR LIMIT=NONE] -->
+    <!-- Body of dialog shown before user limits mobile data usage. [CHAR LIMIT=NONE] -->
     <string name="data_usage_limit_dialog_mobile">Your mobile data connection will be disabled when the specified limit is reached.\n\nTo avoid overage charges, consider using a reduced limit, as device and carrier accounting methods may vary.</string>
-    <!-- First paragraph of dialog shown before user limits 3G data usage. [CHAR LIMIT=NONE] -->
+    <!-- Body of dialog shown before user limits 3G data usage. [CHAR LIMIT=NONE] -->
     <string name="data_usage_limit_dialog_3g">Your 2G-3G data connection will be disabled when the specified limit is reached.\n\nTo avoid overage charges, consider using a reduced limit, as device and carrier accounting methods may vary.</string>
-    <!-- First paragraph of dialog shown before user limits 4G data usage. [CHAR LIMIT=NONE] -->
+    <!-- Body of dialog shown before user limits 4G data usage. [CHAR LIMIT=NONE] -->
     <string name="data_usage_limit_dialog_4g">Your 4G data connection will be disabled when the specified limit is reached.\n\nTo avoid overage charges, consider using a reduced limit, as device and carrier accounting methods may vary.</string>
 
+    <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+    <string name="data_usage_disabled_dialog_3g_title">2G-3G data disabled</string>
+    <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+    <string name="data_usage_disabled_dialog_4g_title">4G data disabled</string>
+    <!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+    <string name="data_usage_disabled_dialog_mobile_title">Mobile data disabled</string>
+    <!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
+    <string name="data_usage_disabled_dialog">The specified data usage limit has been reached.\n\nAdditional data use may incur carrier charges.</string>
+    <!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
+    <string name="data_usage_disabled_dialog_enable">re-enable data</string>
+
 </resources>
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index eff8e17..eafd22b 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -17,6 +17,9 @@
 package com.android.settings;
 
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
+import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT;
+import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_WARNING;
+import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
 import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
 import static android.net.TrafficStats.TEMPLATE_MOBILE_3G_LOWER;
@@ -39,6 +42,7 @@
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
 import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
 import android.os.AsyncTask;
@@ -102,6 +106,7 @@
 
     private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
     private static final String TAG_CYCLE_EDITOR = "cycleEditor";
+    private static final String TAG_POLICY_LIMIT = "policyLimit";
 
     private static final long KB_IN_BYTES = 1024;
     private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
@@ -136,6 +141,8 @@
     private NetworkPolicyModifier mPolicyModifier;
     private NetworkStatsHistory mHistory;
 
+    private String mIntentTab = null;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -208,9 +215,19 @@
     public void onResume() {
         super.onResume();
 
+        // pick default tab based on incoming intent
+        final Intent intent = getActivity().getIntent();
+        mIntentTab = computeTabFromIntent(intent);
+
         // this kicks off chain reaction which creates tabs, binds the body to
         // selected network, and binds chart, cycles and detail list.
         updateTabs();
+
+        // template and tab has been selected; show dialog if limit passed
+        final String action = intent.getAction();
+        if (ACTION_DATA_USAGE_LIMIT.equals(action)) {
+            PolicyLimitFragment.show(this);
+        }
     }
 
     @Override
@@ -276,10 +293,15 @@
         }
 
         if (mTabWidget.getTabCount() > 0) {
-            // select first tab, which will kick off updateBody()
-            mTabHost.setCurrentTab(0);
+            if (mIntentTab != null) {
+                // select default tab, which will kick off updateBody()
+                mTabHost.setCurrentTabByTag(mIntentTab);
+            } else {
+                // select first tab, which will kick off updateBody()
+                mTabHost.setCurrentTab(0);
+            }
         } else {
-            // no tabs shown; update body manually
+            // no tabs visible; update body manually
             updateBody();
         }
     }
@@ -852,6 +874,84 @@
     }
 
     /**
+     * Dialog explaining that {@link NetworkPolicy#limitBytes} has been passed,
+     * and giving the user an option to bypass.
+     */
+    public static class PolicyLimitFragment extends DialogFragment {
+        public static final String EXTRA_TITLE_ID = "titleId";
+
+        public static void show(DataUsageSummary parent) {
+            final Bundle args = new Bundle();
+
+            switch (parent.mTemplate) {
+                case TEMPLATE_MOBILE_3G_LOWER: {
+                    args.putInt(EXTRA_TITLE_ID, R.string.data_usage_disabled_dialog_3g_title);
+                    break;
+                }
+                case TEMPLATE_MOBILE_4G: {
+                    args.putInt(EXTRA_TITLE_ID, R.string.data_usage_disabled_dialog_4g_title);
+                    break;
+                }
+                case TEMPLATE_MOBILE_ALL: {
+                    args.putInt(EXTRA_TITLE_ID, R.string.data_usage_disabled_dialog_mobile_title);
+                    break;
+                }
+            }
+
+            final PolicyLimitFragment dialog = new PolicyLimitFragment();
+            dialog.setArguments(args);
+            dialog.setTargetFragment(parent, 0);
+            dialog.show(parent.getFragmentManager(), TAG_POLICY_LIMIT);
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final Context context = getActivity();
+
+            final int titleId = getArguments().getInt(EXTRA_TITLE_ID);
+
+            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+            builder.setTitle(titleId);
+            builder.setMessage(R.string.data_usage_disabled_dialog);
+
+            builder.setPositiveButton(android.R.string.ok, null);
+            builder.setNegativeButton(R.string.data_usage_disabled_dialog_enable,
+                    new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
+                            if (target != null) {
+                                // TODO: consider "allow 100mb more data", or
+                                // only bypass limit for current cycle.
+                                target.setPolicyLimitBytes(LIMIT_DISABLED);
+                            }
+                        }
+                    });
+
+            return builder.create();
+        }
+    }
+
+    /**
+     * Compute default tab that should be selected, based on
+     * {@link NetworkPolicyManager#EXTRA_NETWORK_TEMPLATE} extra.
+     */
+    private static String computeTabFromIntent(Intent intent) {
+        final int networkTemplate = intent.getIntExtra(EXTRA_NETWORK_TEMPLATE, TEMPLATE_INVALID);
+        switch (networkTemplate) {
+            case TEMPLATE_MOBILE_3G_LOWER:
+                return TAB_3G;
+            case TEMPLATE_MOBILE_4G:
+                return TAB_4G;
+            case TEMPLATE_MOBILE_ALL:
+                return TAB_MOBILE;
+            case TEMPLATE_WIFI:
+                return TAB_WIFI;
+            default:
+                return null;
+        }
+    }
+
+    /**
      * Resolve best descriptive label for the given UID.
      */
     public static CharSequence resolveLabelForUid(PackageManager pm, int uid) {