Fix issue #10948509: Crash in procstats when there is no data
Also make us much better about determining which app to blame for
a particular running process, organize the display of services by
their owning app, apply some new heuristics for deciding what goes
in the process list so that we can still display interesting processes
when we haven't collected pss data for them yet, etc.
Change-Id: I7e87225d3dabc66cf3ff020b5db48401b14aaf47
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 51ff2f2..f0722a8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -801,7 +801,8 @@
<activity android:name="Settings$AppOpsSummaryActivity"
android:label="@string/app_ops_settings"
android:taskAffinity=""
- android:excludeFromRecents="true">
+ android:excludeFromRecents="true"
+ android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.APP_OPS_SETTINGS" />
diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java
index 8308784..0821ced 100644
--- a/src/com/android/settings/applications/ProcStatsEntry.java
+++ b/src/com/android/settings/applications/ProcStatsEntry.java
@@ -21,8 +21,8 @@
import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.ArrayMap;
import android.util.Log;
-import android.util.SparseArray;
import com.android.internal.app.ProcessStats;
import java.util.ArrayList;
@@ -31,11 +31,12 @@
public final class ProcStatsEntry implements Parcelable {
private static final String TAG = "ProcStatsEntry";
+ private static boolean DEBUG = ProcessStatsUi.DEBUG;
final String mPackage;
final int mUid;
final String mName;
- final boolean mUnique;
+ final ArrayList<String> mPackages = new ArrayList<String>();
final long mDuration;
final long mAvgPss;
final long mMaxPss;
@@ -45,33 +46,35 @@
String mBestTargetPackage;
- ArrayList<Service> mServices = new ArrayList<Service>(2);
+ ArrayMap<String, ArrayList<Service>> mServices = new ArrayMap<String, ArrayList<Service>>(1);
public ApplicationInfo mUiTargetApp;
public String mUiLabel;
public String mUiBaseLabel;
public String mUiPackage;
- public ProcStatsEntry(ProcessStats.ProcessState proc,
+ public ProcStatsEntry(ProcessStats.ProcessState proc, String packageName,
ProcessStats.ProcessDataCollection tmpTotals, boolean useUss, boolean weightWithTime) {
ProcessStats.computeProcessData(proc, tmpTotals, 0);
mPackage = proc.mPackage;
mUid = proc.mUid;
mName = proc.mName;
- mUnique = proc.mCommonProcess == proc;
+ mPackages.add(packageName);
mDuration = tmpTotals.totalTime;
mAvgPss = tmpTotals.avgPss;
mMaxPss = tmpTotals.maxPss;
mAvgUss = tmpTotals.avgUss;
mMaxUss = tmpTotals.maxUss;
mWeight = (weightWithTime ? mDuration : 1) * (useUss ? mAvgUss : mAvgPss);
+ if (DEBUG) Log.d(TAG, "New proc entry " + proc.mName + ": dur=" + mDuration
+ + " avgpss=" + mAvgPss + " weight=" + mWeight);
}
public ProcStatsEntry(Parcel in) {
mPackage = in.readString();
mUid = in.readInt();
mName = in.readString();
- mUnique = in.readInt() != 0;
+ in.readStringList(mPackages);
mDuration = in.readLong();
mAvgPss = in.readLong();
mMaxPss = in.readLong();
@@ -79,40 +82,118 @@
mMaxUss = in.readLong();
mWeight = in.readLong();
mBestTargetPackage = in.readString();
- in.readTypedList(mServices, Service.CREATOR);
+ final int N = in.readInt();
+ if (N > 0) {
+ mServices.ensureCapacity(N);
+ for (int i=0; i<N; i++) {
+ String key = in.readString();
+ ArrayList<Service> value = new ArrayList<Service>();
+ in.readTypedList(value, Service.CREATOR);
+ mServices.append(key, value);
+ }
+ }
}
- public void evaluateTargetPackage(ProcessStats stats, ProcessStats.ProcessDataCollection totals,
- Comparator<ProcStatsEntry> compare, boolean useUss, boolean weightWithTime) {
+ public void addPackage(String packageName) {
+ mPackages.add(packageName);
+ }
+
+ public void evaluateTargetPackage(PackageManager pm, ProcessStats stats,
+ ProcessStats.ProcessDataCollection totals, Comparator<ProcStatsEntry> compare,
+ boolean useUss, boolean weightWithTime) {
mBestTargetPackage = null;
- if (mUnique) {
- mBestTargetPackage = mPackage;
+ if (mPackages.size() == 1) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": single pkg " + mPackages.get(0));
+ mBestTargetPackage = mPackages.get(0);
} else {
// See if there is one significant package that was running here.
ArrayList<ProcStatsEntry> subProcs = new ArrayList<ProcStatsEntry>();
- for (int ipkg=0, NPKG=stats.mPackages.getMap().size(); ipkg<NPKG; ipkg++) {
- SparseArray<ProcessStats.PackageState> uids
- = stats.mPackages.getMap().valueAt(ipkg);
- for (int iu=0, NU=uids.size(); iu<NU; iu++) {
- if (uids.keyAt(iu) != mUid) {
- continue;
- }
- ProcessStats.PackageState pkgState = uids.valueAt(iu);
- for (int iproc=0, NPROC=pkgState.mProcesses.size(); iproc<NPROC; iproc++) {
- ProcessStats.ProcessState subProc =
- pkgState.mProcesses.valueAt(iproc);
- if (subProc.mName.equals(mName)) {
- subProcs.add(new ProcStatsEntry(subProc, totals, useUss,
- weightWithTime));
- }
- }
+ for (int ipkg=0; ipkg<mPackages.size(); ipkg++) {
+ ProcessStats.PackageState pkgState = stats.mPackages.get(mPackages.get(ipkg), mUid);
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ", pkg "
+ + mPackages.get(ipkg) + ":");
+ if (pkgState == null) {
+ Log.w(TAG, "No package state found for " + mPackages.get(ipkg) + "/"
+ + mUid + " in process " + mName);
+ continue;
}
+ ProcessStats.ProcessState pkgProc = pkgState.mProcesses.get(mName);
+ if (pkgProc == null) {
+ Log.w(TAG, "No process " + mName + " found in package state "
+ + mPackages.get(ipkg) + "/" + mUid);
+ continue;
+ }
+ subProcs.add(new ProcStatsEntry(pkgProc, pkgState.mPackageName, totals, useUss,
+ weightWithTime));
}
if (subProcs.size() > 1) {
Collections.sort(subProcs, compare);
if (subProcs.get(0).mWeight > (subProcs.get(1).mWeight*3)) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": best pkg "
+ + subProcs.get(0).mPackage + " weight " + subProcs.get(0).mWeight
+ + " better than " + subProcs.get(1).mPackage
+ + " weight " + subProcs.get(1).mWeight);
mBestTargetPackage = subProcs.get(0).mPackage;
+ return;
}
+ // Couldn't find one that is best by weight, let's decide on best another
+ // way: the one that has the longest running service, accounts for at least
+ // half of the maximum weight, and has specified an explicit app icon.
+ long maxWeight = subProcs.get(0).mWeight;
+ long bestRunTime = -1;
+ for (int i=0; i<subProcs.size(); i++) {
+ if (subProcs.get(i).mWeight < (maxWeight/2)) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProcs.get(i).mPackage + " weight " + subProcs.get(i).mWeight
+ + " too small");
+ continue;
+ }
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(subProcs.get(i).mPackage, 0);
+ if (ai.icon == 0) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProcs.get(i).mPackage + " has no icon");
+ continue;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProcs.get(i).mPackage + " failed finding app info");
+ continue;
+ }
+ ArrayList<Service> subProcServices = null;
+ for (int isp=0, NSP=mServices.size(); isp<NSP; isp++) {
+ ArrayList<Service> subServices = mServices.valueAt(isp);
+ if (subServices.get(0).mPackage.equals(subProcs.get(i).mPackage)) {
+ subProcServices = subServices;
+ break;
+ }
+ }
+ long thisRunTime = 0;
+ if (subProcServices != null) {
+ for (int iss=0, NSS=subProcServices.size(); iss<NSS; iss++) {
+ Service service = subProcServices.get(iss);
+ if (service.mDuration > thisRunTime) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProcs.get(i).mPackage + " service " + service.mName
+ + " run time is " + service.mDuration);
+ thisRunTime = service.mDuration;
+ break;
+ }
+ }
+ }
+ if (thisRunTime > bestRunTime) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProcs.get(i).mPackage + " new best run time " + thisRunTime);
+ mBestTargetPackage = subProcs.get(i).mPackage;
+ bestRunTime = thisRunTime;
+ } else {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProcs.get(i).mPackage + " run time " + thisRunTime
+ + " not as good as last " + bestRunTime);
+ }
+ }
+ } else if (subProcs.size() == 1) {
+ mBestTargetPackage = subProcs.get(0).mPackage;
}
}
}
@@ -178,7 +259,12 @@
}
public void addService(ProcessStats.ServiceState svc) {
- mServices.add(new Service(svc));
+ ArrayList<Service> services = mServices.get(svc.mPackage);
+ if (services == null) {
+ services = new ArrayList<Service>();
+ mServices.put(svc.mPackage, services);
+ }
+ services.add(new Service(svc));
}
@Override
@@ -191,7 +277,7 @@
dest.writeString(mPackage);
dest.writeInt(mUid);
dest.writeString(mName);
- dest.writeInt(mUnique ? 1 : 0);
+ dest.writeStringList(mPackages);
dest.writeLong(mDuration);
dest.writeLong(mAvgPss);
dest.writeLong(mMaxPss);
@@ -199,7 +285,12 @@
dest.writeLong(mMaxUss);
dest.writeLong(mWeight);
dest.writeString(mBestTargetPackage);
- dest.writeTypedList(mServices);
+ final int N = mServices.size();
+ dest.writeInt(N);
+ for (int i=0; i<N; i++) {
+ dest.writeString(mServices.keyAt(i));
+ dest.writeTypedList(mServices.valueAt(i));
+ }
}
public static final Parcelable.Creator<ProcStatsEntry> CREATOR
diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java
index fad3745..a1885a7 100644
--- a/src/com/android/settings/applications/ProcessStatsDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsDetail.java
@@ -168,6 +168,23 @@
}
}
+ private void addPackageHeaderItem(ViewGroup parent, String packageName) {
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ ViewGroup item = (ViewGroup) inflater.inflate(R.layout.running_processes_item,
+ null);
+ parent.addView(item);
+ final ImageView icon = (ImageView) item.findViewById(R.id.icon);
+ TextView nameView = (TextView) item.findViewById(R.id.name);
+ TextView descriptionView = (TextView) item.findViewById(R.id.description);
+ try {
+ ApplicationInfo ai = mPm.getApplicationInfo(packageName, 0);
+ icon.setImageDrawable(ai.loadIcon(mPm));
+ nameView.setText(ai.loadLabel(mPm));
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ descriptionView.setText(packageName);
+ }
+
private void addDetailsItem(ViewGroup parent, CharSequence label, CharSequence value) {
LayoutInflater inflater = getActivity().getLayoutInflater();
ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_detail_item_text,
@@ -204,22 +221,31 @@
};
private void fillServicesSection() {
- LayoutInflater inflater = getActivity().getLayoutInflater();
if (mEntry.mServices.size() > 0) {
- ArrayList<ProcStatsEntry.Service> services =
- (ArrayList<ProcStatsEntry.Service>)mEntry.mServices.clone();
- Collections.sort(services, sServiceCompare);
- for (int i=0; i<services.size(); i++) {
- ProcStatsEntry.Service service = services.get(i);
- String label = service.mName;
- int tail = label.lastIndexOf('.');
- if (tail >= 0 && tail < (label.length()-1)) {
- label = label.substring(tail+1);
+ boolean addPackageSections = false;
+ if (mEntry.mServices.size() > 1
+ || !mEntry.mServices.valueAt(0).get(0).mPackage.equals(mEntry.mPackage)) {
+ addPackageSections = true;
+ }
+ for (int ip=0; ip<mEntry.mServices.size(); ip++) {
+ ArrayList<ProcStatsEntry.Service> services =
+ (ArrayList<ProcStatsEntry.Service>)mEntry.mServices.valueAt(ip).clone();
+ Collections.sort(services, sServiceCompare);
+ if (addPackageSections) {
+ addPackageHeaderItem(mServicesParent, services.get(0).mPackage);
}
- long duration = service.mDuration;
- final double percentOfTime = (((double)duration) / mTotalTime) * 100;
- addDetailsItem(mServicesParent, label, getActivity().getResources().getString(
- R.string.percentage, (int) Math.ceil(percentOfTime)));
+ for (int is=0; is<services.size(); is++) {
+ ProcStatsEntry.Service service = services.get(is);
+ String label = service.mName;
+ int tail = label.lastIndexOf('.');
+ if (tail >= 0 && tail < (label.length()-1)) {
+ label = label.substring(tail+1);
+ }
+ long duration = service.mDuration;
+ final double percentOfTime = (((double)duration) / mTotalTime) * 100;
+ addDetailsItem(mServicesParent, label, getActivity().getResources().getString(
+ R.string.percentage, (int) Math.ceil(percentOfTime)));
+ }
}
}
}
diff --git a/src/com/android/settings/applications/ProcessStatsPreference.java b/src/com/android/settings/applications/ProcessStatsPreference.java
index 2dea96a..bf2676d 100644
--- a/src/com/android/settings/applications/ProcessStatsPreference.java
+++ b/src/com/android/settings/applications/ProcessStatsPreference.java
@@ -45,7 +45,7 @@
public void setPercent(double percentOfWeight, double percentOfTime) {
mProgress = (int) Math.ceil(percentOfWeight);
mProgressText = getContext().getResources().getString(
- R.string.percentage, (int) Math.ceil(percentOfTime));
+ R.string.percentage, (int) Math.round(percentOfTime));
notifyChanged();
}
diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java
index b7ffcef..0e27577 100644
--- a/src/com/android/settings/applications/ProcessStatsUi.java
+++ b/src/com/android/settings/applications/ProcessStatsUi.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -30,7 +29,6 @@
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
-import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -39,6 +37,7 @@
import android.view.MenuItem;
import android.view.SubMenu;
import com.android.internal.app.IProcessStats;
+import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
import com.android.settings.R;
import com.android.settings.fuelgauge.Utils;
@@ -50,8 +49,8 @@
import java.util.Comparator;
public class ProcessStatsUi extends PreferenceFragment {
- private static final String TAG = "ProcessStatsUi";
- private static final boolean DEBUG = false;
+ static final String TAG = "ProcessStatsUi";
+ static final boolean DEBUG = false;
private static final String KEY_APP_LIST = "app_list";
private static final String KEY_MEM_STATUS = "mem_status";
@@ -76,6 +75,10 @@
return 1;
} else if (lhs.mWeight > rhs.mWeight) {
return -1;
+ } else if (lhs.mDuration < rhs.mDuration) {
+ return 1;
+ } else if (lhs.mDuration > rhs.mDuration) {
+ return -1;
}
return 0;
}
@@ -112,7 +115,7 @@
// 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 = 3*60*60*1000;
+ 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
@@ -319,6 +322,12 @@
ProcessStats.STATE_CACHED_EMPTY
};
+ private String makeDuration(long time) {
+ StringBuilder sb = new StringBuilder(32);
+ TimeUtils.formatDuration(time, sb);
+ return sb.toString();
+ }
+
private void refreshStats() {
updateMenus();
@@ -378,6 +387,7 @@
mTotalTime = ProcessStats.dumpSingleTime(null, null, mStats.mMemFactorDurations,
mStats.mMemFactor, mStats.mStartTime, now);
+ if (DEBUG) Log.d(TAG, "Total time of stats: " + makeDuration(mTotalTime));
LinearColorPreference colors = new LinearColorPreference(getActivity());
colors.setOrder(-1);
@@ -396,7 +406,7 @@
+ memTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE]) / (float)mTotalTime,
memTimes[ProcessStats.ADJ_MEM_FACTOR_NORMAL] / (float)mTotalTime);
- ArrayList<ProcStatsEntry> procs = new ArrayList<ProcStatsEntry>();
+ ArrayList<ProcStatsEntry> entries = new ArrayList<ProcStatsEntry>();
/*
ArrayList<ProcessStats.ProcessState> rawProcs = mStats.collectProcessesLocked(
@@ -407,50 +417,43 @@
}
*/
- ArrayMap<String, ProcStatsEntry> processes = new ArrayMap<String, ProcStatsEntry>(
- mStats.mProcesses.getMap().size());
- for (int ip=0, N=mStats.mProcesses.getMap().size(); ip<N; ip++) {
- SparseArray<ProcessStats.ProcessState> uids = mStats.mProcesses.getMap().valueAt(ip);
- for (int iu=0; iu<uids.size(); iu++) {
- ProcStatsEntry ent = new ProcStatsEntry(uids.valueAt(iu), totals, mUseUss,
- mStatsType == MENU_TYPE_BACKGROUND);
- procs.add(ent);
- processes.put(ent.mName, ent);
+ if (DEBUG) Log.d(TAG, "-------------------- PULLING PROCESSES");
+
+ final ProcessMap<ProcStatsEntry> entriesMap = new ProcessMap<ProcStatsEntry>();
+ for (int ipkg=0, N=mStats.mPackages.getMap().size(); ipkg<N; ipkg++) {
+ final SparseArray<ProcessStats.PackageState> pkgUids
+ = mStats.mPackages.getMap().valueAt(ipkg);
+ for (int iu=0; iu<pkgUids.size(); iu++) {
+ final ProcessStats.PackageState st = pkgUids.valueAt(iu);
+ for (int iproc=0; iproc<st.mProcesses.size(); iproc++) {
+ final ProcessStats.ProcessState pkgProc = st.mProcesses.valueAt(iproc);
+ final ProcessStats.ProcessState proc = mStats.mProcesses.get(pkgProc.mName,
+ pkgProc.mUid);
+ if (proc == null) {
+ Log.w(TAG, "No process found for pkg " + st.mPackageName
+ + "/" + st.mUid + " proc name " + pkgProc.mName);
+ continue;
+ }
+ ProcStatsEntry ent = entriesMap.get(proc.mName, proc.mUid);
+ if (ent == null) {
+ ent = new ProcStatsEntry(proc, st.mPackageName, totals, mUseUss,
+ mStatsType == MENU_TYPE_BACKGROUND);
+ if (ent.mDuration > 0) {
+ if (DEBUG) Log.d(TAG, "Adding proc " + proc.mName + "/"
+ + proc.mUid + ": time=" + makeDuration(ent.mDuration) + " ("
+ + ((((double)ent.mDuration) / mTotalTime) * 100) + "%)"
+ + " pss=" + ent.mAvgPss);
+ entriesMap.put(proc.mName, proc.mUid, ent);
+ entries.add(ent);
+ }
+ } else {
+ ent.addPackage(st.mPackageName);
+ }
+ }
}
}
- Collections.sort(procs, sEntryCompare);
- 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<N; i++) {
- ProcStatsEntry proc = procs.get(i);
- if (maxWeight < proc.mWeight) {
- maxWeight = proc.mWeight;
- }
- }
- mMaxWeight = maxWeight;
-
- for (int i=0, N=(procs != null ? procs.size() : 0); i<N; i++) {
- ProcStatsEntry proc = procs.get(i);
- final double percentOfWeight = (((double)proc.mWeight) / maxWeight) * 100;
- final double percentOfTime = (((double)proc.mDuration) / mTotalTime) * 100;
- if (percentOfWeight < 1) break;
- ProcessStatsPreference pref = new ProcessStatsPreference(getActivity(), null, proc);
- proc.evaluateTargetPackage(mStats, totals, sEntryCompare, mUseUss,
- mStatsType == MENU_TYPE_BACKGROUND);
- proc.retrieveUiData(pm);
- pref.setTitle(proc.mUiLabel);
- if (proc.mUiTargetApp != null) {
- pref.setIcon(proc.mUiTargetApp.loadIcon(pm));
- }
- pref.setOrder(i);
- pref.setPercent(percentOfWeight, percentOfTime);
- mAppListGroup.addPreference(pref);
- if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) break;
- }
+ if (DEBUG) Log.d(TAG, "-------------------- MAPPING SERVICES");
// Add in service info.
if (mStatsType == MENU_TYPE_BACKGROUND) {
@@ -461,13 +464,85 @@
for (int is=0, NS=ps.mServices.size(); is<NS; is++) {
ProcessStats.ServiceState ss = ps.mServices.valueAt(is);
if (ss.mProcessName != null) {
- ProcStatsEntry ent = processes.get(ss.mProcessName);
- ent.addService(ss);
+ ProcStatsEntry ent = entriesMap.get(ss.mProcessName, uids.keyAt(iu));
+ if (ent != null) {
+ if (DEBUG) Log.d(TAG, "Adding service " + ps.mPackageName
+ + "/" + ss.mName + "/" + uids.keyAt(iu) + " to proc "
+ + ss.mProcessName);
+ ent.addService(ss);
+ } else {
+ Log.w(TAG, "No process " + ss.mProcessName + "/" + uids.keyAt(iu)
+ + " for service " + ss.mName);
+ }
}
}
}
}
}
+
+ /*
+ SparseArray<ArrayMap<String, ProcStatsEntry>> processes
+ = new SparseArray<ArrayMap<String, ProcStatsEntry>>();
+ for (int ip=0, N=mStats.mProcesses.getMap().size(); ip<N; ip++) {
+ SparseArray<ProcessStats.ProcessState> uids = mStats.mProcesses.getMap().valueAt(ip);
+ for (int iu=0; iu<uids.size(); iu++) {
+ ProcessStats.ProcessState st = uids.valueAt(iu);
+ ProcStatsEntry ent = new ProcStatsEntry(st, totals, mUseUss,
+ mStatsType == MENU_TYPE_BACKGROUND);
+ if (ent.mDuration > 0) {
+ if (DEBUG) Log.d(TAG, "Adding proc " + st.mName + "/" + st.mUid + ": time="
+ + makeDuration(ent.mDuration) + " ("
+ + ((((double)ent.mDuration) / mTotalTime) * 100) + "%)");
+ procs.add(ent);
+ ArrayMap<String, ProcStatsEntry> uidProcs = processes.get(ent.mUid);
+ if (uidProcs == null) {
+ uidProcs = new ArrayMap<String, ProcStatsEntry>();
+ processes.put(ent.mUid, uidProcs);
+ }
+ uidProcs.put(ent.mName, ent);
+ }
+ }
+ }
+ */
+
+ Collections.sort(entries, sEntryCompare);
+
+ long maxWeight = 1;
+ for (int i=0, N=(entries != null ? entries.size() : 0); i<N; i++) {
+ ProcStatsEntry proc = entries.get(i);
+ if (maxWeight < proc.mWeight) {
+ maxWeight = proc.mWeight;
+ }
+ }
+ mMaxWeight = maxWeight;
+
+ if (DEBUG) Log.d(TAG, "-------------------- BUILDING UI");
+
+ for (int i=0, N=(entries != null ? entries.size() : 0); i<N; i++) {
+ ProcStatsEntry proc = entries.get(i);
+ final double percentOfWeight = (((double)proc.mWeight) / maxWeight) * 100;
+ final double percentOfTime = (((double)proc.mDuration) / mTotalTime) * 100;
+ if (percentOfWeight < 1 && percentOfTime < 33) {
+ if (DEBUG) Log.d(TAG, "Skipping " + proc.mName + " weight=" + percentOfWeight
+ + " time=" + percentOfTime);
+ continue;
+ }
+ ProcessStatsPreference pref = new ProcessStatsPreference(getActivity(), null, proc);
+ proc.evaluateTargetPackage(pm, mStats, totals, sEntryCompare, mUseUss,
+ mStatsType == MENU_TYPE_BACKGROUND);
+ proc.retrieveUiData(pm);
+ pref.setTitle(proc.mUiLabel);
+ if (proc.mUiTargetApp != null) {
+ pref.setIcon(proc.mUiTargetApp.loadIcon(pm));
+ }
+ pref.setOrder(i);
+ pref.setPercent(percentOfWeight, percentOfTime);
+ mAppListGroup.addPreference(pref);
+ if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) {
+ if (DEBUG) Log.d(TAG, "Done with UI, hit item limit!");
+ break;
+ }
+ }
}
private void load() {