diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 795e1424844c9..f95532dc6b697 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 ef032ba513302..416dba5e886fd 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 5000940b81c6b..fe9a71cf288dc 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);