From cbefd8dd2befcb768f911a63becc427ec4c13250 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 14 May 2014 11:42:00 -0700 Subject: [PATCH] Battery stats more wake history, power save mode. Add new option for battery stats to record the full wake lock history, and recording the current power save mode. Also add in some additional error constants when generating Binder error exceptions. And fix issue #14974572: Avoid repeating wakeup_reason at the beginning of history Change-Id: I7c1a2ab9569de216634f63d8ad69f1294ef1d235 --- core/java/android/os/BatteryStats.java | 110 +++++++++------ .../java/android/os/PowerManagerInternal.java | 8 ++ .../android/internal/app/IBatteryStats.aidl | 9 +- .../android/internal/os/BatteryStatsImpl.java | 125 +++++++++++++----- core/jni/android_util_Binder.cpp | 32 +++++ .../server/am/BatteryStatsService.java | 70 ++++++++-- .../com/android/server/power/Notifier.java | 13 +- .../server/power/PowerManagerService.java | 40 +++++- 8 files changed, 314 insertions(+), 93 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 4857533a13375..cf0caed0df6ac 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -31,7 +31,6 @@ import android.telephony.SignalStrength; import android.text.format.DateFormat; import android.util.Printer; import android.util.SparseArray; -import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.TimeUtils; import com.android.internal.os.BatterySipper; @@ -601,6 +600,7 @@ public abstract class BatteryStats implements Parcelable { public int states; public static final int STATE2_VIDEO_ON_FLAG = 1<<0; + public static final int STATE2_LOW_POWER_FLAG = 1<<1; public int states2; // The wake lock that was acquired at this point. @@ -622,8 +622,11 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_TOP = 0x0003; // Event is about an application package that is at the top of the screen. 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; // Number of event types. - public static final int EVENT_COUNT = 0x0005; + public static final int EVENT_COUNT = 0x0006; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -635,6 +638,8 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_TOP_FINISH = EVENT_TOP | EVENT_FLAG_FINISH; public static final int EVENT_SYNC_START = EVENT_SYNC | EVENT_FLAG_START; 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; // For CMD_EVENT. public int eventCode; @@ -887,6 +892,11 @@ public abstract class BatteryStats implements Parcelable { return true; } + public void removeEvents(int code) { + int idx = code&HistoryItem.EVENT_TYPE_MASK; + mActiveEvents[idx] = null; + } + public HashMap getStateForEvent(int code) { return mActiveEvents[code]; } @@ -996,6 +1006,21 @@ public abstract class BatteryStats implements Parcelable { public abstract long getScreenBrightnessTime(int brightnessBin, long elapsedRealtimeUs, int which); + /** + * Returns the time in microseconds that low power mode has been enabled while the device was + * running on battery. + * + * {@hide} + */ + public abstract long getLowPowerModeEnabledTime(long elapsedRealtimeUs, int which); + + /** + * Returns the number of times that low power mode was enabled. + * + * {@hide} + */ + public abstract int getLowPowerModeEnabledCount(int which); + /** * Returns the time in microseconds that the phone has been on while the device was * running on battery. @@ -1157,14 +1182,15 @@ public abstract class BatteryStats implements Parcelable { public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS = new BitDescription[] { new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"), + new BitDescription(HistoryItem.STATE2_LOW_POWER_FLAG, "low_power", "lp"), }; public static final String[] HISTORY_EVENT_NAMES = new String[] { - "null", "proc", "fg", "top", "sync" + "null", "proc", "fg", "top", "sync", "wake_lock_in" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { - "Enl", "Epr", "Efg", "Etp", "Esy" + "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl" }; /** @@ -1630,11 +1656,12 @@ public abstract class BatteryStats implements Parcelable { final long totalUptime = computeUptime(rawUptime, which); final long screenOnTime = getScreenOnTime(rawRealtime, which); final long interactiveTime = getInteractiveTime(rawRealtime, which); + final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which); final long phoneOnTime = getPhoneOnTime(rawRealtime, which); final long wifiOnTime = getWifiOnTime(rawRealtime, which); final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which); - + StringBuilder sb = new StringBuilder(128); SparseArray uidStats = getUidStats(); @@ -1699,7 +1726,8 @@ public abstract class BatteryStats implements Parcelable { mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes, fullWakeLockTimeTotal, partialWakeLockTimeTotal, 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which), - getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000); + getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000, + lowPowerModeEnabledTime / 1000); // Dump screen brightness stats Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS]; @@ -2092,32 +2120,20 @@ public abstract class BatteryStats implements Parcelable { final long screenOnTime = getScreenOnTime(rawRealtime, which); final long interactiveTime = getInteractiveTime(rawRealtime, which); + final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which); final long phoneOnTime = getPhoneOnTime(rawRealtime, which); final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); final long wifiOnTime = getWifiOnTime(rawRealtime, which); final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which); sb.setLength(0); - sb.append(prefix); - sb.append(" Interactive: "); formatTimeMs(sb, interactiveTime / 1000); - sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime)); - sb.append(")"); - pw.println(sb.toString()); - sb.setLength(0); sb.append(prefix); sb.append(" Screen on: "); formatTimeMs(sb, screenOnTime / 1000); sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime)); sb.append(") "); sb.append(getScreenOnCount(which)); - sb.append("x, Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000); - sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); + sb.append("x, Interactive: "); formatTimeMs(sb, interactiveTime / 1000); + sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime)); sb.append(")"); pw.println(sb.toString()); - if (phoneOnTime != 0) { - sb.setLength(0); - sb.append(prefix); - sb.append(" Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000); - sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); - sb.append(") "); sb.append(getPhoneOnCount(which)); - } sb.setLength(0); sb.append(prefix); sb.append(" Screen brightnesses:"); @@ -2139,7 +2155,24 @@ public abstract class BatteryStats implements Parcelable { } if (!didOne) sb.append(" (no activity)"); pw.println(sb.toString()); - + if (lowPowerModeEnabledTime != 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Low power mode enabled: "); + formatTimeMs(sb, lowPowerModeEnabledTime / 1000); + sb.append("("); + sb.append(formatRatioLocked(lowPowerModeEnabledTime, whichBatteryRealtime)); + sb.append(")"); + pw.println(sb.toString()); + } + if (phoneOnTime != 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); + sb.append(") "); sb.append(getPhoneOnCount(which)); + } + // Calculate wakelock times across all uids. long fullWakeLockTimeTotalMicros = 0; long partialWakeLockTimeTotalMicros = 0; @@ -3004,6 +3037,8 @@ public abstract class BatteryStats implements Parcelable { pw.print(rec.numReadInts); pw.print(") "); } else { + pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); + pw.print(HISTORY_DATA); pw.print(','); if (lastTime < 0) { pw.print(rec.time - baseTime); } else { @@ -3190,6 +3225,7 @@ public abstract class BatteryStats implements Parcelable { } pw.println(); oldState = rec.states; + oldState2 = rec.states2; } } } @@ -3266,21 +3302,25 @@ public abstract class BatteryStats implements Parcelable { if (rec.cmd == HistoryItem.CMD_CURRENT_TIME || rec.cmd == HistoryItem.CMD_RESET) { printed = true; + hprinter.printNextItem(pw, rec, baseTime, checkin, + (flags&DUMP_VERBOSE) != 0); + rec.cmd = HistoryItem.CMD_UPDATE; } else if (rec.currentTime != 0) { printed = true; byte cmd = rec.cmd; rec.cmd = HistoryItem.CMD_CURRENT_TIME; - if (checkin) { - pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); - pw.print(HISTORY_DATA); pw.print(','); - } hprinter.printNextItem(pw, rec, baseTime, checkin, (flags&DUMP_VERBOSE) != 0); rec.cmd = cmd; } if (tracker != null) { - int oldCode = rec.eventCode; - HistoryTag oldTag = rec.eventTag; + if (rec.cmd != HistoryItem.CMD_UPDATE) { + hprinter.printNextItem(pw, rec, baseTime, checkin, + (flags&DUMP_VERBOSE) != 0); + rec.cmd = HistoryItem.CMD_UPDATE; + } + int oldEventCode = rec.eventCode; + HistoryTag oldEventTag = rec.eventTag; rec.eventTag = new HistoryTag(); for (int i=0; i active @@ -3296,24 +3336,18 @@ public abstract class BatteryStats implements Parcelable { rec.eventTag.string = ent.getKey(); rec.eventTag.uid = uids.keyAt(j); rec.eventTag.poolIdx = uids.valueAt(j); - if (checkin) { - pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); - pw.print(HISTORY_DATA); pw.print(','); - } hprinter.printNextItem(pw, rec, baseTime, checkin, (flags&DUMP_VERBOSE) != 0); + rec.wakeReasonTag = null; + rec.wakelockTag = null; } } } - rec.eventCode = oldCode; - rec.eventTag = oldTag; + rec.eventCode = oldEventCode; + rec.eventTag = oldEventTag; tracker = null; } } - if (checkin) { - pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); - pw.print(HISTORY_DATA); pw.print(','); - } hprinter.printNextItem(pw, rec, baseTime, checkin, (flags&DUMP_VERBOSE) != 0); } else if (rec.eventCode != HistoryItem.EVENT_NONE) { diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index cb3d528198254..69b828f82ac8f 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -55,6 +55,14 @@ public abstract class PowerManagerInternal { */ public abstract void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis); + public abstract boolean getLowPowerModeEnabled(); + + public interface LowPowerModeListener { + public void onLowPowerModeChanged(boolean enabled); + } + + public abstract void registerLowPowerModeObserver(LowPowerModeListener listener); + // TODO: Remove this and retrieve as a local service instead. public abstract void setPolicy(WindowManagerPolicy policy); } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 0454749572e28..0769b085b50c5 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -46,14 +46,15 @@ interface IBatteryStats { void noteStartWakelock(int uid, int pid, String name, String historyName, int type, boolean unimportantForLogging); - void noteStopWakelock(int uid, int pid, String name, int type); + void noteStopWakelock(int uid, int pid, String name, String historyName, int type); void noteStartWakelockFromSource(in WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging); - void noteChangeWakelockFromSource(in WorkSource ws, int pid, String name, int type, - in WorkSource newWs, int newPid, String newName, + void noteChangeWakelockFromSource(in WorkSource ws, int pid, String name, String histyoryName, + int type, in WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging); - void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, int type); + void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, String historyName, + int type); 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 7bd5b12fc7913..956c86d9dfd4e 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -48,7 +48,6 @@ import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; import android.util.SparseArray; -import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.TimeUtils; import android.view.Display; @@ -89,7 +88,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 105 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 106 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -236,6 +235,7 @@ public final class BatteryStatsImpl extends BatteryStats { int mWakeLockNesting; boolean mWakeLockImportant; + public boolean mRecordAllWakeLocks; int mScreenState = Display.STATE_UNKNOWN; StopwatchTimer mScreenOnTimer; @@ -246,6 +246,9 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mInteractive; StopwatchTimer mInteractiveTimer; + boolean mLowPowerModeEnabled; + StopwatchTimer mLowPowerModeEnabledTimer; + boolean mPhoneOn; StopwatchTimer mPhoneOnTimer; @@ -2314,6 +2317,14 @@ public final class BatteryStatsImpl extends BatteryStats { private String mInitialAcquireWakeName; private int mInitialAcquireWakeUid = -1; + public void setRecordAllWakeLocksLocked(boolean enabled) { + mRecordAllWakeLocks = enabled; + if (!enabled) { + // Clear out any existing state. + mActiveEvents.removeEvents(HistoryItem.EVENT_WAKE_LOCK); + } + } + public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) { uid = mapUid(uid); @@ -2321,27 +2332,33 @@ public final class BatteryStatsImpl extends BatteryStats { // Only care about partial wake locks, since full wake locks // will be canceled when the user puts the screen to sleep. aggregateLastWakeupUptimeLocked(uptime); + historyName = historyName == null || mRecordAllWakeLocks ? name : historyName; if (mWakeLockNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: " + Integer.toHexString(mHistoryCur.states)); mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; - mHistoryCur.wakelockTag.string = mInitialAcquireWakeName - = historyName != null ? historyName : name; + mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName; mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; mWakeLockImportant = !unimportantForLogging; addHistoryRecordLocked(elapsedRealtime, uptime); - } else if (!mWakeLockImportant && !unimportantForLogging) { + } else if (!mRecordAllWakeLocks && !mWakeLockImportant && !unimportantForLogging) { if (mHistoryLastWritten.wakelockTag != null) { // We'll try to update the last tag. mHistoryLastWritten.wakelockTag = null; mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; - mHistoryCur.wakelockTag.string = mInitialAcquireWakeName - = historyName != null ? historyName : name; + mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName; mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; addHistoryRecordLocked(elapsedRealtime, uptime); } mWakeLockImportant = true; + } else if (mRecordAllWakeLocks) { + if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName, + uid, 0)) { + return; + } + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_WAKE_LOCK_START, + historyName, uid); } mWakeLockNesting++; } @@ -2354,24 +2371,33 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void noteStopWakeLocked(int uid, int pid, String name, int type, long elapsedRealtime, - long uptime) { + public void noteStopWakeLocked(int uid, int pid, String name, String historyName, int type, + long elapsedRealtime, long uptime) { uid = mapUid(uid); if (type == WAKE_TYPE_PARTIAL) { mWakeLockNesting--; + historyName = historyName == null || mRecordAllWakeLocks ? name : historyName; if (mWakeLockNesting == 0) { mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: " + Integer.toHexString(mHistoryCur.states)); - if ((name != null && !name.equals(mInitialAcquireWakeName)) + if (mRecordAllWakeLocks + || (historyName != null && !historyName.equals(mInitialAcquireWakeName)) || uid != mInitialAcquireWakeUid) { mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; - mHistoryCur.wakelockTag.string = name; + mHistoryCur.wakelockTag.string = historyName; mHistoryCur.wakelockTag.uid = uid; } mInitialAcquireWakeName = null; mInitialAcquireWakeUid = -1; addHistoryRecordLocked(elapsedRealtime, uptime); + } else if (mRecordAllWakeLocks) { + if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, + uid, 0)) { + return; + } + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_WAKE_LOCK_FINISH, + historyName, uid); } } if (uid >= 0) { @@ -2391,8 +2417,8 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, int type, - WorkSource newWs, int newPid, String newName, + public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, + String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging) { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); @@ -2406,16 +2432,17 @@ public final class BatteryStatsImpl extends BatteryStats { } final int NO = ws.size(); for (int i=0; i: optional name of package to filter output by."); } + private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) { + i++; + if (i >= args.length) { + pw.println("Missing option argument for " + (enable ? "--enable" : "--disable")); + dumpHelp(pw); + return -1; + } + if ("full-wake-history".equals(args[i])) { + synchronized (mStats) { + mStats.setRecordAllWakeLocksLocked(enable); + } + } else { + pw.println("Unknown enable/disable option: " + args[i]); + dumpHelp(pw); + return -1; + } + return i; + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -662,6 +698,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub { pw.println("Battery stats written."); noOutput = true; } + } else if ("--enable".equals(arg)) { + i = doEnableOrDisable(pw, i, args, true); + if (i < 0) { + return; + } + pw.println("Enabled: " + args[i]); + return; + } else if ("--disable".equals(arg)) { + i = doEnableOrDisable(pw, i, args, false); + if (i < 0) { + return; + } + pw.println("Disabled: " + args[i]); + return; } else if ("-h".equals(arg)) { dumpHelp(pw); return; diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 2d6cc7c97c63f..e244bdea80e73 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -190,14 +190,14 @@ final class Notifier { + ", workSource=" + newWorkSource); } try { - mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, monitorType, - newWorkSource, newOwnerPid, newTag, newHistoryTag, + mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag, + monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag, newMonitorType, unimportantForLogging); } catch (RemoteException ex) { // Ignore } } else { - onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource); + onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag); onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid, newWorkSource, newHistoryTag); } @@ -207,7 +207,7 @@ final class Notifier { * Called when a wake lock is released. */ public void onWakeLockReleased(int flags, String tag, String packageName, - int ownerUid, int ownerPid, WorkSource workSource) { + int ownerUid, int ownerPid, WorkSource workSource, String historyTag) { if (DEBUG) { Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag + "\", packageName=" + packageName @@ -218,9 +218,10 @@ final class Notifier { try { final int monitorType = getBatteryStatsWakeLockMonitorType(flags); if (workSource != null) { - mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, monitorType); + mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, historyTag, + monitorType); } else { - mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, monitorType); + mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, historyTag, monitorType); mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 03941c66b0bc0..f0b7861ac9a5c 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -18,6 +18,7 @@ package com.android.server.power; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; +import com.android.internal.os.BackgroundThread; import com.android.server.BatteryService; import com.android.server.EventLogTags; import com.android.server.LocalServices; @@ -400,7 +401,10 @@ public final class PowerManagerService extends com.android.server.SystemService private long mLastWarningAboutUserActivityPermission = Long.MIN_VALUE; // If true, the device is in low power mode. - private static boolean mLowPowerModeEnabled; + private boolean mLowPowerModeEnabled; + + private final ArrayList mLowPowerModeListeners + = new ArrayList(); private native void nativeInit(); @@ -623,11 +627,24 @@ public final class PowerManagerService extends com.android.server.SystemService Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT); - boolean lowPowerModeEnabled = Settings.Global.getInt(resolver, + final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver, Settings.Global.LOW_POWER_MODE, 0) != 0; if (lowPowerModeEnabled != mLowPowerModeEnabled) { powerHintInternal(POWER_HINT_LOW_POWER_MODE, lowPowerModeEnabled ? 1 : 0); mLowPowerModeEnabled = lowPowerModeEnabled; + BackgroundThread.getHandler().post(new Runnable() { + @Override + public void run() { + ArrayList listeners; + synchronized (mLock) { + listeners = new ArrayList( + mLowPowerModeListeners); + } + for (int i=0; i