diff options
| author | 2013-04-25 14:48:19 -0700 | |
|---|---|---|
| committer | 2013-04-25 17:01:37 -0700 | |
| commit | 3e013e85b0dfb9db58a4401b80d672a7eeb09d47 (patch) | |
| tree | 3ce7ee4ab6c8b1b301a3bb6ee502d4dac2ce5ed7 | |
| parent | 58b98d392d47c2acdf19cea988f0ac547b83e670 (diff) | |
Track foreground activities in battery stats.
To help correlate battery usage against actual foreground app usage,
start tracking time on a per UID basis. It uses the nesting feature
of StopwatchTimer to track multiple PIDs inside the same UID.
Improves units on docs, and persists foreground CPU time with a
consistent ordering. Reports foreground activities time and
foreground CPU time.
Change-Id: I95d12963923e3fd421730f6fbfc842dfd8d3a055
| -rw-r--r-- | core/java/android/os/BatteryStats.java | 71 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 106 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ProcessStats.java | 10 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 17 |
4 files changed, 160 insertions, 44 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 499ec77e3d09..29e8d9c6b588 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -98,6 +98,11 @@ public abstract class BatteryStats implements Parcelable { public static final int VIBRATOR_ON = 9; /** + * A constant indicating a foreground activity timer + */ + public static final int FOREGROUND_ACTIVITY = 10; + + /** * Include all of the data in the stats, including previously saved data. */ public static final int STATS_SINCE_CHARGED = 0; @@ -125,7 +130,7 @@ public abstract class BatteryStats implements Parcelable { /** * Bump the version on this if the checkin format changes. */ - private static final int BATTERY_STATS_CHECKIN_VERSION = 5; + private static final int BATTERY_STATS_CHECKIN_VERSION = 6; private static final long BYTES_PER_KB = 1024; private static final long BYTES_PER_MB = 1048576; // 1024^2 @@ -137,6 +142,7 @@ public abstract class BatteryStats implements Parcelable { private static final String PROCESS_DATA = "pr"; private static final String SENSOR_DATA = "sr"; private static final String VIBRATOR_DATA = "vib"; + private static final String FOREGROUND_DATA = "fg"; private static final String WAKELOCK_DATA = "wl"; private static final String KERNEL_WAKELOCK_DATA = "kwl"; private static final String NETWORK_DATA = "nt"; @@ -276,6 +282,8 @@ public abstract class BatteryStats implements Parcelable { public abstract void noteAudioTurnedOffLocked(); public abstract void noteVideoTurnedOnLocked(); public abstract void noteVideoTurnedOffLocked(); + public abstract void noteActivityResumedLocked(); + public abstract void noteActivityPausedLocked(); public abstract long getWifiRunningTime(long batteryRealtime, int which); public abstract long getFullWifiLockTime(long batteryRealtime, int which); public abstract long getWifiScanTime(long batteryRealtime, int which); @@ -283,6 +291,7 @@ public abstract class BatteryStats implements Parcelable { int which); public abstract long getAudioTurnedOnTime(long batteryRealtime, int which); public abstract long getVideoTurnedOnTime(long batteryRealtime, int which); + public abstract Timer getForegroundActivityTimer(); public abstract Timer getVibratorOnTimer(); /** @@ -1229,7 +1238,7 @@ public abstract class BatteryStats implements Parcelable { final int NU = uidStats.size(); String category = STAT_NAMES[which]; - + // Dump "battery" stat dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, which == STATS_SINCE_CHARGED ? getStartCount() : "N/A", @@ -1417,22 +1426,31 @@ public abstract class BatteryStats implements Parcelable { } } + Timer fgTimer = u.getForegroundActivityTimer(); + if (fgTimer != null) { + // Convert from microseconds to milliseconds with rounding + long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000; + int count = fgTimer.getCountLocked(which); + if (totalTime != 0) { + dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count); + } + } + Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); if (processStats.size() > 0) { for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent : processStats.entrySet()) { Uid.Proc ps = ent.getValue(); - - long userTime = ps.getUserTime(which); - long systemTime = ps.getSystemTime(which); - int starts = ps.getStarts(which); - - if (userTime != 0 || systemTime != 0 || starts != 0) { - dumpLine(pw, uid, category, PROCESS_DATA, - ent.getKey(), // proc - userTime * 10, // cpu time in ms - systemTime * 10, // user time in ms - starts); // process starts + + final long userMillis = ps.getUserTime(which) * 10; + final long systemMillis = ps.getSystemTime(which) * 10; + final long foregroundMillis = ps.getForegroundTime(which) * 10; + final long starts = ps.getStarts(which); + + if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0 + || starts != 0) { + dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis, + systemMillis, foregroundMillis, starts); } } } @@ -1961,6 +1979,24 @@ public abstract class BatteryStats implements Parcelable { } } + Timer fgTimer = u.getForegroundActivityTimer(); + if (fgTimer != null) { + // Convert from microseconds to milliseconds with rounding + long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000; + int count = fgTimer.getCountLocked(which); + if (totalTime != 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Foreground activities: "); + formatTimeMs(sb, totalTime); + sb.append("realtime ("); + sb.append(count); + sb.append(" times)"); + pw.println(sb.toString()); + uidActivity = true; + } + } + Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); if (processStats.size() > 0) { for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent @@ -1968,23 +2004,26 @@ public abstract class BatteryStats implements Parcelable { Uid.Proc ps = ent.getValue(); long userTime; long systemTime; + long foregroundTime; int starts; int numExcessive; userTime = ps.getUserTime(which); systemTime = ps.getSystemTime(which); + foregroundTime = ps.getForegroundTime(which); starts = ps.getStarts(which); numExcessive = which == STATS_SINCE_CHARGED ? ps.countExcessivePowers() : 0; - if (userTime != 0 || systemTime != 0 || starts != 0 + if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0 || numExcessive != 0) { sb.setLength(0); sb.append(prefix); sb.append(" Proc "); sb.append(ent.getKey()); sb.append(":\n"); sb.append(prefix); sb.append(" CPU: "); formatTime(sb, userTime); sb.append("usr + "); - formatTime(sb, systemTime); sb.append("krn"); + formatTime(sb, systemTime); sb.append("krn ; "); + formatTime(sb, foregroundTime); sb.append("fg"); if (starts != 0) { sb.append("\n"); sb.append(prefix); sb.append(" "); sb.append(starts); sb.append(" proc starts"); @@ -2042,7 +2081,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(sent.getKey()); sb.append(":\n"); sb.append(prefix); sb.append(" Created for: "); formatTimeMs(sb, startTime / 1000); - sb.append(" uptime\n"); + sb.append("uptime\n"); sb.append(prefix); sb.append(" Starts: "); sb.append(starts); sb.append(", launches: "); sb.append(launches); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 04b9884113fc..85f7653d514c 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -83,7 +83,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 64 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 65 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -663,7 +663,7 @@ public final class BatteryStatsImpl extends BatteryStats { } public void logState(Printer pw, String prefix) { - pw.println(prefix + " mCount=" + mCount + pw.println(prefix + "mCount=" + mCount + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount + " mUnpluggedCount=" + mUnpluggedCount); pw.println(prefix + "mTotalTime=" + mTotalTime @@ -1048,7 +1048,7 @@ public final class BatteryStatsImpl extends BatteryStats { public void logState(Printer pw, String prefix) { super.logState(pw, prefix); - pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime + pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime + " mAcquireTime=" + mAcquireTime); } @@ -2240,6 +2240,14 @@ public final class BatteryStatsImpl extends BatteryStats { getUidStatsLocked(uid).noteVideoTurnedOffLocked(); } + public void noteActivityResumedLocked(int uid) { + getUidStatsLocked(uid).noteActivityResumedLocked(); + } + + public void noteActivityPausedLocked(int uid) { + getUidStatsLocked(uid).noteActivityPausedLocked(); + } + public void noteVibratorOnLocked(int uid, long durationMillis) { getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis); } @@ -2541,6 +2549,8 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mVideoTurnedOn; StopwatchTimer mVideoTurnedOnTimer; + StopwatchTimer mForegroundActivityTimer; + BatchTimer mVibratorOnTimer; Counter[] mUserActivityCounters; @@ -2776,6 +2786,27 @@ public final class BatteryStatsImpl extends BatteryStats { } } + public StopwatchTimer createForegroundActivityTimerLocked() { + if (mForegroundActivityTimer == null) { + mForegroundActivityTimer = new StopwatchTimer( + Uid.this, FOREGROUND_ACTIVITY, null, mUnpluggables); + } + return mForegroundActivityTimer; + } + + @Override + public void noteActivityResumedLocked() { + // We always start, since we want multiple foreground PIDs to nest + createForegroundActivityTimerLocked().startRunningLocked(BatteryStatsImpl.this); + } + + @Override + public void noteActivityPausedLocked() { + if (mForegroundActivityTimer != null) { + mForegroundActivityTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + public BatchTimer createVibratorOnTimerLocked() { if (mVibratorOnTimer == null) { mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, @@ -2844,6 +2875,11 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override + public Timer getForegroundActivityTimer() { + return mForegroundActivityTimer; + } + + @Override public Timer getVibratorOnTimer() { return mVibratorOnTimer; } @@ -2919,6 +2955,9 @@ public final class BatteryStatsImpl extends BatteryStats { active |= !mVideoTurnedOnTimer.reset(BatteryStatsImpl.this, false); active |= mVideoTurnedOn; } + if (mForegroundActivityTimer != null) { + active |= !mForegroundActivityTimer.reset(BatteryStatsImpl.this, false); + } if (mVibratorOnTimer != null) { if (mVibratorOnTimer.reset(BatteryStatsImpl.this, false)) { mVibratorOnTimer.detach(); @@ -3018,6 +3057,10 @@ public final class BatteryStatsImpl extends BatteryStats { mVideoTurnedOnTimer.detach(); mVideoTurnedOnTimer = null; } + if (mForegroundActivityTimer != null) { + mForegroundActivityTimer.detach(); + mForegroundActivityTimer = null; + } if (mUserActivityCounters != null) { for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { mUserActivityCounters[i].detach(); @@ -3099,6 +3142,12 @@ public final class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } + if (mForegroundActivityTimer != null) { + out.writeInt(1); + mForegroundActivityTimer.writeToParcel(out, batteryRealtime); + } else { + out.writeInt(0); + } if (mVibratorOnTimer != null) { out.writeInt(1); mVibratorOnTimer.writeToParcel(out, batteryRealtime); @@ -3204,6 +3253,12 @@ public final class BatteryStatsImpl extends BatteryStats { mVideoTurnedOnTimer = null; } if (in.readInt() != 0) { + mForegroundActivityTimer = new StopwatchTimer( + Uid.this, FOREGROUND_ACTIVITY, null, mUnpluggables, in); + } else { + mForegroundActivityTimer = null; + } + if (in.readInt() != 0) { mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mUnpluggables, BatteryStatsImpl.this.mOnBatteryInternal, in); } else { @@ -3372,14 +3427,14 @@ public final class BatteryStatsImpl extends BatteryStats { long mSystemTime; /** - * Number of times the process has been started. + * Amount of time the process was running in the foreground. */ - int mStarts; + long mForegroundTime; /** - * Amount of time the process was running in the foreground. + * Number of times the process has been started. */ - long mForegroundTime; + int mStarts; /** * The amount of user time loaded from a previous save. @@ -3392,14 +3447,14 @@ public final class BatteryStatsImpl extends BatteryStats { long mLoadedSystemTime; /** - * The number of times the process has started from a previous save. + * The amount of foreground time loaded from a previous save. */ - int mLoadedStarts; + long mLoadedForegroundTime; /** - * The amount of foreground time loaded from a previous save. + * The number of times the process has started from a previous save. */ - long mLoadedForegroundTime; + int mLoadedStarts; /** * The amount of user time loaded from the previous run. @@ -3412,14 +3467,14 @@ public final class BatteryStatsImpl extends BatteryStats { long mLastSystemTime; /** - * The number of times the process has started from the previous run. + * The amount of foreground time loaded from the previous run */ - int mLastStarts; + long mLastForegroundTime; /** - * The amount of foreground time loaded from the previous run + * The number of times the process has started from the previous run. */ - long mLastForegroundTime; + int mLastStarts; /** * The amount of user time when last unplugged. @@ -3432,14 +3487,14 @@ public final class BatteryStatsImpl extends BatteryStats { long mUnpluggedSystemTime; /** - * The number of times the process has started before unplugged. + * The amount of foreground time since unplugged. */ - int mUnpluggedStarts; + long mUnpluggedForegroundTime; /** - * The amount of foreground time since unplugged. + * The number of times the process has started before unplugged. */ - long mUnpluggedForegroundTime; + int mUnpluggedStarts; SamplingCounter[] mSpeedBins; @@ -3453,8 +3508,8 @@ public final class BatteryStatsImpl extends BatteryStats { public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { mUnpluggedUserTime = mUserTime; mUnpluggedSystemTime = mSystemTime; - mUnpluggedStarts = mStarts; mUnpluggedForegroundTime = mForegroundTime; + mUnpluggedStarts = mStarts; } public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { @@ -5362,6 +5417,9 @@ public final class BatteryStatsImpl extends BatteryStats { u.createVideoTurnedOnTimerLocked().readSummaryFromParcelLocked(in); } if (in.readInt() != 0) { + u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in); + } + if (in.readInt() != 0) { u.createVibratorOnTimerLocked().readSummaryFromParcelLocked(in); } @@ -5415,6 +5473,7 @@ public final class BatteryStatsImpl extends BatteryStats { Uid.Proc p = u.getProcessStatsLocked(procName); p.mUserTime = p.mLoadedUserTime = in.readLong(); p.mSystemTime = p.mLoadedSystemTime = in.readLong(); + p.mForegroundTime = p.mLoadedForegroundTime = in.readLong(); p.mStarts = p.mLoadedStarts = in.readInt(); int NSB = in.readInt(); if (NSB > 100) { @@ -5564,6 +5623,12 @@ public final class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } + if (u.mForegroundActivityTimer != null) { + out.writeInt(1); + u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL); + } else { + out.writeInt(0); + } if (u.mVibratorOnTimer != null) { out.writeInt(1); u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); @@ -5633,6 +5698,7 @@ public final class BatteryStatsImpl extends BatteryStats { Uid.Proc ps = ent.getValue(); out.writeLong(ps.mUserTime); out.writeLong(ps.mSystemTime); + out.writeLong(ps.mForegroundTime); out.writeInt(ps.mStarts); final int N = ps.mSpeedBins.length; out.writeInt(N); diff --git a/core/java/com/android/internal/os/ProcessStats.java b/core/java/com/android/internal/os/ProcessStats.java index b1bb8c173a67..bd0914d4f65c 100644 --- a/core/java/com/android/internal/os/ProcessStats.java +++ b/core/java/com/android/internal/os/ProcessStats.java @@ -518,6 +518,10 @@ public class ProcessStats { return pids; } + /** + * Returns the total time (in clock ticks, or 1/100 sec) spent executing in + * both user and system code. + */ public long getCpuTimeForPid(int pid) { final String statFile = "/proc/" + pid + "/stat"; final long[] statsData = mSinglePidStatsData; @@ -531,9 +535,9 @@ public class ProcessStats { } /** - * Returns the times spent at each CPU speed, since the last call to this method. If this - * is the first time, it will return 1 for each value. - * @return relative times spent at different speed steps. + * Returns the delta time (in clock ticks, or 1/100 sec) spent at each CPU + * speed, since the last call to this method. If this is the first call, it + * will return 1 for each value. */ public long[] getLastCpuSpeedTimes() { if (mCpuSpeedTimes == null) { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 22f77d6677e5..beebc835c961 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2340,13 +2340,19 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) { - if (DEBUG_SWITCH) Slog.d(TAG, "updateUsageStats: comp=" + resumedComponent + "res=" - + resumed); + void updateUsageStats(ActivityRecord component, boolean resumed) { + if (DEBUG_SWITCH) Slog.d(TAG, "updateUsageStats: comp=" + component + "res=" + resumed); + final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); if (resumed) { - mUsageStatsService.noteResumeComponent(resumedComponent.realActivity); + mUsageStatsService.noteResumeComponent(component.realActivity); + synchronized (stats) { + stats.noteActivityResumedLocked(component.app.uid); + } } else { - mUsageStatsService.notePauseComponent(resumedComponent.realActivity); + mUsageStatsService.notePauseComponent(component.realActivity); + synchronized (stats) { + stats.noteActivityPausedLocked(component.app.uid); + } } } @@ -2542,6 +2548,7 @@ public final class ActivityManagerService extends ActivityManagerNative mPendingProcessChanges.clear(); if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "*** Delivering " + N + " process changes"); } + int i = mProcessObservers.beginBroadcast(); while (i > 0) { i--; |