diff options
author | 2018-09-26 15:07:51 +0000 | |
---|---|---|
committer | 2018-09-26 15:07:51 +0000 | |
commit | cc4cb5922381967fc14f99cd4d152ee799bcd420 (patch) | |
tree | 030780110d33a38a8abca823af95f8310c05dba9 | |
parent | 013239edfb4b6bc7a76f154f2f239e89e2e3456d (diff) | |
parent | 4e028d067e88531493795b8206e861f79bfb29f5 (diff) |
Merge "add api to get sections of procstats"
3 files changed, 455 insertions, 254 deletions
diff --git a/core/java/com/android/internal/app/procstats/IProcessStats.aidl b/core/java/com/android/internal/app/procstats/IProcessStats.aidl index 44867c7719cd..0c203ab76346 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<ParcelFileDescriptor> 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<ParcelFileDescriptor> committedStats); } diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java index f6e99ba90b86..e7ac5664c3ee 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<String, SparseArray<LongSparseArray<PackageState>>> pkgMap = mPackages.getMap(); boolean printedHeader = false; - for (int ip=0; ip<pkgMap.size(); ip++) { - final String pkgName = pkgMap.keyAt(ip); - final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip); - for (int iu=0; iu<uids.size(); iu++) { - final int uid = uids.keyAt(iu); - final LongSparseArray<PackageState> 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<NPROCS; iproc++) { - ProcessState proc = pkgState.mProcesses.valueAt(iproc); - if (!pkgMatch && !reqPackage.equals(proc.getName())) { - continue; + if ((section & REPORT_PKG_STATS) != 0) { + ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap = + mPackages.getMap(); + for (int ip = 0; ip < pkgMap.size(); ip++) { + final String pkgName = pkgMap.keyAt(ip); + final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final int uid = uids.keyAt(iu); + final LongSparseArray<PackageState> 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 (activeOnly && !proc.isInUse()) { - pw.print(" (Not active: "); - pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")"); + if (!procMatch) { continue; } - pw.print(" Process "); - pw.print(pkgState.mProcesses.keyAt(iproc)); - if (proc.getCommonProcess().isMultiPackage()) { - pw.print(" (multi, "); - } else { - pw.print(" (unique, "); + } + if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) { + if (!printedHeader) { + if (sepNeeded) pw.println(); + pw.println("Per-Package Stats:"); + printedHeader = true; + sepNeeded = true; } - 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<ProcessState> procs = new ArrayList<ProcessState>(); - 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; + if ((section & REPORT_PKG_PROC_STATS) != 0) { + if (!dumpSummary || dumpAll) { + for (int iproc = 0; iproc < NPROCS; iproc++) { + ProcessState proc = pkgState.mProcesses.valueAt(iproc); + if (!pkgMatch && !reqPackage.equals(proc.getName())) { + continue; + } + if (activeOnly && !proc.isInUse()) { + pw.print(" (Not active: "); + pw.print(pkgState.mProcesses.keyAt(iproc)); + pw.println(")"); + continue; + } + 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.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<ProcessState> procs = new ArrayList<ProcessState>(); + 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); } - 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<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); - } - for (int iasc=0; iasc<NASCS; iasc++) { - AssociationState asc = pkgState.mAssociations.valueAt(iasc); - if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) { - continue; - } - if (activeOnly && !asc.isInUse()) { - pw.print(" (Not active association: "); - pw.print(pkgState.mAssociations.keyAt(iasc)); pw.println(")"); - 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); + } } - if (dumpAll) { - pw.print(" Association "); - } else { - pw.print(" * Asc "); + if ((section & REPORT_PKG_ASC_STATS) != 0) { + for (int iasc = 0; iasc < NASCS; iasc++) { + AssociationState asc = pkgState.mAssociations.valueAt(iasc); + if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) { + continue; + } + if (activeOnly && !asc.isInUse()) { + pw.print(" (Not active association: "); + pw.print(pkgState.mAssociations.keyAt(iasc)); + pw.println(")"); + continue; + } + if (dumpAll) { + pw.print(" Association "); + } else { + pw.print(" * Asc "); + } + pw.print(pkgState.mAssociations.keyAt(iasc)); + pw.println(":"); + pw.print(" Process: "); + pw.println(asc.getProcessName()); + asc.dumpStats(pw, " ", " ", " ", + now, totalTime, dumpDetails, dumpAll); + } } - pw.print(pkgState.mAssociations.keyAt(iasc)); - pw.println(":"); - pw.print(" Process: "); pw.println(asc.getProcessName()); - asc.dumpStats(pw, " ", " ", " ", - now, totalTime, dumpDetails, dumpAll); } } } } - ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); - printedHeader = false; - int numShownProcs = 0, numTotalProcs = 0; - for (int ip=0; ip<procMap.size(); ip++) { - String procName = procMap.keyAt(ip); - SparseArray<ProcessState> 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; + if ((section & REPORT_PROC_STATS) != 0) { + ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); + printedHeader = false; + int numShownProcs = 0, numTotalProcs = 0; + for (int ip = 0; ip < procMap.size(); ip++) { + String procName = procMap.keyAt(ip); + SparseArray<ProcessState> 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); } - 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<String, SparseArray<LongSparseArray<PackageState>>> 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<pkgMap.size(); ip++) { - final String pkgName = pkgMap.keyAt(ip); - if (reqPackage != null && !reqPackage.equals(pkgName)) { - continue; - } - final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip); - for (int iu=0; iu<uids.size(); iu++) { - final int uid = uids.keyAt(iu); - final LongSparseArray<PackageState> 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(); - for (int iproc=0; iproc<NPROCS; iproc++) { - ProcessState proc = pkgState.mProcesses.valueAt(iproc); - proc.dumpPackageProcCheckin(pw, pkgName, uid, vers, - pkgState.mProcesses.keyAt(iproc), now); - } - 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); - } - 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); + + if ((section & REPORT_PKG_STATS) != 0) { + for (int ip = 0; ip < pkgMap.size(); ip++) { + final String pkgName = pkgMap.keyAt(ip); + if (reqPackage != null && !reqPackage.equals(pkgName)) { + continue; + } + final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final int uid = uids.keyAt(iu); + final LongSparseArray<PackageState> 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<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); - for (int ip=0; ip<procMap.size(); ip++) { - String procName = procMap.keyAt(ip); - SparseArray<ProcessState> 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); + if ((section & REPORT_PROC_STATS) != 0) { + ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); + for (int ip = 0; ip < procMap.size(); ip++) { + String procName = procMap.keyAt(ip); + SparseArray<ProcessState> 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<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); - for (int ip=0; ip<procMap.size(); ip++) { - final String procName = procMap.keyAt(ip); - final SparseArray<ProcessState> 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); + if ((section & REPORT_PROC_STATS) != 0) { + for (int ip = 0; ip < procMap.size(); ip++) { + final String procName = procMap.keyAt(ip); + final SparseArray<ProcessState> 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); + } } } - final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap = - mPackages.getMap(); - for (int ip = 0; ip < pkgMap.size(); ip++) { - final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip); - for (int iu = 0; iu < uids.size(); iu++) { - final LongSparseArray<PackageState> 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_PKG_STATS) != 0) { + final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap = + mPackages.getMap(); + for (int ip = 0; ip < pkgMap.size(); ip++) { + final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip); + for (int iu = 0; iu < uids.size(); iu++) { + final LongSparseArray<PackageState> 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); + } } } } - - proto.end(token); } 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<mAssociations.size(); ia++) { - final AssociationState ascState = mAssociations.valueAt(ia); - ascState.writeToProto(proto, ProcessStatsPackageProto.ASSOCIATION_STATS, - now); + if ((section & ProcessStats.REPORT_PKG_ASC_STATS) != 0) { + for (int ia = 0; ia < mAssociations.size(); ia++) { + final AssociationState ascState = mAssociations.valueAt(ia); + ascState.writeToProto(proto, ProcessStatsPackageProto.ASSOCIATION_STATS, + now); + } } proto.end(token); diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java index 8ce650c1a514..6ffd8a9180ba 100644 --- a/services/core/java/com/android/server/am/ProcessStatsService.java +++ b/services/core/java/com/android/server/am/ProcessStatsService.java @@ -23,8 +23,10 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.service.procstats.ProcessStatsServiceDumpProto; +import android.text.format.DateFormat; import android.util.ArrayMap; import android.util.AtomicFile; +import android.util.Log; import android.util.LongSparseArray; import android.util.Slog; import android.util.SparseArray; @@ -47,6 +49,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.locks.ReentrantLock; @@ -482,6 +485,23 @@ public final class ProcessStatsService extends IProcessStats.Stub { return finalRes; } + static int parseSectionOptions(String optionsStr) { + final String sep = ","; + String[] sectionsStr = optionsStr.split(sep); + if (sectionsStr.length == 0) { + return ProcessStats.REPORT_ALL; + } + int res = 0; + List<String> 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<ParcelFileDescriptor> 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<ParcelFileDescriptor> committedStats) { + mAm.mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.PACKAGE_USAGE_STATS, null); + + ProcessStats mergedStats = new ProcessStats(false); + long newHighWaterMark = highWaterMarkMs; + mWriteLock.lock(); + try { + ArrayList<String> 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; i++) { String arg = args[i]; @@ -814,13 +926,14 @@ public final class ProcessStatsService extends IProcessStats.Stub { pw.println("Process stats committed."); quit = true; } - } else if ("--reset".equals(arg)) { - synchronized (mAm) { - mProcessStats.resetSafely(); - mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); - pw.println("Process stats reset."); - quit = true; + } else if ("--section".equals(arg)) { + i++; + if (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 |