From 4e028d067e88531493795b8206e861f79bfb29f5 Mon Sep 17 00:00:00 2001 From: Chenjie Yu Date: Fri, 14 Sep 2018 16:24:26 -0700 Subject: [PATCH] add api to get sections of procstats Add api to collect committed procstats data. Use highwatermark from the user to filter which files to include. This way multiple users in the system can use this api. Also allow ProcessStats.java to dump optional ProcessStatsSectionProto so that other users can use it. Test: will add cts test Change-Id: If37c0fd25814460a1c8d5996d24d138295ff6421 --- .../internal/app/procstats/IProcessStats.aidl | 10 + .../internal/app/procstats/ProcessStats.java | 546 ++++++++++-------- .../server/am/ProcessStatsService.java | 157 ++++- 3 files changed, 457 insertions(+), 256 deletions(-) diff --git a/core/java/com/android/internal/app/procstats/IProcessStats.aidl b/core/java/com/android/internal/app/procstats/IProcessStats.aidl index 44867c7719cd5..0c203ab763464 100644 --- a/core/java/com/android/internal/app/procstats/IProcessStats.aidl +++ b/core/java/com/android/internal/app/procstats/IProcessStats.aidl @@ -24,4 +24,14 @@ interface IProcessStats { byte[] getCurrentStats(out List historic); ParcelFileDescriptor getStatsOverTime(long minTime); int getCurrentMemoryState(); + + /** + * Get stats committed after highWaterMarkMs + * @param highWaterMarkMs Report stats committed after this time. + * @param section Integer mask to indicate which sections to include in the stats. + * @param doAggregate Whether to aggregate the stats or keep them separated. + * @param List of Files of individual commits in protobuf binary or one that is merged from them. + */ + long getCommittedStats(long highWaterMarkMs, int section, boolean doAggregate, + out List committedStats); } diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java index f6e99ba90b86f..e7ac5664c3ee9 100644 --- a/core/java/com/android/internal/app/procstats/ProcessStats.java +++ b/core/java/com/android/internal/app/procstats/ProcessStats.java @@ -158,6 +158,25 @@ public final class ProcessStats implements Parcelable { STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY }; + // Should report process stats. + public static final int REPORT_PROC_STATS = 0x01; + // Should report package process stats. + public static final int REPORT_PKG_PROC_STATS = 0x02; + // Should report package service stats. + public static final int REPORT_PKG_SVC_STATS = 0x04; + // Should report package association stats. + public static final int REPORT_PKG_ASC_STATS = 0x08; + // Should report package stats. + public static final int REPORT_PKG_STATS = 0x0E; + // Should report all stats. + public static final int REPORT_ALL = 0x0F; + + public static final int[] OPTIONS = + {REPORT_PROC_STATS, REPORT_PKG_PROC_STATS, REPORT_PKG_SVC_STATS, REPORT_PKG_ASC_STATS, + REPORT_PKG_STATS, REPORT_ALL}; + public static final String[] OPTIONS_STR = + {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"}; + // Current version of the parcel format. private static final int PARCEL_VERSION = 34; // In-memory Parcel magic number, used to detect attempts to unmarshall bad data @@ -1412,7 +1431,7 @@ public final class ProcessStats implements Parcelable { } public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary, - boolean dumpDetails, boolean dumpAll, boolean activeOnly) { + boolean dumpDetails, boolean dumpAll, boolean activeOnly, int section) { long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor, mStartTime, now); boolean sepNeeded = false; @@ -1421,176 +1440,205 @@ public final class ProcessStats implements Parcelable { mSysMemUsage.dump(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ); sepNeeded = true; } - ArrayMap>> pkgMap = mPackages.getMap(); boolean printedHeader = false; - for (int ip=0; ip> uids = pkgMap.valueAt(ip); - for (int iu=0; iu vpkgs = uids.valueAt(iu); - for (int iv=0; iv>> pkgMap = + mPackages.getMap(); + for (int ip = 0; ip < pkgMap.size(); ip++) { + final String pkgName = pkgMap.keyAt(ip); + final SparseArray> uids = pkgMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final int uid = uids.keyAt(iu); + final LongSparseArray vpkgs = uids.valueAt(iu); + for (int iv = 0; iv < vpkgs.size(); iv++) { + final long vers = vpkgs.keyAt(iv); + final PackageState pkgState = vpkgs.valueAt(iv); + final int NPROCS = pkgState.mProcesses.size(); + final int NSRVS = pkgState.mServices.size(); + final int NASCS = pkgState.mAssociations.size(); + final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); + if (!pkgMatch) { + boolean procMatch = false; + for (int iproc = 0; iproc < NPROCS; iproc++) { + ProcessState proc = pkgState.mProcesses.valueAt(iproc); + if (reqPackage.equals(proc.getName())) { + procMatch = true; + break; + } } - } - if (!procMatch) { - continue; - } - } - if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) { - if (!printedHeader) { - if (sepNeeded) pw.println(); - pw.println("Per-Package Stats:"); - printedHeader = true; - sepNeeded = true; - } - pw.print(" * "); pw.print(pkgName); pw.print(" / "); - UserHandle.formatUid(pw, uid); pw.print(" / v"); - pw.print(vers); pw.println(":"); - } - if (!dumpSummary || dumpAll) { - for (int iproc=0; iproc 0 || NSRVS > 0 || NASCS > 0) { + if (!printedHeader) { + if (sepNeeded) pw.println(); + pw.println("Per-Package Stats:"); + printedHeader = true; + sepNeeded = true; } - pw.print(" Process "); - pw.print(pkgState.mProcesses.keyAt(iproc)); - if (proc.getCommonProcess().isMultiPackage()) { - pw.print(" (multi, "); - } else { - pw.print(" (unique, "); - } - pw.print(proc.getDurationsBucketCount()); - pw.print(" entries)"); + pw.print(" * "); + pw.print(pkgName); + pw.print(" / "); + UserHandle.formatUid(pw, uid); + pw.print(" / v"); + pw.print(vers); pw.println(":"); - proc.dumpProcessState(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, - ALL_PROC_STATES, now); - proc.dumpPss(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, - ALL_PROC_STATES, now); - proc.dumpInternalLocked(pw, " ", dumpAll); } - } else { - ArrayList procs = new ArrayList(); - for (int iproc=0; iproc procs = new ArrayList(); + for (int iproc = 0; iproc < NPROCS; iproc++) { + ProcessState proc = pkgState.mProcesses.valueAt(iproc); + if (!pkgMatch && !reqPackage.equals(proc.getName())) { + continue; + } + if (activeOnly && !proc.isInUse()) { + continue; + } + procs.add(proc); + } + DumpUtils.dumpProcessSummaryLocked(pw, " ", "Prc ", procs, + ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES, + now, totalTime); } - if (activeOnly && !proc.isInUse()) { - continue; + } + if ((section & REPORT_PKG_SVC_STATS) != 0) { + for (int isvc = 0; isvc < NSRVS; isvc++) { + ServiceState svc = pkgState.mServices.valueAt(isvc); + if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) { + continue; + } + if (activeOnly && !svc.isInUse()) { + pw.print(" (Not active service: "); + pw.print(pkgState.mServices.keyAt(isvc)); + pw.println(")"); + continue; + } + if (dumpAll) { + pw.print(" Service "); + } else { + pw.print(" * Svc "); + } + pw.print(pkgState.mServices.keyAt(isvc)); + pw.println(":"); + pw.print(" Process: "); + pw.println(svc.getProcessName()); + svc.dumpStats(pw, " ", " ", " ", + now, totalTime, dumpSummary, dumpAll); } - procs.add(proc); } - DumpUtils.dumpProcessSummaryLocked(pw, " ", "Prc ", procs, - ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES, - now, totalTime); - } - for (int isvc=0; isvc> procMap = mProcesses.getMap(); - printedHeader = false; - int numShownProcs = 0, numTotalProcs = 0; - for (int ip=0; ip uids = procMap.valueAt(ip); - for (int iu=0; iu> procMap = mProcesses.getMap(); + printedHeader = false; + int numShownProcs = 0, numTotalProcs = 0; + for (int ip = 0; ip < procMap.size(); ip++) { + String procName = procMap.keyAt(ip); + SparseArray uids = procMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + int uid = uids.keyAt(iu); + numTotalProcs++; + final ProcessState proc = uids.valueAt(iu); + if (!proc.hasAnyData()) { + continue; + } + if (!proc.isMultiPackage()) { + continue; + } + if (reqPackage != null && !reqPackage.equals(procName) + && !reqPackage.equals(proc.getPackage())) { + continue; + } + numShownProcs++; + if (sepNeeded) { + pw.println(); + } + sepNeeded = true; + if (!printedHeader) { + pw.println("Multi-Package Common Processes:"); + printedHeader = true; + } + if (activeOnly && !proc.isInUse()) { + pw.print(" (Not active: "); + pw.print(procName); + pw.println(")"); + continue; + } + pw.print(" * "); + pw.print(procName); + pw.print(" / "); + UserHandle.formatUid(pw, uid); + pw.print(" ("); + pw.print(proc.getDurationsBucketCount()); + pw.print(" entries)"); + pw.println(":"); + proc.dumpProcessState(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, + ALL_PROC_STATES, now); + proc.dumpPss(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now); + proc.dumpInternalLocked(pw, " ", dumpAll); } - if (!proc.isMultiPackage()) { - continue; - } - if (reqPackage != null && !reqPackage.equals(procName) - && !reqPackage.equals(proc.getPackage())) { - continue; - } - numShownProcs++; - if (sepNeeded) { - pw.println(); - } - sepNeeded = true; - if (!printedHeader) { - pw.println("Multi-Package Common Processes:"); - printedHeader = true; - } - if (activeOnly && !proc.isInUse()) { - pw.print(" (Not active: "); pw.print(procName); pw.println(")"); - continue; - } - pw.print(" * "); pw.print(procName); pw.print(" / "); - UserHandle.formatUid(pw, uid); - pw.print(" ("); pw.print(proc.getDurationsBucketCount()); - pw.print(" entries)"); pw.println(":"); - proc.dumpProcessState(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, - ALL_PROC_STATES, now); - proc.dumpPss(pw, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now); - proc.dumpInternalLocked(pw, " ", dumpAll); } + pw.print(" Total procs: "); pw.print(numShownProcs); + pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); } if (dumpAll) { @@ -1598,8 +1646,7 @@ public final class ProcessStats implements Parcelable { pw.println(); } sepNeeded = true; - pw.print(" Total procs: "); pw.print(numShownProcs); - pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); + if (mTrackingAssociations.size() > 0) { pw.println(); pw.println("Tracking associations:"); @@ -1866,7 +1913,10 @@ public final class ProcessStats implements Parcelable { return outProcs; } - public void dumpCheckinLocked(PrintWriter pw, String reqPackage) { + /** + * Prints checkin style stats dump. + */ + public void dumpCheckinLocked(PrintWriter pw, String reqPackage, int section) { final long now = SystemClock.uptimeMillis(); final ArrayMap>> pkgMap = mPackages.getMap(); @@ -1895,50 +1945,61 @@ public final class ProcessStats implements Parcelable { } pw.println(); pw.print("config,"); pw.println(mRuntime); - for (int ip=0; ip> uids = pkgMap.valueAt(ip); - for (int iu=0; iu vpkgs = uids.valueAt(iu); - for (int iv=0; iv> uids = pkgMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final int uid = uids.keyAt(iu); + final LongSparseArray vpkgs = uids.valueAt(iu); + for (int iv = 0; iv < vpkgs.size(); iv++) { + final long vers = vpkgs.keyAt(iv); + final PackageState pkgState = vpkgs.valueAt(iv); + final int NPROCS = pkgState.mProcesses.size(); + final int NSRVS = pkgState.mServices.size(); + final int NASCS = pkgState.mAssociations.size(); + if ((section & REPORT_PKG_PROC_STATS) != 0) { + for (int iproc = 0; iproc < NPROCS; iproc++) { + ProcessState proc = pkgState.mProcesses.valueAt(iproc); + proc.dumpPackageProcCheckin(pw, pkgName, uid, vers, + pkgState.mProcesses.keyAt(iproc), now); + } + } + if ((section & REPORT_PKG_SVC_STATS) != 0) { + for (int isvc = 0; isvc < NSRVS; isvc++) { + final String serviceName = DumpUtils.collapseString(pkgName, + pkgState.mServices.keyAt(isvc)); + final ServiceState svc = pkgState.mServices.valueAt(isvc); + svc.dumpTimesCheckin(pw, pkgName, uid, vers, serviceName, now); + } + } + if ((section & REPORT_PKG_ASC_STATS) != 0) { + for (int iasc = 0; iasc < NASCS; iasc++) { + final String associationName = DumpUtils.collapseString(pkgName, + pkgState.mAssociations.keyAt(iasc)); + final AssociationState asc = pkgState.mAssociations.valueAt(iasc); + asc.dumpTimesCheckin(pw, pkgName, uid, vers, associationName, now); + } + } } } } } - ArrayMap> procMap = mProcesses.getMap(); - for (int ip=0; ip uids = procMap.valueAt(ip); - for (int iu=0; iu> procMap = mProcesses.getMap(); + for (int ip = 0; ip < procMap.size(); ip++) { + String procName = procMap.keyAt(ip); + SparseArray uids = procMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final int uid = uids.keyAt(iu); + final ProcessState procState = uids.valueAt(iu); + procState.dumpProcCheckin(pw, procName, uid, now); + } } } pw.print("total"); @@ -2013,9 +2074,10 @@ public final class ProcessStats implements Parcelable { } } - public void writeToProto(ProtoOutputStream proto, long fieldId, long now) { - final long token = proto.start(fieldId); - + /** + * Writes to ProtoOutputStream. + */ + public void writeToProto(ProtoOutputStream proto, long now, int section) { proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime); proto.write(ProcessStatsSectionProto.END_REALTIME_MS, mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime); @@ -2024,15 +2086,15 @@ public final class ProcessStats implements Parcelable { proto.write(ProcessStatsSectionProto.RUNTIME, mRuntime); proto.write(ProcessStatsSectionProto.HAS_SWAPPED_PSS, mHasSwappedOutPss); boolean partial = true; - if ((mFlags&FLAG_SHUTDOWN) != 0) { + if ((mFlags & FLAG_SHUTDOWN) != 0) { proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SHUTDOWN); partial = false; } - if ((mFlags&FLAG_SYSPROPS) != 0) { + if ((mFlags & FLAG_SYSPROPS) != 0) { proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SYSPROPS); partial = false; } - if ((mFlags&FLAG_COMPLETE) != 0) { + if ((mFlags & FLAG_COMPLETE) != 0) { proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_COMPLETE); partial = false; } @@ -2041,31 +2103,34 @@ public final class ProcessStats implements Parcelable { } final ArrayMap> procMap = mProcesses.getMap(); - for (int ip=0; ip uids = procMap.valueAt(ip); - for (int iu=0; iu>> pkgMap = - mPackages.getMap(); - for (int ip = 0; ip < pkgMap.size(); ip++) { - final SparseArray> uids = pkgMap.valueAt(ip); - for (int iu = 0; iu < uids.size(); iu++) { - final LongSparseArray vers = uids.valueAt(iu); - for (int iv = 0; iv < vers.size(); iv++) { - final PackageState pkgState = vers.valueAt(iv); - pkgState.writeToProto(proto, ProcessStatsSectionProto.PACKAGE_STATS, now); + if ((section & REPORT_PROC_STATS) != 0) { + for (int ip = 0; ip < procMap.size(); ip++) { + final String procName = procMap.keyAt(ip); + final SparseArray uids = procMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final int uid = uids.keyAt(iu); + final ProcessState procState = uids.valueAt(iu); + procState.writeToProto(proto, ProcessStatsSectionProto.PROCESS_STATS, procName, + uid, now); } } } - proto.end(token); + if ((section & REPORT_PKG_STATS) != 0) { + final ArrayMap>> pkgMap = + mPackages.getMap(); + for (int ip = 0; ip < pkgMap.size(); ip++) { + final SparseArray> uids = pkgMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final LongSparseArray vers = uids.valueAt(iu); + for (int iv = 0; iv < vers.size(); iv++) { + final PackageState pkgState = vers.valueAt(iv); + pkgState.writeToProto(proto, ProcessStatsSectionProto.PACKAGE_STATS, now, + section); + } + } + } + } } final public static class ProcessStateHolder { @@ -2110,30 +2175,39 @@ public final class ProcessStats implements Parcelable { return as; } - public void writeToProto(ProtoOutputStream proto, long fieldId, long now) { + /** + * Writes the containing stats into proto, with options to choose smaller sections. + */ + public void writeToProto(ProtoOutputStream proto, long fieldId, long now, int section) { final long token = proto.start(fieldId); proto.write(ProcessStatsPackageProto.PACKAGE, mPackageName); proto.write(ProcessStatsPackageProto.UID, mUid); proto.write(ProcessStatsPackageProto.VERSION, mVersionCode); - for (int ip = 0; ip < mProcesses.size(); ip++) { - final String procName = mProcesses.keyAt(ip); - final ProcessState procState = mProcesses.valueAt(ip); - procState.writeToProto(proto, ProcessStatsPackageProto.PROCESS_STATS, procName, - mUid, now); + if ((section & ProcessStats.REPORT_PKG_PROC_STATS) != 0) { + for (int ip = 0; ip < mProcesses.size(); ip++) { + final String procName = mProcesses.keyAt(ip); + final ProcessState procState = mProcesses.valueAt(ip); + procState.writeToProto(proto, ProcessStatsPackageProto.PROCESS_STATS, procName, + mUid, now); + } } - for (int is = 0; is < mServices.size(); is++) { - final ServiceState serviceState = mServices.valueAt(is); - serviceState.writeToProto(proto, ProcessStatsPackageProto.SERVICE_STATS, - now); + if ((section & ProcessStats.REPORT_PKG_SVC_STATS) != 0) { + for (int is = 0; is < mServices.size(); is++) { + final ServiceState serviceState = mServices.valueAt(is); + serviceState.writeToProto(proto, ProcessStatsPackageProto.SERVICE_STATS, + now); + } } - for (int ia=0; ia optionStrList = Arrays.asList(ProcessStats.OPTIONS_STR); + for (String sectionStr : sectionsStr) { + int optionIndex = optionStrList.indexOf(sectionStr); + if (optionIndex != -1) { + res |= ProcessStats.OPTIONS[optionIndex]; + } + } + return res; + } + public byte[] getCurrentStats(List historic) { mAm.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); @@ -514,6 +534,95 @@ public final class ProcessStatsService extends IProcessStats.Stub { return current.marshall(); } + /** + * Get stats committed after highWaterMarkMs + * @param highWaterMarkMs Report stats committed after this time. + * @param section Integer mask to indicage which sections to include in the stats. + * @param doAggregate Whether to aggregate the stats or keep them separated. + * @return List of proto binary of individual commit files or one that is merged from them. + */ + @Override + public long getCommittedStats(long highWaterMarkMs, int section, boolean doAggregate, + List committedStats) { + mAm.mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.PACKAGE_USAGE_STATS, null); + + ProcessStats mergedStats = new ProcessStats(false); + long newHighWaterMark = highWaterMarkMs; + mWriteLock.lock(); + try { + ArrayList files = getCommittedFiles(0, false, true); + if (files != null) { + String highWaterMarkStr = + DateFormat.format("yyyy-MM-dd-HH-mm-ss", highWaterMarkMs).toString(); + ProcessStats stats = new ProcessStats(false); + for (int i = files.size() - 1; i >= 0; i--) { + String fileName = files.get(i); + try { + String startTimeStr = fileName.substring( + fileName.lastIndexOf(STATE_FILE_PREFIX) + + STATE_FILE_PREFIX.length(), + fileName.lastIndexOf(STATE_FILE_SUFFIX)); + if (startTimeStr.compareToIgnoreCase(highWaterMarkStr) > 0) { + ParcelFileDescriptor pfd = ParcelFileDescriptor.open( + new File(fileName), + ParcelFileDescriptor.MODE_READ_ONLY); + InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + stats.reset(); + stats.read(is); + is.close(); + if (stats.mTimePeriodStartClock > newHighWaterMark) { + newHighWaterMark = stats.mTimePeriodStartClock; + } + if (doAggregate) { + mergedStats.add(stats); + } else { + committedStats.add(protoToParcelFileDescriptor(stats, section)); + } + if (stats.mReadError != null) { + Log.w(TAG, "Failure reading process stats: " + stats.mReadError); + continue; + } + } + } catch (IOException e) { + Slog.w(TAG, "Failure opening procstat file " + fileName, e); + } catch (IndexOutOfBoundsException e) { + Slog.w(TAG, "Failure to read and parse commit file " + fileName, e); + } + } + if (doAggregate) { + committedStats.add(protoToParcelFileDescriptor(mergedStats, section)); + } + return newHighWaterMark; + } + } catch (IOException e) { + Slog.w(TAG, "Failure opening procstat file", e); + } finally { + mWriteLock.unlock(); + } + return newHighWaterMark; + } + + private ParcelFileDescriptor protoToParcelFileDescriptor(ProcessStats stats, int section) + throws IOException { + final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); + Thread thr = new Thread("ProcessStats pipe output") { + public void run() { + try { + FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]); + final ProtoOutputStream proto = new ProtoOutputStream(fout); + stats.writeToProto(proto, stats.mTimePeriodEndRealtime, section); + proto.flush(); + fout.close(); + } catch (IOException e) { + Slog.w(TAG, "Failure writing pipe", e); + } + } + }; + thr.start(); + return fds[0]; + } + public ParcelFileDescriptor getStatsOverTime(long minTime) { mAm.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); @@ -594,7 +703,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now, String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails, - boolean dumpAll, boolean activeOnly) { + boolean dumpAll, boolean activeOnly, int section) { ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000 - (ProcessStats.COMMIT_PERIOD/2)); if (pfd == null) { @@ -609,11 +718,11 @@ public final class ProcessStatsService extends IProcessStats.Stub { return; } if (isCompact) { - stats.dumpCheckinLocked(pw, reqPackage); + stats.dumpCheckinLocked(pw, reqPackage, section); } else { if (dumpDetails || dumpFullDetails) { stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails, dumpAll, - activeOnly); + activeOnly, section); } else { stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); } @@ -643,6 +752,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { pw.println(" --max: for -a, max num of historical batches to print."); pw.println(" --active: only show currently active processes/services."); pw.println(" --commit: commit current stats to disk and reset to start new stats."); + pw.println(" --section: proc|pkg-proc|pkg-svc|pkg-asc|pkg-all|all "); + pw.println(" options can be combined to select desired stats"); pw.println(" --reset: reset current stats, without committing."); pw.println(" --clear: clear all stats; does both --reset and deletes old stats."); pw.println(" --write: write current in-memory stats to disk."); @@ -696,6 +807,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { int[] csvMemStats = new int[] { ProcessStats.ADJ_MEM_FACTOR_CRITICAL}; boolean csvSepProcStats = true; int[] csvProcStats = ProcessStats.ALL_PROC_STATES; + int section = ProcessStats.REPORT_ALL; if (args != null) { for (int i=0; i= args.length) { + pw.println("Error: argument required for --section"); + dumpHelp(pw); + return; } + section = parseSectionOptions(args[i]); } else if ("--clear".equals(arg)) { synchronized (mAm) { mProcessStats.resetSafely(); @@ -946,7 +1059,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { } else if (aggregateHours != 0) { pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:"); dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact, - dumpDetails, dumpFullDetails, dumpAll, activeOnly); + dumpDetails, dumpFullDetails, dumpAll, activeOnly, section); return; } else if (lastIndex > 0) { pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":"); @@ -968,7 +1081,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX); if (isCheckin || isCompact) { // Don't really need to lock because we uniquely own this object. - processStats.dumpCheckinLocked(pw, reqPackage); + processStats.dumpCheckinLocked(pw, reqPackage, section); } else { pw.print("COMMITTED STATS FROM "); pw.print(processStats.mTimePeriodStartClockStr); @@ -976,7 +1089,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { pw.println(":"); if (dumpDetails || dumpFullDetails) { processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails, - dumpAll, activeOnly); + dumpAll, activeOnly, section); if (dumpAll) { pw.print(" mFile="); pw.println(mFile.getBaseFile()); } @@ -1015,7 +1128,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX); if (isCheckin || isCompact) { // Don't really need to lock because we uniquely own this object. - processStats.dumpCheckinLocked(pw, reqPackage); + processStats.dumpCheckinLocked(pw, reqPackage, section); } else { if (sepNeeded) { pw.println(); @@ -1031,7 +1144,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { // much crud. if (dumpFullDetails) { processStats.dumpLocked(pw, reqPackage, now, false, false, - false, activeOnly); + false, activeOnly, section); } else { processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); } @@ -1054,7 +1167,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { if (!isCheckin) { synchronized (mAm) { if (isCompact) { - mProcessStats.dumpCheckinLocked(pw, reqPackage); + mProcessStats.dumpCheckinLocked(pw, reqPackage, section); } else { if (sepNeeded) { pw.println(); @@ -1062,7 +1175,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { pw.println("CURRENT STATS:"); if (dumpDetails || dumpFullDetails) { mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails, - dumpAll, activeOnly); + dumpAll, activeOnly, section); if (dumpAll) { pw.print(" mFile="); pw.println(mFile.getBaseFile()); } @@ -1078,11 +1191,11 @@ public final class ProcessStatsService extends IProcessStats.Stub { } pw.println("AGGREGATED OVER LAST 24 HOURS:"); dumpAggregatedStats(pw, 24, now, reqPackage, isCompact, - dumpDetails, dumpFullDetails, dumpAll, activeOnly); + dumpDetails, dumpFullDetails, dumpAll, activeOnly, section); pw.println(); pw.println("AGGREGATED OVER LAST 3 HOURS:"); dumpAggregatedStats(pw, 3, now, reqPackage, isCompact, - dumpDetails, dumpFullDetails, dumpAll, activeOnly); + dumpDetails, dumpFullDetails, dumpAll, activeOnly, section); } } } @@ -1099,7 +1212,9 @@ public final class ProcessStatsService extends IProcessStats.Stub { if (stats.mReadError != null) { return; } - stats.writeToProto(proto, fieldId, now); + final long token = proto.start(fieldId); + stats.writeToProto(proto, now, ProcessStats.REPORT_ALL); + proto.end(token); } private void dumpProto(FileDescriptor fd) { @@ -1109,7 +1224,9 @@ public final class ProcessStatsService extends IProcessStats.Stub { long now; synchronized (mAm) { now = SystemClock.uptimeMillis(); - mProcessStats.writeToProto(proto,ProcessStatsServiceDumpProto.PROCSTATS_NOW, now); + final long token = proto.start(ProcessStatsServiceDumpProto.PROCSTATS_NOW); + mProcessStats.writeToProto(proto, now, ProcessStats.REPORT_ALL); + proto.end(token); } // aggregated over last 3 hours procstats