summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/settings/applications/ProcStatsEntry.java330
-rw-r--r--src/com/android/settings/applications/ProcStatsPackageEntry.java145
-rw-r--r--src/com/android/settings/applications/ProcessStatsDetail.java231
-rw-r--r--src/com/android/settings/applications/ProcessStatsPreference.java11
-rw-r--r--src/com/android/settings/applications/ProcessStatsUi.java243
5 files changed, 586 insertions, 374 deletions
diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java
index 8702478..6cb6997 100644
--- a/src/com/android/settings/applications/ProcStatsEntry.java
+++ b/src/com/android/settings/applications/ProcStatsEntry.java
@@ -21,6 +21,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
@@ -38,37 +39,49 @@ public final class ProcStatsEntry implements Parcelable {
final int mUid;
final String mName;
final ArrayList<String> mPackages = new ArrayList<String>();
- final long mDuration;
- final long mAvgPss;
- final long mMaxPss;
- final long mAvgUss;
- final long mMaxUss;
- final long mWeight;
+ final long mBgDuration;
+ final long mAvgBgMem;
+ final long mMaxBgMem;
+ final double mBgWeight;
+ final long mRunDuration;
+ final long mAvgRunMem;
+ final long mMaxRunMem;
+ final double mRunWeight;
String mBestTargetPackage;
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, String packageName,
- ProcessStats.ProcessDataCollection tmpTotals, boolean useUss, boolean weightWithTime) {
- ProcessStats.computeProcessData(proc, tmpTotals, 0);
+ ProcessStats.ProcessDataCollection tmpBgTotals,
+ ProcessStats.ProcessDataCollection tmpRunTotals, boolean useUss) {
+ ProcessStats.computeProcessData(proc, tmpBgTotals, 0);
+ ProcessStats.computeProcessData(proc, tmpRunTotals, 0);
mPackage = proc.mPackage;
mUid = proc.mUid;
mName = proc.mName;
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);
+ mBgDuration = tmpBgTotals.totalTime;
+ mAvgBgMem = useUss ? tmpBgTotals.avgUss : tmpBgTotals.avgPss;
+ mMaxBgMem = useUss ? tmpBgTotals.maxUss : tmpBgTotals.maxPss;
+ mBgWeight = mAvgBgMem * (double) mBgDuration;
+ mRunDuration = tmpRunTotals.totalTime;
+ mAvgRunMem = useUss ? tmpRunTotals.avgUss : tmpRunTotals.avgPss;
+ mMaxRunMem = useUss ? tmpRunTotals.maxUss : tmpRunTotals.maxPss;
+ mRunWeight = mAvgRunMem * (double) mRunDuration;
+ if (DEBUG) Log.d(TAG, "New proc entry " + proc.mName + ": dur=" + mBgDuration
+ + " avgpss=" + mAvgBgMem + " weight=" + mBgWeight);
+ }
+
+ public ProcStatsEntry(String pkgName, int uid, String procName, long duration, long mem) {
+ mPackage = pkgName;
+ mUid = uid;
+ mName = procName;
+ mBgDuration = mRunDuration = duration;
+ mAvgBgMem = mMaxBgMem = mAvgRunMem = mMaxRunMem = mem;
+ mBgWeight = mRunWeight = ((double)duration) * mem;
+ if (DEBUG) Log.d(TAG, "New proc entry " + procName + ": dur=" + mBgDuration
+ + " avgpss=" + mAvgBgMem + " weight=" + mBgWeight);
}
public ProcStatsEntry(Parcel in) {
@@ -76,12 +89,14 @@ public final class ProcStatsEntry implements Parcelable {
mUid = in.readInt();
mName = in.readString();
in.readStringList(mPackages);
- mDuration = in.readLong();
- mAvgPss = in.readLong();
- mMaxPss = in.readLong();
- mAvgUss = in.readLong();
- mMaxUss = in.readLong();
- mWeight = in.readLong();
+ mBgDuration = in.readLong();
+ mAvgBgMem = in.readLong();
+ mMaxBgMem = in.readLong();
+ mBgWeight = in.readDouble();
+ mRunDuration = in.readLong();
+ mAvgRunMem = in.readLong();
+ mMaxRunMem = in.readLong();
+ mRunWeight = in.readDouble();
mBestTargetPackage = in.readString();
final int N = in.readInt();
if (N > 0) {
@@ -100,166 +115,139 @@ public final class ProcStatsEntry implements Parcelable {
}
public void evaluateTargetPackage(PackageManager pm, ProcessStats stats,
- ProcessStats.ProcessDataCollection totals, Comparator<ProcStatsEntry> compare,
- boolean useUss, boolean weightWithTime) {
+ ProcessStats.ProcessDataCollection bgTotals,
+ ProcessStats.ProcessDataCollection runTotals, Comparator<ProcStatsEntry> compare,
+ boolean useUss) {
mBestTargetPackage = null;
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; ipkg<mPackages.size(); ipkg++) {
- SparseArray<ProcessStats.PackageState> vpkgs
- = stats.mPackages.get(mPackages.get(ipkg), mUid);
- for (int ivers=0; ivers<vpkgs.size(); ivers++) {
- ProcessStats.PackageState pkgState = vpkgs.valueAt(ivers);
- if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ", pkg "
- + pkgState + ":");
- 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));
+ return;
+ }
+
+ // If one of the packages is the framework itself, that wins.
+ // See if there is one significant package that was running here.
+ for (int ipkg=0; ipkg<mPackages.size(); ipkg++) {
+ if ("android".equals(mPackages.get(ipkg))) {
+ mBestTargetPackage = mPackages.get(ipkg);
+ return;
+ }
+ }
+
+ // Collect information about each package running in the process.
+ ArrayList<ProcStatsEntry> subProcs = new ArrayList<>();
+ for (int ipkg=0; ipkg<mPackages.size(); ipkg++) {
+ SparseArray<ProcessStats.PackageState> vpkgs
+ = stats.mPackages.get(mPackages.get(ipkg), mUid);
+ for (int ivers=0; ivers<vpkgs.size(); ivers++) {
+ ProcessStats.PackageState pkgState = vpkgs.valueAt(ivers);
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ", pkg "
+ + pkgState + ":");
+ 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, bgTotals,
+ runTotals, useUss));
+ }
+ }
+
+ if (subProcs.size() > 1) {
+ Collections.sort(subProcs, compare);
+ if (subProcs.get(0).mRunWeight > (subProcs.get(1).mRunWeight *3)) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": best pkg "
+ + subProcs.get(0).mPackage + " weight " + subProcs.get(0).mRunWeight
+ + " better than " + subProcs.get(1).mPackage
+ + " weight " + subProcs.get(1).mRunWeight);
+ mBestTargetPackage = subProcs.get(0).mPackage;
+ return;
}
- 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.
+ double maxWeight = subProcs.get(0).mRunWeight;
+ long bestRunTime = -1;
+ boolean bestPersistent = false;
+ for (int i=0; i<subProcs.size(); i++) {
+ final ProcStatsEntry subProc = subProcs.get(i);
+ if (subProc.mRunWeight < (maxWeight/2)) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProc.mPackage + " weight " + subProc.mRunWeight
+ + " too small");
+ continue;
}
- // 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)) {
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(subProc.mPackage, 0);
+ if (ai.icon == 0) {
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
- + subProcs.get(i).mPackage + " weight " + subProcs.get(i).mWeight
- + " too small");
+ + subProc.mPackage + " has no icon");
continue;
}
- try {
- ApplicationInfo ai = pm.getApplicationInfo(subProcs.get(i).mPackage, 0);
- if (ai.icon == 0) {
+ if ((ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0) {
+ long thisRunTime = subProc.mRunDuration;
+ if (!bestPersistent || thisRunTime > bestRunTime) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProc.mPackage + " new best pers run time "
+ + thisRunTime);
+ bestRunTime = thisRunTime;
+ bestPersistent = true;
+ } else {
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
- + subProcs.get(i).mPackage + " has no icon");
- continue;
+ + subProc.mPackage + " pers run time " + thisRunTime
+ + " not as good as last " + bestRunTime);
}
- } 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) {
+ } else if (bestPersistent) {
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);
+ + subProc.mPackage + " is not persistent");
+ continue;
}
+ } catch (PackageManager.NameNotFoundException e) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProc.mPackage + " failed finding app info");
+ continue;
}
- } else if (subProcs.size() == 1) {
- mBestTargetPackage = subProcs.get(0).mPackage;
- }
- }
- }
-
- public void retrieveUiData(PackageManager pm) {
- mUiTargetApp = null;
- mUiLabel = mUiBaseLabel = mName;
- mUiPackage = mBestTargetPackage;
- if (mUiPackage != null) {
- // Only one app associated with this process.
- try {
- mUiTargetApp = pm.getApplicationInfo(mUiPackage,
- PackageManager.GET_DISABLED_COMPONENTS |
- PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
- PackageManager.GET_UNINSTALLED_PACKAGES);
- String name = mUiBaseLabel = mUiTargetApp.loadLabel(pm).toString();
- if (mName.equals(mUiPackage)) {
- mUiLabel = name;
- } else {
- if (mName.startsWith(mUiPackage)) {
- int off = mUiPackage.length();
- if (mName.length() > off) {
- off++;
- }
- mUiLabel = name + " (" + mName.substring(off) + ")";
- } else {
- mUiLabel = name + " (" + mName + ")";
+ 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(subProc.mPackage)) {
+ subProcServices = subServices;
+ break;
}
}
- } catch (PackageManager.NameNotFoundException e) {
- }
- }
- if (mUiTargetApp == null) {
- String[] packages = pm.getPackagesForUid(mUid);
- if (packages != null) {
- for (String curPkg : packages) {
- try {
- final PackageInfo pi = pm.getPackageInfo(curPkg,
- PackageManager.GET_DISABLED_COMPONENTS |
- PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
- PackageManager.GET_UNINSTALLED_PACKAGES);
- if (pi.sharedUserLabel != 0) {
- mUiTargetApp = pi.applicationInfo;
- final CharSequence nm = pm.getText(curPkg,
- pi.sharedUserLabel, pi.applicationInfo);
- if (nm != null) {
- mUiBaseLabel = nm.toString();
- mUiLabel = mUiBaseLabel + " (" + mName + ")";
- } else {
- mUiBaseLabel = mUiTargetApp.loadLabel(pm).toString();
- mUiLabel = mUiBaseLabel + " (" + mName + ")";
- }
+ 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 "
+ + subProc.mPackage + " service " + service.mName
+ + " run time is " + service.mDuration);
+ thisRunTime = service.mDuration;
break;
}
- } catch (PackageManager.NameNotFoundException e) {
}
}
- } else {
- // no current packages for this uid, typically because of uninstall
- Log.i(TAG, "No package for uid " + mUid);
+ if (thisRunTime > bestRunTime) {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProc.mPackage + " new best run time " + thisRunTime);
+ mBestTargetPackage = subProc.mPackage;
+ bestRunTime = thisRunTime;
+ } else {
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
+ + subProc.mPackage + " run time " + thisRunTime
+ + " not as good as last " + bestRunTime);
+ }
}
+ } else if (subProcs.size() == 1) {
+ mBestTargetPackage = subProcs.get(0).mPackage;
}
}
@@ -283,12 +271,14 @@ public final class ProcStatsEntry implements Parcelable {
dest.writeInt(mUid);
dest.writeString(mName);
dest.writeStringList(mPackages);
- dest.writeLong(mDuration);
- dest.writeLong(mAvgPss);
- dest.writeLong(mMaxPss);
- dest.writeLong(mAvgUss);
- dest.writeLong(mMaxUss);
- dest.writeLong(mWeight);
+ dest.writeLong(mBgDuration);
+ dest.writeLong(mAvgBgMem);
+ dest.writeLong(mMaxBgMem);
+ dest.writeDouble(mBgWeight);
+ dest.writeLong(mRunDuration);
+ dest.writeLong(mAvgRunMem);
+ dest.writeLong(mMaxRunMem);
+ dest.writeDouble(mRunWeight);
dest.writeString(mBestTargetPackage);
final int N = mServices.size();
dest.writeInt(N);
diff --git a/src/com/android/settings/applications/ProcStatsPackageEntry.java b/src/com/android/settings/applications/ProcStatsPackageEntry.java
new file mode 100644
index 0000000..3925d1d
--- /dev/null
+++ b/src/com/android/settings/applications/ProcStatsPackageEntry.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 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 android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+
+public class ProcStatsPackageEntry implements Parcelable {
+ private static final String TAG = "ProcStatsEntry";
+ private static boolean DEBUG = ProcessStatsUi.DEBUG;
+
+ final String mPackage;
+ final ArrayList<ProcStatsEntry> mEntries = new ArrayList<ProcStatsEntry>();
+
+ long mBgDuration;
+ long mAvgBgMem;
+ long mMaxBgMem;
+ double mBgWeight;
+ long mRunDuration;
+ long mAvgRunMem;
+ long mMaxRunMem;
+ double mRunWeight;
+
+ public ApplicationInfo mUiTargetApp;
+ public String mUiLabel;
+
+ public ProcStatsPackageEntry(String pkg) {
+ mPackage = pkg;
+ }
+
+ public ProcStatsPackageEntry(Parcel in) {
+ mPackage = in.readString();
+ in.readTypedList(mEntries, ProcStatsEntry.CREATOR);
+ mBgDuration = in.readLong();
+ mAvgBgMem = in.readLong();
+ mMaxBgMem = in.readLong();
+ mBgWeight = in.readDouble();
+ mRunDuration = in.readLong();
+ mAvgRunMem = in.readLong();
+ mMaxRunMem = in.readLong();
+ mRunWeight = in.readDouble();
+ }
+
+ public void addEntry(ProcStatsEntry entry) {
+ mEntries.add(entry);
+ }
+
+ public void updateMetrics() {
+ mBgDuration = mAvgBgMem = mMaxBgMem = 0;
+ mBgWeight = 0;
+ mRunDuration = mAvgRunMem = mMaxRunMem = 0;
+ mRunWeight = 0;
+ final int N = mEntries.size();
+ for (int i=0; i<N; i++) {
+ ProcStatsEntry entry = mEntries.get(i);
+ mBgDuration += entry.mBgDuration;
+ mAvgBgMem += entry.mAvgBgMem;
+ if (entry.mMaxBgMem > mMaxBgMem) {
+ mMaxBgMem = entry.mMaxBgMem;
+ }
+ mBgWeight += entry.mBgWeight;
+ mRunDuration += entry.mRunDuration;
+ mAvgRunMem += entry.mAvgRunMem;
+ if (entry.mMaxRunMem > mMaxRunMem) {
+ mMaxRunMem = entry.mMaxRunMem;
+ }
+ mRunWeight += entry.mRunWeight;
+ }
+ mAvgBgMem /= N;
+ mAvgRunMem /= N;
+ }
+
+ public void retrieveUiData(Context context, PackageManager pm) {
+ mUiTargetApp = null;
+ mUiLabel = mPackage;
+ // Only one app associated with this process.
+ try {
+ if ("os".equals(mPackage)) {
+ mUiTargetApp = pm.getApplicationInfo("android",
+ PackageManager.GET_DISABLED_COMPONENTS |
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ mUiLabel = context.getString(R.string.process_stats_os_label);
+ } else {
+ mUiTargetApp = pm.getApplicationInfo(mPackage,
+ PackageManager.GET_DISABLED_COMPONENTS |
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ mUiLabel = mUiTargetApp.loadLabel(pm).toString();
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mPackage);
+ dest.writeTypedList(mEntries);
+ dest.writeLong(mBgDuration);
+ dest.writeLong(mAvgBgMem);
+ dest.writeLong(mMaxBgMem);
+ dest.writeDouble(mBgWeight);
+ dest.writeLong(mRunDuration);
+ dest.writeLong(mAvgRunMem);
+ dest.writeLong(mMaxRunMem);
+ dest.writeDouble(mRunWeight);
+ }
+
+ public static final Parcelable.Creator<ProcStatsPackageEntry> CREATOR
+ = new Parcelable.Creator<ProcStatsPackageEntry>() {
+ public ProcStatsPackageEntry createFromParcel(Parcel in) {
+ return new ProcStatsPackageEntry(in);
+ }
+
+ public ProcStatsPackageEntry[] newArray(int size) {
+ return new ProcStatsPackageEntry[size];
+ }
+ };
+}
diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java
index 30f6b52..f0e76d4 100644
--- a/src/com/android/settings/applications/ProcessStatsDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsDetail.java
@@ -16,20 +16,14 @@
package com.android.settings.applications;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
-import android.os.UserHandle;
import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,6 +38,7 @@ import com.android.settings.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import static com.android.settings.Utils.prepareCustomPreferencesList;
@@ -52,25 +47,28 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
public static final int ACTION_FORCE_STOP = 1;
- public static final String EXTRA_ENTRY = "entry";
+ public static final String EXTRA_PACKAGE_ENTRY = "package_entry";
public static final String EXTRA_USE_USS = "use_uss";
public static final String EXTRA_MAX_WEIGHT = "max_weight";
+ public static final String EXTRA_WEIGHT_TO_RAM = "weight_to_ram";
public static final String EXTRA_TOTAL_TIME = "total_time";
private PackageManager mPm;
private DevicePolicyManager mDpm;
- private ProcStatsEntry mEntry;
+ private ProcStatsPackageEntry mApp;
private boolean mUseUss;
- private long mMaxWeight;
+ private double mMaxWeight;
+ private double mWeightToRam;
private long mTotalTime;
+ private long mOnePercentTime;
private View mRootView;
private TextView mTitleView;
private ViewGroup mTwoButtonsPanel;
private Button mForceStopButton;
private Button mReportButton;
- private ViewGroup mDetailsParent;
+ private ViewGroup mProcessesParent;
private ViewGroup mServicesParent;
@Override
@@ -79,11 +77,13 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
mPm = getActivity().getPackageManager();
mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
final Bundle args = getArguments();
- mEntry = (ProcStatsEntry)args.getParcelable(EXTRA_ENTRY);
- mEntry.retrieveUiData(mPm);
+ mApp = args.getParcelable(EXTRA_PACKAGE_ENTRY);
+ mApp.retrieveUiData(getActivity(), mPm);
mUseUss = args.getBoolean(EXTRA_USE_USS);
- mMaxWeight = args.getLong(EXTRA_MAX_WEIGHT);
+ mMaxWeight = args.getDouble(EXTRA_MAX_WEIGHT);
+ mWeightToRam = args.getDouble(EXTRA_WEIGHT_TO_RAM);
mTotalTime = args.getLong(EXTRA_TOTAL_TIME);
+ mOnePercentTime = mTotalTime/100;
}
@Override
@@ -109,24 +109,22 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
}
private void createDetails() {
- final double percentOfWeight = (((double)mEntry.mWeight) / mMaxWeight) * 100;
+ final double percentOfWeight = (mApp.mBgWeight / mMaxWeight) * 100;
int appLevel = (int) Math.ceil(percentOfWeight);
- String appLevelText = Utils.formatPercentage(mEntry.mDuration, mTotalTime);
+ String appLevelText = Formatter.formatShortFileSize(getActivity(),
+ (long)(mApp.mRunWeight * mWeightToRam));
// Set all values in the header.
- final TextView summary = (TextView) mRootView.findViewById(android.R.id.summary);
- summary.setText(mEntry.mName);
- summary.setVisibility(View.VISIBLE);
mTitleView = (TextView) mRootView.findViewById(android.R.id.title);
- mTitleView.setText(mEntry.mUiBaseLabel);
+ mTitleView.setText(mApp.mUiLabel);
final TextView text1 = (TextView)mRootView.findViewById(android.R.id.text1);
text1.setText(appLevelText);
final ProgressBar progress = (ProgressBar) mRootView.findViewById(android.R.id.progress);
progress.setProgress(appLevel);
final ImageView icon = (ImageView) mRootView.findViewById(android.R.id.icon);
- if (mEntry.mUiTargetApp != null) {
- icon.setImageDrawable(mEntry.mUiTargetApp.loadIcon(mPm));
+ if (mApp.mUiTargetApp != null) {
+ icon.setImageDrawable(mApp.mUiTargetApp.loadIcon(mPm));
}
mTwoButtonsPanel = (ViewGroup)mRootView.findViewById(R.id.two_buttons_panel);
@@ -135,13 +133,17 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
mForceStopButton.setEnabled(false);
mReportButton.setVisibility(View.INVISIBLE);
- mDetailsParent = (ViewGroup)mRootView.findViewById(R.id.details);
+ mProcessesParent = (ViewGroup)mRootView.findViewById(R.id.processes);
mServicesParent = (ViewGroup)mRootView.findViewById(R.id.services);
- fillDetailsSection();
+ fillProcessesSection();
fillServicesSection();
+ if (mServicesParent.getChildCount() <= 0) {
+ mServicesParent.setVisibility(View.GONE);
+ mRootView.findViewById(R.id.services_label).setVisibility(View.GONE);
+ }
- if (mEntry.mUid >= android.os.Process.FIRST_APPLICATION_UID) {
+ if (mApp.mEntries.get(0).mUid >= android.os.Process.FIRST_APPLICATION_UID) {
mForceStopButton.setText(R.string.force_stop);
mForceStopButton.setTag(ACTION_FORCE_STOP);
mForceStopButton.setOnClickListener(this);
@@ -191,15 +193,43 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
valueView.setText(value);
}
- private void fillDetailsSection() {
- addDetailsItem(mDetailsParent, getResources().getText(R.string.process_stats_avg_ram_use),
- Formatter.formatShortFileSize(getActivity(),
- (mUseUss ? mEntry.mAvgUss : mEntry.mAvgPss) * 1024));
- addDetailsItem(mDetailsParent, getResources().getText(R.string.process_stats_max_ram_use),
- Formatter.formatShortFileSize(getActivity(),
- (mUseUss ? mEntry.mMaxUss : mEntry.mMaxPss) * 1024));
- addDetailsItem(mDetailsParent, getResources().getText(R.string.process_stats_run_time),
- Utils.formatPercentage(mEntry.mDuration, mTotalTime));
+ final static Comparator<ProcStatsEntry> sEntryCompare = new Comparator<ProcStatsEntry>() {
+ @Override
+ public int compare(ProcStatsEntry lhs, ProcStatsEntry rhs) {
+ if (lhs.mRunWeight < rhs.mRunWeight) {
+ return 1;
+ } else if (lhs.mRunWeight > rhs.mRunWeight) {
+ return -1;
+ }
+ return 0;
+ }
+ };
+
+ private void fillProcessesSection() {
+ final ArrayList<ProcStatsEntry> entries = new ArrayList<>();
+ for (int ie=0; ie<mApp.mEntries.size(); ie++) {
+ ProcStatsEntry entry = mApp.mEntries.get(ie);
+ entries.add(entry);
+ }
+ Collections.sort(entries, sEntryCompare);
+ for (int ie=0; ie<entries.size(); ie++) {
+ ProcStatsEntry entry = entries.get(ie);
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ ViewGroup item = (ViewGroup) inflater.inflate(R.layout.process_stats_proc_details,
+ null);
+ mProcessesParent.addView(item);
+ ((TextView)item.findViewById(R.id.processes_name)).setText(entry.mName);
+ addDetailsItem(item, getResources().getText(R.string.process_stats_ram_use),
+ Formatter.formatShortFileSize(getActivity(),
+ (long)(entry.mRunWeight * mWeightToRam)));
+ if (entry.mBgWeight > 0) {
+ addDetailsItem(item, getResources().getText(R.string.process_stats_bg_ram_use),
+ Formatter.formatShortFileSize(getActivity(),
+ (long)(entry.mBgWeight * mWeightToRam)));
+ }
+ addDetailsItem(item, getResources().getText(R.string.process_stats_run_time),
+ Utils.formatPercentage(entry.mRunDuration, mTotalTime));
+ }
}
final static Comparator<ProcStatsEntry.Service> sServiceCompare
@@ -215,55 +245,65 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
}
};
- final static Comparator<ArrayList<ProcStatsEntry.Service>> sServicePkgCompare
- = new Comparator<ArrayList<ProcStatsEntry.Service>>() {
+ final static Comparator<PkgService> sServicePkgCompare = new Comparator<PkgService>() {
@Override
- public int compare(ArrayList<ProcStatsEntry.Service> lhs,
- ArrayList<ProcStatsEntry.Service> rhs) {
- long topLhs = lhs.size() > 0 ? lhs.get(0).mDuration : 0;
- long topRhs = rhs.size() > 0 ? rhs.get(0).mDuration : 0;
- if (topLhs < topRhs) {
+ public int compare(PkgService lhs, PkgService rhs) {
+ if (lhs.mDuration < rhs.mDuration) {
return 1;
- } else if (topLhs > topRhs) {
+ } else if (lhs.mDuration > rhs.mDuration) {
return -1;
}
return 0;
}
};
+ static class PkgService {
+ final ArrayList<ProcStatsEntry.Service> mServices = new ArrayList<>();
+ long mDuration;
+ }
+
private void fillServicesSection() {
- if (mEntry.mServices.size() > 0) {
- boolean addPackageSections = false;
- // Sort it all.
- ArrayList<ArrayList<ProcStatsEntry.Service>> servicePkgs
- = new ArrayList<ArrayList<ProcStatsEntry.Service>>();
- 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);
- servicePkgs.add(services);
+ final HashMap<String, PkgService> pkgServices = new HashMap<>();
+ final ArrayList<PkgService> pkgList = new ArrayList<>();
+ for (int ie=0; ie< mApp.mEntries.size(); ie++) {
+ ProcStatsEntry ent = mApp.mEntries.get(ie);
+ for (int ip=0; ip<ent.mServices.size(); ip++) {
+ String pkg = ent.mServices.keyAt(ip);
+ PkgService psvc = null;
+ ArrayList<ProcStatsEntry.Service> services = ent.mServices.valueAt(ip);
+ for (int is=services.size()-1; is>=0; is--) {
+ ProcStatsEntry.Service pent = services.get(is);
+ if (pent.mDuration >= mOnePercentTime) {
+ if (psvc == null) {
+ psvc = pkgServices.get(pkg);
+ if (psvc == null) {
+ psvc = new PkgService();
+ pkgServices.put(pkg, psvc);
+ pkgList.add(psvc);
+ }
+ }
+ psvc.mServices.add(pent);
+ psvc.mDuration += pent.mDuration;
+ }
+ }
}
- if (mEntry.mServices.size() > 1
- || !mEntry.mServices.valueAt(0).get(0).mPackage.equals(mEntry.mPackage)) {
- addPackageSections = true;
- // Sort these so that the one(s) with the longest run durations are on top.
- Collections.sort(servicePkgs, sServicePkgCompare);
+ }
+ Collections.sort(pkgList, sServicePkgCompare);
+ for (int ip=0; ip<pkgList.size(); ip++) {
+ ArrayList<ProcStatsEntry.Service> services = pkgList.get(ip).mServices;
+ Collections.sort(services, sServiceCompare);
+ if (pkgList.size() > 1) {
+ addPackageHeaderItem(mServicesParent, services.get(0).mPackage);
}
- for (int ip=0; ip<servicePkgs.size(); ip++) {
- ArrayList<ProcStatsEntry.Service> services = servicePkgs.get(ip);
- 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)) {
- label = label.substring(tail+1);
- }
- String percentage = Utils.formatPercentage(service.mDuration, mTotalTime);
- addDetailsItem(mServicesParent, label, percentage);
+ 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);
}
+ String percentage = Utils.formatPercentage(service.mDuration, mTotalTime);
+ addDetailsItem(mServicesParent, label, percentage);
}
}
}
@@ -271,39 +311,40 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
private void killProcesses() {
ActivityManager am = (ActivityManager)getActivity().getSystemService(
Context.ACTIVITY_SERVICE);
- am.forceStopPackage(mEntry.mUiPackage);
+ for (int i=0; i< mApp.mEntries.size(); i++) {
+ ProcStatsEntry ent = mApp.mEntries.get(i);
+ for (int j=0; j<ent.mPackages.size(); j++) {
+ am.forceStopPackage(ent.mPackages.get(j));
+ }
+ }
checkForceStop();
}
- private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED);
- }
- };
-
private void checkForceStop() {
- if (mEntry.mUiPackage == null || mEntry.mUid < Process.FIRST_APPLICATION_UID) {
+ if (mApp.mEntries.get(0).mUid < Process.FIRST_APPLICATION_UID) {
mForceStopButton.setEnabled(false);
return;
}
- if (mDpm.packageHasActiveAdmins(mEntry.mUiPackage)) {
- mForceStopButton.setEnabled(false);
- return;
- }
- try {
- ApplicationInfo info = mPm.getApplicationInfo(mEntry.mUiPackage, 0);
- if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {
- mForceStopButton.setEnabled(true);
+ boolean isStarted = false;
+ for (int i=0; i< mApp.mEntries.size(); i++) {
+ ProcStatsEntry ent = mApp.mEntries.get(i);
+ for (int j=0; j<ent.mPackages.size(); j++) {
+ String pkg = ent.mPackages.get(j);
+ if (mDpm.packageHasActiveAdmins(pkg)) {
+ mForceStopButton.setEnabled(false);
+ return;
+ }
+ try {
+ ApplicationInfo info = mPm.getApplicationInfo(pkg, 0);
+ if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {
+ isStarted = true;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
}
- } catch (PackageManager.NameNotFoundException e) {
}
- Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
- Uri.fromParts("package", mEntry.mUiPackage, null));
- intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { mEntry.mUiPackage });
- intent.putExtra(Intent.EXTRA_UID, mEntry.mUid);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mEntry.mUid));
- getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
- Activity.RESULT_CANCELED, null, null);
+ if (isStarted) {
+ mForceStopButton.setEnabled(true);
+ }
}
}
diff --git a/src/com/android/settings/applications/ProcessStatsPreference.java b/src/com/android/settings/applications/ProcessStatsPreference.java
index adf80e5..a0839d3 100644
--- a/src/com/android/settings/applications/ProcessStatsPreference.java
+++ b/src/com/android/settings/applications/ProcessStatsPreference.java
@@ -29,7 +29,7 @@ import com.android.settings.R;
import com.android.settings.Utils;
public class ProcessStatsPreference extends Preference {
- private ProcStatsEntry mEntry;
+ private ProcStatsPackageEntry mEntry;
private int mProgress;
private CharSequence mProgressText;
@@ -51,18 +51,19 @@ public class ProcessStatsPreference extends Preference {
setLayoutResource(R.layout.preference_app_percentage);
}
- public void init(Drawable icon, ProcStatsEntry entry) {
+ public void init(Drawable icon, ProcStatsPackageEntry entry) {
mEntry = entry;
setIcon(icon != null ? icon : new ColorDrawable(0));
}
- public ProcStatsEntry getEntry() {
+ public ProcStatsPackageEntry getEntry() {
return mEntry;
}
- public void setPercent(double percentOfWeight, double percentOfTime) {
+ public void setPercent(double percentOfWeight, double percentOfTime, long memory) {
mProgress = (int) Math.ceil(percentOfWeight);
- mProgressText = Utils.formatPercentage((int) percentOfTime);
+ //mProgressText = Utils.formatPercentage((int) percentOfTime);
+ mProgressText = Formatter.formatShortFileSize(getContext(), memory);
notifyChanged();
}
diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java
index 30a8817..a5ebd22 100644
--- a/src/com/android/settings/applications/ProcessStatsUi.java
+++ b/src/com/android/settings/applications/ProcessStatsUi.java
@@ -19,6 +19,7 @@ package com.android.settings.applications;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -50,6 +51,7 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
public class ProcessStatsUi extends PreferenceFragment
implements LinearColorBar.OnRegionTappedListener {
@@ -75,13 +77,30 @@ public class ProcessStatsUi extends PreferenceFragment
final static Comparator<ProcStatsEntry> sEntryCompare = new Comparator<ProcStatsEntry>() {
@Override
public int compare(ProcStatsEntry lhs, ProcStatsEntry rhs) {
- if (lhs.mWeight < rhs.mWeight) {
+ if (lhs.mRunWeight < rhs.mRunWeight) {
return 1;
- } else if (lhs.mWeight > rhs.mWeight) {
+ } else if (lhs.mRunWeight > rhs.mRunWeight) {
return -1;
- } else if (lhs.mDuration < rhs.mDuration) {
+ } else if (lhs.mRunDuration < rhs.mRunDuration) {
return 1;
- } else if (lhs.mDuration > rhs.mDuration) {
+ } else if (lhs.mRunDuration > rhs.mRunDuration) {
+ return -1;
+ }
+ return 0;
+ }
+ };
+
+ final static Comparator<ProcStatsPackageEntry> sPackageEntryCompare
+ = new Comparator<ProcStatsPackageEntry>() {
+ @Override
+ public int compare(ProcStatsPackageEntry lhs, ProcStatsPackageEntry rhs) {
+ if (lhs.mRunWeight < rhs.mRunWeight) {
+ return 1;
+ } else if (lhs.mRunWeight > rhs.mRunWeight) {
+ return -1;
+ } else if (lhs.mRunDuration < rhs.mRunDuration) {
+ return 1;
+ } else if (lhs.mRunDuration > rhs.mRunDuration) {
return -1;
}
return 0;
@@ -112,7 +131,7 @@ public class ProcessStatsUi extends PreferenceFragment
private PreferenceGroup mAppListGroup;
private Preference mMemStatusPref;
- long mMaxWeight;
+ double mMaxWeight;
long mTotalTime;
long[] mMemTimes = new long[ProcessStats.ADJ_MEM_FACTOR_COUNT];
@@ -123,6 +142,7 @@ public class ProcessStatsUi extends PreferenceFragment
double mMemKernelWeight;
double mMemNativeWeight;
double mMemTotalWeight;
+ double mWeightToRam;
// The actual duration value to use for each duration option. Note these
// are lower than the actual duration, since our durations are computed in
@@ -218,9 +238,10 @@ public class ProcessStatsUi extends PreferenceFragment
ProcessStatsPreference pgp = (ProcessStatsPreference) preference;
Bundle args = new Bundle();
- args.putParcelable(ProcessStatsDetail.EXTRA_ENTRY, pgp.getEntry());
+ args.putParcelable(ProcessStatsDetail.EXTRA_PACKAGE_ENTRY, pgp.getEntry());
args.putBoolean(ProcessStatsDetail.EXTRA_USE_USS, mUseUss);
- args.putLong(ProcessStatsDetail.EXTRA_MAX_WEIGHT, mMaxWeight);
+ args.putDouble(ProcessStatsDetail.EXTRA_MAX_WEIGHT, mMaxWeight);
+ args.putDouble(ProcessStatsDetail.EXTRA_WEIGHT_TO_RAM, mWeightToRam);
args.putLong(ProcessStatsDetail.EXTRA_TOTAL_TIME, mTotalTime);
((SettingsActivity) getActivity()).startPreferencePanel(
ProcessStatsDetail.class.getName(), args, R.string.details_title, null, null, 0);
@@ -406,31 +427,6 @@ public class ProcessStatsUi extends PreferenceFragment
final long elapsedTime = mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime;
- mMemStatusPref.setOrder(-2);
- mAppListGroup.addPreference(mMemStatusPref);
- String durationString = Utils.formatElapsedTime(getActivity(), elapsedTime, false);
- CharSequence memString;
- CharSequence[] memStatesStr = getResources().getTextArray(R.array.ram_states);
- if (mMemState >= 0 && mMemState < memStatesStr.length) {
- memString = memStatesStr[mMemState];
- } else {
- memString = "?";
- }
- mMemStatusPref.setTitle(getActivity().getString(R.string.process_stats_total_duration,
- getActivity().getString(statsLabel), durationString));
- mMemStatusPref.setSummary(getActivity().getString(R.string.process_stats_memory_status,
- memString));
- /*
- 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);
- mAppListGroup.addPreference(hist);
- */
-
long now = SystemClock.uptimeMillis();
final PackageManager pm = getActivity().getPackageManager();
@@ -470,9 +466,13 @@ public class ProcessStatsUi extends PreferenceFragment
memStates = ProcessStats.ALL_MEM_ADJ;
break;
}
- colors.setColoredRegions(LinearColorBar.REGION_RED);
+ Resources res = getResources();
+ colors.setColors(res.getColor(R.color.running_processes_apps_ram),
+ res.getColor(R.color.running_processes_apps_ram),
+ res.getColor(R.color.running_processes_free_ram));
// Compute memory badness for chart color.
+ /*
int[] badColors = com.android.settings.Utils.BADNESS_COLORS;
long timeGood = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_NORMAL];
timeGood += (mMemTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE]*2)/3;
@@ -480,6 +480,7 @@ public class ProcessStatsUi extends PreferenceFragment
float memBadness = ((float)timeGood)/mTotalTime;
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,
@@ -547,6 +548,8 @@ public class ProcessStatsUi extends PreferenceFragment
memReader.readMemInfo();
double realTotalRam = memReader.getTotalSize();
double totalScale = realTotalRam / totalRam;
+ mWeightToRam = totalScale / memTotalTime * 1024;
+ mMaxWeight = totalRam / mWeightToRam;
double realUsedRam = usedRam * totalScale;
double realFreeRam = freeRam * totalScale;
if (DEBUG) {
@@ -558,12 +561,15 @@ public class ProcessStatsUi extends PreferenceFragment
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
((ActivityManager)getActivity().getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(
memInfo);
+ long baseCacheRam;
if (memInfo.hiddenAppThreshold >= realFreeRam) {
realUsedRam = realFreeRam;
realFreeRam = 0;
+ baseCacheRam = (long)realFreeRam;
} else {
realUsedRam += memInfo.hiddenAppThreshold;
realFreeRam -= memInfo.hiddenAppThreshold;
+ baseCacheRam = memInfo.hiddenAppThreshold;
}
if (DEBUG) {
Log.i(TAG, "Adj Scaled Used RAM: " + Formatter.formatShortFileSize(getActivity(),
@@ -572,6 +578,22 @@ public class ProcessStatsUi extends PreferenceFragment
(long)realFreeRam));
}
+ mMemStatusPref.setOrder(-2);
+ mAppListGroup.addPreference(mMemStatusPref);
+ String durationString = Utils.formatElapsedTime(getActivity(), elapsedTime, false);
+ String usedString = Formatter.formatShortFileSize(getActivity(), (long) realUsedRam);
+ String totalString = Formatter.formatShortFileSize(getActivity(), (long)realTotalRam);
+ CharSequence memString;
+ CharSequence[] memStatesStr = getResources().getTextArray(R.array.ram_states);
+ if (mMemState >= 0 && mMemState < memStatesStr.length) {
+ memString = memStatesStr[mMemState];
+ } else {
+ memString = "?";
+ }
+ mMemStatusPref.setTitle(getActivity().getString(R.string.process_stats_total_duration,
+ usedString, totalString, durationString));
+ mMemStatusPref.setSummary(getActivity().getString(R.string.process_stats_memory_status,
+ memString));
float usedRatio = (float)(realUsedRam/(realFreeRam+realUsedRam));
colors.setRatios(usedRatio, 0, 1-usedRatio);
@@ -605,17 +627,20 @@ public class ProcessStatsUi extends PreferenceFragment
mAppListGroup.addPreference(colors);
- ProcessStats.ProcessDataCollection totals = new ProcessStats.ProcessDataCollection(
+ ProcessStats.ProcessDataCollection bgTotals = new ProcessStats.ProcessDataCollection(
ProcessStats.ALL_SCREEN_ADJ, memStates, stats);
+ ProcessStats.ProcessDataCollection runTotals = new ProcessStats.ProcessDataCollection(
+ ProcessStats.ALL_SCREEN_ADJ, memStates, ProcessStats.NON_CACHED_PROC_STATES);
- ArrayList<ProcStatsEntry> entries = new ArrayList<ProcStatsEntry>();
+ final ArrayList<ProcStatsEntry> procEntries = new ArrayList<>();
+ final ArrayList<ProcStatsPackageEntry> pkgEntries = new ArrayList<>();
/*
ArrayList<ProcessStats.ProcessState> rawProcs = mStats.collectProcessesLocked(
ProcessStats.ALL_SCREEN_ADJ, ProcessStats.ALL_MEM_ADJ,
ProcessStats.BACKGROUND_PROC_STATES, now, null);
for (int i=0, N=(rawProcs != null ? rawProcs.size() : 0); i<N; i++) {
- procs.add(new ProcStatsEntry(rawProcs.get(i), totals));
+ procs.add(new ProcStatsEntry(rawProcs.get(i), bgTotals));
}
*/
@@ -640,15 +665,15 @@ public class ProcessStatsUi extends PreferenceFragment
}
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) {
+ ent = new ProcStatsEntry(proc, st.mPackageName, bgTotals, runTotals,
+ mUseUss);
+ if (ent.mRunWeight > 0) {
if (DEBUG) Log.d(TAG, "Adding proc " + proc.mName + "/"
- + proc.mUid + ": time=" + makeDuration(ent.mDuration) + " ("
- + ((((double)ent.mDuration) / memTotalTime) * 100) + "%)"
- + " pss=" + ent.mAvgPss);
+ + proc.mUid + ": time=" + makeDuration(ent.mRunDuration) + " ("
+ + ((((double)ent.mRunDuration) / memTotalTime) * 100) + "%)"
+ + " pss=" + ent.mAvgRunMem);
entriesMap.put(proc.mName, proc.mUid, ent);
- entries.add(ent);
+ procEntries.add(ent);
}
} else {
ent.addPackage(st.mPackageName);
@@ -672,7 +697,8 @@ 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 = entriesMap.get(ss.mProcessName, uids.keyAt(iu));
+ 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 "
@@ -689,90 +715,99 @@ 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) / memTotalTime) * 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);
- }
+ // Combine processes into packages.
+ HashMap<String, ProcStatsPackageEntry> pkgMap = new HashMap<>();
+ for (int i=procEntries.size()-1; i>=0; i--) {
+ ProcStatsEntry proc = procEntries.get(i);
+ proc.evaluateTargetPackage(pm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
+ ProcStatsPackageEntry pkg = pkgMap.get(proc.mBestTargetPackage);
+ if (pkg == null) {
+ pkg = new ProcStatsPackageEntry(proc.mBestTargetPackage);
+ pkgMap.put(proc.mBestTargetPackage, pkg);
+ pkgEntries.add(pkg);
}
+ pkg.addEntry(proc);
}
- */
- 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;
- }
+ // Add in fake entry representing the OS itself.
+ ProcStatsPackageEntry osPkg = new ProcStatsPackageEntry("os");
+ pkgMap.put("os", osPkg);
+ pkgEntries.add(osPkg);
+ ProcStatsEntry osEntry;
+ if (totalMem.sysMemNativeWeight > 0) {
+ osEntry = new ProcStatsEntry("os", 0,
+ getString(R.string.process_stats_os_native), memTotalTime,
+ (long)(totalMem.sysMemNativeWeight/memTotalTime));
+ osEntry.evaluateTargetPackage(pm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
+ osPkg.addEntry(osEntry);
}
- if (mStatsType == MENU_TYPE_BACKGROUND) {
- mMaxWeight = (long)(mShowSystem ? persBackgroundWeight : backgroundWeight);
- if (mMaxWeight < maxWeight) {
- mMaxWeight = maxWeight;
- }
- if (DEBUG) {
- Log.i(TAG, "Bar max RAM: " + Formatter.formatShortFileSize(getActivity(),
- (mMaxWeight * 1024) / memTotalTime));
- }
- } else {
- mMaxWeight = maxWeight;
+ if (totalMem.sysMemKernelWeight > 0) {
+ osEntry = new ProcStatsEntry("os", 0,
+ getString(R.string.process_stats_os_kernel), memTotalTime,
+ (long)(totalMem.sysMemKernelWeight/memTotalTime));
+ osEntry.evaluateTargetPackage(pm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
+ osPkg.addEntry(osEntry);
+ }
+ if (totalMem.sysMemZRamWeight > 0) {
+ osEntry = new ProcStatsEntry("os", 0,
+ getString(R.string.process_stats_os_zram), memTotalTime,
+ (long)(totalMem.sysMemZRamWeight/memTotalTime));
+ osEntry.evaluateTargetPackage(pm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
+ osPkg.addEntry(osEntry);
}
+ if (baseCacheRam > 0) {
+ osEntry = new ProcStatsEntry("os", 0,
+ getString(R.string.process_stats_os_cache), memTotalTime, baseCacheRam/1024);
+ osEntry.evaluateTargetPackage(pm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
+ osPkg.addEntry(osEntry);
+ }
+
+ for (int i=0, N=pkgEntries.size(); i<N; i++) {
+ ProcStatsPackageEntry pkg = pkgEntries.get(i);
+ pkg.updateMetrics();
+ }
+
+ Collections.sort(pkgEntries, sPackageEntryCompare);
+
+ // Now collect the per-process information into applications, so that applications
+ // running as multiple processes will have only one entry representing all of them.
if (DEBUG) Log.d(TAG, "-------------------- BUILDING UI");
// 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;
+ int end = pkgEntries.size()-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) {
+ ProcStatsPackageEntry pkg = pkgEntries.get(end);
+ final double percentOfWeight = (pkg.mRunWeight / mMaxWeight) * 100;
+ final double percentOfTime = (((double)pkg.mRunDuration) / memTotalTime) * 100;
+ if (percentOfWeight >= .01 || 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;
+ ProcStatsPackageEntry pkg = pkgEntries.get(i);
+ final double percentOfWeight = (pkg.mRunWeight / mMaxWeight) * 100;
+ final double percentOfTime = (((double)pkg.mRunDuration) / memTotalTime) * 100;
ProcessStatsPreference pref = new ProcessStatsPreference(getActivity());
- pref.init(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.init(null, pkg);
+ pkg.retrieveUiData(getActivity(), pm);
+ pref.setTitle(pkg.mUiLabel);
+ if (pkg.mUiTargetApp != null) {
+ pref.setIcon(pkg.mUiTargetApp.loadIcon(pm));
}
pref.setOrder(i);
- pref.setPercent(percentOfWeight, percentOfTime);
+ pref.setPercent(percentOfWeight, percentOfTime,
+ (long)(pkg.mRunWeight * mWeightToRam));
mAppListGroup.addPreference(pref);
if (mStatsType == MENU_TYPE_BACKGROUND) {
if (DEBUG) {
- Log.i(TAG, "App " + proc.mUiLabel + ": weightedRam="
+ Log.i(TAG, "App " + pkg.mUiLabel + ": weightedRam="
+ Formatter.formatShortFileSize(getActivity(),
- (proc.mWeight * 1024) / memTotalTime)
+ (long)((pkg.mRunWeight * 1024) / memTotalTime))
+ ", avgRam=" + Formatter.formatShortFileSize(getActivity(),
- (proc.mAvgPss*1024)));
+ (pkg.mAvgRunMem *1024)));
}
}