diff options
Diffstat (limited to 'src/com')
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))); } } |