From d0db6f00435b83c88f041ccf0cfcb9986ae8e6ef Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 18 Jul 2016 14:14:20 -0700 Subject: [PATCH] Add reporting of long wake locks. These appear as a new event in the battery stats history, "longwake" in the long version and "Elw" in the checkin. The power manager keeps track of which wake locks are held for a long time and reports them to battery stats. Long is currently considered 1 minute or more. Once it is long, the start event will appear, and once if is released the event will end. In the case of a wake lock changing (typically its work source changing), for purposes of this accounting this is considering a pure release of the old state and start of the new state... so the timer will reset back to one minute until the wake lock is considered long. This is done to prevent things that make lots of changes to wake lock work sources from spamming the log. Bug: 28753137 Change-Id: I33b6168c57a7ea6ea558273dec731704123124a5 --- core/java/android/os/BatteryStats.java | 12 +- .../android/internal/app/IBatteryStats.aidl | 2 + .../android/internal/os/BatteryStatsImpl.java | 30 ++++ .../server/am/BatteryStatsService.java | 14 ++ .../com/android/server/power/Notifier.java | 42 +++++ .../server/power/PowerManagerService.java | 154 +++++++++++++++++- 6 files changed, 246 insertions(+), 8 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 1b9e2aa3896af..af9c99f20ae3f 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1302,9 +1302,11 @@ public abstract class BatteryStats implements Parcelable { // Event for the UID that woke up the application processor. // Used for wakeups coming from WiFi, modem, etc. public static final int EVENT_WAKEUP_AP = 0x0013; + // Event for reporting that a specific partial wake lock has been held for a long duration. + public static final int EVENT_LONG_WAKE_LOCK = 0x0014; // Number of event types. - public static final int EVENT_COUNT = 0x0014; + public static final int EVENT_COUNT = 0x0015; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -1332,6 +1334,10 @@ public abstract class BatteryStats implements Parcelable { EVENT_TEMP_WHITELIST | EVENT_FLAG_START; public static final int EVENT_TEMP_WHITELIST_FINISH = EVENT_TEMP_WHITELIST | EVENT_FLAG_FINISH; + public static final int EVENT_LONG_WAKE_LOCK_START = + EVENT_LONG_WAKE_LOCK | EVENT_FLAG_START; + public static final int EVENT_LONG_WAKE_LOCK_FINISH = + EVENT_LONG_WAKE_LOCK | EVENT_FLAG_FINISH; // For CMD_EVENT. public int eventCode; @@ -1996,13 +2002,13 @@ public abstract class BatteryStats implements Parcelable { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist", - "screenwake", "wakeupap" + "screenwake", "wakeupap", "longwake" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw", - "Esw", "Ewa" + "Esw", "Ewa", "Elw" }; /** diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index ca69746784dd8..5623a2cb430c1 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -79,6 +79,8 @@ interface IBatteryStats { String newHistoryName, int newType, boolean newUnimportantForLogging); void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, String historyName, int type); + void noteLongPartialWakelockStart(String name, String historyName, int uid); + void noteLongPartialWakelockFinish(String name, String historyName, int uid); void noteVibratorOn(int uid, long durationMillis); void noteVibratorOff(int uid); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 11c1de19bb961..b174e33251682 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -3285,6 +3285,36 @@ public class BatteryStatsImpl extends BatteryStats { } } + public void noteLongPartialWakelockStart(String name, String historyName, int uid) { + uid = mapUid(uid); + final long elapsedRealtime = mClocks.elapsedRealtime(); + final long uptime = mClocks.uptimeMillis(); + if (historyName == null) { + historyName = name; + } + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid, + 0)) { + return; + } + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START, + historyName, uid); + } + + public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { + uid = mapUid(uid); + final long elapsedRealtime = mClocks.elapsedRealtime(); + final long uptime = mClocks.uptimeMillis(); + if (historyName == null) { + historyName = name; + } + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid, + 0)) { + return; + } + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, + historyName, uid); + } + void aggregateLastWakeupUptimeLocked(long uptimeMs) { if (mLastWakeupReason != null) { long deltaUptime = uptimeMs - mLastWakeupUptimeMs; diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 7fe29b086556e..ff13125a84173 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -484,6 +484,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } + public void noteLongPartialWakelockStart(String name, String historyName, int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteLongPartialWakelockStart(name, historyName, uid); + } + } + + public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteLongPartialWakelockFinish(name, historyName, uid); + } + } + public void noteStartSensor(int uid, int sensor) { enforceCallingPermission(); synchronized (mStats) { diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 9ccfd67980f53..4e9f5a2b2b52a 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -194,6 +194,48 @@ final class Notifier { } } + public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource, + String historyTag) { + if (DEBUG) { + Slog.d(TAG, "onLongPartialWakeLockStart: ownerUid=" + ownerUid + + ", workSource=" + workSource); + } + + try { + if (workSource != null) { + final int N = workSource.size(); + for (int i=0; i