Unbanish memory screen and new UX

Give memory screen a makeover so that it looks nice enough to be
restored to its rightful home.

Bug: 20694769
Change-Id: I2f6933037b3fbbfb0d9fe5e3ca821ef59e171faa
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index 2da39da..2fe631d 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -26,7 +26,8 @@
     // Declare new temporary categories here, starting after this value.
     public static final int UNDECLARED = 100000;
 
-    public static final int APPLICATIONS_MANAGE_ASSIST = UNDECLARED+1;
+    public static final int APPLICATIONS_MANAGE_ASSIST = UNDECLARED + 1;
+    public static final int PROCESS_STATS_SUMMARY = UNDECLARED + 2;
 
     /**
      * Declare the view of this category.
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index d3d515e..b7f62a3 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -147,6 +147,8 @@
     private static final int SECONDS_PER_HOUR = 60 * 60;
     private static final int SECONDS_PER_DAY = 24 * 60 * 60;
 
+    public static final String OS_PKG = "os";
+
     private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<Bitmap>();
 
     /**
diff --git a/src/com/android/settings/applications/LayoutPreference.java b/src/com/android/settings/applications/LayoutPreference.java
index 8a4e533..75387d3 100644
--- a/src/com/android/settings/applications/LayoutPreference.java
+++ b/src/com/android/settings/applications/LayoutPreference.java
@@ -33,6 +33,7 @@
 
     public LayoutPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
+        setSelectable(false);
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, com.android.internal.R.styleable.Preference, 0, 0);
         int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout,
diff --git a/src/com/android/settings/applications/ProcStatsData.java b/src/com/android/settings/applications/ProcStatsData.java
index af7d94d..5dba409 100644
--- a/src/com/android/settings/applications/ProcStatsData.java
+++ b/src/com/android/settings/applications/ProcStatsData.java
@@ -35,6 +35,7 @@
 import com.android.internal.app.ProcessStats.TotalMemoryUseCollection;
 import com.android.internal.util.MemInfoReader;
 import com.android.settings.R;
+import com.android.settings.Utils;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -57,8 +58,6 @@
     private IProcessStats mProcessStats;
     private ProcessStats mStats;
 
-    private int mMemState;
-
     private boolean mUseUss;
     private long mDuration;
 
@@ -187,28 +186,28 @@
         ProcStatsPackageEntry osPkg = new ProcStatsPackageEntry("os", memTotalTime);
         ProcStatsEntry osEntry;
         if (totalMem.sysMemNativeWeight > 0) {
-            osEntry = new ProcStatsEntry("os", 0,
+            osEntry = new ProcStatsEntry(Utils.OS_PKG, 0,
                     mContext.getString(R.string.process_stats_os_native), memTotalTime,
                     (long) (totalMem.sysMemNativeWeight / memTotalTime));
             osEntry.evaluateTargetPackage(mPm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
             osPkg.addEntry(osEntry);
         }
         if (totalMem.sysMemKernelWeight > 0) {
-            osEntry = new ProcStatsEntry("os", 0,
+            osEntry = new ProcStatsEntry(Utils.OS_PKG, 0,
                     mContext.getString(R.string.process_stats_os_kernel), memTotalTime,
                     (long) (totalMem.sysMemKernelWeight / memTotalTime));
             osEntry.evaluateTargetPackage(mPm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
             osPkg.addEntry(osEntry);
         }
         if (totalMem.sysMemZRamWeight > 0) {
-            osEntry = new ProcStatsEntry("os", 0,
+            osEntry = new ProcStatsEntry(Utils.OS_PKG, 0,
                     mContext.getString(R.string.process_stats_os_zram), memTotalTime,
                     (long) (totalMem.sysMemZRamWeight / memTotalTime));
             osEntry.evaluateTargetPackage(mPm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
             osPkg.addEntry(osEntry);
         }
         if (baseCacheRam > 0) {
-            osEntry = new ProcStatsEntry("os", 0,
+            osEntry = new ProcStatsEntry(Utils.OS_PKG, 0,
                     mContext.getString(R.string.process_stats_os_cache), memTotalTime,
                     baseCacheRam / 1024);
             osEntry.evaluateTargetPackage(mPm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
@@ -296,7 +295,6 @@
 
     private void load() {
         try {
-            mMemState = mProcessStats.getCurrentMemoryState();
             ParcelFileDescriptor pfd = mProcessStats.getStatsOverTime(mDuration);
             mStats = new ProcessStats(false);
             InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
diff --git a/src/com/android/settings/applications/ProcStatsPackageEntry.java b/src/com/android/settings/applications/ProcStatsPackageEntry.java
index e056b06..ef74bc6 100644
--- a/src/com/android/settings/applications/ProcStatsPackageEntry.java
+++ b/src/com/android/settings/applications/ProcStatsPackageEntry.java
@@ -23,6 +23,7 @@
 import android.os.Parcelable;
 
 import com.android.settings.R;
+import com.android.settings.Utils;
 
 import java.util.ArrayList;
 
@@ -89,10 +90,10 @@
         final int N = mEntries.size();
         for (int i=0; i < N; i++) {
             ProcStatsEntry entry = mEntries.get(i);
-            mBgDuration += entry.mBgDuration;
+            mBgDuration = Math.max(entry.mBgDuration, mBgDuration);
             mAvgBgMem += entry.mAvgBgMem;
             mBgWeight += entry.mBgWeight;
-            mRunDuration += entry.mRunDuration;
+            mRunDuration = Math.max(entry.mRunDuration, mRunDuration);
             mAvgRunMem += entry.mAvgRunMem;
             mRunWeight += entry.mRunWeight;
 
@@ -161,12 +162,15 @@
 
     // TODO: Find better place for this.
     public static CharSequence getFrequency(float amount, Context context) {
-        if (amount> ALWAYS_THRESHOLD) {
-            return context.getString(R.string.always_running);
-        } else if (amount> SOMETIMES_THRESHOLD) {
-            return context.getString(R.string.sometimes_running);
+        if (amount > ALWAYS_THRESHOLD) {
+            return context.getString(R.string.always_running,
+                    Utils.formatPercentage((int) (amount * 100)));
+        } else if (amount > SOMETIMES_THRESHOLD) {
+            return context.getString(R.string.sometimes_running,
+                    Utils.formatPercentage((int) (amount * 100)));
         } else {
-            return context.getString(R.string.rarely_running);
+            return context.getString(R.string.rarely_running,
+                    Utils.formatPercentage((int) (amount * 100)));
         }
     }
 }
diff --git a/src/com/android/settings/applications/ProcessStatsBase.java b/src/com/android/settings/applications/ProcessStatsBase.java
new file mode 100644
index 0000000..c2f96d2
--- /dev/null
+++ b/src/com/android/settings/applications/ProcessStatsBase.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015 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.applications;
+
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+
+import com.android.internal.app.ProcessStats;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+public abstract class ProcessStatsBase extends SettingsPreferenceFragment
+        implements OnItemSelectedListener {
+    private static final String DURATION = "duration";
+
+    protected static final String ARG_TRANSFER_STATS = "transfer_stats";
+    protected static final String ARG_DURATION_INDEX = "duration_index";
+
+    protected static final int NUM_DURATIONS = 4;
+
+    // The actual duration value to use for each duration option.  Note these
+    // are lower than the actual duration, since our durations are computed in
+    // batches of 3 hours so we want to allow the time we use to be slightly
+    // smaller than the actual time selected instead of bumping up to 3 hours
+    // beyond it.
+    private static final long DURATION_QUANTUM = ProcessStats.COMMIT_PERIOD;
+    protected static long[] sDurations = new long[] {
+        3 * 60 * 60 * 1000 - DURATION_QUANTUM / 2, 6 * 60 *60 * 1000 - DURATION_QUANTUM / 2,
+        12 * 60 * 60 * 1000 - DURATION_QUANTUM / 2, 24 * 60 * 60 * 1000 - DURATION_QUANTUM / 2
+    };
+    protected static int[] sDurationLabels = new int[] {
+            R.string.menu_duration_3h, R.string.menu_duration_6h,
+            R.string.menu_duration_12h, R.string.menu_duration_1d
+    };
+
+    private ViewGroup mSpinnerHeader;
+    private Spinner mFilterSpinner;
+    private ArrayAdapter<String> mFilterAdapter;
+
+    protected ProcStatsData mStatsManager;
+    protected int mDurationIndex;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        Bundle args = getArguments();
+        mStatsManager = new ProcStatsData(getActivity(), icicle != null
+                || (args != null && args.getBoolean(ARG_TRANSFER_STATS, false)));
+
+        mDurationIndex = icicle != null
+                ? icicle.getInt(ARG_DURATION_INDEX)
+                : args != null ? args.getInt(ARG_DURATION_INDEX) : 0;
+        mStatsManager.setDuration(icicle != null
+                ? icicle.getLong(DURATION, sDurations[0]) : sDurations[0]);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putLong(DURATION, mStatsManager.getDuration());
+        outState.putInt(ARG_DURATION_INDEX, mDurationIndex);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mStatsManager.refreshStats(false);
+        refreshUi();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (getActivity().isChangingConfigurations()) {
+            mStatsManager.xferStats();
+        }
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        mSpinnerHeader = (ViewGroup) setPinnedHeaderView(R.layout.apps_filter_spinner);
+        mFilterSpinner = (Spinner) mSpinnerHeader.findViewById(R.id.filter_spinner);
+        mFilterAdapter = new ArrayAdapter<String>(getActivity(), R.layout.filter_spinner_item);
+        mFilterAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        for (int i = 0; i < NUM_DURATIONS; i++) {
+            mFilterAdapter.add(getString(sDurationLabels[i]));
+        }
+        mFilterSpinner.setAdapter(mFilterAdapter);
+        mFilterSpinner.setSelection(mDurationIndex);
+        mFilterSpinner.setOnItemSelectedListener(this);
+    }
+
+    @Override
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        mDurationIndex = position;
+        mStatsManager.setDuration(sDurations[position]);
+        refreshUi();
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
+        // Select something.
+        mFilterSpinner.setSelection(0);
+    }
+
+    public abstract void refreshUi();
+}
diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java
index b29b2fe..1cf5ab4 100644
--- a/src/com/android/settings/applications/ProcessStatsDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsDetail.java
@@ -31,13 +31,15 @@
 import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.os.Process;
+import android.preference.Preference;
 import android.preference.PreferenceCategory;
-import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.View;
-import android.widget.Button;
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
@@ -46,6 +48,7 @@
 import com.android.settings.CancellablePreference.OnCancelListener;
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
 import com.android.settings.applications.ProcStatsEntry.Service;
 
 import java.util.ArrayList;
@@ -54,36 +57,35 @@
 import java.util.HashMap;
 import java.util.List;
 
-public class ProcessStatsDetail extends SettingsPreferenceFragment
-        implements Button.OnClickListener {
+public class ProcessStatsDetail extends SettingsPreferenceFragment {
 
     private static final String TAG = "ProcessStatsDetail";
 
-    public static final int ACTION_FORCE_STOP = 1;
+    public static final int MENU_FORCE_STOP = 1;
 
     public static final String EXTRA_PACKAGE_ENTRY = "package_entry";
-    public static final String EXTRA_USE_USS = "use_uss";
     public static final String EXTRA_WEIGHT_TO_RAM = "weight_to_ram";
     public static final String EXTRA_TOTAL_TIME = "total_time";
     public static final String EXTRA_MAX_MEMORY_USAGE = "max_memory_usage";
     public static final String EXTRA_TOTAL_SCALE = "total_scale";
 
-    private static final String KEY_DETAILS_HEADER = "details_header";
+    private static final String KEY_DETAILS_HEADER = "status_header";
+
+    private static final String KEY_FREQUENCY = "frequency";
+    private static final String KEY_MAX_USAGE = "max_usage";
 
     private final ArrayMap<ComponentName, CancellablePreference> mServiceMap = new ArrayMap<>();
 
     private PackageManager mPm;
     private DevicePolicyManager mDpm;
 
+    private MenuItem mForceStop;
+
     private ProcStatsPackageEntry mApp;
-    private boolean mUseUss;
     private double mWeightToRam;
     private long mTotalTime;
     private long mOnePercentTime;
 
-    private Button mForceStopButton;
-    private Button mReportButton;
-
     private LinearColorBar mColorBar;
 
     private double mMaxMemoryUsage;
@@ -98,7 +100,6 @@
         final Bundle args = getArguments();
         mApp = args.getParcelable(EXTRA_PACKAGE_ENTRY);
         mApp.retrieveUiData(getActivity(), mPm);
-        mUseUss = args.getBoolean(EXTRA_USE_USS);
         mWeightToRam = args.getDouble(EXTRA_WEIGHT_TO_RAM);
         mTotalTime = args.getLong(EXTRA_TOTAL_TIME);
         mMaxMemoryUsage = args.getDouble(EXTRA_MAX_MEMORY_USAGE);
@@ -107,6 +108,7 @@
 
         mServiceMap.clear();
         createDetails();
+        setHasOptionsMenu(true);
     }
 
     @Override
@@ -115,7 +117,8 @@
 
         AppHeader.createAppHeader(this,
                 mApp.mUiTargetApp != null ? mApp.mUiTargetApp.loadIcon(mPm) : new ColorDrawable(0),
-                mApp.mUiLabel, AppInfoWithHeader.getInfoIntent(this, mApp.mPackage));
+                mApp.mUiLabel, mApp.mPackage.equals(Utils.OS_PKG) ? null
+                        : AppInfoWithHeader.getInfoIntent(this, mApp.mPackage));
     }
 
     @Override
@@ -126,8 +129,8 @@
     @Override
     public void onResume() {
         super.onResume();
-        checkForceStop();
 
+        checkForceStop();
         updateRunningServices();
     }
 
@@ -173,55 +176,42 @@
 
         LayoutPreference headerLayout = (LayoutPreference) findPreference(KEY_DETAILS_HEADER);
 
-        TextView avgUsed = (TextView) headerLayout.findViewById(R.id.memory_avg);
-        TextView maxUsed = (TextView) headerLayout.findViewById(R.id.memory_max);
-        avgUsed.setText(getString(R.string.memory_avg_desc,
-                Formatter.formatShortFileSize(getActivity(),
-                        (long) (Math.max(mApp.mBgWeight, mApp.mRunWeight) * mWeightToRam))));
-        maxUsed.setText(getString(R.string.memory_max_desc,
-                Formatter.formatShortFileSize(getActivity(),
-                        (long) (Math.max(mApp.mMaxBgMem, mApp.mMaxRunMem) * 1024 * mTotalScale))));
-
-        mForceStopButton = (Button) headerLayout.findViewById(R.id.right_button);
-        mReportButton = (Button) headerLayout.findViewById(R.id.left_button);
-
-        if (mApp.mEntries.get(0).mUid >= android.os.Process.FIRST_APPLICATION_UID) {
-            mForceStopButton.setEnabled(false);
-            mReportButton.setVisibility(View.INVISIBLE);
-
-            mForceStopButton.setText(R.string.force_stop);
-            mForceStopButton.setTag(ACTION_FORCE_STOP);
-            mForceStopButton.setOnClickListener(this);
-        } else {
-            mReportButton.setVisibility(View.GONE);
-            mForceStopButton.setVisibility(View.GONE);
-        }
-
         // TODO: Find way to share this code with ProcessStatsPreference.
         boolean statsForeground = mApp.mRunWeight > mApp.mBgWeight;
-        float avgRatio = (float) ((statsForeground ? mApp.mRunWeight : mApp.mBgWeight)
-                * mWeightToRam / mMaxMemoryUsage);
-        float maxRatio = (float) ((statsForeground ? mApp.mMaxRunMem : mApp.mMaxBgMem)
-                * mTotalScale * 1024 / mMaxMemoryUsage - avgRatio);
-        float remainingRatio = 1 - avgRatio - maxRatio;
+        double avgRam = (statsForeground ? mApp.mRunWeight : mApp.mBgWeight) * mWeightToRam;
+        float avgRatio = (float) (avgRam / mMaxMemoryUsage);
+        float remainingRatio = 1 - avgRatio;
         mColorBar = (LinearColorBar) headerLayout.findViewById(R.id.color_bar);
         Context context = getActivity();
-        mColorBar.setColors(context.getColor(R.color.memory_avg_use),
-                context.getColor(R.color.memory_max_use),
+        mColorBar.setColors( context.getColor(R.color.memory_max_use), 0,
                 context.getColor(R.color.memory_remaining));
-        mColorBar.setRatios(avgRatio, maxRatio, remainingRatio);
+        mColorBar.setRatios(avgRatio, 0, remainingRatio);
+        ((TextView) headerLayout.findViewById(R.id.memory_state)).setText(
+                Formatter.formatShortFileSize(getContext(), (long) avgRam));
+
+        long duration = Math.max(mApp.mRunDuration, mApp.mBgDuration);
+        CharSequence frequency = ProcStatsPackageEntry.getFrequency(duration
+                / (float) mTotalTime, getActivity());
+        findPreference(KEY_FREQUENCY).setSummary(frequency);
+        double max = Math.max(mApp.mMaxBgMem, mApp.mMaxRunMem) * mTotalScale * 1024;
+        findPreference(KEY_MAX_USAGE).setSummary(
+                Formatter.formatShortFileSize(getContext(), (long) max));
     }
 
-    public void onClick(View v) {
-        doAction((Integer) v.getTag());
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        mForceStop = menu.add(0, MENU_FORCE_STOP, 0, R.string.force_stop);
+        checkForceStop();
     }
 
-    private void doAction(int action) {
-        switch (action) {
-            case ACTION_FORCE_STOP:
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_FORCE_STOP:
                 killProcesses();
-                break;
+                return true;
         }
+        return false;
     }
 
     final static Comparator<ProcStatsEntry> sEntryCompare = new Comparator<ProcStatsEntry>() {
@@ -250,8 +240,7 @@
         Collections.sort(entries, sEntryCompare);
         for (int ie = 0; ie < entries.size(); ie++) {
             ProcStatsEntry entry = entries.get(ie);
-            PreferenceCategory processPref = new PreferenceCategory(getActivity());
-            processPref.setLayoutResource(R.layout.process_preference_category);
+            Preference processPref = new Preference(getActivity());
             processPref.setTitle(entry.mLabel);
 
             long duration = Math.max(entry.mRunDuration, entry.mBgDuration);
@@ -259,11 +248,10 @@
                     (long) (entry.mBgWeight * mWeightToRam));
             String memoryString = Formatter.formatShortFileSize(getActivity(), memoryUse);
             CharSequence frequency = ProcStatsPackageEntry.getFrequency(duration
-                    / (float)mTotalTime, getActivity());
+                    / (float) mTotalTime, getActivity());
             processPref.setSummary(
                     getString(R.string.memory_use_running_format, memoryString, frequency));
             getPreferenceScreen().addPreference(processPref);
-            fillServicesSection(entry, processPref);
         }
     }
 
@@ -423,12 +411,14 @@
                 am.forceStopPackage(ent.mPackages.get(j));
             }
         }
-        checkForceStop();
     }
 
     private void checkForceStop() {
+        if (mForceStop == null) {
+            return;
+        }
         if (mApp.mEntries.get(0).mUid < Process.FIRST_APPLICATION_UID) {
-            mForceStopButton.setEnabled(false);
+            mForceStop.setVisible(false);
             return;
         }
         boolean isStarted = false;
@@ -437,7 +427,7 @@
             for (int j=0; j<ent.mPackages.size(); j++) {
                 String pkg = ent.mPackages.get(j);
                 if (mDpm.packageHasActiveAdmins(pkg)) {
-                    mForceStopButton.setEnabled(false);
+                    mForceStop.setEnabled(false);
                     return;
                 }
                 try {
@@ -450,7 +440,7 @@
             }
         }
         if (isStarted) {
-            mForceStopButton.setEnabled(true);
+            mForceStop.setVisible(true);
         }
     }
 }
diff --git a/src/com/android/settings/applications/ProcessStatsPreference.java b/src/com/android/settings/applications/ProcessStatsPreference.java
index ffbc560..48c6a9f 100644
--- a/src/com/android/settings/applications/ProcessStatsPreference.java
+++ b/src/com/android/settings/applications/ProcessStatsPreference.java
@@ -21,8 +21,8 @@
 import android.graphics.drawable.ColorDrawable;
 import android.preference.Preference;
 import android.text.TextUtils;
+import android.text.format.Formatter;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 
 import com.android.settings.R;
@@ -30,11 +30,9 @@
 public class ProcessStatsPreference extends Preference {
 
     private ProcStatsPackageEntry mEntry;
-    private final int mAvgColor;
-    private final int mMaxColor;
+    private final int mColor;
     private final int mRemainingColor;
-    private float mAvgRatio;
-    private float mMaxRatio;
+    private float mRatio;
     private float mRemainingRatio;
 
     public ProcessStatsPreference(Context context) {
@@ -53,13 +51,12 @@
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
         setLayoutResource(R.layout.app_item_linear_color);
-        mAvgColor = context.getColor(R.color.memory_avg_use);
-        mMaxColor = context.getColor(R.color.memory_max_use);
+        mColor = context.getColor(R.color.memory_max_use);
         mRemainingColor = context.getColor(R.color.memory_remaining);
     }
 
     public void init(ProcStatsPackageEntry entry, PackageManager pm, double maxMemory,
-            double weightToRam, double totalScale) {
+            double weightToRam, double totalScale, boolean avg) {
         mEntry = entry;
         setTitle(TextUtils.isEmpty(entry.mUiLabel) ? entry.mPackage : entry.mUiLabel);
         if (entry.mUiTargetApp != null) {
@@ -68,13 +65,11 @@
             setIcon(new ColorDrawable(0));
         }
         boolean statsForeground = entry.mRunWeight > entry.mBgWeight;
-        setSummary(entry.mRunDuration > entry.mBgDuration ? entry.getRunningFrequency(getContext())
-                : entry.getBackgroundFrequency(getContext()));
-        mAvgRatio = (float) ((statsForeground ? entry.mRunWeight : entry.mBgWeight)
-                * weightToRam / maxMemory);
-        mMaxRatio = (float) ((statsForeground ? entry.mMaxRunMem : entry.mMaxBgMem)
-                * totalScale * 1024 / maxMemory - mAvgRatio);
-        mRemainingRatio = 1 - mAvgRatio - mMaxRatio;
+        double amount = avg ? (statsForeground ? entry.mRunWeight : entry.mBgWeight) * weightToRam
+                : (statsForeground ? entry.mMaxRunMem : entry.mMaxBgMem) * totalScale * 1024;
+        setSummary(Formatter.formatShortFileSize(getContext(), (long) amount));
+        mRatio = (float) (amount / maxMemory);
+        mRemainingRatio = 1 - mRatio;
     }
 
     public ProcStatsPackageEntry getEntry() {
@@ -86,7 +81,7 @@
         super.onBindView(view);
 
         LinearColorBar linearColorBar = (LinearColorBar) view.findViewById(R.id.linear_color_bar);
-        linearColorBar.setColors(mAvgColor, mMaxColor, mRemainingColor);
-        linearColorBar.setRatios(mAvgRatio, mMaxRatio, mRemainingRatio);
+        linearColorBar.setColors(mColor, mColor, mRemainingColor);
+        linearColorBar.setRatios(mRatio, 0, mRemainingRatio);
     }
 }
diff --git a/src/com/android/settings/applications/ProcessStatsSummary.java b/src/com/android/settings/applications/ProcessStatsSummary.java
new file mode 100644
index 0000000..068cb43
--- /dev/null
+++ b/src/com/android/settings/applications/ProcessStatsSummary.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 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.applications;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.text.format.Formatter;
+import android.widget.TextView;
+
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.ProcStatsData.MemInfo;
+
+public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenceClickListener {
+
+    private static final String KEY_STATUS_HEADER = "status_header";
+
+    private static final String KEY_PERFORMANCE = "performance";
+    private static final String KEY_TOTAL_MEMORY = "total_memory";
+    private static final String KEY_AVERAGY_USED = "average_used";
+    private static final String KEY_FREE = "free";
+    private static final String KEY_APP_LIST = "apps_list";
+
+    private LinearColorBar mColors;
+    private LayoutPreference mHeader;
+    private TextView mMemStatus;
+
+    private Preference mPerformance;
+    private Preference mTotalMemory;
+    private Preference mAverageUsed;
+    private Preference mFree;
+    private Preference mAppListPreference;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        addPreferencesFromResource(R.xml.process_stats_summary);
+        mHeader = (LayoutPreference) findPreference(KEY_STATUS_HEADER);
+        mMemStatus = (TextView) mHeader.findViewById(R.id.memory_state);
+        mColors = (LinearColorBar) mHeader.findViewById(R.id.color_bar);
+
+        mPerformance = findPreference(KEY_PERFORMANCE);
+        mTotalMemory = findPreference(KEY_TOTAL_MEMORY);
+        mAverageUsed = findPreference(KEY_AVERAGY_USED);
+        mFree = findPreference(KEY_FREE);
+        mAppListPreference = findPreference(KEY_APP_LIST);
+        mAppListPreference.setOnPreferenceClickListener(this);
+    }
+
+    @Override
+    public void refreshUi() {
+        Context context = getContext();
+        int memColor = context.getColor(R.color.running_processes_apps_ram);
+        mColors.setColors(memColor, memColor, context.getColor(R.color.running_processes_free_ram));
+
+        MemInfo memInfo = mStatsManager.getMemInfo();
+
+        double usedRam = memInfo.realUsedRam;
+        double totalRam = memInfo.realTotalRam;
+        double freeRam = memInfo.realFreeRam;
+        String usedString = Formatter.formatShortFileSize(context, (long) usedRam);
+        String totalString = Formatter.formatShortFileSize(context, (long) totalRam);
+        String freeString = Formatter.formatShortFileSize(context, (long) freeRam);
+        CharSequence memString;
+        CharSequence[] memStatesStr = getResources().getTextArray(R.array.ram_states);
+        int memState = mStatsManager.getMemState();
+        if (memState >= 0 && memState < memStatesStr.length - 1) {
+            memString = memStatesStr[memState];
+        } else {
+            memString = memStatesStr[memStatesStr.length - 1];
+        }
+        mMemStatus.setText(usedString);
+        float usedRatio = (float)(usedRam / (freeRam + usedRam));
+        mColors.setRatios(usedRatio, 0, 1 - usedRatio);
+
+        mPerformance.setSummary(memString);
+        mTotalMemory.setSummary(totalString);
+        mAverageUsed.setSummary(Utils.formatPercentage((long) usedRam, (long) totalRam));
+        mFree.setSummary(freeString);
+        String durationString = getString(sDurationLabels[mDurationIndex]);
+        int numApps = mStatsManager.getEntries().size();
+        mAppListPreference.setSummary(getResources().getQuantityString(
+                R.plurals.memory_usage_apps_summary, numApps, numApps, durationString));
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.PROCESS_STATS_SUMMARY;
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        if (preference == mAppListPreference) {
+            Bundle args = new Bundle();
+            args.putBoolean(ARG_TRANSFER_STATS, true);
+            args.putInt(ARG_DURATION_INDEX, mDurationIndex);
+            mStatsManager.xferStats();
+            startFragment(this, ProcessStatsUi.class.getName(), R.string.app_memory_use, 0, args);
+            return true;
+        }
+        return false;
+    }
+
+}
diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java
index 3dc0661..a4ecbdd 100644
--- a/src/com/android/settings/applications/ProcessStatsUi.java
+++ b/src/com/android/settings/applications/ProcessStatsUi.java
@@ -16,171 +16,89 @@
 
 package com.android.settings.applications;
 
-import android.app.AlertDialog;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
-import android.text.format.Formatter;
 import android.util.Log;
 import android.util.TimeUtils;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.widget.TextView;
 
 import com.android.internal.app.ProcessStats;
 import com.android.internal.logging.MetricsLogger;
-import com.android.settings.InstrumentedPreferenceFragment;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
-import com.android.settings.Utils;
 import com.android.settings.applications.ProcStatsData.MemInfo;
 
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
-public class ProcessStatsUi extends InstrumentedPreferenceFragment {
-    private static final String MEM_REGION = "mem_region";
-    private static final String STATS_TYPE = "stats_type";
-    private static final String USE_USS = "use_uss";
-    private static final String SHOW_SYSTEM = "show_system";
-    private static final String SHOW_PERCENTAGE = "show_percentage";
-    private static final String DURATION = "duration";
+public class ProcessStatsUi extends ProcessStatsBase {
     static final String TAG = "ProcessStatsUi";
     static final boolean DEBUG = false;
 
     private static final String KEY_APP_LIST = "app_list";
-    private static final String KEY_STATUS_HEADER = "status_header";
 
-    private static final int NUM_DURATIONS = 4;
-
-    private static final int MENU_STATS_REFRESH = Menu.FIRST;
-    private static final int MENU_DURATION = Menu.FIRST + 1;
-    private static final int MENU_SHOW_PERCENTAGE = MENU_DURATION + NUM_DURATIONS;
-    private static final int MENU_SHOW_SYSTEM = MENU_SHOW_PERCENTAGE + 1;
-    private static final int MENU_USE_USS = MENU_SHOW_SYSTEM + 1;
-    private static final int MENU_TYPE_BACKGROUND = MENU_USE_USS + 1;
-    private static final int MENU_TYPE_FOREGROUND = MENU_TYPE_BACKGROUND + 1;
-    private static final int MENU_TYPE_CACHED = MENU_TYPE_FOREGROUND + 1;
-
-    static final int MAX_ITEMS_TO_LIST = 60;
-
-    final static Comparator<ProcStatsPackageEntry> sPackageEntryCompare
-            = new Comparator<ProcStatsPackageEntry>() {
-        @Override
-        public int compare(ProcStatsPackageEntry lhs, ProcStatsPackageEntry rhs) {
-            double rhsWeight = Math.max(rhs.mRunWeight, rhs.mBgWeight);
-            double lhsWeight = Math.max(lhs.mRunWeight, lhs.mBgWeight);
-            if (lhsWeight == rhsWeight) {
-                return 0;
-            }
-            return lhsWeight < rhsWeight ? 1 : -1;
-        }
-    };
-
-    private boolean mShowPercentage;
-    private boolean mShowSystem;
-    private boolean mUseUss;
-    private int mMemRegion;
-
-    private MenuItem[] mDurationMenus = new MenuItem[NUM_DURATIONS];
-    private MenuItem mShowPercentageMenu;
-    private MenuItem mShowSystemMenu;
-    private MenuItem mUseUssMenu;
-    private MenuItem mTypeBackgroundMenu;
-    private MenuItem mTypeForegroundMenu;
-    private MenuItem mTypeCachedMenu;
+    private static final int MENU_SHOW_AVG = Menu.FIRST;
+    private static final int MENU_SHOW_MAX = Menu.FIRST + 1;
 
     private PreferenceGroup mAppListGroup;
-    private TextView mMemStatus;
-
-    private long[] mMemTimes = new long[ProcessStats.ADJ_MEM_FACTOR_COUNT];
-    private LinearColorBar mColors;
-    private TextView mMemUsed;
-    private LayoutPreference mHeader;
     private PackageManager mPm;
-    private long memTotalTime;
 
-    private int mStatsType;
-
-    // The actual duration value to use for each duration option.  Note these
-    // are lower than the actual duration, since our durations are computed in
-    // batches of 3 hours so we want to allow the time we use to be slightly
-    // smaller than the actual time selected instead of bumping up to 3 hours
-    // beyond it.
-    private static final long DURATION_QUANTUM = ProcessStats.COMMIT_PERIOD;
-    private static long[] sDurations = new long[] {
-        3*60*60*1000 - DURATION_QUANTUM/2, 6*60*60*1000 - DURATION_QUANTUM/2,
-        12*60*60*1000 - DURATION_QUANTUM/2, 24*60*60*1000 - DURATION_QUANTUM/2
-    };
-    private static int[] sDurationLabels = new int[] {
-            R.string.menu_duration_3h, R.string.menu_duration_6h,
-            R.string.menu_duration_12h, R.string.menu_duration_1d
-    };
-
-    private ProcStatsData mStatsManager;
-    private double mMaxMemoryUsage;
+    private boolean mShowMax;
+    private MenuItem mMenuAvg;
+    private MenuItem mMenuMax;
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        mStatsManager = new ProcStatsData(getActivity(), icicle != null);
-
         mPm = getActivity().getPackageManager();
 
-        addPreferencesFromResource(R.xml.process_stats_summary);
+        addPreferencesFromResource(R.xml.process_stats_ui);
         mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
-        mHeader = (LayoutPreference)mAppListGroup.findPreference(KEY_STATUS_HEADER);
-        mMemStatus = (TextView) mHeader.findViewById(R.id.memory_state);
-        mColors = (LinearColorBar) mHeader.findViewById(R.id.color_bar);
-        mMemUsed = (TextView) mHeader.findViewById(R.id.memory_used);
-        mStatsManager.setDuration(icicle != null
-                ? icicle.getLong(DURATION, sDurations[0]) : sDurations[0]);
-        mShowPercentage = icicle != null ? icicle.getBoolean(SHOW_PERCENTAGE) : true;
-        mShowSystem = icicle != null ? icicle.getBoolean(SHOW_SYSTEM) : false;
-        mUseUss = icicle != null ? icicle.getBoolean(USE_USS) : false;
-        mStatsType = icicle != null ? icicle.getInt(STATS_TYPE, MENU_TYPE_BACKGROUND)
-                : MENU_TYPE_BACKGROUND;
-        mMemRegion = icicle != null ? icicle.getInt(MEM_REGION, LinearColorBar.REGION_GREEN)
-                : LinearColorBar.REGION_GREEN;
         setHasOptionsMenu(true);
     }
 
     @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        mMenuAvg = menu.add(0, MENU_SHOW_AVG, 0, R.string.sort_avg_use);
+        mMenuMax = menu.add(0, MENU_SHOW_MAX, 0, R.string.sort_max_use);
+        updateMenu();
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_SHOW_AVG:
+            case MENU_SHOW_MAX:
+                mShowMax = !mShowMax;
+                refreshUi();
+                updateMenu();
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    private void updateMenu() {
+        mMenuMax.setVisible(!mShowMax);
+        mMenuAvg.setVisible(mShowMax);
+    }
+
+    @Override
     protected int getMetricsCategory() {
         return MetricsLogger.APPLICATIONS_PROCESS_STATS_UI;
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        mStatsManager.refreshStats(false);
-        refreshUi();
-    }
-
-    @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        outState.putLong(DURATION, mStatsManager.getDuration());
-        outState.putBoolean(SHOW_PERCENTAGE, mShowPercentage);
-        outState.putBoolean(SHOW_SYSTEM, mShowSystem);
-        outState.putBoolean(USE_USS, mUseUss);
-        outState.putInt(STATS_TYPE, mStatsType);
-        outState.putInt(MEM_REGION, mMemRegion);
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        if (getActivity().isChangingConfigurations()) {
-            mStatsManager.xferStats();
-        }
     }
 
     @Override
@@ -192,142 +110,19 @@
         ProcessStatsPreference pgp = (ProcessStatsPreference) preference;
         Bundle args = new Bundle();
         args.putParcelable(ProcessStatsDetail.EXTRA_PACKAGE_ENTRY, pgp.getEntry());
-        args.putBoolean(ProcessStatsDetail.EXTRA_USE_USS, mUseUss);
+        MemInfo memInfo = mStatsManager.getMemInfo();
         args.putDouble(ProcessStatsDetail.EXTRA_WEIGHT_TO_RAM,
-                mStatsManager.getMemInfo().weightToRam);
-        args.putLong(ProcessStatsDetail.EXTRA_TOTAL_TIME, memTotalTime);
-        args.putDouble(ProcessStatsDetail.EXTRA_MAX_MEMORY_USAGE, mMaxMemoryUsage);
-        args.putDouble(ProcessStatsDetail.EXTRA_TOTAL_SCALE, mStatsManager.getMemInfo().totalScale);
+                memInfo.weightToRam);
+        args.putLong(ProcessStatsDetail.EXTRA_TOTAL_TIME, memInfo.memTotalTime);
+        args.putDouble(ProcessStatsDetail.EXTRA_MAX_MEMORY_USAGE,
+                memInfo.usedWeight * memInfo.weightToRam);
+        args.putDouble(ProcessStatsDetail.EXTRA_TOTAL_SCALE, memInfo.totalScale);
         ((SettingsActivity) getActivity()).startPreferencePanel(
                 ProcessStatsDetail.class.getName(), args, R.string.details_title, null, null, 0);
 
         return super.onPreferenceTreeClick(preferenceScreen, preference);
     }
 
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        MenuItem refresh = menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh)
-                .setIcon(R.drawable.ic_menu_refresh_holo_dark)
-                .setAlphabeticShortcut('r');
-        refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
-                MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-        menu.add(0, MENU_DURATION, 0, R.string.menu_proc_stats_duration);
-
-        // Hide these for now, until their need is determined.
-//        mShowPercentageMenu = menu.add(0, MENU_SHOW_PERCENTAGE, 0, R.string.menu_show_percentage)
-//                .setAlphabeticShortcut('p')
-//                .setCheckable(true);
-//        mShowSystemMenu = menu.add(0, MENU_SHOW_SYSTEM, 0, R.string.menu_show_system)
-//                .setAlphabeticShortcut('s')
-//                .setCheckable(true);
-//        mUseUssMenu = menu.add(0, MENU_USE_USS, 0, R.string.menu_use_uss)
-//                .setAlphabeticShortcut('u')
-//                .setCheckable(true);
-//        subMenu = menu.addSubMenu(R.string.menu_proc_stats_type);
-//        mTypeBackgroundMenu = subMenu.add(0, MENU_TYPE_BACKGROUND, 0,
-//                R.string.menu_proc_stats_type_background)
-//                .setAlphabeticShortcut('b')
-//                .setCheckable(true);
-//        mTypeForegroundMenu = subMenu.add(0, MENU_TYPE_FOREGROUND, 0,
-//                R.string.menu_proc_stats_type_foreground)
-//                .setAlphabeticShortcut('f')
-//                .setCheckable(true);
-//        mTypeCachedMenu = subMenu.add(0, MENU_TYPE_CACHED, 0,
-//                R.string.menu_proc_stats_type_cached)
-//                .setCheckable(true);
-
-        updateMenus();
-    }
-
-    void updateMenus() {
-        int closestIndex = 0;
-        long closestDelta = Math.abs(sDurations[0] - mStatsManager.getDuration());
-        for (int i = 1; i < NUM_DURATIONS; i++) {
-            long delta = Math.abs(sDurations[i] - mStatsManager.getDuration());
-            if (delta < closestDelta) {
-                closestDelta = delta;
-                closestIndex = i;
-            }
-        }
-        for (int i=0; i<NUM_DURATIONS; i++) {
-            if (mDurationMenus[i] != null) {
-                mDurationMenus[i].setChecked(i == closestIndex);
-            }
-        }
-        mStatsManager.setDuration(sDurations[closestIndex]);
-        if (mShowPercentageMenu != null) {
-            mShowPercentageMenu.setChecked(mShowPercentage);
-        }
-        if (mShowSystemMenu != null) {
-            mShowSystemMenu.setChecked(mShowSystem);
-            mShowSystemMenu.setEnabled(mStatsType == MENU_TYPE_BACKGROUND);
-        }
-        if (mUseUssMenu != null) {
-            mUseUssMenu.setChecked(mUseUss);
-        }
-        if (mTypeBackgroundMenu != null) {
-            mTypeBackgroundMenu.setChecked(mStatsType == MENU_TYPE_BACKGROUND);
-        }
-        if (mTypeForegroundMenu != null) {
-            mTypeForegroundMenu.setChecked(mStatsType == MENU_TYPE_FOREGROUND);
-        }
-        if (mTypeCachedMenu != null) {
-            mTypeCachedMenu.setChecked(mStatsType == MENU_TYPE_CACHED);
-        }
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case MENU_STATS_REFRESH:
-                mStatsManager.refreshStats(false);
-                refreshUi();
-                return true;
-            case MENU_SHOW_PERCENTAGE:
-                mShowPercentage = !mShowPercentage;
-                refreshUi();
-                return true;
-            case MENU_SHOW_SYSTEM:
-                mShowSystem = !mShowSystem;
-                refreshUi();
-                return true;
-            case MENU_USE_USS:
-                mUseUss = !mUseUss;
-                refreshUi();
-                return true;
-            case MENU_TYPE_BACKGROUND:
-            case MENU_TYPE_FOREGROUND:
-            case MENU_TYPE_CACHED:
-                mStatsType = item.getItemId();
-                if (mStatsType == MENU_TYPE_FOREGROUND) {
-                    mStatsManager.setStats(FOREGROUND_PROC_STATES);
-                } else if (mStatsType == MENU_TYPE_CACHED) {
-                    mStatsManager.setStats(CACHED_PROC_STATES);
-                } else {
-                    mStatsManager.setStats(mShowSystem ? BACKGROUND_AND_SYSTEM_PROC_STATES
-                            : ProcessStats.BACKGROUND_PROC_STATES);
-                }
-                refreshUi();
-                return true;
-            case MENU_DURATION:
-                CharSequence[] durations = new CharSequence[sDurationLabels.length];
-                for (int i = 0; i < sDurationLabels.length; i++) {
-                    durations[i] = getString(sDurationLabels[i]);
-                }
-                new AlertDialog.Builder(getContext())
-                        .setTitle(item.getTitle())
-                        .setItems(durations, new DialogInterface.OnClickListener() {
-                            @Override
-                            public void onClick(DialogInterface dialog, int which) {
-                                mStatsManager.setDuration(sDurations[which]);
-                                refreshUi();
-                            }
-                        }).show();
-                return true;
-        }
-        return false;
-    }
-
     /**
      * All states in which we consider a process to be actively running (rather than
      * something that can be freely killed to reclaim RAM).  Note this also includes
@@ -358,103 +153,66 @@
         return sb.toString();
     }
 
-    private void refreshUi() {
-        updateMenus();
-
+    public void refreshUi() {
         mAppListGroup.removeAll();
         mAppListGroup.setOrderingAsAdded(false);
-        mHeader.setOrder(-1);
-        mAppListGroup.addPreference(mHeader);
-
-        final long elapsedTime = mStatsManager.getElapsedTime();
+        mAppListGroup.setTitle(mShowMax ? R.string.maximum_memory_use
+                : R.string.average_memory_use);
 
         final Context context = getActivity();
-        // TODO: More Colors.
-
-        // For computing the ratio to show, we want to count the baseline cached RAM we
-        // need (at which point we start killing processes) as used RAM, so that if we
-        // reach the point of thrashing due to no RAM for any background processes we
-        // report that as RAM being full.  To do this, we need to first convert the weights
-        // back to actual RAM...  and since the RAM values we compute here won't exactly
-        // match the real physical RAM, scale those to the actual physical RAM.  No problem!
         MemInfo memInfo = mStatsManager.getMemInfo();
 
-        memTotalTime = memInfo.memTotalTime;
-        double usedRam = memInfo.realUsedRam;
-        double totalRam = memInfo.realTotalRam;
-        double freeRam = memInfo.realFreeRam;
-        String durationString = Utils.formatElapsedTime(context, elapsedTime, false);
-        String usedString = Formatter.formatShortFileSize(context, (long) usedRam);
-        String totalString = Formatter.formatShortFileSize(context, (long) totalRam);
-        CharSequence memString;
-        CharSequence[] memStatesStr = getResources().getTextArray(R.array.ram_states);
-        int memState = mStatsManager.getMemState();
-        int memColor;
-        if (memState >= 0 && memState < memStatesStr.length) {
-            memString = memStatesStr[memState];
-            memColor = getResources().getIntArray(R.array.ram_colors)[memState];
-        } else {
-            memString = "?";
-            memColor = context.getColor(R.color.running_processes_apps_ram);
-        }
-        mColors.setColors(memColor, memColor, context.getColor(R.color.running_processes_free_ram));
-        if (mShowPercentage) {
-            mMemUsed.setText(context.getString(
-                    R.string.process_stats_total_duration_percentage,
-                    Utils.formatPercentage((long) usedRam, (long) totalRam),
-                    durationString));
-        } else {
-            mMemUsed.setText(context.getString(R.string.process_stats_total_duration,
-                    usedString, totalString, durationString));
-        }
-        mMemStatus.setText(memString);
-        float usedRatio = (float)(usedRam / (freeRam + usedRam));
-        mColors.setRatios(usedRatio, 0, 1-usedRatio);
-
         List<ProcStatsPackageEntry> pkgEntries = mStatsManager.getEntries();
 
         // Update everything and get the absolute maximum of memory usage for scaling.
-        mMaxMemoryUsage = 0;
         for (int i=0, N=pkgEntries.size(); i<N; i++) {
             ProcStatsPackageEntry pkg = pkgEntries.get(i);
             pkg.updateMetrics();
-            double maxMem = Math.max(pkg.mMaxBgMem, pkg.mMaxRunMem) * 1024 * memInfo.totalScale;
-            if (maxMem > mMaxMemoryUsage) {
-                mMaxMemoryUsage = maxMem;
-            }
         }
 
-        Collections.sort(pkgEntries, sPackageEntryCompare);
+        Collections.sort(pkgEntries, mShowMax ? sMaxPackageEntryCompare : sPackageEntryCompare);
 
         // Now collect the per-process information into applications, so that applications
         // running as multiple processes will have only one entry representing all of them.
 
         if (DEBUG) Log.d(TAG, "-------------------- BUILDING UI");
 
-        // Find where we should stop.  Because we have two properties we are looking at,
-        // we need to go from the back looking for the first place either holds.
-        int end = pkgEntries.size()-1;
-        while (end >= 0) {
-            ProcStatsPackageEntry pkg = pkgEntries.get(end);
-            final double percentOfWeight = (pkg.mRunWeight
-                    / (memInfo.totalRam / memInfo.weightToRam)) * 100;
-            final double percentOfTime = (((double) pkg.mRunDuration) / memTotalTime) * 100;
-            if (percentOfWeight >= .01 || percentOfTime >= 25) {
-                break;
-            }
-            end--;
-        }
-        for (int i=0; i <= end; i++) {
+        double maxMemory = mShowMax ? memInfo.realTotalRam
+                : memInfo.usedWeight * memInfo.weightToRam;
+        for (int i = 0; i < pkgEntries.size(); i++) {
             ProcStatsPackageEntry pkg = pkgEntries.get(i);
             ProcessStatsPreference pref = new ProcessStatsPreference(context);
             pkg.retrieveUiData(context, mPm);
-            pref.init(pkg, mPm, mMaxMemoryUsage, memInfo.weightToRam, memInfo.totalScale);
+            pref.init(pkg, mPm, maxMemory, memInfo.weightToRam,
+                    memInfo.totalScale, !mShowMax);
             pref.setOrder(i);
             mAppListGroup.addPreference(pref);
-            if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) {
-                if (DEBUG) Log.d(TAG, "Done with UI, hit item limit!");
-                break;
-            }
         }
     }
+
+    final static Comparator<ProcStatsPackageEntry> sPackageEntryCompare
+            = new Comparator<ProcStatsPackageEntry>() {
+        @Override
+        public int compare(ProcStatsPackageEntry lhs, ProcStatsPackageEntry rhs) {
+            double rhsWeight = Math.max(rhs.mRunWeight, rhs.mBgWeight);
+            double lhsWeight = Math.max(lhs.mRunWeight, lhs.mBgWeight);
+            if (lhsWeight == rhsWeight) {
+                return 0;
+            }
+            return lhsWeight < rhsWeight ? 1 : -1;
+        }
+    };
+
+    final static Comparator<ProcStatsPackageEntry> sMaxPackageEntryCompare
+            = new Comparator<ProcStatsPackageEntry>() {
+        @Override
+        public int compare(ProcStatsPackageEntry lhs, ProcStatsPackageEntry rhs) {
+            double rhsMax = Math.max(rhs.mMaxBgMem, rhs.mMaxRunMem);
+            double lhsMax = Math.max(lhs.mMaxBgMem, lhs.mMaxRunMem);
+            if (lhsMax == rhsMax) {
+                return 0;
+            }
+            return lhsMax < rhsMax ? 1 : -1;
+        }
+    };
 }
diff --git a/src/com/android/settings/applications/SpacePreference.java b/src/com/android/settings/applications/SpacePreference.java
new file mode 100644
index 0000000..deaa987
--- /dev/null
+++ b/src/com/android/settings/applications/SpacePreference.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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.applications;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.Space;
+
+/**
+ * A blank preference that has a specified height by android:layout_height.  It can be used
+ * to fine tune screens that combine custom layouts and standard preferences.
+ */
+public class SpacePreference extends Preference {
+
+    private int mHeight;
+
+    public SpacePreference(Context context, AttributeSet attrs) {
+        this(context, attrs, com.android.internal.R.attr.preferenceStyle);
+    }
+
+    public SpacePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public SpacePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                new int[] { com.android.internal.R.attr.layout_height }, defStyleAttr, defStyleRes);
+        mHeight = a.getDimensionPixelSize(0, 0);
+    }
+
+    public void setHeight(int height) {
+        mHeight = height;
+    }
+
+    @Override
+    protected View onCreateView(ViewGroup parent) {
+        return new Space(getContext());
+    }
+
+    @Override
+    protected void onBindView(View view) {
+        super.onBindView(view);
+
+        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mHeight);
+        view.setLayoutParams(params);
+    }
+
+}