From bd754f44cd8a39bd2298e0d6496c50b79162fb90 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 23 Jul 2013 15:52:36 -0700 Subject: [PATCH] Fix bug that was causing us to lose total memory buckets. When safely resetting stats after committing them, we were mistakenly clearing the current memory state so we would lose that total memory time until the memory state changes again. Also improve the summary output to print percentages, which make more sense for that display. Change-Id: I0fe45fd78e97ec8b94976170dd42f4ed345a5899 --- .../java/com/android/server/am/ActiveServices.java | 30 ++-- .../java/com/android/server/am/ProcessTracker.java | 194 ++++++++++++++------- .../java/com/android/server/am/ServiceRecord.java | 17 +- 3 files changed, 158 insertions(+), 83 deletions(-) diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 795e1424844c..f95532dc6b69 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -243,8 +243,9 @@ public final class ActiveServices { } r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; - if (r.tracker != null) { - r.tracker.setStarted(true, mAm.mProcessTracker.getMemFactorLocked(), r.lastActivity); + ProcessTracker.ServiceState stracker = r.getTracker(); + if (stracker != null) { + stracker.setStarted(true, mAm.mProcessTracker.getMemFactorLocked(), r.lastActivity); } r.callStart = false; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), @@ -505,8 +506,9 @@ public final class ActiveServices { s.lastActivity = SystemClock.uptimeMillis(); if (!s.hasAutoCreateConnections()) { // This is the first binding, let the tracker know. - if (s.tracker != null) { - s.tracker.setBound(true, mAm.mProcessTracker.getMemFactorLocked(), + ProcessTracker.ServiceState stracker = s.getTracker(); + if (stracker != null) { + stracker.setBound(true, mAm.mProcessTracker.getMemFactorLocked(), s.lastActivity); } } @@ -771,12 +773,7 @@ public final class ActiveServices { sInfo.applicationInfo.uid, sInfo.packageName, sInfo.name); } - ProcessTracker.ServiceState tracker = null; - if ((sInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { - tracker = mAm.mProcessTracker.getServiceStateLocked(sInfo.packageName, - sInfo.applicationInfo.uid, sInfo.name); - } - r = new ServiceRecord(mAm, ss, name, filter, sInfo, res, tracker); + r = new ServiceRecord(mAm, ss, name, filter, sInfo, res); res.setService(r); mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r); mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r); @@ -827,8 +824,9 @@ public final class ActiveServices { + why + " of " + r.shortName); long now = SystemClock.uptimeMillis(); if (r.executeNesting == 0) { - if (r.tracker != null) { - r.tracker.setExecuting(true, mAm.mProcessTracker.getMemFactorLocked(), now); + ProcessTracker.ServiceState stracker = r.getTracker(); + if (stracker != null) { + stracker.setExecuting(true, mAm.mProcessTracker.getMemFactorLocked(), now); } if (r.app != null) { if (r.app.executingServices.size() == 0) { @@ -1340,6 +1338,10 @@ public final class ActiveServices { if (r.tracker != null) { r.tracker.setStarted(false, memFactor, now); r.tracker.setBound(false, memFactor, now); + if (r.executeNesting == 0) { + r.tracker.makeInactive(); + r.tracker = null; + } } } @@ -1500,6 +1502,10 @@ public final class ActiveServices { if (r.tracker != null) { r.tracker.setExecuting(false, mAm.mProcessTracker.getMemFactorLocked(), SystemClock.uptimeMillis()); + if (inStopping) { + r.tracker.makeInactive(); + r.tracker = null; + } } } } diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java index ef032ba51330..416dba5e886f 100644 --- a/services/java/com/android/server/am/ProcessTracker.java +++ b/services/java/com/android/server/am/ProcessTracker.java @@ -547,6 +547,8 @@ public final class ProcessTracker { } public static final class ServiceState { + int mActive = 1; + final long[] mStartedDurations = new long[ADJ_COUNT]; int mStartedCount; int mStartedState = STATE_NOTHING; @@ -562,11 +564,30 @@ public final class ProcessTracker { int mExecState = STATE_NOTHING; long mExecStartTime; + void makeActive() { + mActive++; + } + + void makeInactive() { + /* + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "Making " + this + " inactive", here); + */ + mActive--; + } + + boolean isActive() { + return mActive > 0; + } + void resetSafely(long now) { for (int i=0; i procs = collectProcessesLocked(screenStates, memStates, procStates, now, reqPackage); if (procs.size() > 0) { @@ -1469,7 +1509,8 @@ public final class ProcessTracker { pw.println(); pw.println(header); } - dumpProcessSummary(pw, prefix, procs, screenStates, memStates, procStates, now); + dumpProcessSummaryLocked(pw, prefix, procs, screenStates, memStates, procStates, + now, totalTime); } } @@ -1659,6 +1700,7 @@ public final class ProcessTracker { final PackageState as = mState.getPackageStateLocked(packageName, uid); ServiceState ss = as.mServices.get(className); if (ss != null) { + ss.makeActive(); return ss; } ss = new ServiceState(); @@ -1684,11 +1726,16 @@ public final class ProcessTracker { ArrayMap services = pkg.mServices; for (int k=0; k (mState.mLastWriteTime+WRITE_PERIOD)) { if (SystemClock.elapsedRealtime() > (mState.mTimePeriodStartRealtime+COMMIT_PERIOD)) { mCommitPending = true; - mState.mFlags |= State.FLAG_COMPLETE; } return true; } @@ -1845,7 +1891,7 @@ public final class ProcessTracker { } } - static void dumpSingleTime(PrintWriter pw, String prefix, long[] durations, + static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations, int curState, long curStartTime, long now) { long totalTime = 0; int printedScreen = -1; @@ -1857,27 +1903,32 @@ public final class ProcessTracker { String running = ""; if (curState == state) { time += now - curStartTime; - running = " (running)"; + if (pw != null) { + running = " (running)"; + } } if (time != 0) { - pw.print(prefix); - printScreenLabel(pw, printedScreen != iscreen - ? iscreen : STATE_NOTHING); - printedScreen = iscreen; - printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING); - printedMem = imem; - TimeUtils.formatDuration(time, pw); pw.println(running); + if (pw != null) { + pw.print(prefix); + printScreenLabel(pw, printedScreen != iscreen + ? iscreen : STATE_NOTHING); + printedScreen = iscreen; + printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING); + printedMem = imem; + TimeUtils.formatDuration(time, pw); pw.println(running); + } totalTime += time; } } } - if (totalTime != 0) { + if (totalTime != 0 && pw != null) { pw.print(prefix); printScreenLabel(pw, STATE_NOTHING); pw.print("TOTAL: "); TimeUtils.formatDuration(totalTime, pw); pw.println(); } + return totalTime; } static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations, @@ -1934,8 +1985,16 @@ public final class ProcessTracker { procStates = _procStates; } - void print(PrintWriter pw, boolean full) { - TimeUtils.formatDuration(totalTime, pw); + void print(PrintWriter pw, long overallTime, boolean full) { + double percent = ((double)totalTime/(double)overallTime) * 100; + if (percent < 1) { + pw.print(String.format("%.2f", percent)); + } else if (percent < 10) { + pw.print(String.format("%.1f", percent)); + } else { + pw.print(String.format("%.0f", percent)); + } + pw.print("%"); if (numPss > 0) { pw.print(" ("); printSizeValue(pw, minPss * 1024); @@ -2075,7 +2134,7 @@ public final class ProcessTracker { if (memStates.length > 1) { printMemLabel(pw, STATE_NOTHING); } - pw.print("TOTAL : "); + pw.print("TOTAL : "); TimeUtils.formatDuration(totalTime, pw); pw.println(); } @@ -2230,7 +2289,7 @@ public final class ProcessTracker { static void dumpProcessSummaryDetails(PrintWriter pw, ProcessState proc, String prefix, String label, int[] screenStates, int[] memStates, int[] procStates, - long now, boolean full) { + long now, long totalTime, boolean full) { ProcessDataCollection totals = new ProcessDataCollection(screenStates, memStates, procStates); computeProcessData(proc, totals, now); @@ -2241,15 +2300,16 @@ public final class ProcessTracker { if (label != null) { pw.print(label); } - totals.print(pw, full); + totals.print(pw, totalTime, full); if (prefix != null) { pw.println(); } } } - static void dumpProcessSummary(PrintWriter pw, String prefix, ArrayList procs, - int[] screenStates, int[] memStates, int[] procStates, long now) { + static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, + ArrayList procs, int[] screenStates, int[] memStates, int[] procStates, + long now, long totalTime) { for (int i=procs.size()-1; i>=0; i--) { ProcessState proc = procs.get(i); pw.print(prefix); @@ -2259,30 +2319,30 @@ public final class ProcessTracker { UserHandle.formatUid(pw, proc.mUid); pw.println(":"); dumpProcessSummaryDetails(pw, proc, prefix, " TOTAL: ", screenStates, memStates, - procStates, now, true); + procStates, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Persistent: ", screenStates, memStates, - new int[] { STATE_PERSISTENT }, now, true); + new int[] { STATE_PERSISTENT }, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Top: ", screenStates, memStates, - new int[] {STATE_TOP}, now, true); + new int[] {STATE_TOP}, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Imp Fg: ", screenStates, memStates, - new int[] { STATE_IMPORTANT_FOREGROUND }, now, true); + new int[] { STATE_IMPORTANT_FOREGROUND }, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Imp Bg: ", screenStates, memStates, - new int[] {STATE_IMPORTANT_BACKGROUND}, now, true); + new int[] {STATE_IMPORTANT_BACKGROUND}, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Backup: ", screenStates, memStates, - new int[] {STATE_BACKUP}, now, true); + new int[] {STATE_BACKUP}, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Heavy Wgt: ", screenStates, memStates, - new int[] {STATE_HEAVY_WEIGHT}, now, true); + new int[] {STATE_HEAVY_WEIGHT}, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Service: ", screenStates, memStates, - new int[] {STATE_SERVICE}, now, true); + new int[] {STATE_SERVICE}, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Receiver: ", screenStates, memStates, - new int[] {STATE_RECEIVER}, now, true); + new int[] {STATE_RECEIVER}, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " Home: ", screenStates, memStates, - new int[] {STATE_HOME}, now, true); - dumpProcessSummaryDetails(pw, proc, prefix, " Last Act: ", screenStates, memStates, - new int[] {STATE_LAST_ACTIVITY}, now, true); + new int[] {STATE_HOME}, now, totalTime, true); + dumpProcessSummaryDetails(pw, proc, prefix, " (Last Act): ", screenStates, memStates, + new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true); dumpProcessSummaryDetails(pw, proc, prefix, " (Cached): ", screenStates, memStates, new int[] {STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_ACTIVITY_CLIENT, - STATE_CACHED_EMPTY}, now, true); + STATE_CACHED_EMPTY}, now, totalTime, true); } } diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index 5000940b81c6..fe9a71cf288d 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -73,7 +73,6 @@ final class ServiceRecord extends Binder { final String dataDir; // where activity data should go final boolean exported; // from ServiceInfo.exported final Runnable restarter; // used to schedule retries of starting the service - final ProcessTracker.ServiceState tracker; // tracking service execution, may be null final long createTime; // when this service was created final ArrayMap bindings = new ArrayMap(); @@ -84,6 +83,7 @@ final class ServiceRecord extends Binder { ProcessRecord app; // where this service is running or null. ProcessRecord isolatedProc; // keep track of isolated process, if requested + ProcessTracker.ServiceState tracker; // tracking service execution, may be null boolean isForeground; // is service currently in foreground mode? int foregroundId; // Notification ID of last foreground req. Notification foregroundNoti; // Notification record of foreground state. @@ -282,8 +282,7 @@ final class ServiceRecord extends Binder { ServiceRecord(ActivityManagerService ams, BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name, - Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter, - ProcessTracker.ServiceState tracker) { + Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter) { this.ams = ams; this.stats = servStats; this.name = name; @@ -299,12 +298,22 @@ final class ServiceRecord extends Binder { dataDir = sInfo.applicationInfo.dataDir; exported = sInfo.exported; this.restarter = restarter; - this.tracker = tracker; createTime = SystemClock.elapsedRealtime(); lastActivity = SystemClock.uptimeMillis(); userId = UserHandle.getUserId(appInfo.uid); } + public ProcessTracker.ServiceState getTracker() { + if (tracker != null) { + return tracker; + } + if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { + tracker = ams.mProcessTracker.getServiceStateLocked(serviceInfo.packageName, + serviceInfo.applicationInfo.uid, serviceInfo.name); + } + return tracker; + } + public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); -- 2.11.0