diff --git a/res/values/strings.xml b/res/values/strings.xml index feab24ebebd..b787c8dbe2e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3550,12 +3550,14 @@ - + Process Stats - + Geeky stats about running processes - + Memory use + + Over %1$s diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java new file mode 100644 index 00000000000..dec283f1b73 --- /dev/null +++ b/src/com/android/settings/applications/ProcStatsEntry.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 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 com.android.internal.app.ProcessStats; + +public class ProcStatsEntry { + final String mPackage; + final int mUid; + final String mName; + final boolean mUnique; + final long mDuration; + final long mAvgPss; + final long mWeight; + + ProcStatsEntry(ProcessStats.ProcessState proc, ProcessStats.ProcessDataCollection tmpTotals) { + ProcessStats.computeProcessData(proc, tmpTotals, 0); + mPackage = proc.mPackage; + mUid = proc.mUid; + mName = proc.mName; + mUnique = proc.mCommonProcess == proc; + mDuration = tmpTotals.totalTime; + mAvgPss = tmpTotals.avgPss; + mWeight = mDuration * mAvgPss; + } +} diff --git a/src/com/android/settings/applications/ProcessStatsPreference.java b/src/com/android/settings/applications/ProcessStatsPreference.java index 1b9e85207d3..64ab0b676f3 100644 --- a/src/com/android/settings/applications/ProcessStatsPreference.java +++ b/src/com/android/settings/applications/ProcessStatsPreference.java @@ -36,9 +36,10 @@ public class ProcessStatsPreference extends Preference { setIcon(icon != null ? icon : new ColorDrawable(0)); } - public void setPercent(double percentOfTotal, long pss) { - mProgress = (int) Math.ceil(percentOfTotal); - mProgressText = pss > 0 ? Formatter.formatShortFileSize(getContext(), pss) : ""; + public void setPercent(double percentOfWeight, double percentOfTime) { + mProgress = (int) Math.ceil(percentOfWeight); + mProgressText = getContext().getResources().getString( + R.string.percentage, (int) Math.ceil(percentOfTime)); notifyChanged(); } diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java index 6434e9efe60..3632288a27f 100644 --- a/src/com/android/settings/applications/ProcessStatsUi.java +++ b/src/com/android/settings/applications/ProcessStatsUi.java @@ -31,16 +31,22 @@ import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; +import android.text.format.DateFormat; import android.util.Log; +import android.util.TimeUtils; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import com.android.internal.app.IProcessStats; import com.android.internal.app.ProcessStats; import com.android.settings.R; +import com.android.settings.fuelgauge.Utils; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; public class ProcessStatsUi extends PreferenceFragment { private static final String TAG = "ProcessStatsUi"; @@ -161,6 +167,15 @@ public class ProcessStatsUi extends PreferenceFragment { mMemStatusPref.setOrder(-2); mAppListGroup.addPreference(mMemStatusPref); + String durationString = Utils.formatElapsedTime(getActivity(), + mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime); + mMemStatusPref.setTitle(getActivity().getString(R.string.process_stats_total_duration, + durationString)); + /* + mMemStatusPref.setTitle(DateFormat.format(DateFormat.getBestDateTimePattern( + getActivity().getResources().getConfiguration().locale, + "MMMM dd, yyyy h:mm a"), mStats.mTimePeriodStartClock)); + */ /* BatteryHistoryPreference hist = new BatteryHistoryPreference(getActivity(), mStats); hist.setOrder(-1); @@ -176,45 +191,73 @@ public class ProcessStatsUi extends PreferenceFragment { mTotalTime = ProcessStats.dumpSingleTime(null, null, mStats.mMemFactorDurations, mStats.mMemFactor, mStats.mStartTime, now); - ArrayList procs = mStats.collectProcessesLocked( + ArrayList rawProcs = mStats.collectProcessesLocked( ProcessStats.ALL_SCREEN_ADJ, ProcessStats.ALL_MEM_ADJ, ProcessStats.BACKGROUND_PROC_STATES, now, null); final PackageManager pm = getActivity().getPackageManager(); + ArrayList procs = new ArrayList(); + for (int i=0, N=(rawProcs != null ? rawProcs.size() : 0); i() { + @Override + public int compare(ProcStatsEntry lhs, ProcStatsEntry rhs) { + if (lhs.mWeight < rhs.mWeight) { + return 1; + } else if (lhs.mWeight > rhs.mWeight) { + return -1; + } + return 0; + } + }); + while (procs.size() > MAX_ITEMS_TO_LIST) { + procs.remove(procs.size()-1); + } + + long maxWeight = 0; for (int i=0, N=(procs != null ? procs.size() : 0); i off) { + if (proc.mName.startsWith(proc.mPackage)) { + int off = proc.mPackage.length(); + if (proc.mName.length() > off) { off++; } - label = name + " (" + ps.mName.substring(off) + ")"; + label = name + " (" + proc.mName.substring(off) + ")"; } else { - label = name + " (" + ps.mName + ")"; + label = name + " (" + proc.mName + ")"; } } } catch (PackageManager.NameNotFoundException e) { } } if (targetApp == null) { - String[] packages = pm.getPackagesForUid(ps.mUid); + String[] packages = pm.getPackagesForUid(proc.mUid); for (String pkgName : packages) { try { final PackageInfo pi = pm.getPackageInfo(pkgName, @@ -226,9 +269,10 @@ public class ProcessStatsUi extends PreferenceFragment { final CharSequence nm = pm.getText(pkgName, pi.sharedUserLabel, pi.applicationInfo); if (nm != null) { - label = nm.toString() + " (" + ps.mName + ")"; + label = nm.toString() + " (" + proc.mName + ")"; } else { - label = targetApp.loadLabel(pm).toString() + " (" + ps.mName + ")"; + label = targetApp.loadLabel(pm).toString() + " (" + + proc.mName + ")"; } break; } @@ -240,9 +284,8 @@ public class ProcessStatsUi extends PreferenceFragment { if (targetApp != null) { pref.setIcon(targetApp.loadIcon(pm)); } - pref.setOrder(N+100-i); - ProcessStats.computeProcessData(ps, totals, now); - pref.setPercent(percentOfTotal, totals.avgPss * 1024); + pref.setOrder(i); + pref.setPercent(percentOfWeight, percentOfTime); mAppListGroup.addPreference(pref); if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) break; } @@ -252,16 +295,42 @@ public class ProcessStatsUi extends PreferenceFragment { try { ArrayList fds = new ArrayList(); byte[] data = mProcessStats.getCurrentStats(fds); - for (int i=0; i 0 && (mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime) + < (24*60*60*1000)) { + Log.i(TAG, "Not enough data, loading next file @ " + i); + ProcessStats stats = new ProcessStats(false); + InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(fds.get(i)); + stats.read(stream); + try { + stream.close(); + } catch (IOException e) { + } + if (stats.mReadError == null) { + mStats.add(stats); + StringBuilder sb = new StringBuilder(); + sb.append("Added stats: "); + sb.append(stats.mTimePeriodStartClockStr); + sb.append(", over "); + TimeUtils.formatDuration( + stats.mTimePeriodEndRealtime-stats.mTimePeriodStartRealtime, sb); + Log.i(TAG, sb.toString()); + } else { + Log.w(TAG, "Read error: " + stats.mReadError); + } + i--; + } + while (i >= 0) { + try { + fds.get(i).close(); + } catch (IOException e) { + } + i--; + } } catch (RemoteException e) { Log.e(TAG, "RemoteException:", e); }