diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java index 4bd9b37e154b7..26bcce4993483 100644 --- a/core/java/android/util/ArrayMap.java +++ b/core/java/android/util/ArrayMap.java @@ -550,6 +550,43 @@ public final class ArrayMap implements Map { return result; } + /** + * {@inheritDoc} + * + *

This implementation composes a string by iterating over its mappings. If + * this map contains itself as a key or a value, the string "(this Map)" + * will appear in its place. + */ + @Override + public String toString() { + if (isEmpty()) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(mSize * 28); + buffer.append('{'); + for (int i=0; i 0) { + buffer.append(", "); + } + Object key = keyAt(i); + if (key != this) { + buffer.append(key); + } else { + buffer.append("(this Map)"); + } + buffer.append('='); + Object value = valueAt(i); + if (value != this) { + buffer.append(value); + } else { + buffer.append("(this Map)"); + } + } + buffer.append('}'); + return buffer.toString(); + } + // ------------------------------------------------------------------------ // Interop with traditional Java containers. Not as efficient as using // specialized collection APIs. diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java index a84c47c3057cc..2d3380e14982c 100644 --- a/core/java/android/util/ArraySet.java +++ b/core/java/android/util/ArraySet.java @@ -493,6 +493,36 @@ public final class ArraySet implements Collection, Set { return result; } + /** + * {@inheritDoc} + * + *

This implementation composes a string by iterating over its values. If + * this set contains itself as a value, the string "(this Set)" + * will appear in its place. + */ + @Override + public String toString() { + if (isEmpty()) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(mSize * 14); + buffer.append('{'); + for (int i=0; i 0) { + buffer.append(", "); + } + Object value = valueAt(i); + if (value != this) { + buffer.append(value); + } else { + buffer.append("(this Set)"); + } + } + buffer.append('}'); + return buffer.toString(); + } + // ------------------------------------------------------------------------ // Interop with traditional Java containers. Not as efficient as using // specialized collection APIs. diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index bdfa44709560c..6b13fc7f6295e 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -406,7 +406,7 @@ public final class ActivityManagerService extends ActivityManagerNative * Tracking long-term execution of processes to look for abuse and other * bad app behavior. */ - final ProcessTracker mProcessTracker = new ProcessTracker(); + ProcessTracker mProcessTracker; /** * The currently running isolated processes. @@ -1547,6 +1547,7 @@ public final class ActivityManagerService extends ActivityManagerNative m.mContext = context; m.mFactoryTest = factoryTest; m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface()); + m.mProcessTracker = new ProcessTracker(context); m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper); @@ -10173,12 +10174,12 @@ public final class ActivityManagerService extends ActivityManagerNative } String[] newArgs = new String[args.length - opti]; - if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti); + System.arraycopy(args, opti, newArgs, 0, args.length - opti); TaskRecord lastTask = null; boolean needSep = false; for (int i=activities.size()-1; i>=0; i--) { - ActivityRecord r = (ActivityRecord)activities.get(i); + ActivityRecord r = activities.get(i); if (needSep) { pw.println(); } diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java index b5d783d341e86..7ea4a32e02ad5 100644 --- a/services/java/com/android/server/am/ProcessList.java +++ b/services/java/com/android/server/am/ProcessList.java @@ -244,7 +244,8 @@ final class ProcessList { } int adjToTrackedState(int adj) { - return adj >= FOREGROUND_APP_ADJ ? mAdjToTrackedState[adj] : ProcessTracker.STATE_NOTHING; + return adj >= FOREGROUND_APP_ADJ + ? mAdjToTrackedState[adj] : ProcessTracker.STATE_PERSISTENT; } private void writeFile(String path, String data) { diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index cc0a5a3e4e18b..e72656f8e3f13 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -451,8 +451,8 @@ final class ProcessRecord { ProcessList plist) { int state = this == TOP_APP ? ProcessTracker.STATE_TOP : plist.adjToTrackedState(setAdj); - for (int ip=pkgList.size()-1; ip>=0; ip--) { - pkgList.valueAt(ip).setState(state, memFactor, now); + if (pkgList.size() > 0) { + pkgList.valueAt(0).setState(state, memFactor, now, pkgList); } } @@ -461,8 +461,8 @@ final class ProcessRecord { */ public void resetPackageList() { long now = SystemClock.uptimeMillis(); - for (int i=0; i 0) { + pkgList.valueAt(0).setState(ProcessTracker.STATE_NOTHING, 0, now, pkgList); } pkgList.clear(); pkgList.put(info.packageName, baseProcessTracker); diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java index ec8a0b24b3791..8a83412dd1493 100644 --- a/services/java/com/android/server/am/ProcessTracker.java +++ b/services/java/com/android/server/am/ProcessTracker.java @@ -16,9 +16,12 @@ package com.android.server.am; +import android.content.Context; +import android.content.pm.PackageManager; import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.SparseArray; import android.util.TimeUtils; import com.android.server.ProcessMap; @@ -26,20 +29,22 @@ import com.android.server.ProcessMap; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; public final class ProcessTracker { public static final int STATE_NOTHING = -1; - public static final int STATE_TOP = 0; - public static final int STATE_FOREGROUND = 1; - public static final int STATE_VISIBLE = 2; - public static final int STATE_PERCEPTIBLE = 3; - public static final int STATE_BACKUP = 4; - public static final int STATE_SERVICE = 5; - public static final int STATE_HOME = 6; - public static final int STATE_PREVIOUS = 7; - public static final int STATE_CACHED = 8; + public static final int STATE_PERSISTENT = 0; + public static final int STATE_TOP = 1; + public static final int STATE_FOREGROUND = 2; + public static final int STATE_VISIBLE = 3; + public static final int STATE_PERCEPTIBLE = 4; + public static final int STATE_BACKUP = 5; + public static final int STATE_SERVICE = 6; + public static final int STATE_HOME = 7; + public static final int STATE_PREVIOUS = 8; + public static final int STATE_CACHED = 9; public static final int STATE_COUNT = STATE_CACHED+1; public static final int ADJ_NOTHING = -1; @@ -53,12 +58,32 @@ public final class ProcessTracker { public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD; public static final int ADJ_COUNT = ADJ_SCREEN_ON*2; - static String[] STATE_NAMES = new String[] { - "Top ", "Foreground ", "Visible ", "Perceptible", "Backup ", - "Service ", "Home ", "Previous ", "Cached " + static final String[] STATE_NAMES = new String[] { + "Persistent ", "Top ", "Foreground ", "Visible ", "Perceptible", + "Backup ", "Service ", "Home ", "Previous ", "Cached " }; + static final String[] ADJ_SCREEN_NAMES_CSV = new String[] { + "off", "on" + }; + + static final String[] ADJ_MEM_NAMES_CSV = new String[] { + "norm", "mod", "low", "crit" + }; + + static final String[] STATE_NAMES_CSV = new String[] { + "pers", "top", "fore", "vis", "percept", + "backup", "service", "home", "prev", "cached" + }; + + static final String CSV_SEP = "\t"; + + final Context mContext; + final State mState = new State(); + public static final class ProcessState { + final State mState; + final ProcessState mCommonProcess; final String mPackage; final int mUid; final String mName; @@ -67,26 +92,96 @@ public final class ProcessTracker { int mCurState = STATE_NOTHING; long mStartTime; + boolean mMultiPackage; + long mTmpTotalTime; - public ProcessState(String pkg, int uid, String name) { + /** + * Create a new top-level process state, for the initial case where there is only + * a single package running in a process. The initial state is not running. + */ + public ProcessState(State state, String pkg, int uid, String name) { + mState = state; + mCommonProcess = null; mPackage = pkg; mUid = uid; mName = name; } - public void setState(int state, int memFactor, long now) { + /** + * Create a new per-package process state for an existing top-level process + * state. The current running state of the top-level process is also copied, + * marked as started running at 'now'. + */ + public ProcessState(ProcessState commonProcess, String pkg, int uid, String name, + long now) { + mState = commonProcess.mState; + mCommonProcess = commonProcess; + mPackage = pkg; + mUid = uid; + mName = name; + mCurState = commonProcess.mCurState; + mStartTime = now; + } + + ProcessState clone(String pkg, long now) { + ProcessState pnew = new ProcessState(this, pkg, mUid, mName, now); + pnew.add(this, now); + return pnew; + } + + public void setState(int state, int memFactor, long now, + ArrayMap pkgList) { if (state != STATE_NOTHING) { state += memFactor*STATE_COUNT; } + + if (mCommonProcess != null) { + // First update the common process. + mCommonProcess.setState(state, now); + if (!mCommonProcess.mMultiPackage) { + // This common process is for a single package, so it is shared + // with the per-package state. Nothing more to do. + return; + } + } + + for (int ip=pkgList.size()-1; ip>=0; ip--) { + ProcessState proc = pkgList.valueAt(ip); + if (proc.mMultiPackage) { + // The array map is still pointing to a common process state + // that is now shared across packages. Update it to point to + // the new per-package state. + proc = mState.mPackages.get(pkgList.keyAt(ip), + proc.mUid).mProcesses.get(proc.mName); + if (proc == null) { + throw new IllegalStateException("Didn't create per-package process"); + } + pkgList.setValueAt(ip, proc); + } + proc.setState(state, now); + } + } + + void setState(int state, long now) { if (mCurState != state) { if (mCurState != STATE_NOTHING) { - mDurations[mCurState] += now - mStartTime; + long dur = now - mStartTime; + mDurations[mCurState] += dur; } mCurState = state; mStartTime = now; } } + + void add(ProcessState other, long now) { + for (int i=0; i<(STATE_COUNT*ADJ_COUNT); i++) { + mDurations[i] += other.mDurations[i]; + if (other.mCurState == i) { + mDurations[i] += now - other.mStartTime; + } + } + } } public static final class ServiceState { @@ -157,39 +252,78 @@ public final class ProcessTracker { static final class State { final ProcessMap mPackages = new ProcessMap(); + final ProcessMap mProcesses = new ProcessMap(); final long[] mMemFactorDurations = new long[ADJ_COUNT]; int mMemFactor = STATE_NOTHING; long mStartTime; - } - final State mState = new State(); - - public ProcessTracker() { - } - - private PackageState getPackageStateLocked(String packageName, int uid) { - PackageState as = mState.mPackages.get(packageName, uid); - if (as != null) { + PackageState getPackageStateLocked(String packageName, int uid) { + PackageState as = mPackages.get(packageName, uid); + if (as != null) { + return as; + } + as = new PackageState(uid); + mPackages.put(packageName, uid, as); return as; } - as = new PackageState(uid); - mState.mPackages.put(packageName, uid, as); - return as; + + ProcessState getProcessStateLocked(String packageName, int uid, String processName) { + final PackageState pkgState = getPackageStateLocked(packageName, uid); + ProcessState ps = pkgState.mProcesses.get(processName); + if (ps != null) { + return ps; + } + ProcessState commonProc = mProcesses.get(processName, uid); + if (commonProc == null) { + commonProc = new ProcessState(this, packageName, uid, processName); + mProcesses.put(processName, uid, commonProc); + } + if (!commonProc.mMultiPackage) { + if (packageName.equals(commonProc.mPackage)) { + // This common process is not in use by multiple packages, and + // is for the calling package, so we can just use it directly. + ps = commonProc; + } else { + // This common process has not been in use by multiple packages, + // but it was created for a different package than the caller. + // We need to convert it to a multi-package process. + commonProc.mMultiPackage = true; + // The original package it was created for now needs to point + // to its own copy. + long now = SystemClock.uptimeMillis(); + pkgState.mProcesses.put(commonProc.mPackage, commonProc.clone( + commonProc.mPackage, now)); + ps = new ProcessState(commonProc, packageName, uid, processName, now); + } + } else { + // The common process is for multiple packages, we need to create a + // separate object for the per-package data. + ps = new ProcessState(commonProc, packageName, uid, processName, + SystemClock.uptimeMillis()); + } + pkgState.mProcesses.put(processName, ps); + return ps; + } + + void reset() { + mPackages.getMap().clear(); + mProcesses.getMap().clear(); + Arrays.fill(mMemFactorDurations, 0); + mMemFactor = STATE_NOTHING; + mStartTime = 0; + } + } + + public ProcessTracker(Context context) { + mContext = context; } public ProcessState getProcessStateLocked(String packageName, int uid, String processName) { - final PackageState as = getPackageStateLocked(packageName, uid); - ProcessState ps = as.mProcesses.get(processName); - if (ps != null) { - return ps; - } - ps = new ProcessState(packageName, uid, processName); - as.mProcesses.put(processName, ps); - return ps; + return mState.getProcessStateLocked(packageName, uid, processName); } public ServiceState getServiceStateLocked(String packageName, int uid, String className) { - final PackageState as = getPackageStateLocked(packageName, uid); + final PackageState as = mState.getPackageStateLocked(packageName, uid); ServiceState ss = as.mServices.get(className); if (ss != null) { return ss; @@ -252,6 +386,22 @@ public final class ProcessTracker { } } + static private void printScreenLabelCsv(PrintWriter pw, int offset) { + switch (offset) { + case ADJ_NOTHING: + break; + case ADJ_SCREEN_OFF: + pw.print(ADJ_SCREEN_NAMES_CSV[0]); + break; + case ADJ_SCREEN_ON: + pw.print(ADJ_SCREEN_NAMES_CSV[1]); + break; + default: + pw.print("???"); + break; + } + } + static private void printMemLabel(PrintWriter pw, int offset) { switch (offset) { case ADJ_NOTHING: @@ -275,6 +425,16 @@ public final class ProcessTracker { } } + static private void printMemLabelCsv(PrintWriter pw, int offset) { + if (offset >= ADJ_MEM_FACTOR_NORMAL) { + if (offset <= ADJ_MEM_FACTOR_CRITICAL) { + pw.print(ADJ_MEM_NAMES_CSV[offset]); + } else { + pw.print("???"); + } + } + } + static void dumpSingleTime(PrintWriter pw, String prefix, long[] durations, int curState, long curStartTime, long now) { long totalTime = 0; @@ -310,6 +470,43 @@ public final class ProcessTracker { } } + static void dumpSingleTimeCsv(PrintWriter pw, String sep, long[] durations, + int curState, long curStartTime, long now) { + for (int iscreen=0; iscreen collectProcessesLocked(int[] screenStates, int[] memStates, - int[] procStates, long now) { - ArrayList outProcs = new ArrayList(); - ArrayMap> pmap = mState.mPackages.getMap(); - for (int ip=0; ip procs = pmap.valueAt(ip); + int[] procStates, long now, String reqPackage) { + ArraySet foundProcs = new ArraySet(); + ArrayMap> pkgMap = mState.mPackages.getMap(); + for (int ip=0; ip procs = pkgMap.valueAt(ip); for (int iu=0; iu 0) { - outProcs.add(state.mProcesses.valueAt(iproc)); + ProcessState proc = state.mProcesses.valueAt(iproc); + if (proc.mCommonProcess != null) { + proc = proc.mCommonProcess; } + foundProcs.add(proc); } } } + ArrayList outProcs = new ArrayList(foundProcs.size()); + for (int i=0; i 0) { + outProcs.add(proc); + } + } Collections.sort(outProcs, new Comparator() { @Override public int compare(ProcessState lhs, ProcessState rhs) { @@ -376,7 +585,6 @@ public final class ProcessTracker { time += now - proc.mStartTime; running = " (running)"; } - totalTime += time; if (time != 0) { pw.print(prefix); if (screenStates.length > 1) { @@ -409,26 +617,119 @@ public final class ProcessTracker { } } + void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates, + int[] memStates, int[] procStates) { + final int NS = screenStates != null ? screenStates.length : 1; + final int NM = memStates != null ? memStates.length : 1; + final int NP = procStates != null ? procStates.length : 1; + for (int is=0; is 1) { + printScreenLabelCsv(pw, screenStates[is]); + printed = true; + } + if (memStates != null && memStates.length > 1) { + if (printed) { + pw.print("-"); + } + printMemLabelCsv(pw, memStates[im]); + printed = true; + } + if (procStates != null && procStates.length > 1) { + if (printed) { + pw.print("-"); + } + pw.print(STATE_NAMES_CSV[procStates[ip]]); + } + } + } + } + } + + void dumpProcessStateCsv(PrintWriter pw, ProcessState proc, + boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, + boolean sepProcStates, int[] procStates, long now) { + final int NSS = sepScreenStates ? screenStates.length : 1; + final int NMS = sepMemStates ? memStates.length : 1; + final int NPS = sepProcStates ? procStates.length : 1; + for (int iss=0; iss procs, int[] screenStates, int[] memStates, int[] procStates, long now) { String innerPrefix = prefix + " "; for (int i=procs.size()-1; i>=0; i--) { ProcessState proc = procs.get(i); pw.print(prefix); - pw.print(proc.mPackage); + pw.print(proc.mName); pw.print(" / "); UserHandle.formatUid(pw, proc.mUid); - pw.print(" / "); - pw.print(proc.mName); pw.println(":"); dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now); } } + void dumpProcessListCsv(PrintWriter pw, ArrayList procs, + boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, + boolean sepProcStates, int[] procStates, long now) { + pw.print("process"); + pw.print(CSV_SEP); + pw.print("uid"); + dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null, + sepMemStates ? memStates : null, + sepProcStates ? procStates : null); + pw.println(); + for (int i=procs.size()-1; i>=0; i--) { + ProcessState proc = procs.get(i); + pw.print(proc.mName); + pw.print(CSV_SEP); + UserHandle.formatUid(pw, proc.mUid); + dumpProcessStateCsv(pw, proc, sepScreenStates, screenStates, + sepMemStates, memStates, sepProcStates, procStates, now); + pw.println(); + } + } + void dumpFilteredProcesses(PrintWriter pw, String header, String prefix, - int[] screenStates, int[] memStates, int[] procStates, long now) { + int[] screenStates, int[] memStates, int[] procStates, long now, String reqPackage) { ArrayList procs = collectProcessesLocked(screenStates, memStates, - procStates, now); + procStates, now, reqPackage); if (procs.size() > 0) { pw.println(); pw.println(header); @@ -436,100 +737,405 @@ public final class ProcessTracker { } } - public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) { - final long now = SystemClock.uptimeMillis(); - ArrayMap> pmap = mState.mPackages.getMap(); - pw.println("Per-Package Process Stats:"); - for (int ip=0; ip procs = pmap.valueAt(ip); - for (int iu=0; iu procs = collectProcessesLocked(screenStates, memStates, + procStates, now, reqPackage); + if (procs.size() > 0) { + if (header != null) { + pw.println(header); + } + dumpProcessListCsv(pw, procs, sepScreenStates, screenStates, + sepMemStates, memStates, sepProcStates, procStates, now); + return true; + } + return false; + } + + void dumpAllProcessState(PrintWriter pw, String prefix, boolean isCheckin, + ProcessState proc, long now) { + long totalTime = 0; + int printedScreen = -1; + for (int iscreen=0; iscreen res = new ArrayList(); + int lastPos = 0; + for (int i=0; i<=arg.length(); i++) { + char c = i < arg.length() ? arg.charAt(i) : 0; + if (c != ',' && c != '+' && c != ' ' && c != 0) { + continue; + } + boolean isSep = c == ','; + if (lastPos == 0) { + // We now know the type of op. + outSep[0] = isSep; + } else if (c != 0 && outSep[0] != isSep) { + outError[0] = "inconsistent separators (can't mix ',' with '+')"; + return null; + } + if (lastPos < (i-1)) { + String str = arg.substring(lastPos, i); + for (int j=0; j]"); + pw.println(" --checkin: format output for a checkin report."); + pw.println(" --csv: output data suitable for putting in a spreadsheet."); + pw.println(" --csv-screen: on, off."); + pw.println(" --csv-mem: norm, mod, low, crit."); + pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,"); + pw.println(" service, home, prev, cached"); + pw.println(" --reset: reset the stats, clearing all current data."); + pw.println(" -h: print this help text."); + pw.println(" : optional name of package to filter output by."); + } + + public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) { + final long now = SystemClock.uptimeMillis(); + + boolean isCheckin = false; + boolean isCsv = false; + String reqPackage = null; + boolean csvSepScreenStats = false; + int[] csvScreenStats = new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON}; + boolean csvSepMemStats = false; + int[] csvMemStats = new int[] {ADJ_MEM_FACTOR_CRITICAL}; + boolean csvSepProcStats = true; + int[] csvProcStats = new int[] { + STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE, + STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME, + STATE_PREVIOUS, STATE_CACHED }; + if (args != null) { + for (int i=0; i= args.length) { + pw.println("Error: argument required for --csv-screen"); + dumpHelp(pw); + return; + } + boolean[] sep = new boolean[1]; + String[] error = new String[1]; + csvScreenStats = parseStateList(ADJ_SCREEN_NAMES_CSV, ADJ_SCREEN_MOD, + args[i], sep, error); + if (csvScreenStats == null) { + pw.println("Error in \"" + args[i] + "\": " + error[0]); + dumpHelp(pw); + return; + } + csvSepScreenStats = sep[0]; + } else if ("--csv-mem".equals(arg)) { + i++; + if (i >= args.length) { + pw.println("Error: argument required for --csv-mem"); + dumpHelp(pw); + return; + } + boolean[] sep = new boolean[1]; + String[] error = new String[1]; + csvMemStats = parseStateList(ADJ_MEM_NAMES_CSV, 1, args[i], sep, error); + if (csvMemStats == null) { + pw.println("Error in \"" + args[i] + "\": " + error[0]); + dumpHelp(pw); + return; + } + csvSepMemStats = sep[0]; + } else if ("--csv-proc".equals(arg)) { + i++; + if (i >= args.length) { + pw.println("Error: argument required for --csv-proc"); + dumpHelp(pw); + return; + } + boolean[] sep = new boolean[1]; + String[] error = new String[1]; + csvProcStats = parseStateList(STATE_NAMES_CSV, 1, args[i], sep, error); + if (csvProcStats == null) { + pw.println("Error in \"" + args[i] + "\": " + error[0]); + dumpHelp(pw); + return; + } + csvSepProcStats = sep[0]; + } else if ("--reset".equals(arg)) { + mState.reset(); + pw.println("Process stats reset."); + return; + } else if ("-h".equals(arg)) { + dumpHelp(pw); + return; + } else if ("-a".equals(arg)) { + // ignore + } else if (arg.length() > 0 && arg.charAt(0) == '-'){ + pw.println("Unknown option: " + arg); + dumpHelp(pw); + return; + } else { + // Not an option, last argument must be a package name. + try { + mContext.getPackageManager().getPackageUid(arg, + UserHandle.getCallingUserId()); + reqPackage = arg; + } catch (PackageManager.NameNotFoundException e) { + pw.println("Unknown package: " + arg); + dumpHelp(pw); + return; + } + } + } + } + + if (isCsv) { + pw.print("Processes running summed over"); + if (!csvSepScreenStats) { + for (int i=0; i> pkgMap = mState.mPackages.getMap(); + boolean printedHeader = false; + if (isCheckin) { + pw.println("vers,1"); + } + for (int ip=0; ip uids = pkgMap.valueAt(ip); + for (int iu=0; iu 0 || NSRVS > 0) { + if (!printedHeader) { + pw.println("Per-Package Process Stats:"); + printedHeader = true; + } + pw.print(" * "); pw.print(pkgName); pw.print(" / "); + UserHandle.formatUid(pw, uid); pw.println(":"); + } + } + for (int iproc=0; iproc> procMap = mState.mProcesses.getMap(); + for (int ip=0; ip uids = procMap.valueAt(ip); + for (int iu=0; iu