Merge "Make proc stats UI app-centric instead of process-centric."
This commit is contained in:
committed by
Android (Google) Code Review
commit
1836796559
@@ -49,21 +49,18 @@
|
|||||||
<include layout="@layout/two_buttons_panel"/>
|
<include layout="@layout/two_buttons_panel"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="?android:attr/listSeparatorTextViewStyle"
|
|
||||||
android:text="@string/details_subtitle" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/details"
|
android:id="@+id/processes"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<!-- Insert detail items here -->
|
<!-- Insert process items here -->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/services_label"
|
||||||
style="?android:attr/listSeparatorTextViewStyle"
|
style="?android:attr/listSeparatorTextViewStyle"
|
||||||
android:text="@string/services_subtitle" />
|
android:text="@string/services_subtitle" />
|
||||||
|
|
||||||
|
28
res/layout/process_stats_proc_details.xml
Normal file
28
res/layout/process_stats_proc_details.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/processes"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/processes_name"
|
||||||
|
style="?android:attr/listSeparatorTextViewStyle" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@@ -4059,8 +4059,9 @@
|
|||||||
<!-- [CHAR LIMIT=NONE] Label for amount of memory use -->
|
<!-- [CHAR LIMIT=NONE] Label for amount of memory use -->
|
||||||
<string name="app_memory_use">Memory use</string>
|
<string name="app_memory_use">Memory use</string>
|
||||||
<!-- [CHAR LIMIT=NONE] Label for process stats, duration of time the stats are over -->
|
<!-- [CHAR LIMIT=NONE] Label for process stats, duration of time the stats are over -->
|
||||||
<string name="process_stats_total_duration"><xliff:g id="type">%1$s</xliff:g> apps over
|
<string name="process_stats_total_duration"><xliff:g id="usedRam">%1$s</xliff:g>
|
||||||
<xliff:g id="time">%2$s</xliff:g></string>
|
of <xliff:g id="totalRam">%2$s</xliff:g> used over
|
||||||
|
<xliff:g id="time">%3$s</xliff:g></string>
|
||||||
<!-- [CHAR LIMIT=NONE] Label for process stats, text for stats type -->
|
<!-- [CHAR LIMIT=NONE] Label for process stats, text for stats type -->
|
||||||
<string name="process_stats_type_background">Background</string>
|
<string name="process_stats_type_background">Background</string>
|
||||||
<!-- [CHAR LIMIT=NONE] Label for process stats, text for stats type -->
|
<!-- [CHAR LIMIT=NONE] Label for process stats, text for stats type -->
|
||||||
@@ -4070,12 +4071,24 @@
|
|||||||
<!-- [CHAR LIMIT=NONE] Label for process stats, duration of time the stats are over -->
|
<!-- [CHAR LIMIT=NONE] Label for process stats, duration of time the stats are over -->
|
||||||
<string name="process_stats_memory_status">Device memory is currently
|
<string name="process_stats_memory_status">Device memory is currently
|
||||||
<xliff:g id="memstate">%1$s</xliff:g></string>
|
<xliff:g id="memstate">%1$s</xliff:g></string>
|
||||||
|
<!-- [CHAR LIMIT=NONE] Label OS "process" app -->
|
||||||
|
<string name="process_stats_os_label">Android OS</string>
|
||||||
|
<!-- [CHAR LIMIT=NONE] Name of OS "process" for all native processes -->
|
||||||
|
<string name="process_stats_os_native">Native</string>
|
||||||
|
<!-- [CHAR LIMIT=NONE] Name of OS "process" for all kernel memory -->
|
||||||
|
<string name="process_stats_os_kernel">Kernel</string>
|
||||||
|
<!-- [CHAR LIMIT=NONE] Name of OS "process" for all zram memory -->
|
||||||
|
<string name="process_stats_os_zram">Z-Ram</string>
|
||||||
|
<!-- [CHAR LIMIT=NONE] Name of OS "process" for base memory needed for caches -->
|
||||||
|
<string name="process_stats_os_cache">Caches</string>
|
||||||
<!-- [CHAR LIMIT=NONE] Label for item showing details of average RAM use -->
|
<!-- [CHAR LIMIT=NONE] Label for item showing details of average RAM use -->
|
||||||
<string name="process_stats_avg_ram_use">Average RAM use</string>
|
<string name="process_stats_ram_use">RAM use</string>
|
||||||
<!-- [CHAR LIMIT=NONE] Label for item showing details of maximum RAM use -->
|
<!-- [CHAR LIMIT=NONE] Label for item showing details of average RAM use -->
|
||||||
<string name="process_stats_max_ram_use">Maximum RAM use</string>
|
<string name="process_stats_bg_ram_use">RAM use (background)</string>
|
||||||
<!-- [CHAR LIMIT=NONE] Label for item showing percent of time spent running -->
|
<!-- [CHAR LIMIT=NONE] Label for item showing percent of time spent running -->
|
||||||
<string name="process_stats_run_time">Run time</string>
|
<string name="process_stats_run_time">Run time</string>
|
||||||
|
<!-- [CHAR LIMIT=NONE] Subtitle for process stats processes list -->
|
||||||
|
<string name="processes_subtitle">Processes</string>
|
||||||
<!-- [CHAR LIMIT=NONE] Subtitle for process stats services list -->
|
<!-- [CHAR LIMIT=NONE] Subtitle for process stats services list -->
|
||||||
<string name="services_subtitle">Services</string>
|
<string name="services_subtitle">Services</string>
|
||||||
<!-- [CHAR LIMIT=NONE] Menu for process stats to select duration of stats to show -->
|
<!-- [CHAR LIMIT=NONE] Menu for process stats to select duration of stats to show -->
|
||||||
|
@@ -21,6 +21,7 @@ import android.content.pm.PackageInfo;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.Process;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
@@ -38,37 +39,49 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
final int mUid;
|
final int mUid;
|
||||||
final String mName;
|
final String mName;
|
||||||
final ArrayList<String> mPackages = new ArrayList<String>();
|
final ArrayList<String> mPackages = new ArrayList<String>();
|
||||||
final long mDuration;
|
final long mBgDuration;
|
||||||
final long mAvgPss;
|
final long mAvgBgMem;
|
||||||
final long mMaxPss;
|
final long mMaxBgMem;
|
||||||
final long mAvgUss;
|
final double mBgWeight;
|
||||||
final long mMaxUss;
|
final long mRunDuration;
|
||||||
final long mWeight;
|
final long mAvgRunMem;
|
||||||
|
final long mMaxRunMem;
|
||||||
|
final double mRunWeight;
|
||||||
|
|
||||||
String mBestTargetPackage;
|
String mBestTargetPackage;
|
||||||
|
|
||||||
ArrayMap<String, ArrayList<Service>> mServices = new ArrayMap<String, ArrayList<Service>>(1);
|
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,
|
public ProcStatsEntry(ProcessStats.ProcessState proc, String packageName,
|
||||||
ProcessStats.ProcessDataCollection tmpTotals, boolean useUss, boolean weightWithTime) {
|
ProcessStats.ProcessDataCollection tmpBgTotals,
|
||||||
ProcessStats.computeProcessData(proc, tmpTotals, 0);
|
ProcessStats.ProcessDataCollection tmpRunTotals, boolean useUss) {
|
||||||
|
ProcessStats.computeProcessData(proc, tmpBgTotals, 0);
|
||||||
|
ProcessStats.computeProcessData(proc, tmpRunTotals, 0);
|
||||||
mPackage = proc.mPackage;
|
mPackage = proc.mPackage;
|
||||||
mUid = proc.mUid;
|
mUid = proc.mUid;
|
||||||
mName = proc.mName;
|
mName = proc.mName;
|
||||||
mPackages.add(packageName);
|
mPackages.add(packageName);
|
||||||
mDuration = tmpTotals.totalTime;
|
mBgDuration = tmpBgTotals.totalTime;
|
||||||
mAvgPss = tmpTotals.avgPss;
|
mAvgBgMem = useUss ? tmpBgTotals.avgUss : tmpBgTotals.avgPss;
|
||||||
mMaxPss = tmpTotals.maxPss;
|
mMaxBgMem = useUss ? tmpBgTotals.maxUss : tmpBgTotals.maxPss;
|
||||||
mAvgUss = tmpTotals.avgUss;
|
mBgWeight = mAvgBgMem * (double) mBgDuration;
|
||||||
mMaxUss = tmpTotals.maxUss;
|
mRunDuration = tmpRunTotals.totalTime;
|
||||||
mWeight = (weightWithTime ? mDuration : 1) * (useUss ? mAvgUss : mAvgPss);
|
mAvgRunMem = useUss ? tmpRunTotals.avgUss : tmpRunTotals.avgPss;
|
||||||
if (DEBUG) Log.d(TAG, "New proc entry " + proc.mName + ": dur=" + mDuration
|
mMaxRunMem = useUss ? tmpRunTotals.maxUss : tmpRunTotals.maxPss;
|
||||||
+ " avgpss=" + mAvgPss + " weight=" + mWeight);
|
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) {
|
public ProcStatsEntry(Parcel in) {
|
||||||
@@ -76,12 +89,14 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
mUid = in.readInt();
|
mUid = in.readInt();
|
||||||
mName = in.readString();
|
mName = in.readString();
|
||||||
in.readStringList(mPackages);
|
in.readStringList(mPackages);
|
||||||
mDuration = in.readLong();
|
mBgDuration = in.readLong();
|
||||||
mAvgPss = in.readLong();
|
mAvgBgMem = in.readLong();
|
||||||
mMaxPss = in.readLong();
|
mMaxBgMem = in.readLong();
|
||||||
mAvgUss = in.readLong();
|
mBgWeight = in.readDouble();
|
||||||
mMaxUss = in.readLong();
|
mRunDuration = in.readLong();
|
||||||
mWeight = in.readLong();
|
mAvgRunMem = in.readLong();
|
||||||
|
mMaxRunMem = in.readLong();
|
||||||
|
mRunWeight = in.readDouble();
|
||||||
mBestTargetPackage = in.readString();
|
mBestTargetPackage = in.readString();
|
||||||
final int N = in.readInt();
|
final int N = in.readInt();
|
||||||
if (N > 0) {
|
if (N > 0) {
|
||||||
@@ -100,15 +115,27 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void evaluateTargetPackage(PackageManager pm, ProcessStats stats,
|
public void evaluateTargetPackage(PackageManager pm, ProcessStats stats,
|
||||||
ProcessStats.ProcessDataCollection totals, Comparator<ProcStatsEntry> compare,
|
ProcessStats.ProcessDataCollection bgTotals,
|
||||||
boolean useUss, boolean weightWithTime) {
|
ProcessStats.ProcessDataCollection runTotals, Comparator<ProcStatsEntry> compare,
|
||||||
|
boolean useUss) {
|
||||||
mBestTargetPackage = null;
|
mBestTargetPackage = null;
|
||||||
if (mPackages.size() == 1) {
|
if (mPackages.size() == 1) {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": single pkg " + mPackages.get(0));
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": single pkg " + mPackages.get(0));
|
||||||
mBestTargetPackage = mPackages.get(0);
|
mBestTargetPackage = mPackages.get(0);
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If one of the packages is the framework itself, that wins.
|
||||||
// See if there is one significant package that was running here.
|
// 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++) {
|
||||||
|
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++) {
|
for (int ipkg=0; ipkg<mPackages.size(); ipkg++) {
|
||||||
SparseArray<ProcessStats.PackageState> vpkgs
|
SparseArray<ProcessStats.PackageState> vpkgs
|
||||||
= stats.mPackages.get(mPackages.get(ipkg), mUid);
|
= stats.mPackages.get(mPackages.get(ipkg), mUid);
|
||||||
@@ -127,48 +154,70 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
+ mPackages.get(ipkg) + "/" + mUid);
|
+ mPackages.get(ipkg) + "/" + mUid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
subProcs.add(new ProcStatsEntry(pkgProc, pkgState.mPackageName, totals, useUss,
|
subProcs.add(new ProcStatsEntry(pkgProc, pkgState.mPackageName, bgTotals,
|
||||||
weightWithTime));
|
runTotals, useUss));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subProcs.size() > 1) {
|
if (subProcs.size() > 1) {
|
||||||
Collections.sort(subProcs, compare);
|
Collections.sort(subProcs, compare);
|
||||||
if (subProcs.get(0).mWeight > (subProcs.get(1).mWeight*3)) {
|
if (subProcs.get(0).mRunWeight > (subProcs.get(1).mRunWeight *3)) {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": best pkg "
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": best pkg "
|
||||||
+ subProcs.get(0).mPackage + " weight " + subProcs.get(0).mWeight
|
+ subProcs.get(0).mPackage + " weight " + subProcs.get(0).mRunWeight
|
||||||
+ " better than " + subProcs.get(1).mPackage
|
+ " better than " + subProcs.get(1).mPackage
|
||||||
+ " weight " + subProcs.get(1).mWeight);
|
+ " weight " + subProcs.get(1).mRunWeight);
|
||||||
mBestTargetPackage = subProcs.get(0).mPackage;
|
mBestTargetPackage = subProcs.get(0).mPackage;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Couldn't find one that is best by weight, let's decide on best another
|
// 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
|
// 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.
|
// half of the maximum weight, and has specified an explicit app icon.
|
||||||
long maxWeight = subProcs.get(0).mWeight;
|
double maxWeight = subProcs.get(0).mRunWeight;
|
||||||
long bestRunTime = -1;
|
long bestRunTime = -1;
|
||||||
|
boolean bestPersistent = false;
|
||||||
for (int i=0; i<subProcs.size(); i++) {
|
for (int i=0; i<subProcs.size(); i++) {
|
||||||
if (subProcs.get(i).mWeight < (maxWeight/2)) {
|
final ProcStatsEntry subProc = subProcs.get(i);
|
||||||
|
if (subProc.mRunWeight < (maxWeight/2)) {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
||||||
+ subProcs.get(i).mPackage + " weight " + subProcs.get(i).mWeight
|
+ subProc.mPackage + " weight " + subProc.mRunWeight
|
||||||
+ " too small");
|
+ " too small");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ApplicationInfo ai = pm.getApplicationInfo(subProcs.get(i).mPackage, 0);
|
ApplicationInfo ai = pm.getApplicationInfo(subProc.mPackage, 0);
|
||||||
if (ai.icon == 0) {
|
if (ai.icon == 0) {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
||||||
+ subProcs.get(i).mPackage + " has no icon");
|
+ subProc.mPackage + " has no icon");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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 "
|
||||||
|
+ subProc.mPackage + " pers run time " + thisRunTime
|
||||||
|
+ " not as good as last " + bestRunTime);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (bestPersistent) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
||||||
|
+ subProc.mPackage + " is not persistent");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
||||||
+ subProcs.get(i).mPackage + " failed finding app info");
|
+ subProc.mPackage + " failed finding app info");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ArrayList<Service> subProcServices = null;
|
ArrayList<Service> subProcServices = null;
|
||||||
for (int isp=0, NSP=mServices.size(); isp<NSP; isp++) {
|
for (int isp=0, NSP=mServices.size(); isp<NSP; isp++) {
|
||||||
ArrayList<Service> subServices = mServices.valueAt(isp);
|
ArrayList<Service> subServices = mServices.valueAt(isp);
|
||||||
if (subServices.get(0).mPackage.equals(subProcs.get(i).mPackage)) {
|
if (subServices.get(0).mPackage.equals(subProc.mPackage)) {
|
||||||
subProcServices = subServices;
|
subProcServices = subServices;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -179,7 +228,7 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
Service service = subProcServices.get(iss);
|
Service service = subProcServices.get(iss);
|
||||||
if (service.mDuration > thisRunTime) {
|
if (service.mDuration > thisRunTime) {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
||||||
+ subProcs.get(i).mPackage + " service " + service.mName
|
+ subProc.mPackage + " service " + service.mName
|
||||||
+ " run time is " + service.mDuration);
|
+ " run time is " + service.mDuration);
|
||||||
thisRunTime = service.mDuration;
|
thisRunTime = service.mDuration;
|
||||||
break;
|
break;
|
||||||
@@ -188,12 +237,12 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
}
|
}
|
||||||
if (thisRunTime > bestRunTime) {
|
if (thisRunTime > bestRunTime) {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
||||||
+ subProcs.get(i).mPackage + " new best run time " + thisRunTime);
|
+ subProc.mPackage + " new best run time " + thisRunTime);
|
||||||
mBestTargetPackage = subProcs.get(i).mPackage;
|
mBestTargetPackage = subProc.mPackage;
|
||||||
bestRunTime = thisRunTime;
|
bestRunTime = thisRunTime;
|
||||||
} else {
|
} else {
|
||||||
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg "
|
||||||
+ subProcs.get(i).mPackage + " run time " + thisRunTime
|
+ subProc.mPackage + " run time " + thisRunTime
|
||||||
+ " not as good as last " + bestRunTime);
|
+ " not as good as last " + bestRunTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,67 +250,6 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
mBestTargetPackage = subProcs.get(0).mPackage;
|
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 + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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 + ")";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no current packages for this uid, typically because of uninstall
|
|
||||||
Log.i(TAG, "No package for uid " + mUid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addService(ProcessStats.ServiceState svc) {
|
public void addService(ProcessStats.ServiceState svc) {
|
||||||
ArrayList<Service> services = mServices.get(svc.mPackage);
|
ArrayList<Service> services = mServices.get(svc.mPackage);
|
||||||
@@ -283,12 +271,14 @@ public final class ProcStatsEntry implements Parcelable {
|
|||||||
dest.writeInt(mUid);
|
dest.writeInt(mUid);
|
||||||
dest.writeString(mName);
|
dest.writeString(mName);
|
||||||
dest.writeStringList(mPackages);
|
dest.writeStringList(mPackages);
|
||||||
dest.writeLong(mDuration);
|
dest.writeLong(mBgDuration);
|
||||||
dest.writeLong(mAvgPss);
|
dest.writeLong(mAvgBgMem);
|
||||||
dest.writeLong(mMaxPss);
|
dest.writeLong(mMaxBgMem);
|
||||||
dest.writeLong(mAvgUss);
|
dest.writeDouble(mBgWeight);
|
||||||
dest.writeLong(mMaxUss);
|
dest.writeLong(mRunDuration);
|
||||||
dest.writeLong(mWeight);
|
dest.writeLong(mAvgRunMem);
|
||||||
|
dest.writeLong(mMaxRunMem);
|
||||||
|
dest.writeDouble(mRunWeight);
|
||||||
dest.writeString(mBestTargetPackage);
|
dest.writeString(mBestTargetPackage);
|
||||||
final int N = mServices.size();
|
final int N = mServices.size();
|
||||||
dest.writeInt(N);
|
dest.writeInt(N);
|
||||||
|
145
src/com/android/settings/applications/ProcStatsPackageEntry.java
Normal file
145
src/com/android/settings/applications/ProcStatsPackageEntry.java
Normal file
@@ -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];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@@ -16,20 +16,14 @@
|
|||||||
|
|
||||||
package com.android.settings.applications;
|
package com.android.settings.applications;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.text.format.Formatter;
|
import android.text.format.Formatter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -44,6 +38,7 @@ import com.android.settings.Utils;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import static com.android.settings.Utils.prepareCustomPreferencesList;
|
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 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_USE_USS = "use_uss";
|
||||||
public static final String EXTRA_MAX_WEIGHT = "max_weight";
|
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";
|
public static final String EXTRA_TOTAL_TIME = "total_time";
|
||||||
|
|
||||||
private PackageManager mPm;
|
private PackageManager mPm;
|
||||||
private DevicePolicyManager mDpm;
|
private DevicePolicyManager mDpm;
|
||||||
|
|
||||||
private ProcStatsEntry mEntry;
|
private ProcStatsPackageEntry mApp;
|
||||||
private boolean mUseUss;
|
private boolean mUseUss;
|
||||||
private long mMaxWeight;
|
private double mMaxWeight;
|
||||||
|
private double mWeightToRam;
|
||||||
private long mTotalTime;
|
private long mTotalTime;
|
||||||
|
private long mOnePercentTime;
|
||||||
|
|
||||||
private View mRootView;
|
private View mRootView;
|
||||||
private TextView mTitleView;
|
private TextView mTitleView;
|
||||||
private ViewGroup mTwoButtonsPanel;
|
private ViewGroup mTwoButtonsPanel;
|
||||||
private Button mForceStopButton;
|
private Button mForceStopButton;
|
||||||
private Button mReportButton;
|
private Button mReportButton;
|
||||||
private ViewGroup mDetailsParent;
|
private ViewGroup mProcessesParent;
|
||||||
private ViewGroup mServicesParent;
|
private ViewGroup mServicesParent;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,11 +77,13 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
|
|||||||
mPm = getActivity().getPackageManager();
|
mPm = getActivity().getPackageManager();
|
||||||
mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
|
mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||||
final Bundle args = getArguments();
|
final Bundle args = getArguments();
|
||||||
mEntry = (ProcStatsEntry)args.getParcelable(EXTRA_ENTRY);
|
mApp = args.getParcelable(EXTRA_PACKAGE_ENTRY);
|
||||||
mEntry.retrieveUiData(mPm);
|
mApp.retrieveUiData(getActivity(), mPm);
|
||||||
mUseUss = args.getBoolean(EXTRA_USE_USS);
|
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);
|
mTotalTime = args.getLong(EXTRA_TOTAL_TIME);
|
||||||
|
mOnePercentTime = mTotalTime/100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -109,24 +109,22 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createDetails() {
|
private void createDetails() {
|
||||||
final double percentOfWeight = (((double)mEntry.mWeight) / mMaxWeight) * 100;
|
final double percentOfWeight = (mApp.mBgWeight / mMaxWeight) * 100;
|
||||||
|
|
||||||
int appLevel = (int) Math.ceil(percentOfWeight);
|
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.
|
// 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 = (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);
|
final TextView text1 = (TextView)mRootView.findViewById(android.R.id.text1);
|
||||||
text1.setText(appLevelText);
|
text1.setText(appLevelText);
|
||||||
final ProgressBar progress = (ProgressBar) mRootView.findViewById(android.R.id.progress);
|
final ProgressBar progress = (ProgressBar) mRootView.findViewById(android.R.id.progress);
|
||||||
progress.setProgress(appLevel);
|
progress.setProgress(appLevel);
|
||||||
final ImageView icon = (ImageView) mRootView.findViewById(android.R.id.icon);
|
final ImageView icon = (ImageView) mRootView.findViewById(android.R.id.icon);
|
||||||
if (mEntry.mUiTargetApp != null) {
|
if (mApp.mUiTargetApp != null) {
|
||||||
icon.setImageDrawable(mEntry.mUiTargetApp.loadIcon(mPm));
|
icon.setImageDrawable(mApp.mUiTargetApp.loadIcon(mPm));
|
||||||
}
|
}
|
||||||
|
|
||||||
mTwoButtonsPanel = (ViewGroup)mRootView.findViewById(R.id.two_buttons_panel);
|
mTwoButtonsPanel = (ViewGroup)mRootView.findViewById(R.id.two_buttons_panel);
|
||||||
@@ -135,13 +133,17 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
|
|||||||
mForceStopButton.setEnabled(false);
|
mForceStopButton.setEnabled(false);
|
||||||
mReportButton.setVisibility(View.INVISIBLE);
|
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);
|
mServicesParent = (ViewGroup)mRootView.findViewById(R.id.services);
|
||||||
|
|
||||||
fillDetailsSection();
|
fillProcessesSection();
|
||||||
fillServicesSection();
|
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.setText(R.string.force_stop);
|
||||||
mForceStopButton.setTag(ACTION_FORCE_STOP);
|
mForceStopButton.setTag(ACTION_FORCE_STOP);
|
||||||
mForceStopButton.setOnClickListener(this);
|
mForceStopButton.setOnClickListener(this);
|
||||||
@@ -191,15 +193,43 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
|
|||||||
valueView.setText(value);
|
valueView.setText(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillDetailsSection() {
|
final static Comparator<ProcStatsEntry> sEntryCompare = new Comparator<ProcStatsEntry>() {
|
||||||
addDetailsItem(mDetailsParent, getResources().getText(R.string.process_stats_avg_ram_use),
|
@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(),
|
Formatter.formatShortFileSize(getActivity(),
|
||||||
(mUseUss ? mEntry.mAvgUss : mEntry.mAvgPss) * 1024));
|
(long)(entry.mRunWeight * mWeightToRam)));
|
||||||
addDetailsItem(mDetailsParent, getResources().getText(R.string.process_stats_max_ram_use),
|
if (entry.mBgWeight > 0) {
|
||||||
|
addDetailsItem(item, getResources().getText(R.string.process_stats_bg_ram_use),
|
||||||
Formatter.formatShortFileSize(getActivity(),
|
Formatter.formatShortFileSize(getActivity(),
|
||||||
(mUseUss ? mEntry.mMaxUss : mEntry.mMaxPss) * 1024));
|
(long)(entry.mBgWeight * mWeightToRam)));
|
||||||
addDetailsItem(mDetailsParent, getResources().getText(R.string.process_stats_run_time),
|
}
|
||||||
Utils.formatPercentage(mEntry.mDuration, mTotalTime));
|
addDetailsItem(item, getResources().getText(R.string.process_stats_run_time),
|
||||||
|
Utils.formatPercentage(entry.mRunDuration, mTotalTime));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final static Comparator<ProcStatsEntry.Service> sServiceCompare
|
final static Comparator<ProcStatsEntry.Service> sServiceCompare
|
||||||
@@ -215,43 +245,54 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final static Comparator<ArrayList<ProcStatsEntry.Service>> sServicePkgCompare
|
final static Comparator<PkgService> sServicePkgCompare = new Comparator<PkgService>() {
|
||||||
= new Comparator<ArrayList<ProcStatsEntry.Service>>() {
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(ArrayList<ProcStatsEntry.Service> lhs,
|
public int compare(PkgService lhs, PkgService rhs) {
|
||||||
ArrayList<ProcStatsEntry.Service> rhs) {
|
if (lhs.mDuration < rhs.mDuration) {
|
||||||
long topLhs = lhs.size() > 0 ? lhs.get(0).mDuration : 0;
|
|
||||||
long topRhs = rhs.size() > 0 ? rhs.get(0).mDuration : 0;
|
|
||||||
if (topLhs < topRhs) {
|
|
||||||
return 1;
|
return 1;
|
||||||
} else if (topLhs > topRhs) {
|
} else if (lhs.mDuration > rhs.mDuration) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static class PkgService {
|
||||||
|
final ArrayList<ProcStatsEntry.Service> mServices = new ArrayList<>();
|
||||||
|
long mDuration;
|
||||||
|
}
|
||||||
|
|
||||||
private void fillServicesSection() {
|
private void fillServicesSection() {
|
||||||
if (mEntry.mServices.size() > 0) {
|
final HashMap<String, PkgService> pkgServices = new HashMap<>();
|
||||||
boolean addPackageSections = false;
|
final ArrayList<PkgService> pkgList = new ArrayList<>();
|
||||||
// Sort it all.
|
for (int ie=0; ie< mApp.mEntries.size(); ie++) {
|
||||||
ArrayList<ArrayList<ProcStatsEntry.Service>> servicePkgs
|
ProcStatsEntry ent = mApp.mEntries.get(ie);
|
||||||
= new ArrayList<ArrayList<ProcStatsEntry.Service>>();
|
for (int ip=0; ip<ent.mServices.size(); ip++) {
|
||||||
for (int ip=0; ip<mEntry.mServices.size(); ip++) {
|
String pkg = ent.mServices.keyAt(ip);
|
||||||
ArrayList<ProcStatsEntry.Service> services =
|
PkgService psvc = null;
|
||||||
(ArrayList<ProcStatsEntry.Service>)mEntry.mServices.valueAt(ip).clone();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(pkgList, sServicePkgCompare);
|
||||||
|
for (int ip=0; ip<pkgList.size(); ip++) {
|
||||||
|
ArrayList<ProcStatsEntry.Service> services = pkgList.get(ip).mServices;
|
||||||
Collections.sort(services, sServiceCompare);
|
Collections.sort(services, sServiceCompare);
|
||||||
servicePkgs.add(services);
|
if (pkgList.size() > 1) {
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
for (int ip=0; ip<servicePkgs.size(); ip++) {
|
|
||||||
ArrayList<ProcStatsEntry.Service> services = servicePkgs.get(ip);
|
|
||||||
if (addPackageSections) {
|
|
||||||
addPackageHeaderItem(mServicesParent, services.get(0).mPackage);
|
addPackageHeaderItem(mServicesParent, services.get(0).mPackage);
|
||||||
}
|
}
|
||||||
for (int is=0; is<services.size(); is++) {
|
for (int is=0; is<services.size(); is++) {
|
||||||
@@ -266,44 +307,44 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void killProcesses() {
|
private void killProcesses() {
|
||||||
ActivityManager am = (ActivityManager)getActivity().getSystemService(
|
ActivityManager am = (ActivityManager)getActivity().getSystemService(
|
||||||
Context.ACTIVITY_SERVICE);
|
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();
|
checkForceStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private void checkForceStop() {
|
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);
|
mForceStopButton.setEnabled(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mDpm.packageHasActiveAdmins(mEntry.mUiPackage)) {
|
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);
|
mForceStopButton.setEnabled(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ApplicationInfo info = mPm.getApplicationInfo(mEntry.mUiPackage, 0);
|
ApplicationInfo info = mPm.getApplicationInfo(pkg, 0);
|
||||||
if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {
|
if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {
|
||||||
mForceStopButton.setEnabled(true);
|
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 });
|
if (isStarted) {
|
||||||
intent.putExtra(Intent.EXTRA_UID, mEntry.mUid);
|
mForceStopButton.setEnabled(true);
|
||||||
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mEntry.mUid));
|
}
|
||||||
getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
|
|
||||||
Activity.RESULT_CANCELED, null, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ import com.android.settings.R;
|
|||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
|
|
||||||
public class ProcessStatsPreference extends Preference {
|
public class ProcessStatsPreference extends Preference {
|
||||||
private ProcStatsEntry mEntry;
|
private ProcStatsPackageEntry mEntry;
|
||||||
private int mProgress;
|
private int mProgress;
|
||||||
private CharSequence mProgressText;
|
private CharSequence mProgressText;
|
||||||
|
|
||||||
@@ -51,18 +51,19 @@ public class ProcessStatsPreference extends Preference {
|
|||||||
setLayoutResource(R.layout.preference_app_percentage);
|
setLayoutResource(R.layout.preference_app_percentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(Drawable icon, ProcStatsEntry entry) {
|
public void init(Drawable icon, ProcStatsPackageEntry entry) {
|
||||||
mEntry = entry;
|
mEntry = entry;
|
||||||
setIcon(icon != null ? icon : new ColorDrawable(0));
|
setIcon(icon != null ? icon : new ColorDrawable(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProcStatsEntry getEntry() {
|
public ProcStatsPackageEntry getEntry() {
|
||||||
return mEntry;
|
return mEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPercent(double percentOfWeight, double percentOfTime) {
|
public void setPercent(double percentOfWeight, double percentOfTime, long memory) {
|
||||||
mProgress = (int) Math.ceil(percentOfWeight);
|
mProgress = (int) Math.ceil(percentOfWeight);
|
||||||
mProgressText = Utils.formatPercentage((int) percentOfTime);
|
//mProgressText = Utils.formatPercentage((int) percentOfTime);
|
||||||
|
mProgressText = Formatter.formatShortFileSize(getContext(), memory);
|
||||||
notifyChanged();
|
notifyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@ package com.android.settings.applications;
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -50,6 +51,7 @@ import java.io.InputStream;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class ProcessStatsUi extends PreferenceFragment
|
public class ProcessStatsUi extends PreferenceFragment
|
||||||
implements LinearColorBar.OnRegionTappedListener {
|
implements LinearColorBar.OnRegionTappedListener {
|
||||||
@@ -75,13 +77,30 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
final static Comparator<ProcStatsEntry> sEntryCompare = new Comparator<ProcStatsEntry>() {
|
final static Comparator<ProcStatsEntry> sEntryCompare = new Comparator<ProcStatsEntry>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(ProcStatsEntry lhs, ProcStatsEntry rhs) {
|
public int compare(ProcStatsEntry lhs, ProcStatsEntry rhs) {
|
||||||
if (lhs.mWeight < rhs.mWeight) {
|
if (lhs.mRunWeight < rhs.mRunWeight) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (lhs.mWeight > rhs.mWeight) {
|
} else if (lhs.mRunWeight > rhs.mRunWeight) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (lhs.mDuration < rhs.mDuration) {
|
} else if (lhs.mRunDuration < rhs.mRunDuration) {
|
||||||
return 1;
|
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 -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -112,7 +131,7 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
private PreferenceGroup mAppListGroup;
|
private PreferenceGroup mAppListGroup;
|
||||||
private Preference mMemStatusPref;
|
private Preference mMemStatusPref;
|
||||||
|
|
||||||
long mMaxWeight;
|
double mMaxWeight;
|
||||||
long mTotalTime;
|
long mTotalTime;
|
||||||
|
|
||||||
long[] mMemTimes = new long[ProcessStats.ADJ_MEM_FACTOR_COUNT];
|
long[] mMemTimes = new long[ProcessStats.ADJ_MEM_FACTOR_COUNT];
|
||||||
@@ -123,6 +142,7 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
double mMemKernelWeight;
|
double mMemKernelWeight;
|
||||||
double mMemNativeWeight;
|
double mMemNativeWeight;
|
||||||
double mMemTotalWeight;
|
double mMemTotalWeight;
|
||||||
|
double mWeightToRam;
|
||||||
|
|
||||||
// The actual duration value to use for each duration option. Note these
|
// The actual duration value to use for each duration option. Note these
|
||||||
// are lower than the actual duration, since our durations are computed in
|
// 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;
|
ProcessStatsPreference pgp = (ProcessStatsPreference) preference;
|
||||||
Bundle args = new Bundle();
|
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.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);
|
args.putLong(ProcessStatsDetail.EXTRA_TOTAL_TIME, mTotalTime);
|
||||||
((SettingsActivity) getActivity()).startPreferencePanel(
|
((SettingsActivity) getActivity()).startPreferencePanel(
|
||||||
ProcessStatsDetail.class.getName(), args, R.string.details_title, null, null, 0);
|
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;
|
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();
|
long now = SystemClock.uptimeMillis();
|
||||||
|
|
||||||
final PackageManager pm = getActivity().getPackageManager();
|
final PackageManager pm = getActivity().getPackageManager();
|
||||||
@@ -470,9 +466,13 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
memStates = ProcessStats.ALL_MEM_ADJ;
|
memStates = ProcessStats.ALL_MEM_ADJ;
|
||||||
break;
|
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.
|
// Compute memory badness for chart color.
|
||||||
|
/*
|
||||||
int[] badColors = com.android.settings.Utils.BADNESS_COLORS;
|
int[] badColors = com.android.settings.Utils.BADNESS_COLORS;
|
||||||
long timeGood = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_NORMAL];
|
long timeGood = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_NORMAL];
|
||||||
timeGood += (mMemTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE]*2)/3;
|
timeGood += (mMemTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE]*2)/3;
|
||||||
@@ -480,6 +480,7 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
float memBadness = ((float)timeGood)/mTotalTime;
|
float memBadness = ((float)timeGood)/mTotalTime;
|
||||||
int badnessColor = badColors[1 + Math.round(memBadness*(badColors.length-2))];
|
int badnessColor = badColors[1 + Math.round(memBadness*(badColors.length-2))];
|
||||||
colors.setColors(badnessColor, badnessColor, badnessColor);
|
colors.setColors(badnessColor, badnessColor, badnessColor);
|
||||||
|
*/
|
||||||
|
|
||||||
// We are now going to scale the mMemTimes to match the total elapsed time.
|
// 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,
|
// 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();
|
memReader.readMemInfo();
|
||||||
double realTotalRam = memReader.getTotalSize();
|
double realTotalRam = memReader.getTotalSize();
|
||||||
double totalScale = realTotalRam / totalRam;
|
double totalScale = realTotalRam / totalRam;
|
||||||
|
mWeightToRam = totalScale / memTotalTime * 1024;
|
||||||
|
mMaxWeight = totalRam / mWeightToRam;
|
||||||
double realUsedRam = usedRam * totalScale;
|
double realUsedRam = usedRam * totalScale;
|
||||||
double realFreeRam = freeRam * totalScale;
|
double realFreeRam = freeRam * totalScale;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -558,12 +561,15 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
|
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
|
||||||
((ActivityManager)getActivity().getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(
|
((ActivityManager)getActivity().getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(
|
||||||
memInfo);
|
memInfo);
|
||||||
|
long baseCacheRam;
|
||||||
if (memInfo.hiddenAppThreshold >= realFreeRam) {
|
if (memInfo.hiddenAppThreshold >= realFreeRam) {
|
||||||
realUsedRam = realFreeRam;
|
realUsedRam = realFreeRam;
|
||||||
realFreeRam = 0;
|
realFreeRam = 0;
|
||||||
|
baseCacheRam = (long)realFreeRam;
|
||||||
} else {
|
} else {
|
||||||
realUsedRam += memInfo.hiddenAppThreshold;
|
realUsedRam += memInfo.hiddenAppThreshold;
|
||||||
realFreeRam -= memInfo.hiddenAppThreshold;
|
realFreeRam -= memInfo.hiddenAppThreshold;
|
||||||
|
baseCacheRam = memInfo.hiddenAppThreshold;
|
||||||
}
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.i(TAG, "Adj Scaled Used RAM: " + Formatter.formatShortFileSize(getActivity(),
|
Log.i(TAG, "Adj Scaled Used RAM: " + Formatter.formatShortFileSize(getActivity(),
|
||||||
@@ -572,6 +578,22 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
(long)realFreeRam));
|
(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));
|
float usedRatio = (float)(realUsedRam/(realFreeRam+realUsedRam));
|
||||||
colors.setRatios(usedRatio, 0, 1-usedRatio);
|
colors.setRatios(usedRatio, 0, 1-usedRatio);
|
||||||
|
|
||||||
@@ -605,17 +627,20 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
|
|
||||||
mAppListGroup.addPreference(colors);
|
mAppListGroup.addPreference(colors);
|
||||||
|
|
||||||
ProcessStats.ProcessDataCollection totals = new ProcessStats.ProcessDataCollection(
|
ProcessStats.ProcessDataCollection bgTotals = new ProcessStats.ProcessDataCollection(
|
||||||
ProcessStats.ALL_SCREEN_ADJ, memStates, stats);
|
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(
|
ArrayList<ProcessStats.ProcessState> rawProcs = mStats.collectProcessesLocked(
|
||||||
ProcessStats.ALL_SCREEN_ADJ, ProcessStats.ALL_MEM_ADJ,
|
ProcessStats.ALL_SCREEN_ADJ, ProcessStats.ALL_MEM_ADJ,
|
||||||
ProcessStats.BACKGROUND_PROC_STATES, now, null);
|
ProcessStats.BACKGROUND_PROC_STATES, now, null);
|
||||||
for (int i=0, N=(rawProcs != null ? rawProcs.size() : 0); i<N; i++) {
|
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);
|
ProcStatsEntry ent = entriesMap.get(proc.mName, proc.mUid);
|
||||||
if (ent == null) {
|
if (ent == null) {
|
||||||
ent = new ProcStatsEntry(proc, st.mPackageName, totals, mUseUss,
|
ent = new ProcStatsEntry(proc, st.mPackageName, bgTotals, runTotals,
|
||||||
mStatsType == MENU_TYPE_BACKGROUND);
|
mUseUss);
|
||||||
if (ent.mDuration > 0) {
|
if (ent.mRunWeight > 0) {
|
||||||
if (DEBUG) Log.d(TAG, "Adding proc " + proc.mName + "/"
|
if (DEBUG) Log.d(TAG, "Adding proc " + proc.mName + "/"
|
||||||
+ proc.mUid + ": time=" + makeDuration(ent.mDuration) + " ("
|
+ proc.mUid + ": time=" + makeDuration(ent.mRunDuration) + " ("
|
||||||
+ ((((double)ent.mDuration) / memTotalTime) * 100) + "%)"
|
+ ((((double)ent.mRunDuration) / memTotalTime) * 100) + "%)"
|
||||||
+ " pss=" + ent.mAvgPss);
|
+ " pss=" + ent.mAvgRunMem);
|
||||||
entriesMap.put(proc.mName, proc.mUid, ent);
|
entriesMap.put(proc.mName, proc.mUid, ent);
|
||||||
entries.add(ent);
|
procEntries.add(ent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ent.addPackage(st.mPackageName);
|
ent.addPackage(st.mPackageName);
|
||||||
@@ -672,7 +697,8 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
for (int is=0, NS=ps.mServices.size(); is<NS; is++) {
|
for (int is=0, NS=ps.mServices.size(); is<NS; is++) {
|
||||||
ProcessStats.ServiceState ss = ps.mServices.valueAt(is);
|
ProcessStats.ServiceState ss = ps.mServices.valueAt(is);
|
||||||
if (ss.mProcessName != null) {
|
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 (ent != null) {
|
||||||
if (DEBUG) Log.d(TAG, "Adding service " + ps.mPackageName
|
if (DEBUG) Log.d(TAG, "Adding service " + ps.mPackageName
|
||||||
+ "/" + ss.mName + "/" + uids.keyAt(iu) + " to proc "
|
+ "/" + ss.mName + "/" + uids.keyAt(iu) + " to proc "
|
||||||
@@ -689,90 +715,99 @@ public class ProcessStatsUi extends PreferenceFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Combine processes into packages.
|
||||||
SparseArray<ArrayMap<String, ProcStatsEntry>> processes
|
HashMap<String, ProcStatsPackageEntry> pkgMap = new HashMap<>();
|
||||||
= new SparseArray<ArrayMap<String, ProcStatsEntry>>();
|
for (int i=procEntries.size()-1; i>=0; i--) {
|
||||||
for (int ip=0, N=mStats.mProcesses.getMap().size(); ip<N; ip++) {
|
ProcStatsEntry proc = procEntries.get(i);
|
||||||
SparseArray<ProcessStats.ProcessState> uids = mStats.mProcesses.getMap().valueAt(ip);
|
proc.evaluateTargetPackage(pm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
|
||||||
for (int iu=0; iu<uids.size(); iu++) {
|
ProcStatsPackageEntry pkg = pkgMap.get(proc.mBestTargetPackage);
|
||||||
ProcessStats.ProcessState st = uids.valueAt(iu);
|
if (pkg == null) {
|
||||||
ProcStatsEntry ent = new ProcStatsEntry(st, totals, mUseUss,
|
pkg = new ProcStatsPackageEntry(proc.mBestTargetPackage);
|
||||||
mStatsType == MENU_TYPE_BACKGROUND);
|
pkgMap.put(proc.mBestTargetPackage, pkg);
|
||||||
if (ent.mDuration > 0) {
|
pkgEntries.add(pkg);
|
||||||
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);
|
pkg.addEntry(proc);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Collections.sort(entries, sEntryCompare);
|
// 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 (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);
|
||||||
|
}
|
||||||
|
|
||||||
long maxWeight = 1;
|
for (int i=0, N=pkgEntries.size(); i<N; i++) {
|
||||||
for (int i=0, N=(entries != null ? entries.size() : 0); i<N; i++) {
|
ProcStatsPackageEntry pkg = pkgEntries.get(i);
|
||||||
ProcStatsEntry proc = entries.get(i);
|
pkg.updateMetrics();
|
||||||
if (maxWeight < proc.mWeight) {
|
|
||||||
maxWeight = proc.mWeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
if (DEBUG) Log.d(TAG, "-------------------- BUILDING UI");
|
||||||
|
|
||||||
// Find where we should stop. Because we have two properties we are looking at,
|
// 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.
|
// 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) {
|
while (end >= 0) {
|
||||||
ProcStatsEntry proc = entries.get(end);
|
ProcStatsPackageEntry pkg = pkgEntries.get(end);
|
||||||
final double percentOfWeight = (((double)proc.mWeight) / mMaxWeight) * 100;
|
final double percentOfWeight = (pkg.mRunWeight / mMaxWeight) * 100;
|
||||||
final double percentOfTime = (((double)proc.mDuration) / memTotalTime) * 100;
|
final double percentOfTime = (((double)pkg.mRunDuration) / memTotalTime) * 100;
|
||||||
if (percentOfWeight >= 1 || percentOfTime >= 25) {
|
if (percentOfWeight >= .01 || percentOfTime >= 25) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
end--;
|
end--;
|
||||||
}
|
}
|
||||||
for (int i=0; i<=end; i++) {
|
for (int i=0; i<=end; i++) {
|
||||||
ProcStatsEntry proc = entries.get(i);
|
ProcStatsPackageEntry pkg = pkgEntries.get(i);
|
||||||
final double percentOfWeight = (((double)proc.mWeight) / mMaxWeight) * 100;
|
final double percentOfWeight = (pkg.mRunWeight / mMaxWeight) * 100;
|
||||||
final double percentOfTime = (((double)proc.mDuration) / memTotalTime) * 100;
|
final double percentOfTime = (((double)pkg.mRunDuration) / memTotalTime) * 100;
|
||||||
ProcessStatsPreference pref = new ProcessStatsPreference(getActivity());
|
ProcessStatsPreference pref = new ProcessStatsPreference(getActivity());
|
||||||
pref.init(null, proc);
|
pref.init(null, pkg);
|
||||||
proc.evaluateTargetPackage(pm, mStats, totals, sEntryCompare, mUseUss,
|
pkg.retrieveUiData(getActivity(), pm);
|
||||||
mStatsType == MENU_TYPE_BACKGROUND);
|
pref.setTitle(pkg.mUiLabel);
|
||||||
proc.retrieveUiData(pm);
|
if (pkg.mUiTargetApp != null) {
|
||||||
pref.setTitle(proc.mUiLabel);
|
pref.setIcon(pkg.mUiTargetApp.loadIcon(pm));
|
||||||
if (proc.mUiTargetApp != null) {
|
|
||||||
pref.setIcon(proc.mUiTargetApp.loadIcon(pm));
|
|
||||||
}
|
}
|
||||||
pref.setOrder(i);
|
pref.setOrder(i);
|
||||||
pref.setPercent(percentOfWeight, percentOfTime);
|
pref.setPercent(percentOfWeight, percentOfTime,
|
||||||
|
(long)(pkg.mRunWeight * mWeightToRam));
|
||||||
mAppListGroup.addPreference(pref);
|
mAppListGroup.addPreference(pref);
|
||||||
if (mStatsType == MENU_TYPE_BACKGROUND) {
|
if (mStatsType == MENU_TYPE_BACKGROUND) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.i(TAG, "App " + proc.mUiLabel + ": weightedRam="
|
Log.i(TAG, "App " + pkg.mUiLabel + ": weightedRam="
|
||||||
+ Formatter.formatShortFileSize(getActivity(),
|
+ Formatter.formatShortFileSize(getActivity(),
|
||||||
(proc.mWeight * 1024) / memTotalTime)
|
(long)((pkg.mRunWeight * 1024) / memTotalTime))
|
||||||
+ ", avgRam=" + Formatter.formatShortFileSize(getActivity(),
|
+ ", avgRam=" + Formatter.formatShortFileSize(getActivity(),
|
||||||
(proc.mAvgPss*1024)));
|
(pkg.mAvgRunMem *1024)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user