diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 51ff2f2dfd2..f0722a81592 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -801,7 +801,8 @@ + android:excludeFromRecents="true" + android:enabled="false"> diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java index 830878438f0..0821ced2336 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.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 mPackages = new ArrayList(); final long mDuration; final long mAvgPss; final long mMaxPss; @@ -45,33 +46,35 @@ public final class ProcStatsEntry implements Parcelable { String mBestTargetPackage; - ArrayList mServices = new ArrayList(2); + ArrayMap> mServices = new ArrayMap>(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 value = new ArrayList(); + in.readTypedList(value, Service.CREATOR); + mServices.append(key, value); + } + } } - public void evaluateTargetPackage(ProcessStats stats, ProcessStats.ProcessDataCollection totals, - Comparator compare, boolean useUss, boolean weightWithTime) { + public void addPackage(String packageName) { + mPackages.add(packageName); + } + + public void evaluateTargetPackage(PackageManager pm, ProcessStats stats, + ProcessStats.ProcessDataCollection totals, Comparator 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 subProcs = new ArrayList(); - for (int ipkg=0, NPKG=stats.mPackages.getMap().size(); ipkg uids - = stats.mPackages.getMap().valueAt(ipkg); - for (int iu=0, NU=uids.size(); iu 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 subProcServices = null; + for (int isp=0, NSP=mServices.size(); isp 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 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 services = mServices.get(svc.mPackage); + if (services == null) { + services = new ArrayList(); + 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 CREATOR diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java index fad37452363..a1885a74843 100644 --- a/src/com/android/settings/applications/ProcessStatsDetail.java +++ b/src/com/android/settings/applications/ProcessStatsDetail.java @@ -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,22 +221,31 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen }; private void fillServicesSection() { - LayoutInflater inflater = getActivity().getLayoutInflater(); if (mEntry.mServices.size() > 0) { - ArrayList services = - (ArrayList)mEntry.mServices.clone(); - Collections.sort(services, sServiceCompare); - for (int i=0; i= 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 services = + (ArrayList)mEntry.mServices.valueAt(ip).clone(); + Collections.sort(services, sServiceCompare); + if (addPackageSections) { + addPackageHeaderItem(mServicesParent, services.get(0).mPackage); + } + for (int is=0; is= 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))); } - 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 2dea96a3f06..bf2676d4357 100644 --- a/src/com/android/settings/applications/ProcessStatsPreference.java +++ b/src/com/android/settings/applications/ProcessStatsPreference.java @@ -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(); } diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java index b7ffcefaa19..0e27577ed79 100644 --- a/src/com/android/settings/applications/ProcessStatsUi.java +++ b/src/com/android/settings/applications/ProcessStatsUi.java @@ -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 procs = new ArrayList(); + ArrayList entries = new ArrayList(); /* ArrayList rawProcs = mStats.collectProcessesLocked( @@ -407,50 +417,43 @@ public class ProcessStatsUi extends PreferenceFragment { } */ - ArrayMap processes = new ArrayMap( - mStats.mProcesses.getMap().size()); - for (int ip=0, N=mStats.mProcesses.getMap().size(); ip uids = mStats.mProcesses.getMap().valueAt(ip); - for (int iu=0; iu entriesMap = new ProcessMap(); + for (int ipkg=0, N=mStats.mPackages.getMap().size(); ipkg pkgUids + = mStats.mPackages.getMap().valueAt(ipkg); + for (int iu=0; iu 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 (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 @@ public class ProcessStatsUi extends PreferenceFragment { for (int is=0, NS=ps.mServices.size(); is> processes + = new SparseArray>(); + for (int ip=0, N=mStats.mProcesses.getMap().size(); ip uids = mStats.mProcesses.getMap().valueAt(ip); + for (int iu=0; iu 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 uidProcs = processes.get(ent.mUid); + if (uidProcs == null) { + uidProcs = new ArrayMap(); + 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