Merge "Clean up some unnecessary inheritance."
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 0725386..a37039f 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -515,7 +515,7 @@
         if (resultTo == null) {
             context.startActivity(intent);
         } else {
-            resultTo.startActivityForResult(intent, resultRequestCode);
+            resultTo.getActivity().startActivityForResult(intent, resultRequestCode);
         }
     }
 
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 8a99e03..f7992cc 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -22,8 +22,10 @@
 import android.app.DialogFragment;
 import android.app.Fragment;
 import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -74,6 +76,7 @@
     protected static final int DLG_BASE = 0;
 
     protected boolean mFinishing;
+    protected boolean mListeningToPackageRemove;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -90,6 +93,7 @@
         mUsbManager = IUsbManager.Stub.asInterface(b);
 
         retrieveAppEntry();
+        startListeningToPackageRemove();
     }
 
     @Override
@@ -114,6 +118,7 @@
 
     @Override
     public void onDestroy() {
+        stopListeningToPackageRemove();
         mSession.release();
         super.onDestroy();
     }
@@ -246,4 +251,37 @@
             return dialogFragment;
         }
     }
+
+    protected void startListeningToPackageRemove() {
+        if (mListeningToPackageRemove) {
+            return;
+        }
+        mListeningToPackageRemove = true;
+        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addDataScheme("package");
+        getContext().registerReceiver(mPackageRemovedReceiver, filter);
+    }
+
+    protected void stopListeningToPackageRemove() {
+        if (!mListeningToPackageRemove) {
+            return;
+        }
+        mListeningToPackageRemove = false;
+        getContext().unregisterReceiver(mPackageRemovedReceiver);
+    }
+
+    protected void onPackageRemoved() {
+        getActivity().finishAndRemoveTask();
+    }
+
+    protected final BroadcastReceiver mPackageRemovedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String packageName = intent.getData().getSchemeSpecificPart();
+            if (!mFinishing && mAppEntry.info.packageName.equals(packageName)) {
+                onPackageRemoved();
+            }
+        }
+    };
+
 }
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 3f42293..1cf55a4 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -29,7 +29,6 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.Loader;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -165,8 +164,6 @@
     private Preference mMemoryPreference;
 
     private boolean mDisableAfterUninstall;
-    private boolean mListeningToPackageRemove;
-
     // Used for updating notification preference.
     private final NotificationBackend mBackend = new NotificationBackend();
 
@@ -326,7 +323,6 @@
             removePreference(KEY_DATA);
         }
         mBatteryHelper = new BatteryStatsHelper(getActivity(), true);
-        startListeningToPackageRemove();
     }
 
     @Override
@@ -362,7 +358,6 @@
     @Override
     public void onDestroy() {
         TrafficStats.closeQuietly(mStatsSession);
-        stopListeningToPackageRemove();
         super.onDestroy();
     }
 
@@ -742,7 +737,7 @@
         intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName);
         intent.putExtra(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
         try {
-            startActivity(intent);
+            getActivity().startActivityForResult(intent, SUB_INFO_FRAGMENT);
         } catch (ActivityNotFoundException e) {
             Log.w(LOG_TAG, "No app can handle android.intent.action.MANAGE_APP_PERMISSIONS");
         }
@@ -1090,6 +1085,12 @@
         return summary.toString();
     }
 
+    @Override
+    protected void onPackageRemoved() {
+        getActivity().finishActivity(SUB_INFO_FRAGMENT);
+        super.onPackageRemoved();
+    }
+
     private class MemoryUpdater extends AsyncTask<Void, Void, ProcStatsPackageEntry> {
 
         @Override
@@ -1246,33 +1247,4 @@
             mPermissionsPreference.setSummary(summary);
         }
     };
-
-    private void startListeningToPackageRemove() {
-        if (mListeningToPackageRemove) {
-            return;
-        }
-        mListeningToPackageRemove = true;
-        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addDataScheme("package");
-        getContext().registerReceiver(mPackageRemovedReceiver, filter);
-    }
-
-    private void stopListeningToPackageRemove() {
-        if (!mListeningToPackageRemove) {
-            return;
-        }
-        mListeningToPackageRemove = false;
-        getContext().unregisterReceiver(mPackageRemovedReceiver);
-    }
-
-    private final BroadcastReceiver mPackageRemovedReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String packageName = intent.getData().getSchemeSpecificPart();
-            if (!mFinishing && mAppEntry.info.packageName.equals(packageName)) {
-                getActivity().finishAndRemoveTask();
-            }
-        }
-    };
-
 }
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 45fdc1d..84bac17 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -215,9 +215,12 @@
                 final int userId = UidDetailProvider.getUserIdForKey(mAppItem.key);
                 final UserManager um = UserManager.get(getActivity());
                 final UserInfo info = um.getUserInfo(userId);
-                final PackageManager pm = getPackageManager();
-                mIcon = Utils.getUserIcon(getActivity(), um, info);
-                mLabel = Utils.getUserLabel(getActivity(), info);
+                if (info != null) {
+                    mIcon = Utils.getUserIcon(getActivity(), um, info);
+                    mLabel = Utils.getUserLabel(getActivity(), info);
+                } else {
+                    mLabel = getContext().getString(R.string.data_usage_uninstalled_apps_users);
+                }
                 mPackageName = getActivity().getPackageName();
             }
             removePreference(KEY_UNRESTRICTED_DATA);
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index a23f811..10a0ac072 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -17,6 +17,7 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
+import android.app.Fragment;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
@@ -44,7 +45,7 @@
 import static android.net.TrafficStats.MB_IN_BYTES;
 
 public class BillingCycleSettings extends DataUsageBase implements
-        Preference.OnPreferenceChangeListener {
+        Preference.OnPreferenceChangeListener, DataUsageEditController {
 
     private static final String TAG = "BillingCycleSettings";
     private static final boolean LOGD = false;
@@ -146,33 +147,50 @@
         updatePrefs();
     }
 
+    @Override
+    public NetworkPolicyEditor getNetworkPolicyEditor() {
+        return services.mPolicyEditor;
+    }
+
+    @Override
+    public NetworkTemplate getNetworkTemplate() {
+        return mNetworkTemplate;
+    }
+
+    @Override
+    public void updateDataUsage() {
+        updatePrefs();
+    }
+
     /**
      * Dialog to edit {@link NetworkPolicy#warningBytes}.
      */
     public static class BytesEditorFragment extends DialogFragment
-            implements DialogInterface.OnClickListener{
+            implements DialogInterface.OnClickListener {
         private static final String EXTRA_TEMPLATE = "template";
         private static final String EXTRA_LIMIT = "limit";
         private View mView;
 
-        public static void show(BillingCycleSettings parent, boolean isLimit) {
-            if (!parent.isAdded()) return;
+        public static void show(DataUsageEditController parent, boolean isLimit) {
+            if (! (parent instanceof Fragment)) {
+                return;
+            }
+            Fragment targetFragment = (Fragment) parent;
+            if (!targetFragment.isAdded()) return;
 
             final Bundle args = new Bundle();
-            args.putParcelable(EXTRA_TEMPLATE, parent.mNetworkTemplate);
+            args.putParcelable(EXTRA_TEMPLATE, parent.getNetworkTemplate());
             args.putBoolean(EXTRA_LIMIT, isLimit);
 
             final BytesEditorFragment dialog = new BytesEditorFragment();
             dialog.setArguments(args);
-            dialog.setTargetFragment(parent, 0);
-            dialog.show(parent.getFragmentManager(), TAG_WARNING_EDITOR);
+            dialog.setTargetFragment(targetFragment, 0);
+            dialog.show(targetFragment.getFragmentManager(), TAG_WARNING_EDITOR);
         }
 
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
             final Context context = getActivity();
-
-
             final LayoutInflater dialogInflater = LayoutInflater.from(context);
             final boolean isLimit = getArguments().getBoolean(EXTRA_LIMIT);
             mView = dialogInflater.inflate(R.layout.data_usage_bytes_editor, null, false);
@@ -187,8 +205,8 @@
         }
 
         private void setupPicker(EditText bytesPicker, Spinner type) {
-            final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
-            final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+            final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+            final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
 
             final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
             final boolean isLimit = getArguments().getBoolean(EXTRA_LIMIT);
@@ -221,8 +239,8 @@
             if (which != DialogInterface.BUTTON_POSITIVE) {
                 return;
             }
-            final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
-            final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+            final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+            final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
 
             final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
             final boolean isLimit = getArguments().getBoolean(EXTRA_LIMIT);
@@ -243,7 +261,7 @@
             } else {
                 editor.setPolicyWarningBytes(template, correctedBytes);
             }
-            target.updatePrefs();
+            target.updateDataUsage();
         }
     }
 
@@ -251,7 +269,7 @@
      * Dialog to edit {@link NetworkPolicy#cycleDay}.
      */
     public static class CycleEditorFragment extends DialogFragment implements
-            DialogInterface.OnClickListener{
+            DialogInterface.OnClickListener {
         private static final String EXTRA_TEMPLATE = "template";
         private NumberPicker mCycleDayPicker;
 
@@ -270,8 +288,8 @@
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
             final Context context = getActivity();
-            final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
-            final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+            final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+            final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
 
             final AlertDialog.Builder builder = new AlertDialog.Builder(context);
             final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
@@ -296,8 +314,8 @@
         @Override
         public void onClick(DialogInterface dialog, int which) {
             final NetworkTemplate template = getArguments().getParcelable(EXTRA_TEMPLATE);
-            final BillingCycleSettings target = (BillingCycleSettings) getTargetFragment();
-            final NetworkPolicyEditor editor = target.services.mPolicyEditor;
+            final DataUsageEditController target = (DataUsageEditController) getTargetFragment();
+            final NetworkPolicyEditor editor = target.getNetworkPolicyEditor();
 
             // clear focus to finish pending text edits
             mCycleDayPicker.clearFocus();
@@ -305,7 +323,7 @@
             final int cycleDay = mCycleDayPicker.getValue();
             final String cycleTimezone = new Time().timezone;
             editor.setPolicyCycleDay(template, cycleDay, cycleTimezone);
-            target.updatePrefs();
+            target.updateDataUsage();
         }
     }
 
@@ -314,7 +332,7 @@
      * {@link NetworkPolicy#limitBytes}.
      */
     public static class ConfirmLimitFragment extends DialogFragment implements
-            DialogInterface.OnClickListener{
+            DialogInterface.OnClickListener {
         private static final String EXTRA_MESSAGE = "message";
         private static final String EXTRA_LIMIT_BYTES = "limitBytes";
         public static final float FLOAT = 1.2f;
diff --git a/src/com/android/settings/datausage/DataUsageEditController.java b/src/com/android/settings/datausage/DataUsageEditController.java
new file mode 100644
index 0000000..adc0fe7
--- /dev/null
+++ b/src/com/android/settings/datausage/DataUsageEditController.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.datausage;
+
+import android.net.NetworkTemplate;
+import com.android.settingslib.NetworkPolicyEditor;
+
+/**
+ * Used to create a dialog that modifies the Cellular data warning amount.
+ */
+public interface DataUsageEditController {
+    /**
+     * @return NetworkPolicyEditor to update the values of the data warning and usage limits.
+     */
+    NetworkPolicyEditor getNetworkPolicyEditor();
+
+    /**
+     * @return NetworkTemplate to get the currently set values of the data warning and usage limits.
+     */
+    NetworkTemplate getNetworkTemplate();
+
+    /**
+     * Callback to update the UI and values changed by the Dialog.
+     */
+    void updateDataUsage();
+}
diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java
index 8de6a84..6b3b874 100644
--- a/src/com/android/settings/datausage/DataUsageSummary.java
+++ b/src/com/android/settings/datausage/DataUsageSummary.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.INetworkStatsSession;
+import android.net.NetworkPolicy;
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
 import android.os.Bundle;
@@ -48,6 +49,7 @@
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
+import com.android.settingslib.NetworkPolicyEditor;
 import com.android.settingslib.net.DataUsageController;
 
 import java.util.ArrayList;
@@ -56,7 +58,7 @@
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 
-public class DataUsageSummary extends DataUsageBase implements Indexable {
+public class DataUsageSummary extends DataUsageBase implements Indexable, DataUsageEditController {
 
     private static final String TAG = "DataUsageSummary";
     static final boolean LOGD = false;
@@ -87,15 +89,13 @@
             hasMobileData = false;
         }
         mDefaultTemplate = getDefaultTemplate(getContext(), defaultSubId);
-        if (hasMobileData) {
-            mLimitPreference = findPreference(KEY_LIMIT_SUMMARY);
-        } else {
-            removePreference(KEY_LIMIT_SUMMARY);
-        }
+        mSummaryPreference = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
+
         if (!hasMobileData || !isAdmin()) {
             removePreference(KEY_RESTRICT_BACKGROUND);
         }
         if (hasMobileData) {
+            mLimitPreference = findPreference(KEY_LIMIT_SUMMARY);
             List<SubscriptionInfo> subscriptions =
                     services.mSubscriptionManager.getActiveSubscriptionInfoList();
             if (subscriptions == null || subscriptions.size() == 0) {
@@ -104,6 +104,10 @@
             for (int i = 0; subscriptions != null && i < subscriptions.size(); i++) {
                 addMobileSection(subscriptions.get(i).getSubscriptionId());
             }
+            mSummaryPreference.setSelectable(true);
+        } else {
+            removePreference(KEY_LIMIT_SUMMARY);
+            mSummaryPreference.setSelectable(false);
         }
         boolean hasWifiRadio = hasWifiRadio(getContext());
         if (hasWifiRadio) {
@@ -116,7 +120,6 @@
                 : hasWifiRadio ? R.string.wifi_data_template
                 : R.string.ethernet_data_template;
 
-        mSummaryPreference = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
         setHasOptionsMenu(true);
     }
 
@@ -142,6 +145,15 @@
         return false;
     }
 
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        if (preference == findPreference(KEY_STATUS_HEADER)) {
+            BillingCycleSettings.BytesEditorFragment.show(this, false);
+            return false;
+        }
+        return super.onPreferenceTreeClick(preference);
+    }
+
     private void addMobileSection(int subId) {
         TemplatePreferenceCategory category = (TemplatePreferenceCategory)
                 inflatePreferences(R.xml.data_usage_cellular);
@@ -213,6 +225,8 @@
         DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
                 mDefaultTemplate);
         Context context = getContext();
+        NetworkPolicy policy = services.mPolicyEditor.getPolicy(mDefaultTemplate);
+        info.warningLevel = policy.warningBytes;
         if (mSummaryPreference != null) {
             mSummaryPreference.setTitle(
                     formatTitle(context, getString(mDataUsageTemplate), info.usageLevel));
@@ -247,6 +261,21 @@
         return MetricsEvent.DATA_USAGE_SUMMARY;
     }
 
+    @Override
+    public NetworkPolicyEditor getNetworkPolicyEditor() {
+        return services.mPolicyEditor;
+    }
+
+    @Override
+    public NetworkTemplate getNetworkTemplate() {
+        return mDefaultTemplate;
+    }
+
+    @Override
+    public void updateDataUsage() {
+        updateState();
+    }
+
     /**
      * Test if device has an ethernet network connection.
      */