Fix some things in settings: manage apps, battery, procstats

Issue #17461567: java.lang.ArithmeticException: divide by zero when
looking at Settings > Battery

Yeah, let's not do that.

Issue #17365562: Running services RAM totals are wrong

Okay so like a few months ago, I had this vacation coming up, and
it was around the feature complete (hahah) deadline, and I had to
rush to get this in before I left.  So I rushed.  And, well, I forgot
a few things.  Here they are.  We now show the right numbers and
even update things correctly when you change what processes are
being shown.  Wow.

Finally, fixed a few issues in the dev tools procstats UI.

Change-Id: I8348a9c2ec3226a455c5c8465729e4487f324c8b
diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java
index 03e4b75..30a8817 100644
--- a/src/com/android/settings/applications/ProcessStatsUi.java
+++ b/src/com/android/settings/applications/ProcessStatsUi.java
@@ -404,10 +404,11 @@
         mAppListGroup.removeAll();
         mAppListGroup.setOrderingAsAdded(false);
 
+        final long elapsedTime = mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime;
+
         mMemStatusPref.setOrder(-2);
         mAppListGroup.addPreference(mMemStatusPref);
-        String durationString = Utils.formatElapsedTime(getActivity(),
-                mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime, false);
+        String durationString = Utils.formatElapsedTime(getActivity(), elapsedTime, false);
         CharSequence memString;
         CharSequence[] memStatesStr = getResources().getTextArray(R.array.ram_states);
         if (mMemState >= 0 && mMemState < memStatesStr.length) {
@@ -480,6 +481,15 @@
         int badnessColor = badColors[1 + Math.round(memBadness*(badColors.length-2))];
         colors.setColors(badnessColor, badnessColor, badnessColor);
 
+        // We are now going to scale the mMemTimes to match the total elapsed time.
+        // These are in uptime, so they will often be smaller than the elapsed time,
+        // but if the user taps on the bar we want to show the times to them.  It is confusing
+        // to see them be smaller than what we told them the measured duration is, so just
+        // scaling them up with make things look reasonable with them none the wiser.
+        for (int i=0; i<ProcessStats.ADJ_MEM_FACTOR_COUNT; i++) {
+            mMemTimes[i] = (long)((mMemTimes[i]*(double)elapsedTime)/mTotalTime);
+        }
+
         ProcessStats.TotalMemoryUseCollection totalMem = new ProcessStats.TotalMemoryUseCollection(
                 ProcessStats.ALL_SCREEN_ADJ, memStates);
         mStats.computeTotalMemoryUse(totalMem, now);
@@ -728,15 +738,22 @@
 
         if (DEBUG) Log.d(TAG, "-------------------- BUILDING UI");
 
-        for (int i=0, N=(entries != null ? entries.size() : 0); i<N; i++) {
+        // 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 = entries != null ? entries.size()-1 : -1;
+        while (end >= 0) {
+            ProcStatsEntry proc = entries.get(end);
+            final double percentOfWeight = (((double)proc.mWeight) / mMaxWeight) * 100;
+            final double percentOfTime = (((double)proc.mDuration) / memTotalTime) * 100;
+            if (percentOfWeight >= 1 || percentOfTime >= 25) {
+                break;
+            }
+            end--;
+        }
+        for (int i=0; i<=end; i++) {
             ProcStatsEntry proc = entries.get(i);
             final double percentOfWeight = (((double)proc.mWeight) / mMaxWeight) * 100;
             final double percentOfTime = (((double)proc.mDuration) / memTotalTime) * 100;
-            if (percentOfWeight < 1 && percentOfTime < 33) {
-                if (DEBUG) Log.d(TAG, "Skipping " + proc.mName + " weight=" + percentOfWeight
-                        + " time=" + percentOfTime);
-                continue;
-            }
             ProcessStatsPreference pref = new ProcessStatsPreference(getActivity());
             pref.init(null, proc);
             proc.evaluateTargetPackage(pm, mStats, totals, sEntryCompare, mUseUss,
diff --git a/src/com/android/settings/applications/RunningProcessesView.java b/src/com/android/settings/applications/RunningProcessesView.java
index 58b37ec..13d9655 100644
--- a/src/com/android/settings/applications/RunningProcessesView.java
+++ b/src/com/android/settings/applications/RunningProcessesView.java
@@ -75,18 +75,19 @@
     View mHeader;
     ServiceListAdapter mAdapter;
     LinearColorBar mColorBar;
+    TextView mBackgroundProcessPrefix;
+    TextView mAppsProcessPrefix;
+    TextView mForegroundProcessPrefix;
     TextView mBackgroundProcessText;
     TextView mAppsProcessText;
     TextView mForegroundProcessText;
-    
-    int mLastNumBackgroundProcesses = -1;
-    int mLastNumForegroundProcesses = -1;
-    int mLastNumServiceProcesses = -1;
-    long mLastBackgroundProcessMemory = -1;
-    long mLastForegroundProcessMemory = -1;
-    long mLastServiceProcessMemory = -1;
-    long mLastAvailMemory = -1;
-    
+
+    long mCurTotalRam = -1;
+    long mCurHighRam = -1;      // "System" or "Used"
+    long mCurMedRam = -1;       // "Apps" or "Cached"
+    long mCurLowRam = -1;       // "Free"
+    boolean mCurShowCached = false;
+
     Dialog mCurDialog;
 
     MemInfoReader mMemInfoReader = new MemInfoReader();
@@ -98,7 +99,7 @@
         ViewHolder mHolder;
         long mFirstRunTime;
         boolean mSetBackground;
-        
+
         void updateTime(Context context, StringBuilder builder) {
             TextView uptimeView = null;
             
@@ -126,7 +127,7 @@
                     uptimeView = mHolder.uptime;
                 }
             }
-            
+
             if (uptimeView != null) {
                 mSetBackground = false;
                 if (mFirstRunTime >= 0) {
@@ -228,8 +229,7 @@
                 mShowBackground = showBackground;
                 mState.setWatchingBackgroundItems(showBackground);
                 refreshItems();
-                notifyDataSetChanged();
-                mColorBar.setShowingGreen(mShowBackground);
+                refreshUi(true);
             }
         }
 
@@ -329,53 +329,71 @@
             mDataAvail = null;
         }
 
+        mMemInfoReader.readMemInfo();
+
+        /*
         // This is the amount of available memory until we start killing
         // background services.
-        mMemInfoReader.readMemInfo();
         long availMem = mMemInfoReader.getFreeSize() + mMemInfoReader.getCachedSize()
                 - SECONDARY_SERVER_MEM;
         if (availMem < 0) {
             availMem = 0;
         }
+        */
 
         synchronized (mState.mLock) {
-            if (mLastNumBackgroundProcesses != mState.mNumBackgroundProcesses
-                    || mLastBackgroundProcessMemory != mState.mBackgroundProcessMemory
-                    || mLastNumForegroundProcesses != mState.mNumForegroundProcesses
-                    || mLastForegroundProcessMemory != mState.mForegroundProcessMemory
-                    || mLastNumServiceProcesses != mState.mNumServiceProcesses
-                    || mLastServiceProcessMemory != mState.mServiceProcessMemory
-                    || mLastAvailMemory != availMem) {
-                mLastNumBackgroundProcesses = mState.mNumBackgroundProcesses;
-                mLastBackgroundProcessMemory = mState.mBackgroundProcessMemory;
-                mLastForegroundProcessMemory = mState.mForegroundProcessMemory;
-                mLastServiceProcessMemory = mState.mServiceProcessMemory;
-                mLastAvailMemory = availMem;
-                long freeMem = mLastAvailMemory + mLastBackgroundProcessMemory;
+            if (mCurShowCached != mAdapter.mShowBackground) {
+                mCurShowCached = mAdapter.mShowBackground;
+                if (mCurShowCached) {
+                    mForegroundProcessPrefix.setText(getResources().getText(
+                            R.string.running_processes_header_used_prefix));
+                    mAppsProcessPrefix.setText(getResources().getText(
+                            R.string.running_processes_header_cached_prefix));
+                } else {
+                    mForegroundProcessPrefix.setText(getResources().getText(
+                            R.string.running_processes_header_system_prefix));
+                    mAppsProcessPrefix.setText(getResources().getText(
+                            R.string.running_processes_header_apps_prefix));
+                }
+            }
+
+            final long totalRam = mMemInfoReader.getTotalSize();
+            final long medRam;
+            final long lowRam;
+            if (mCurShowCached) {
+                lowRam = mMemInfoReader.getFreeSize() + mMemInfoReader.getCachedSize();
+                medRam = mState.mBackgroundProcessMemory;
+            } else {
+                lowRam = mMemInfoReader.getFreeSize() + mMemInfoReader.getCachedSize()
+                        + mState.mBackgroundProcessMemory;
+                medRam = mState.mServiceProcessMemory;
+
+            }
+            final long highRam = totalRam - medRam - lowRam;
+
+            if (mCurTotalRam != totalRam || mCurHighRam != highRam || mCurMedRam != medRam
+                    || mCurLowRam != lowRam) {
+                mCurTotalRam = totalRam;
+                mCurHighRam = highRam;
+                mCurMedRam = medRam;
+                mCurLowRam = lowRam;
                 BidiFormatter bidiFormatter = BidiFormatter.getInstance();
                 String sizeStr = bidiFormatter.unicodeWrap(
-                        Formatter.formatShortFileSize(getContext(), freeMem));
+                        Formatter.formatShortFileSize(getContext(), lowRam));
                 mBackgroundProcessText.setText(getResources().getString(
                         R.string.running_processes_header_ram, sizeStr));
                 sizeStr = bidiFormatter.unicodeWrap(
-                        Formatter.formatShortFileSize(getContext(),
-                                mLastForegroundProcessMemory + mLastServiceProcessMemory));
+                        Formatter.formatShortFileSize(getContext(), medRam));
                 mAppsProcessText.setText(getResources().getString(
                         R.string.running_processes_header_ram, sizeStr));
                 sizeStr = bidiFormatter.unicodeWrap(
-                        Formatter.formatShortFileSize(getContext(),
-                                mMemInfoReader.getTotalSize() - freeMem
-                                - mLastForegroundProcessMemory - mLastServiceProcessMemory));
+                        Formatter.formatShortFileSize(getContext(), highRam));
                 mForegroundProcessText.setText(getResources().getString(
                         R.string.running_processes_header_ram, sizeStr));
+                mColorBar.setRatios(highRam/(float)totalRam,
+                        medRam/(float)totalRam,
+                        lowRam/(float)totalRam);
             }
-
-            float totalMem = mMemInfoReader.getTotalSize();
-            float totalShownMem = availMem + mLastBackgroundProcessMemory
-                    + mLastServiceProcessMemory;
-            mColorBar.setRatios((totalMem-totalShownMem)/totalMem,
-                    mLastServiceProcessMemory/totalMem,
-                    mLastBackgroundProcessMemory/totalMem);
         }
     }
     
@@ -435,6 +453,9 @@
         mColorBar.setColors(res.getColor(R.color.running_processes_system_ram),
                 res.getColor(R.color.running_processes_apps_ram),
                 res.getColor(R.color.running_processes_free_ram));
+        mBackgroundProcessPrefix = (TextView)mHeader.findViewById(R.id.freeSizePrefix);
+        mAppsProcessPrefix = (TextView)mHeader.findViewById(R.id.appsSizePrefix);
+        mForegroundProcessPrefix = (TextView)mHeader.findViewById(R.id.systemSizePrefix);
         mBackgroundProcessText = (TextView)mHeader.findViewById(R.id.freeSize);
         mAppsProcessText = (TextView)mHeader.findViewById(R.id.appsSize);
         mForegroundProcessText = (TextView)mHeader.findViewById(R.id.systemSize);
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
index 7aebb17..c16708d 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
@@ -1011,7 +1011,7 @@
             mTimeRemainPath.close();
         }
 
-        if (mStartWallTime > 0) {
+        if (mStartWallTime > 0 && mEndWallTime > mStartWallTime) {
             // Create the time labels at the bottom.
             boolean is24hr = is24Hour();
             Calendar calStart = Calendar.getInstance();