From fdb1956ff71ff57fcdaafaaeb7f42c19de3d7c2f Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 11 Jul 2014 16:03:36 -0700 Subject: Fix issue #15681802: Missing RESET:TIME in complete battery histories But wait, there's more! - Keep track of sync durations in the aggregated stats. - Add events for users that are running and in the foreground. - Rework the activity manager's tracking of stuff using battery in the background to be based on proc stats, which allows it to be better about determing when it should reset its tracking of background work. - Also add tracking of scheduled job execution, like we are doing for syncs. - And once I started hooking battery stats in to JobSchedulerService, I found a few things I couldn't stop myself from changing: (1) make it very explicit that it doesn't start scheduling jobs until we have reached the point in system boot where third party apps are allowed to run, and (2) adjust the various for loops to not use iterators. Change-Id: I69d812e27bcfee9e58a614f0f6b1c7545d7530b1 --- core/java/android/os/BatteryStats.java | 133 ++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 10 deletions(-) (limited to 'core/java/android/os/BatteryStats.java') diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 7fd166059ac4..aab7b1f504ba 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -119,6 +119,16 @@ public abstract class BatteryStats implements Parcelable { */ public static final int PROCESS_STATE = 12; + /** + * A constant indicating a sync timer + */ + public static final int SYNC = 13; + + /** + * A constant indicating a job timer + */ + public static final int JOB = 14; + /** * Include all of the data in the stats, including previously saved data. */ @@ -157,6 +167,8 @@ public abstract class BatteryStats implements Parcelable { private static final String FOREGROUND_DATA = "fg"; private static final String STATE_TIME_DATA = "st"; private static final String WAKELOCK_DATA = "wl"; + private static final String SYNC_DATA = "sy"; + private static final String JOB_DATA = "jb"; private static final String KERNEL_WAKELOCK_DATA = "kwl"; private static final String WAKEUP_REASON_DATA = "wr"; private static final String NETWORK_DATA = "nt"; @@ -272,6 +284,20 @@ public abstract class BatteryStats implements Parcelable { */ public abstract Map getWakelockStats(); + /** + * Returns a mapping containing sync statistics. + * + * @return a Map from Strings to Timer objects. + */ + public abstract Map getSyncStats(); + + /** + * Returns a mapping containing scheduled job statistics. + * + * @return a Map from Strings to Timer objects. + */ + public abstract Map getJobStats(); + /** * The statistics associated with a particular wake lock. */ @@ -660,13 +686,19 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_FOREGROUND = 0x0002; // Event is about an application package that is at the top of the screen. public static final int EVENT_TOP = 0x0003; - // Event is about an application package that is at the top of the screen. + // Event is about active sync operations. public static final int EVENT_SYNC = 0x0004; // Events for all additional wake locks aquired/release within a wake block. // These are not generated by default. public static final int EVENT_WAKE_LOCK = 0x0005; + // Event is about an application executing a scheduled job. + public static final int EVENT_JOB = 0x0006; + // Events for users running. + public static final int EVENT_USER_RUNNING = 0x0007; + // Events for foreground user. + public static final int EVENT_USER_FOREGROUND = 0x0008; // Number of event types. - public static final int EVENT_COUNT = 0x0006; + public static final int EVENT_COUNT = 0x0009; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -680,6 +712,14 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_SYNC_FINISH = EVENT_SYNC | EVENT_FLAG_FINISH; public static final int EVENT_WAKE_LOCK_START = EVENT_WAKE_LOCK | EVENT_FLAG_START; public static final int EVENT_WAKE_LOCK_FINISH = EVENT_WAKE_LOCK | EVENT_FLAG_FINISH; + public static final int EVENT_JOB_START = EVENT_JOB | EVENT_FLAG_START; + public static final int EVENT_JOB_FINISH = EVENT_JOB | EVENT_FLAG_FINISH; + public static final int EVENT_USER_RUNNING_START = EVENT_USER_RUNNING | EVENT_FLAG_START; + public static final int EVENT_USER_RUNNING_FINISH = EVENT_USER_RUNNING | EVENT_FLAG_FINISH; + public static final int EVENT_USER_FOREGROUND_START = + EVENT_USER_FOREGROUND | EVENT_FLAG_START; + public static final int EVENT_USER_FOREGROUND_FINISH = + EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH; // For CMD_EVENT. public int eventCode; @@ -1269,11 +1309,11 @@ public abstract class BatteryStats implements Parcelable { }; public static final String[] HISTORY_EVENT_NAMES = new String[] { - "null", "proc", "fg", "top", "sync", "wake_lock_in" + "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { - "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl" + "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf" }; /** @@ -2080,10 +2120,9 @@ public abstract class BatteryStats implements Parcelable { } } - Map wakelocks = u.getWakelockStats(); + Map wakelocks = u.getWakelockStats(); if (wakelocks.size() > 0) { - for (Map.Entry ent - : wakelocks.entrySet()) { + for (Map.Entry ent : wakelocks.entrySet()) { Uid.Wakelock wl = ent.getValue(); String linePrefix = ""; sb.setLength(0); @@ -2105,6 +2144,32 @@ public abstract class BatteryStats implements Parcelable { } } + Map syncs = u.getSyncStats(); + if (syncs.size() > 0) { + for (Map.Entry ent : syncs.entrySet()) { + Timer timer = ent.getValue(); + // Convert from microseconds to milliseconds with rounding + long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + int count = timer.getCountLocked(which); + if (totalTime != 0) { + dumpLine(pw, uid, category, SYNC_DATA, ent.getKey(), totalTime, count); + } + } + } + + Map jobs = u.getJobStats(); + if (jobs.size() > 0) { + for (Map.Entry ent : jobs.entrySet()) { + Timer timer = ent.getValue(); + // Convert from microseconds to milliseconds with rounding + long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + int count = timer.getCountLocked(which); + if (totalTime != 0) { + dumpLine(pw, uid, category, JOB_DATA, ent.getKey(), totalTime, count); + } + } + } + SparseArray sensors = u.getSensorStats(); int NSE = sensors.size(); for (int ise=0; ise 0) { long totalFull = 0, totalPartial = 0, totalWindow = 0; int count = 0; - for (Map.Entry ent - : wakelocks.entrySet()) { + for (Map.Entry ent : wakelocks.entrySet()) { Uid.Wakelock wl = ent.getValue(); String linePrefix = ": "; sb.setLength(0); @@ -2998,6 +3062,56 @@ public abstract class BatteryStats implements Parcelable { } } + Map syncs = u.getSyncStats(); + if (syncs.size() > 0) { + for (Map.Entry ent : syncs.entrySet()) { + Timer timer = ent.getValue(); + // Convert from microseconds to milliseconds with rounding + long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + int count = timer.getCountLocked(which); + sb.setLength(0); + sb.append(prefix); + sb.append(" Sync "); + sb.append(ent.getKey()); + sb.append(": "); + if (totalTime != 0) { + formatTimeMs(sb, totalTime); + sb.append("realtime ("); + sb.append(count); + sb.append(" times)"); + } else { + sb.append("(not used)"); + } + pw.println(sb.toString()); + uidActivity = true; + } + } + + Map jobs = u.getJobStats(); + if (syncs.size() > 0) { + for (Map.Entry ent : jobs.entrySet()) { + Timer timer = ent.getValue(); + // Convert from microseconds to milliseconds with rounding + long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + int count = timer.getCountLocked(which); + sb.setLength(0); + sb.append(prefix); + sb.append(" Job "); + sb.append(ent.getKey()); + sb.append(": "); + if (totalTime != 0) { + formatTimeMs(sb, totalTime); + sb.append("realtime ("); + sb.append(count); + sb.append(" times)"); + } else { + sb.append("(not used)"); + } + pw.println(sb.toString()); + uidActivity = true; + } + } + SparseArray sensors = u.getSensorStats(); int NSE = sensors.size(); for (int ise=0; ise