Loading core/java/com/android/internal/app/procstats/AssociationState.java 0 → 100644 +293 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.internal.app.procstats; import android.os.Parcel; import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; import android.util.TimeUtils; import java.io.PrintWriter; import java.util.Objects; public final class AssociationState { private static final String TAG = "ProcessStats"; private static final boolean DEBUG = false; private final String mPackage; private final String mProcessName; private final String mName; private final DurationsTable mDurations; public final class SourceState { public void stop() { mNesting--; if (mNesting == 0) { mDuration += SystemClock.uptimeMillis() - mStartTime; mNumActive--; } } int mNesting; int mCount; long mStartTime; long mDuration; } final static class SourceKey { int mUid; String mProcess; SourceKey(int uid, String process) { mUid = uid; mProcess = process; } public boolean equals(Object o) { if (!(o instanceof SourceKey)) { return false; } SourceKey s = (SourceKey) o; return s.mUid == mUid && Objects.equals(s.mProcess, mProcess); } @Override public int hashCode() { return Integer.hashCode(mUid) ^ (mProcess == null ? 0 : mProcess.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(64); sb.append("SourceKey{"); UserHandle.formatUid(sb, mUid); sb.append(' '); sb.append(mProcess); sb.append('}'); return sb.toString(); } } /** * All known sources for this target component... uid -> process name -> source state. */ private final ArrayMap<SourceKey, SourceState> mSources = new ArrayMap<>(); private final SourceKey mTmpSourceKey = new SourceKey(0, null); private int mNumActive; public AssociationState(ProcessStats processStats, String pkg, String name, String processName) { mPackage = pkg; mName = name; mProcessName = processName; mDurations = new DurationsTable(processStats.mTableData); } public String getPackage() { return mPackage; } public String getProcessName() { return mProcessName; } public String getName() { return mName; } public SourceState startSource(int uid, String processName) { mTmpSourceKey.mUid = uid; mTmpSourceKey.mProcess = processName; SourceState src = mSources.get(mTmpSourceKey); if (src == null) { src = new SourceState(); mSources.put(new SourceKey(uid, processName), src); } src.mNesting++; if (src.mNesting == 1) { src.mCount++; src.mStartTime = SystemClock.uptimeMillis(); mNumActive++; } return src; } public void add(AssociationState other) { mDurations.addDurations(other.mDurations); for (int isrc = other.mSources.size() - 1; isrc >= 0; isrc--) { final SourceKey key = other.mSources.keyAt(isrc); final SourceState otherSrc = other.mSources.valueAt(isrc); SourceState mySrc = mSources.get(key); if (mySrc == null) { mySrc = new SourceState(); mSources.put(key, mySrc); } mySrc.mCount += otherSrc.mCount; mySrc.mDuration += otherSrc.mDuration; } } public boolean isInUse() { return mNumActive > 0; } public void resetSafely(long now) { mDurations.resetTable(); if (!isInUse()) { mSources.clear(); } else { // We have some active sources... clear out everything but those. for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) { SourceState src = mSources.valueAt(isrc); if (src.mNesting > 0) { src.mCount = 1; src.mStartTime = now; src.mDuration = 0; } else { mSources.removeAt(isrc); } } } } public void writeToParcel(ProcessStats stats, Parcel out, long now) { mDurations.writeToParcel(out); final int NSRC = mSources.size(); out.writeInt(NSRC); for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); out.writeInt(key.mUid); stats.writeCommonString(out, key.mProcess); out.writeInt(src.mCount); out.writeLong(src.mDuration); } } public String readFromParcel(ProcessStats stats, Parcel in, int parcelVersion) { if (!mDurations.readFromParcel(in)) { return "Duration table corrupt"; } final int NSRC = in.readInt(); if (NSRC < 0 || NSRC > 100000) { return "Association with bad src count: " + NSRC; } for (int isrc = 0; isrc < NSRC; isrc++) { final int uid = in.readInt(); final String procName = stats.readCommonString(in, parcelVersion); final SourceKey key = new SourceKey(uid, procName); final SourceState src = new SourceState(); src.mCount = in.readInt(); src.mDuration = in.readLong(); mSources.put(key, src); } return null; } public void commitStateTime(long now) { if (isInUse()) { for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) { SourceState src = mSources.valueAt(isrc); if (src.mNesting > 0) { src.mDuration += now - src.mStartTime; src.mStartTime = now; } } } } public void dumpStats(PrintWriter pw, String prefix, String prefixInner, String headerPrefix, long now, long totalTime, boolean dumpSummary, boolean dumpAll) { if (dumpAll) { pw.print(prefix); pw.print("mNumActive="); pw.println(mNumActive); } final int NSRC = mSources.size(); for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); pw.print(prefixInner); pw.print("<- "); pw.print(key.mProcess); pw.print(" / "); UserHandle.formatUid(pw, key.mUid); pw.println(":"); pw.print(prefixInner); pw.print(" Count "); pw.print(src.mCount); long duration = src.mDuration; if (src.mNesting > 0) { duration += now - src.mStartTime; } if (dumpAll) { pw.print(" / Duration "); TimeUtils.formatDuration(duration, pw); pw.print(" / "); } else { pw.print(" / time "); } DumpUtils.printPercent(pw, (double)duration/(double)totalTime); if (src.mNesting > 0) { pw.print(" (running)"); } pw.println(); } } public void dumpTimesCheckin(PrintWriter pw, String pkgName, int uid, long vers, String associationName, long now) { final int NSRC = mSources.size(); for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); pw.print("pkgasc"); pw.print(","); pw.print(pkgName); pw.print(","); pw.print(uid); pw.print(","); pw.print(vers); pw.print(","); pw.print(associationName); pw.print(","); pw.print(key.mProcess); pw.print(","); pw.print(key.mUid); pw.print(","); pw.print(src.mCount); long duration = src.mDuration; if (src.mNesting > 0) { duration += now - src.mStartTime; } pw.print(","); pw.print(duration); pw.println(); } } public String toString() { return "AssociationState{" + Integer.toHexString(System.identityHashCode(this)) + " " + mName + " pkg=" + mPackage + " proc=" + Integer.toHexString(System.identityHashCode(this)) + "}"; } } core/java/com/android/internal/app/procstats/DumpUtils.java +3 −2 Original line number Diff line number Diff line Loading @@ -362,12 +362,13 @@ public final class DumpUtils { } } public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, String header, ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates, long now, long totalTime) { for (int i=procs.size()-1; i>=0; i--) { final ProcessState proc = procs.get(i); proc.dumpSummary(pw, prefix, screenStates, memStates, procStates, now, totalTime); proc.dumpSummary(pw, prefix, header, screenStates, memStates, procStates, now, totalTime); } } Loading core/java/com/android/internal/app/procstats/ProcessState.java +9 −6 Original line number Diff line number Diff line Loading @@ -580,7 +580,7 @@ public final class ProcessState { ProcessStateHolder holder = pkgList.valueAt(index); ProcessState proc = holder.state; if (mDead && proc.mCommonProcess != proc) { // Somehow we are contining to use a process state that is dead, because // Somehow we are continuing to use a process state that is dead, because // it was not being told it was active during the last commit. We can recover // from this by generating a fresh new state, but this is bad because we // are losing whatever data we had in the old process state. Loading @@ -600,17 +600,17 @@ public final class ProcessState { + pkgList.keyAt(index) + "/" + proc.mUid + " for multi-proc " + proc.mName); } PackageState pkg = vpkg.get(proc.mVersion); if (pkg == null) { PackageState expkg = vpkg.get(proc.mVersion); if (expkg == null) { throw new IllegalStateException("No existing package " + pkgList.keyAt(index) + "/" + proc.mUid + " for multi-proc " + proc.mName + " version " + proc.mVersion); } String savedName = proc.mName; proc = pkg.mProcesses.get(proc.mName); proc = expkg.mProcesses.get(proc.mName); if (proc == null) { throw new IllegalStateException("Didn't create per-package process " + savedName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid); + savedName + " in pkg " + expkg.mPackageName + "/" + expkg.mUid); } holder.state = proc; } Loading Loading @@ -769,11 +769,14 @@ public final class ProcessState { return totalTime; } public void dumpSummary(PrintWriter pw, String prefix, public void dumpSummary(PrintWriter pw, String prefix, String header, int[] screenStates, int[] memStates, int[] procStates, long now, long totalTime) { pw.print(prefix); pw.print("* "); if (header != null) { pw.print(header); } pw.print(mName); pw.print(" / "); UserHandle.formatUid(pw, mUid); Loading core/java/com/android/internal/app/procstats/ProcessStats.java +158 −30 File changed.Preview size limit exceeded, changes collapsed. Show changes core/java/com/android/internal/app/procstats/ServiceState.java +81 −24 Original line number Diff line number Diff line Loading @@ -18,30 +18,13 @@ package com.android.internal.app.procstats; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.text.format.DateFormat; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import com.android.internal.app.procstats.ProcessStats; import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING; 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.Comparator; import java.util.Objects; public final class ServiceState { private static final String TAG = "ProcessStats"; Loading @@ -51,7 +34,8 @@ public final class ServiceState { public static final int SERVICE_STARTED = 1; public static final int SERVICE_BOUND = 2; public static final int SERVICE_EXEC = 3; public static final int SERVICE_COUNT = 4; public static final int SERVICE_FOREGROUND = 4; public static final int SERVICE_COUNT = 5; private final String mPackage; private final String mProcessName; Loading Loading @@ -79,6 +63,10 @@ public final class ServiceState { private int mExecState = STATE_NOTHING; private long mExecStartTime; private int mForegroundCount; private int mForegroundState = STATE_NOTHING; private long mForegroundStartTime; public ServiceState(ProcessStats processStats, String pkg, String name, String processName, ProcessState proc) { mPackage = pkg; Loading Loading @@ -121,6 +109,9 @@ public final class ServiceState { if (mExecState != ProcessStats.STATE_NOTHING) { setExecuting(true, memFactor, now); } if (mForegroundState != ProcessStats.STATE_NOTHING) { setForeground(true, memFactor, now); } } } Loading @@ -133,7 +124,8 @@ public final class ServiceState { // There was already an old owner, reset this object for its // new owner. mOwner = newOwner; if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING || mForegroundState != STATE_NOTHING) { long now = SystemClock.uptimeMillis(); if (mStarted) { if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner Loading @@ -153,6 +145,12 @@ public final class ServiceState { + mPackage + " service=" + mName + " proc=" + mProc); setExecuting(false, 0, now); } if (mForegroundState != STATE_NOTHING) { if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner + " from " + mOwner + " while foreground: pkg=" + mPackage + " service=" + mName + " proc=" + mProc); setForeground(false, 0, now); } } } } Loading @@ -161,7 +159,8 @@ public final class ServiceState { public void clearCurrentOwner(Object owner, boolean silently) { if (mOwner == owner) { mProc.decActiveServices(mName); if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING || mForegroundState != STATE_NOTHING) { long now = SystemClock.uptimeMillis(); if (mStarted) { if (!silently) { Loading @@ -187,6 +186,14 @@ public final class ServiceState { } setExecuting(false, 0, now); } if (mForegroundState != STATE_NOTHING) { if (!silently) { Slog.wtfStack(TAG, "Service owner " + owner + " cleared while foreground: pkg=" + mPackage + " service=" + mName + " proc=" + mProc); } setForeground(false, 0, now); } } mOwner = null; } Loading @@ -206,6 +213,7 @@ public final class ServiceState { mStartedCount += other.mStartedCount; mBoundCount += other.mBoundCount; mExecCount += other.mExecCount; mForegroundCount += other.mForegroundCount; } public void resetSafely(long now) { Loading @@ -214,7 +222,9 @@ public final class ServiceState { mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0; mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0; mExecCount = mExecState != STATE_NOTHING ? 1 : 0; mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now; mForegroundCount = mForegroundState != STATE_NOTHING ? 1 : 0; mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = mForegroundStartTime = now; } public void writeToParcel(Parcel out, long now) { Loading @@ -223,6 +233,7 @@ public final class ServiceState { out.writeInt(mStartedCount); out.writeInt(mBoundCount); out.writeInt(mExecCount); out.writeInt(mForegroundCount); } public boolean readFromParcel(Parcel in) { Loading @@ -233,6 +244,7 @@ public final class ServiceState { mStartedCount = in.readInt(); mBoundCount = in.readInt(); mExecCount = in.readInt(); mForegroundCount = in.readInt(); return true; } Loading @@ -257,11 +269,17 @@ public final class ServiceState { now - mExecStartTime); mExecStartTime = now; } if (mForegroundState != STATE_NOTHING) { mDurations.addDuration(SERVICE_FOREGROUND + (mForegroundState*SERVICE_COUNT), now - mForegroundStartTime); mForegroundStartTime = now; } } private void updateRunning(int memFactor, long now) { final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING; || mExecState != STATE_NOTHING || mForegroundState != STATE_NOTHING) ? memFactor : STATE_NOTHING; if (mRunState != state) { if (mRunState != STATE_NOTHING) { mDurations.addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), Loading Loading @@ -348,6 +366,24 @@ public final class ServiceState { } } public void setForeground(boolean foreground, int memFactor, long now) { if (mOwner == null) { Slog.wtf(TAG, "Foregrounding service " + this + " without owner"); } final int state = foreground ? memFactor : STATE_NOTHING; if (mForegroundState != state) { if (mForegroundState != STATE_NOTHING) { mDurations.addDuration(SERVICE_FOREGROUND + (mForegroundState*SERVICE_COUNT), now - mForegroundStartTime); } else if (foreground) { mForegroundCount++; } mForegroundState = state; mForegroundStartTime = now; updateRunning(memFactor, now); } } public long getDuration(int opType, int curState, long startTime, int memFactor, long now) { int state = opType + (memFactor*SERVICE_COUNT); Loading @@ -366,6 +402,9 @@ public final class ServiceState { dumpStats(pw, prefix, prefixInner, headerPrefix, "Started", mStartedCount, ServiceState.SERVICE_STARTED, mStartedState, mStartedStartTime, now, totalTime, !dumpSummary || dumpAll); dumpStats(pw, prefix, prefixInner, headerPrefix, "Foreground", mForegroundCount, ServiceState.SERVICE_FOREGROUND, mForegroundState, mForegroundStartTime, now, totalTime, !dumpSummary || dumpAll); dumpStats(pw, prefix, prefixInner, headerPrefix, "Bound", mBoundCount, ServiceState.SERVICE_BOUND, mBoundState, mBoundStartTime, now, totalTime, !dumpSummary || dumpAll); Loading Loading @@ -393,11 +432,19 @@ public final class ServiceState { pw.print(" op count "); pw.print(count); pw.println(":"); dumpTime(pw, prefixInner, serviceType, state, startTime, now); } else { long myTime = dumpTime(null, null, serviceType, state, startTime, now); long myTime = dumpTimeInternal(null, null, serviceType, state, startTime, now, true); pw.print(prefix); pw.print(headerPrefix); pw.print(header); pw.print(" count "); pw.print(count); pw.print(" / time "); boolean isRunning = myTime < 0; if (isRunning) { myTime = -myTime; } DumpUtils.printPercent(pw, (double)myTime/(double)totalTime); if (isRunning) { pw.print(" (running)"); } pw.println(); } } Loading @@ -405,8 +452,14 @@ public final class ServiceState { public long dumpTime(PrintWriter pw, String prefix, int serviceType, int curState, long curStartTime, long now) { return dumpTimeInternal(pw, prefix, serviceType, curState, curStartTime, now, false); } long dumpTimeInternal(PrintWriter pw, String prefix, int serviceType, int curState, long curStartTime, long now, boolean negativeIfRunning) { long totalTime = 0; int printedScreen = -1; boolean isRunning = false; for (int iscreen=0; iscreen<ProcessStats.ADJ_COUNT; iscreen+=ProcessStats.ADJ_SCREEN_MOD) { int printedMem = -1; for (int imem=0; imem<ProcessStats.ADJ_MEM_FACTOR_COUNT; imem++) { Loading @@ -415,6 +468,7 @@ public final class ServiceState { String running = ""; if (curState == state && pw != null) { running = " (running)"; isRunning = true; } if (time != 0) { if (pw != null) { Loading @@ -438,7 +492,7 @@ public final class ServiceState { TimeUtils.formatDuration(totalTime, pw); pw.println(); } return totalTime; return (isRunning && negativeIfRunning) ? -totalTime : totalTime; } public void dumpTimesCheckin(PrintWriter pw, String pkgName, int uid, long vers, Loading @@ -447,6 +501,9 @@ public final class ServiceState { ServiceState.SERVICE_RUN, mRunCount, mRunState, mRunStartTime, now); dumpTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName, ServiceState.SERVICE_STARTED, mStartedCount, mStartedState, mStartedStartTime, now); dumpTimeCheckin(pw, "pkgsvc-fg", pkgName, uid, vers, serviceName, ServiceState.SERVICE_FOREGROUND, mForegroundCount, mForegroundState, mForegroundStartTime, now); dumpTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName, ServiceState.SERVICE_BOUND, mBoundCount, mBoundState, mBoundStartTime, now); dumpTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName, Loading Loading
core/java/com/android/internal/app/procstats/AssociationState.java 0 → 100644 +293 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.internal.app.procstats; import android.os.Parcel; import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; import android.util.TimeUtils; import java.io.PrintWriter; import java.util.Objects; public final class AssociationState { private static final String TAG = "ProcessStats"; private static final boolean DEBUG = false; private final String mPackage; private final String mProcessName; private final String mName; private final DurationsTable mDurations; public final class SourceState { public void stop() { mNesting--; if (mNesting == 0) { mDuration += SystemClock.uptimeMillis() - mStartTime; mNumActive--; } } int mNesting; int mCount; long mStartTime; long mDuration; } final static class SourceKey { int mUid; String mProcess; SourceKey(int uid, String process) { mUid = uid; mProcess = process; } public boolean equals(Object o) { if (!(o instanceof SourceKey)) { return false; } SourceKey s = (SourceKey) o; return s.mUid == mUid && Objects.equals(s.mProcess, mProcess); } @Override public int hashCode() { return Integer.hashCode(mUid) ^ (mProcess == null ? 0 : mProcess.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(64); sb.append("SourceKey{"); UserHandle.formatUid(sb, mUid); sb.append(' '); sb.append(mProcess); sb.append('}'); return sb.toString(); } } /** * All known sources for this target component... uid -> process name -> source state. */ private final ArrayMap<SourceKey, SourceState> mSources = new ArrayMap<>(); private final SourceKey mTmpSourceKey = new SourceKey(0, null); private int mNumActive; public AssociationState(ProcessStats processStats, String pkg, String name, String processName) { mPackage = pkg; mName = name; mProcessName = processName; mDurations = new DurationsTable(processStats.mTableData); } public String getPackage() { return mPackage; } public String getProcessName() { return mProcessName; } public String getName() { return mName; } public SourceState startSource(int uid, String processName) { mTmpSourceKey.mUid = uid; mTmpSourceKey.mProcess = processName; SourceState src = mSources.get(mTmpSourceKey); if (src == null) { src = new SourceState(); mSources.put(new SourceKey(uid, processName), src); } src.mNesting++; if (src.mNesting == 1) { src.mCount++; src.mStartTime = SystemClock.uptimeMillis(); mNumActive++; } return src; } public void add(AssociationState other) { mDurations.addDurations(other.mDurations); for (int isrc = other.mSources.size() - 1; isrc >= 0; isrc--) { final SourceKey key = other.mSources.keyAt(isrc); final SourceState otherSrc = other.mSources.valueAt(isrc); SourceState mySrc = mSources.get(key); if (mySrc == null) { mySrc = new SourceState(); mSources.put(key, mySrc); } mySrc.mCount += otherSrc.mCount; mySrc.mDuration += otherSrc.mDuration; } } public boolean isInUse() { return mNumActive > 0; } public void resetSafely(long now) { mDurations.resetTable(); if (!isInUse()) { mSources.clear(); } else { // We have some active sources... clear out everything but those. for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) { SourceState src = mSources.valueAt(isrc); if (src.mNesting > 0) { src.mCount = 1; src.mStartTime = now; src.mDuration = 0; } else { mSources.removeAt(isrc); } } } } public void writeToParcel(ProcessStats stats, Parcel out, long now) { mDurations.writeToParcel(out); final int NSRC = mSources.size(); out.writeInt(NSRC); for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); out.writeInt(key.mUid); stats.writeCommonString(out, key.mProcess); out.writeInt(src.mCount); out.writeLong(src.mDuration); } } public String readFromParcel(ProcessStats stats, Parcel in, int parcelVersion) { if (!mDurations.readFromParcel(in)) { return "Duration table corrupt"; } final int NSRC = in.readInt(); if (NSRC < 0 || NSRC > 100000) { return "Association with bad src count: " + NSRC; } for (int isrc = 0; isrc < NSRC; isrc++) { final int uid = in.readInt(); final String procName = stats.readCommonString(in, parcelVersion); final SourceKey key = new SourceKey(uid, procName); final SourceState src = new SourceState(); src.mCount = in.readInt(); src.mDuration = in.readLong(); mSources.put(key, src); } return null; } public void commitStateTime(long now) { if (isInUse()) { for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) { SourceState src = mSources.valueAt(isrc); if (src.mNesting > 0) { src.mDuration += now - src.mStartTime; src.mStartTime = now; } } } } public void dumpStats(PrintWriter pw, String prefix, String prefixInner, String headerPrefix, long now, long totalTime, boolean dumpSummary, boolean dumpAll) { if (dumpAll) { pw.print(prefix); pw.print("mNumActive="); pw.println(mNumActive); } final int NSRC = mSources.size(); for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); pw.print(prefixInner); pw.print("<- "); pw.print(key.mProcess); pw.print(" / "); UserHandle.formatUid(pw, key.mUid); pw.println(":"); pw.print(prefixInner); pw.print(" Count "); pw.print(src.mCount); long duration = src.mDuration; if (src.mNesting > 0) { duration += now - src.mStartTime; } if (dumpAll) { pw.print(" / Duration "); TimeUtils.formatDuration(duration, pw); pw.print(" / "); } else { pw.print(" / time "); } DumpUtils.printPercent(pw, (double)duration/(double)totalTime); if (src.mNesting > 0) { pw.print(" (running)"); } pw.println(); } } public void dumpTimesCheckin(PrintWriter pw, String pkgName, int uid, long vers, String associationName, long now) { final int NSRC = mSources.size(); for (int isrc = 0; isrc < NSRC; isrc++) { final SourceKey key = mSources.keyAt(isrc); final SourceState src = mSources.valueAt(isrc); pw.print("pkgasc"); pw.print(","); pw.print(pkgName); pw.print(","); pw.print(uid); pw.print(","); pw.print(vers); pw.print(","); pw.print(associationName); pw.print(","); pw.print(key.mProcess); pw.print(","); pw.print(key.mUid); pw.print(","); pw.print(src.mCount); long duration = src.mDuration; if (src.mNesting > 0) { duration += now - src.mStartTime; } pw.print(","); pw.print(duration); pw.println(); } } public String toString() { return "AssociationState{" + Integer.toHexString(System.identityHashCode(this)) + " " + mName + " pkg=" + mPackage + " proc=" + Integer.toHexString(System.identityHashCode(this)) + "}"; } }
core/java/com/android/internal/app/procstats/DumpUtils.java +3 −2 Original line number Diff line number Diff line Loading @@ -362,12 +362,13 @@ public final class DumpUtils { } } public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, String header, ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates, long now, long totalTime) { for (int i=procs.size()-1; i>=0; i--) { final ProcessState proc = procs.get(i); proc.dumpSummary(pw, prefix, screenStates, memStates, procStates, now, totalTime); proc.dumpSummary(pw, prefix, header, screenStates, memStates, procStates, now, totalTime); } } Loading
core/java/com/android/internal/app/procstats/ProcessState.java +9 −6 Original line number Diff line number Diff line Loading @@ -580,7 +580,7 @@ public final class ProcessState { ProcessStateHolder holder = pkgList.valueAt(index); ProcessState proc = holder.state; if (mDead && proc.mCommonProcess != proc) { // Somehow we are contining to use a process state that is dead, because // Somehow we are continuing to use a process state that is dead, because // it was not being told it was active during the last commit. We can recover // from this by generating a fresh new state, but this is bad because we // are losing whatever data we had in the old process state. Loading @@ -600,17 +600,17 @@ public final class ProcessState { + pkgList.keyAt(index) + "/" + proc.mUid + " for multi-proc " + proc.mName); } PackageState pkg = vpkg.get(proc.mVersion); if (pkg == null) { PackageState expkg = vpkg.get(proc.mVersion); if (expkg == null) { throw new IllegalStateException("No existing package " + pkgList.keyAt(index) + "/" + proc.mUid + " for multi-proc " + proc.mName + " version " + proc.mVersion); } String savedName = proc.mName; proc = pkg.mProcesses.get(proc.mName); proc = expkg.mProcesses.get(proc.mName); if (proc == null) { throw new IllegalStateException("Didn't create per-package process " + savedName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid); + savedName + " in pkg " + expkg.mPackageName + "/" + expkg.mUid); } holder.state = proc; } Loading Loading @@ -769,11 +769,14 @@ public final class ProcessState { return totalTime; } public void dumpSummary(PrintWriter pw, String prefix, public void dumpSummary(PrintWriter pw, String prefix, String header, int[] screenStates, int[] memStates, int[] procStates, long now, long totalTime) { pw.print(prefix); pw.print("* "); if (header != null) { pw.print(header); } pw.print(mName); pw.print(" / "); UserHandle.formatUid(pw, mUid); Loading
core/java/com/android/internal/app/procstats/ProcessStats.java +158 −30 File changed.Preview size limit exceeded, changes collapsed. Show changes
core/java/com/android/internal/app/procstats/ServiceState.java +81 −24 Original line number Diff line number Diff line Loading @@ -18,30 +18,13 @@ package com.android.internal.app.procstats; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.text.format.DateFormat; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import com.android.internal.app.procstats.ProcessStats; import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING; 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.Comparator; import java.util.Objects; public final class ServiceState { private static final String TAG = "ProcessStats"; Loading @@ -51,7 +34,8 @@ public final class ServiceState { public static final int SERVICE_STARTED = 1; public static final int SERVICE_BOUND = 2; public static final int SERVICE_EXEC = 3; public static final int SERVICE_COUNT = 4; public static final int SERVICE_FOREGROUND = 4; public static final int SERVICE_COUNT = 5; private final String mPackage; private final String mProcessName; Loading Loading @@ -79,6 +63,10 @@ public final class ServiceState { private int mExecState = STATE_NOTHING; private long mExecStartTime; private int mForegroundCount; private int mForegroundState = STATE_NOTHING; private long mForegroundStartTime; public ServiceState(ProcessStats processStats, String pkg, String name, String processName, ProcessState proc) { mPackage = pkg; Loading Loading @@ -121,6 +109,9 @@ public final class ServiceState { if (mExecState != ProcessStats.STATE_NOTHING) { setExecuting(true, memFactor, now); } if (mForegroundState != ProcessStats.STATE_NOTHING) { setForeground(true, memFactor, now); } } } Loading @@ -133,7 +124,8 @@ public final class ServiceState { // There was already an old owner, reset this object for its // new owner. mOwner = newOwner; if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING || mForegroundState != STATE_NOTHING) { long now = SystemClock.uptimeMillis(); if (mStarted) { if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner Loading @@ -153,6 +145,12 @@ public final class ServiceState { + mPackage + " service=" + mName + " proc=" + mProc); setExecuting(false, 0, now); } if (mForegroundState != STATE_NOTHING) { if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner + " from " + mOwner + " while foreground: pkg=" + mPackage + " service=" + mName + " proc=" + mProc); setForeground(false, 0, now); } } } } Loading @@ -161,7 +159,8 @@ public final class ServiceState { public void clearCurrentOwner(Object owner, boolean silently) { if (mOwner == owner) { mProc.decActiveServices(mName); if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING || mForegroundState != STATE_NOTHING) { long now = SystemClock.uptimeMillis(); if (mStarted) { if (!silently) { Loading @@ -187,6 +186,14 @@ public final class ServiceState { } setExecuting(false, 0, now); } if (mForegroundState != STATE_NOTHING) { if (!silently) { Slog.wtfStack(TAG, "Service owner " + owner + " cleared while foreground: pkg=" + mPackage + " service=" + mName + " proc=" + mProc); } setForeground(false, 0, now); } } mOwner = null; } Loading @@ -206,6 +213,7 @@ public final class ServiceState { mStartedCount += other.mStartedCount; mBoundCount += other.mBoundCount; mExecCount += other.mExecCount; mForegroundCount += other.mForegroundCount; } public void resetSafely(long now) { Loading @@ -214,7 +222,9 @@ public final class ServiceState { mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0; mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0; mExecCount = mExecState != STATE_NOTHING ? 1 : 0; mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = now; mForegroundCount = mForegroundState != STATE_NOTHING ? 1 : 0; mRunStartTime = mStartedStartTime = mBoundStartTime = mExecStartTime = mForegroundStartTime = now; } public void writeToParcel(Parcel out, long now) { Loading @@ -223,6 +233,7 @@ public final class ServiceState { out.writeInt(mStartedCount); out.writeInt(mBoundCount); out.writeInt(mExecCount); out.writeInt(mForegroundCount); } public boolean readFromParcel(Parcel in) { Loading @@ -233,6 +244,7 @@ public final class ServiceState { mStartedCount = in.readInt(); mBoundCount = in.readInt(); mExecCount = in.readInt(); mForegroundCount = in.readInt(); return true; } Loading @@ -257,11 +269,17 @@ public final class ServiceState { now - mExecStartTime); mExecStartTime = now; } if (mForegroundState != STATE_NOTHING) { mDurations.addDuration(SERVICE_FOREGROUND + (mForegroundState*SERVICE_COUNT), now - mForegroundStartTime); mForegroundStartTime = now; } } private void updateRunning(int memFactor, long now) { final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING; || mExecState != STATE_NOTHING || mForegroundState != STATE_NOTHING) ? memFactor : STATE_NOTHING; if (mRunState != state) { if (mRunState != STATE_NOTHING) { mDurations.addDuration(SERVICE_RUN + (mRunState*SERVICE_COUNT), Loading Loading @@ -348,6 +366,24 @@ public final class ServiceState { } } public void setForeground(boolean foreground, int memFactor, long now) { if (mOwner == null) { Slog.wtf(TAG, "Foregrounding service " + this + " without owner"); } final int state = foreground ? memFactor : STATE_NOTHING; if (mForegroundState != state) { if (mForegroundState != STATE_NOTHING) { mDurations.addDuration(SERVICE_FOREGROUND + (mForegroundState*SERVICE_COUNT), now - mForegroundStartTime); } else if (foreground) { mForegroundCount++; } mForegroundState = state; mForegroundStartTime = now; updateRunning(memFactor, now); } } public long getDuration(int opType, int curState, long startTime, int memFactor, long now) { int state = opType + (memFactor*SERVICE_COUNT); Loading @@ -366,6 +402,9 @@ public final class ServiceState { dumpStats(pw, prefix, prefixInner, headerPrefix, "Started", mStartedCount, ServiceState.SERVICE_STARTED, mStartedState, mStartedStartTime, now, totalTime, !dumpSummary || dumpAll); dumpStats(pw, prefix, prefixInner, headerPrefix, "Foreground", mForegroundCount, ServiceState.SERVICE_FOREGROUND, mForegroundState, mForegroundStartTime, now, totalTime, !dumpSummary || dumpAll); dumpStats(pw, prefix, prefixInner, headerPrefix, "Bound", mBoundCount, ServiceState.SERVICE_BOUND, mBoundState, mBoundStartTime, now, totalTime, !dumpSummary || dumpAll); Loading Loading @@ -393,11 +432,19 @@ public final class ServiceState { pw.print(" op count "); pw.print(count); pw.println(":"); dumpTime(pw, prefixInner, serviceType, state, startTime, now); } else { long myTime = dumpTime(null, null, serviceType, state, startTime, now); long myTime = dumpTimeInternal(null, null, serviceType, state, startTime, now, true); pw.print(prefix); pw.print(headerPrefix); pw.print(header); pw.print(" count "); pw.print(count); pw.print(" / time "); boolean isRunning = myTime < 0; if (isRunning) { myTime = -myTime; } DumpUtils.printPercent(pw, (double)myTime/(double)totalTime); if (isRunning) { pw.print(" (running)"); } pw.println(); } } Loading @@ -405,8 +452,14 @@ public final class ServiceState { public long dumpTime(PrintWriter pw, String prefix, int serviceType, int curState, long curStartTime, long now) { return dumpTimeInternal(pw, prefix, serviceType, curState, curStartTime, now, false); } long dumpTimeInternal(PrintWriter pw, String prefix, int serviceType, int curState, long curStartTime, long now, boolean negativeIfRunning) { long totalTime = 0; int printedScreen = -1; boolean isRunning = false; for (int iscreen=0; iscreen<ProcessStats.ADJ_COUNT; iscreen+=ProcessStats.ADJ_SCREEN_MOD) { int printedMem = -1; for (int imem=0; imem<ProcessStats.ADJ_MEM_FACTOR_COUNT; imem++) { Loading @@ -415,6 +468,7 @@ public final class ServiceState { String running = ""; if (curState == state && pw != null) { running = " (running)"; isRunning = true; } if (time != 0) { if (pw != null) { Loading @@ -438,7 +492,7 @@ public final class ServiceState { TimeUtils.formatDuration(totalTime, pw); pw.println(); } return totalTime; return (isRunning && negativeIfRunning) ? -totalTime : totalTime; } public void dumpTimesCheckin(PrintWriter pw, String pkgName, int uid, long vers, Loading @@ -447,6 +501,9 @@ public final class ServiceState { ServiceState.SERVICE_RUN, mRunCount, mRunState, mRunStartTime, now); dumpTimeCheckin(pw, "pkgsvc-start", pkgName, uid, vers, serviceName, ServiceState.SERVICE_STARTED, mStartedCount, mStartedState, mStartedStartTime, now); dumpTimeCheckin(pw, "pkgsvc-fg", pkgName, uid, vers, serviceName, ServiceState.SERVICE_FOREGROUND, mForegroundCount, mForegroundState, mForegroundStartTime, now); dumpTimeCheckin(pw, "pkgsvc-bound", pkgName, uid, vers, serviceName, ServiceState.SERVICE_BOUND, mBoundCount, mBoundState, mBoundStartTime, now); dumpTimeCheckin(pw, "pkgsvc-exec", pkgName, uid, vers, serviceName, Loading