Merge "Fix issue #10948509: Crash in procstats when there is no data" into klp-dev

This commit is contained in:
Dianne Hackborn
2013-09-30 00:22:01 +00:00
committed by Android (Google) Code Review
5 changed files with 288 additions and 95 deletions

View File

@@ -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" />

View File

@@ -21,8 +21,8 @@ import android.content.pm.PackageInfo;
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 @@ import java.util.Comparator;
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 @@ public final class ProcStatsEntry implements Parcelable {
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 @@ public final class ProcStatsEntry implements Parcelable {
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) {
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.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,
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 final class ProcStatsEntry implements Parcelable {
}
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 @@ public final class ProcStatsEntry implements Parcelable {
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 @@ public final class ProcStatsEntry implements Parcelable {
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

View File

@@ -168,6 +168,23 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
}
}
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,13 +221,21 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
};
private void fillServicesSection() {
LayoutInflater inflater = getActivity().getLayoutInflater();
if (mEntry.mServices.size() > 0) {
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.clone();
(ArrayList<ProcStatsEntry.Service>)mEntry.mServices.valueAt(ip).clone();
Collections.sort(services, sServiceCompare);
for (int i=0; i<services.size(); i++) {
ProcStatsEntry.Service service = services.get(i);
if (addPackageSections) {
addPackageHeaderItem(mServicesParent, services.get(0).mPackage);
}
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)) {
@@ -223,6 +248,7 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
}
}
}
}
private void killProcesses() {
ActivityManager am = (ActivityManager)getActivity().getSystemService(

View File

@@ -45,7 +45,7 @@ public class ProcessStatsPreference extends Preference {
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();
}

View File

@@ -19,7 +19,6 @@ package com.android.settings.applications;
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.PreferenceActivity;
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.MenuInflater;
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.Collections;
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 @@ public class ProcessStatsUi extends PreferenceFragment {
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 @@ public class ProcessStatsUi extends PreferenceFragment {
// 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 @@ public class ProcessStatsUi extends PreferenceFragment {
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 @@ public class ProcessStatsUi extends PreferenceFragment {
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 @@ public class ProcessStatsUi extends PreferenceFragment {
+ 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 @@ public class ProcessStatsUi extends PreferenceFragment {
}
*/
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,
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);
procs.add(ent);
processes.put(ent.mName, ent);
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,8 +464,15 @@ public class ProcessStatsUi extends PreferenceFragment {
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);
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);
}
}
}
@@ -470,6 +480,71 @@ public class ProcessStatsUi extends PreferenceFragment {
}
}
/*
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() {
try {
mLastDuration = mDuration;