diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java index 1c1fc2c96f864..1853c65a299d8 100644 --- a/core/java/android/os/BatteryConsumer.java +++ b/core/java/android/os/BatteryConsumer.java @@ -174,7 +174,7 @@ public abstract class BatteryConsumer { public static final int PROCESS_STATE_BACKGROUND = 2; public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3; - static final int PROCESS_STATE_COUNT = 4; + public static final int PROCESS_STATE_COUNT = 4; private static final String[] sProcessStateNames = new String[PROCESS_STATE_COUNT]; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 30613b97f1780..da968b378325f 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -653,6 +653,24 @@ public abstract class BatteryStats implements Parcelable { } } + /** + * Maps BatteryStats.Uid process state to the BatteryConsumer process state. + */ + public static @BatteryConsumer.ProcessState int + mapUidProcessStateToBatteryConsumerProcessState(int processState) { + switch (processState) { + case BatteryStats.Uid.PROCESS_STATE_TOP: + return BatteryConsumer.PROCESS_STATE_FOREGROUND; + case BatteryStats.Uid.PROCESS_STATE_BACKGROUND: + case BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING: + return BatteryConsumer.PROCESS_STATE_BACKGROUND; + case BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE: + return BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE; + default: + return BatteryConsumer.PROCESS_STATE_ANY; + } + } + /** * Returns true if battery consumption is tracked on a per-process-state basis. */ diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 985331c5c0477..da4208065ec5c 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -160,7 +160,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - static final int VERSION = 202; + static final int VERSION = 203; // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks @@ -237,6 +237,10 @@ public class BatteryStatsImpl extends BatteryStats { return mKernelMemoryStats; } + private static final int[] SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS = { + MeasuredEnergyStats.POWER_BUCKET_CPU, + }; + @GuardedBy("this") public boolean mPerProcStateCpuTimesAvailable = true; @@ -526,6 +530,7 @@ public class BatteryStatsImpl extends BatteryStats { * mPendingRemovedUids queue. */ @GuardedBy("this") + @SuppressWarnings("GuardedBy") // errorprone false positive on removeLocked public void clearPendingRemovedUidsLocked() { long cutOffTimeMs = mClock.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS; while (!mPendingRemovedUids.isEmpty() @@ -1061,6 +1066,10 @@ public class BatteryStatsImpl extends BatteryStats { int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; + @GuardedBy("this") + @VisibleForTesting + protected @Nullable MeasuredEnergyStats.Config mMeasuredEnergyStatsConfig; + /** * Accumulated global (generally, device-wide total) charge consumption of various consumers * while on battery. @@ -3564,6 +3573,7 @@ public class BatteryStatsImpl extends BatteryStats { // from a battery level change. static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001; + @GuardedBy("this") public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) { if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) { dest.writeInt(DELTA_TIME_ABS); @@ -3836,11 +3846,13 @@ public class BatteryStatsImpl extends BatteryStats { mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs; } + @GuardedBy("this") @Override public void commitCurrentHistoryBatchLocked() { mHistoryLastWritten.cmd = HistoryItem.CMD_NULL; } + @GuardedBy("this") public void createFakeHistoryEvents(long numEvents) { final long elapsedRealtimeMs = mClock.elapsedRealtime(); final long uptimeMs = mClock.uptimeMillis(); @@ -3852,6 +3864,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) { if (!mHaveBatteryLevel || !mRecordingHistory) { return; @@ -3955,6 +3968,7 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur); } + @GuardedBy("this") private void addHistoryBufferLocked(long elapsedRealtimeMs, byte cmd, HistoryItem cur) { if (mBatteryStatsHistoryIterator != null) { throw new IllegalStateException("Can't do this while iterating history!"); @@ -3981,6 +3995,7 @@ public class BatteryStatsImpl extends BatteryStats { int mChangedStates = 0; int mChangedStates2 = 0; + @GuardedBy("this") void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) { if (mTrackRunningHistoryElapsedRealtimeMs != 0) { final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs; @@ -4001,10 +4016,12 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur); } + @GuardedBy("this") void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) { addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur); } + @GuardedBy("this") public void addHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, String name, int uid) { mHistoryCur.eventCode = code; @@ -4014,6 +4031,7 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs, byte cmd, HistoryItem cur) { HistoryItem rec = mHistoryCache; if (rec != null) { @@ -4026,6 +4044,7 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(rec); } + @GuardedBy("this") void addHistoryRecordLocked(HistoryItem rec) { mNumHistoryItems++; rec.next = null; @@ -4038,6 +4057,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") void clearHistoryLocked() { if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!"); mHistoryBaseTimeMs = 0; @@ -4100,6 +4120,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void updateBatteryPropertiesLocked() { try { IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface( @@ -4112,11 +4133,14 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void addIsolatedUidLocked(int isolatedUid, int appUid) { addIsolatedUidLocked(isolatedUid, appUid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") + @SuppressWarnings("GuardedBy") // errorprone false positive on u.addIsolatedUid public void addIsolatedUidLocked(int isolatedUid, int appUid, long elapsedRealtimeMs, long uptimeMs) { mIsolatedUids.put(isolatedUid, appUid); @@ -4191,10 +4215,12 @@ public class BatteryStatsImpl extends BatteryStats { return isolated > 0 ? isolated : uid; } + @GuardedBy("this") public void noteEventLocked(int code, String name, int uid) { noteEventLocked(code, name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteEventLocked(int code, String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); @@ -4204,6 +4230,7 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid); } + @GuardedBy("this") public void noteCurrentTimeChangedLocked() { final long currentTime = mClock.currentTimeMillis(); final long elapsedRealtime = mClock.elapsedRealtime(); @@ -4211,15 +4238,18 @@ public class BatteryStatsImpl extends BatteryStats { noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime); } + @GuardedBy("this") public void noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs) { recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") public void noteProcessStartLocked(String name, int uid) { noteProcessStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteProcessStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); @@ -4236,10 +4266,12 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid); } + @GuardedBy("this") public void noteProcessCrashLocked(String name, int uid) { noteProcessCrashLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteProcessCrashLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); @@ -4249,10 +4281,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteProcessAnrLocked(String name, int uid) { noteProcessAnrLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (isOnBattery()) { @@ -4261,10 +4295,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteUidProcessStateLocked(int uid, int state) { noteUidProcessStateLocked(uid, state, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") + @SuppressWarnings("GuardedBy") // errorprone false positive on u.updateUidProcessStateLocked public void noteUidProcessStateLocked(int uid, int state, long elapsedRealtimeMs, long uptimeMs) { int parentUid = mapUid(uid); @@ -4282,10 +4319,12 @@ public class BatteryStatsImpl extends BatteryStats { .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") public void noteProcessFinishLocked(String name, int uid) { noteProcessFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteProcessFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); @@ -4299,10 +4338,12 @@ public class BatteryStatsImpl extends BatteryStats { name, uid); } + @GuardedBy("this") public void noteSyncStartLocked(String name, int uid) { noteSyncStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -4313,10 +4354,12 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid); } + @GuardedBy("this") public void noteSyncFinishLocked(String name, int uid) { noteSyncFinishLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -4328,10 +4371,12 @@ public class BatteryStatsImpl extends BatteryStats { name, uid); } + @GuardedBy("this") public void noteJobStartLocked(String name, int uid) { noteJobStartLocked(name, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -4342,11 +4387,13 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid); } + @GuardedBy("this") public void noteJobFinishLocked(String name, int uid, int stopReason) { noteJobFinishLocked(name, uid, stopReason, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteJobFinishLocked(String name, int uid, int stopReason, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); @@ -4358,11 +4405,13 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid); } + @GuardedBy("this") public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) { noteJobsDeferredLocked(uid, numDeferred, sinceLast, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); @@ -4370,34 +4419,33 @@ public class BatteryStatsImpl extends BatteryStats { .noteJobsDeferredLocked(numDeferred, sinceLast); } + @GuardedBy("this") public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) { noteAlarmStartLocked(name, workSource, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteAlarmStartLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs) { noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid, elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) { noteAlarmFinishLocked(name, workSource, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs) { noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid, elapsedRealtimeMs, uptimeMs); } - private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, - int uid) { - noteAlarmStartOrFinishLocked(historyItem, name, workSource, uid, - mClock.elapsedRealtime(), mClock.uptimeMillis()); - } - + @GuardedBy("this") private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid, long elapsedRealtimeMs, long uptimeMs) { if (!mRecordAllHistory) { @@ -4430,12 +4478,14 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag) { noteWakupAlarmLocked(packageName, uid, workSource, tag, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag, long elapsedRealtimeMs, long uptimeMs) { if (workSource != null) { @@ -4481,6 +4531,7 @@ public class BatteryStatsImpl extends BatteryStats { mExternalSync.scheduleCpuSyncDueToWakelockChange(0 /* delayMillis */); } + @GuardedBy("this") public void setRecordAllHistoryLocked(boolean enabled) { mRecordAllHistory = enabled; if (!enabled) { @@ -4524,6 +4575,7 @@ public class BatteryStatsImpl extends BatteryStats { mNoAutoReset = enabled; } + @GuardedBy("this") public void setPretendScreenOff(boolean pretendScreenOff) { if (mPretendScreenOff != pretendScreenOff) { mPretendScreenOff = pretendScreenOff; @@ -4537,12 +4589,14 @@ public class BatteryStatsImpl extends BatteryStats { private String mInitialAcquireWakeName; private int mInitialAcquireWakeUid = -1; + @GuardedBy("this") public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging) { noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) { final int mappedUid = mapUid(uid); @@ -4613,12 +4667,14 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type) { noteStopWakeLocked(uid, pid, wc, name, historyName, type, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs) { final int mappedUid = mapUid(uid); @@ -4701,12 +4757,14 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging) { noteStartWakeFromSourceLocked(ws, pid, name, historyName, type, unimportantForLogging, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) { @@ -4726,6 +4784,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") 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) { @@ -4734,6 +4793,7 @@ public class BatteryStatsImpl extends BatteryStats { mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") 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, @@ -4780,12 +4840,14 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type) { noteStopWakeFromSourceLocked(ws, pid, name, historyName, type, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); @@ -4804,23 +4866,27 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteLongPartialWakelockStart(String name, String historyName, int uid) { noteLongPartialWakelockStart(name, historyName, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") public void noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource) { noteLongPartialWakelockStartFromSource(name, historyName, workSource, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) { final int N = workSource.size(); @@ -4841,6 +4907,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { if (historyName == null) { @@ -4854,23 +4921,27 @@ public class BatteryStatsImpl extends BatteryStats { historyName, uid); } + @GuardedBy("this") public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { noteLongPartialWakelockFinish(name, historyName, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") public void noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource) { noteLongPartialWakelockFinishFromSource(name, historyName, workSource, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) { final int N = workSource.size(); @@ -4891,6 +4962,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { if (historyName == null) { @@ -4904,6 +4976,7 @@ public class BatteryStatsImpl extends BatteryStats { historyName, uid); } + @GuardedBy("this") void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) { if (mLastWakeupReason != null) { long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs; @@ -4915,10 +4988,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWakeupReasonLocked(String reason) { noteWakeupReasonLocked(reason, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) { if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": " + Integer.toHexString(mHistoryCur.states)); @@ -4931,11 +5006,13 @@ public class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") public boolean startAddingCpuLocked() { mExternalSync.cancelCpuSyncDueToWakelockChange(); return mOnBatteryInternal; } + @GuardedBy("this") public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, int statSoftIrqTimeMs, int statIdleTimeMs) { @@ -4985,10 +5062,12 @@ public class BatteryStatsImpl extends BatteryStats { int mSensorNesting; + @GuardedBy("this") public void noteStartSensorLocked(int uid, int sensor) { noteStartSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mSensorNesting == 0) { @@ -5002,10 +5081,12 @@ public class BatteryStatsImpl extends BatteryStats { .noteStartSensor(sensor, elapsedRealtimeMs); } + @GuardedBy("this") public void noteStopSensorLocked(int uid, int sensor) { noteStopSensorLocked(uid, sensor, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); mSensorNesting--; @@ -5021,10 +5102,12 @@ public class BatteryStatsImpl extends BatteryStats { int mGpsNesting; + @GuardedBy("this") public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) { noteGpsChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs) { for (int i = 0; i < newWs.size(); ++i) { @@ -5053,6 +5136,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void noteStartGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); @@ -5076,6 +5160,7 @@ public class BatteryStatsImpl extends BatteryStats { getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs); } + @GuardedBy("this") private void noteStopGpsLocked(int uid, WorkChain workChain, long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); @@ -5100,10 +5185,12 @@ public class BatteryStatsImpl extends BatteryStats { getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs); } + @GuardedBy("this") public void noteGpsSignalQualityLocked(int signalLevel) { noteGpsSignalQualityLocked(signalLevel, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) { if (mGpsNesting == 0) { return; @@ -5372,6 +5459,7 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteScreenBrightnessLocked(int brightness) { noteScreenBrightnessLocked(0, brightness); } @@ -5379,6 +5467,7 @@ public class BatteryStatsImpl extends BatteryStats { /** * Note screen brightness change for a display. */ + @GuardedBy("this") public void noteScreenBrightnessLocked(int display, int brightness) { noteScreenBrightnessLocked(display, brightness, mClock.elapsedRealtime(), mClock.uptimeMillis()); @@ -5388,6 +5477,7 @@ public class BatteryStatsImpl extends BatteryStats { /** * Note screen brightness change for a display. */ + @GuardedBy("this") public void noteScreenBrightnessLocked(int display, int brightness, long elapsedRealtimeMs, long uptimeMs) { // Bin the brightness. @@ -5425,6 +5515,7 @@ public class BatteryStatsImpl extends BatteryStats { maybeUpdateOverallScreenBrightness(overallBin, elapsedRealtimeMs, uptimeMs); } + @GuardedBy("this") private int evaluateOverallScreenBrightnessBinLocked() { int overallBin = -1; final int numDisplays = getDisplayCount(); @@ -5442,6 +5533,7 @@ public class BatteryStatsImpl extends BatteryStats { return overallBin; } + @GuardedBy("this") private void maybeUpdateOverallScreenBrightness(int overallBin, long elapsedRealtimeMs, long uptimeMs) { if (mScreenBrightnessBin != overallBin) { @@ -5469,10 +5561,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteUserActivityLocked(int uid, int event) { noteUserActivityLocked(uid, event, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) { if (mOnBatteryInternal) { uid = mapUid(uid); @@ -5480,20 +5574,24 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWakeUpLocked(String reason, int reasonUid) { noteWakeUpLocked(reason, reasonUid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs) { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason, reasonUid); } + @GuardedBy("this") public void noteInteractiveLocked(boolean interactive) { noteInteractiveLocked(interactive, mClock.elapsedRealtime()); } + @GuardedBy("this") public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) { if (mInteractive != interactive) { mInteractive = interactive; @@ -5506,11 +5604,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteConnectivityChangedLocked(int type, String extra) { noteConnectivityChangedLocked(type, extra, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs) { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED, @@ -5518,6 +5618,7 @@ public class BatteryStatsImpl extends BatteryStats { mNumConnectivityChange++; } + @GuardedBy("this") private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid) { uid = mapUid(uid); @@ -5529,11 +5630,13 @@ public class BatteryStatsImpl extends BatteryStats { /** * Updates the radio power state and returns true if an external stats collection should occur. */ + @GuardedBy("this") public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) { return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs) { if (mMobileRadioPowerState != powerState) { @@ -5578,6 +5681,7 @@ public class BatteryStatsImpl extends BatteryStats { return false; } + @GuardedBy("this") public void notePowerSaveModeLocked(boolean enabled) { notePowerSaveModeLocked(enabled, mClock.elapsedRealtime(), mClock.uptimeMillis()); } @@ -5585,6 +5689,7 @@ public class BatteryStatsImpl extends BatteryStats { /** * Toggles the power save mode state. */ + @GuardedBy("this") public void notePowerSaveModeLockedInit(boolean enabled, long elapsedRealtimeMs, long uptimeMs) { if (mPowerSaveModeEnabled != enabled) { @@ -5599,6 +5704,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) { if (mPowerSaveModeEnabled != enabled) { int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0; @@ -5624,11 +5730,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) { noteDeviceIdleModeLocked(mode, activeReason, activeUid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, long elapsedRealtimeMs, long uptimeMs) { boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP; @@ -5702,11 +5810,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void notePackageInstalledLocked(String pkgName, long versionCode) { notePackageInstalledLocked(pkgName, versionCode, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs) { // XXX need to figure out what to do with long version codes. @@ -5719,10 +5829,12 @@ public class BatteryStatsImpl extends BatteryStats { addPackageChange(pc); } + @GuardedBy("this") public void notePackageUninstalledLocked(String pkgName) { notePackageUninstalledLocked(pkgName, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs) { addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, @@ -5740,10 +5852,12 @@ public class BatteryStatsImpl extends BatteryStats { mDailyPackageChanges.add(pc); } + @GuardedBy("this") void stopAllGpsSignalQualityTimersLocked(int except) { stopAllGpsSignalQualityTimersLocked(except, mClock.elapsedRealtime()); } + @GuardedBy("this") void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) { for (int i = 0; i < mGpsSignalQualityTimer.length; i++) { if (i == except) { @@ -5756,10 +5870,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void notePhoneOnLocked() { notePhoneOnLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) { if (!mPhoneOn) { mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG; @@ -5772,10 +5888,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void notePhoneOffLocked() { notePhoneOffLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) { if (mPhoneOn) { mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG; @@ -5787,6 +5905,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void registerUsbStateReceiver(Context context) { final IntentFilter usbStateFilter = new IntentFilter(); usbStateFilter.addAction(UsbManager.ACTION_USB_STATE); @@ -5811,6 +5930,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, long uptimeMs) { int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED; @@ -5825,6 +5945,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) { for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) { if (i == except) { @@ -5849,6 +5970,7 @@ public class BatteryStatsImpl extends BatteryStats { return state; } + @GuardedBy("this") private void updateAllPhoneStateLocked(int state, int simState, int strengthBin, long elapsedRealtimeMs, long uptimeMs) { boolean scanning = false; @@ -5945,10 +6067,12 @@ public class BatteryStatsImpl extends BatteryStats { * Telephony stack updates the phone state. * @param state phone state from ServiceState.getState() */ + @GuardedBy("this") public void notePhoneStateLocked(int state, int simState) { notePhoneStateLocked(state, simState, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void notePhoneStateLocked(int state, int simState, long elapsedRealtimeMs, long uptimeMs) { updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw, @@ -5956,11 +6080,13 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) { notePhoneSignalStrengthLocked(signalStrength, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void notePhoneSignalStrengthLocked(SignalStrength signalStrength, long elapsedRealtimeMs, long uptimeMs) { // Bin the strength. @@ -5970,11 +6096,13 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) { notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType, long elapsedRealtimeMs, long uptimeMs) { // BatteryStats uses 0 to represent no network type. @@ -6014,10 +6142,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiOnLocked() { noteWifiOnLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) { if (!mWifiOn) { mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG; @@ -6030,10 +6160,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiOffLocked() { noteWifiOffLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) { if (mWifiOn) { mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG; @@ -6047,10 +6179,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteAudioOnLocked(int uid) { noteAudioOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mAudioOnNesting == 0) { @@ -6066,10 +6200,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteAudioOffLocked(int uid) { noteAudioOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mAudioOnNesting == 0) { return; @@ -6087,10 +6223,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteVideoOnLocked(int uid) { noteVideoOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mVideoOnNesting == 0) { @@ -6106,10 +6244,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteVideoOffLocked(int uid) { noteVideoOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mVideoOnNesting == 0) { return; @@ -6126,10 +6266,12 @@ public class BatteryStatsImpl extends BatteryStats { .noteVideoTurnedOffLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteResetAudioLocked() { noteResetAudioLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) { if (mAudioOnNesting > 0) { mAudioOnNesting = 0; @@ -6145,10 +6287,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteResetVideoLocked() { noteResetVideoLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) { if (mVideoOnNesting > 0) { mVideoOnNesting = 0; @@ -6164,31 +6308,37 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteActivityResumedLocked(int uid) { noteActivityResumedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteActivityResumedLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteActivityPausedLocked(int uid) { noteActivityPausedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteActivityPausedLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteVibratorOnLocked(int uid, long durationMillis) { noteVibratorOnLocked(uid, durationMillis, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteVibratorOnLocked(int uid, long durationMillis, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); @@ -6196,20 +6346,24 @@ public class BatteryStatsImpl extends BatteryStats { .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs); } + @GuardedBy("this") public void noteVibratorOffLocked(int uid) { noteVibratorOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteVibratorOffLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteFlashlightOnLocked(int uid) { noteFlashlightOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mFlashlightOnNesting++ == 0) { @@ -6223,10 +6377,12 @@ public class BatteryStatsImpl extends BatteryStats { .noteFlashlightTurnedOnLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteFlashlightOffLocked(int uid) { noteFlashlightOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mFlashlightOnNesting == 0) { return; @@ -6243,10 +6399,12 @@ public class BatteryStatsImpl extends BatteryStats { .noteFlashlightTurnedOffLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteCameraOnLocked(int uid) { noteCameraOnLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mCameraOnNesting++ == 0) { @@ -6260,10 +6418,12 @@ public class BatteryStatsImpl extends BatteryStats { .noteCameraTurnedOnLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteCameraOffLocked(int uid) { noteCameraOffLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mCameraOnNesting == 0) { return; @@ -6280,10 +6440,12 @@ public class BatteryStatsImpl extends BatteryStats { .noteCameraTurnedOffLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteResetCameraLocked() { noteResetCameraLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) { if (mCameraOnNesting > 0) { mCameraOnNesting = 0; @@ -6299,10 +6461,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteResetFlashlightLocked() { noteResetFlashlightLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) { if (mFlashlightOnNesting > 0) { mFlashlightOnNesting = 0; @@ -6318,6 +6482,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); @@ -6333,11 +6498,13 @@ public class BatteryStatsImpl extends BatteryStats { .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized); } + @GuardedBy("this") public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) { noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); @@ -6355,6 +6522,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); @@ -6378,11 +6546,13 @@ public class BatteryStatsImpl extends BatteryStats { return mapUid(uid); } + @GuardedBy("this") public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) { noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); @@ -6400,10 +6570,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteResetBluetoothScanLocked() { noteResetBluetoothScanLocked(mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) { if (mBluetoothScanNesting > 0) { mBluetoothScanNesting = 0; @@ -6419,11 +6591,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) { noteBluetoothScanResultsFromSourceLocked(ws, numNewResults, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); @@ -6444,6 +6618,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid) { uid = mapUid(uid); @@ -6452,11 +6627,13 @@ public class BatteryStatsImpl extends BatteryStats { getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked(); } + @GuardedBy("this") public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) { noteWifiRadioPowerState(powerState, timestampNs, uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid, long elapsedRealtimeMs, long uptimeMs) { if (mWifiRadioPowerState != powerState) { @@ -6480,10 +6657,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiRunningLocked(WorkSource ws) { noteWifiRunningLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { if (!mGlobalWifiRunning) { mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG; @@ -6514,11 +6693,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) { noteWifiRunningChangedLocked(oldWs, newWs, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, long elapsedRealtimeMs, long uptimeMs) { if (mGlobalWifiRunning) { @@ -6558,10 +6739,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiStoppedLocked(WorkSource ws) { noteWifiStoppedLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { if (mGlobalWifiRunning) { mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG; @@ -6592,10 +6775,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiStateLocked(int wifiState, String accessPoint) { noteWifiStateLocked(wifiState, accessPoint, mClock.elapsedRealtime()); } + @GuardedBy("this") public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) { if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState); if (mWifiState != wifiState) { @@ -6608,11 +6793,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) { noteWifiSupplicantStateChangedLocked(supplState, failedAuth, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, long elapsedRealtimeMs, long uptimeMs) { if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState); @@ -6631,6 +6818,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) { for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { if (i == except) { @@ -6642,10 +6830,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiRssiChangedLocked(int newRssi) { noteWifiRssiChangedLocked(newRssi, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) { int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS); if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin); @@ -6674,10 +6864,12 @@ public class BatteryStatsImpl extends BatteryStats { int mWifiFullLockNesting = 0; @UnsupportedAppUsage + @GuardedBy("this") public void noteFullWifiLockAcquiredLocked(int uid) { noteFullWifiLockAcquiredLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mWifiFullLockNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG; @@ -6691,10 +6883,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteFullWifiLockReleasedLocked(int uid) { noteFullWifiLockReleasedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { mWifiFullLockNesting--; if (mWifiFullLockNesting == 0) { @@ -6709,10 +6903,12 @@ public class BatteryStatsImpl extends BatteryStats { int mWifiScanNesting = 0; + @GuardedBy("this") public void noteWifiScanStartedLocked(int uid) { noteWifiScanStartedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mWifiScanNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG; @@ -6725,10 +6921,12 @@ public class BatteryStatsImpl extends BatteryStats { .noteWifiScanStartedLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteWifiScanStoppedLocked(int uid) { noteWifiScanStoppedLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { mWifiScanNesting--; if (mWifiScanNesting == 0) { @@ -6765,11 +6963,13 @@ public class BatteryStatsImpl extends BatteryStats { int mWifiMulticastNesting = 0; + @GuardedBy("this") @UnsupportedAppUsage public void noteWifiMulticastEnabledLocked(int uid) { noteWifiMulticastEnabledLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mWifiMulticastNesting == 0) { @@ -6790,10 +6990,12 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void noteWifiMulticastDisabledLocked(int uid) { noteWifiMulticastDisabledLocked(uid, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); mWifiMulticastNesting--; @@ -6813,11 +7015,13 @@ public class BatteryStatsImpl extends BatteryStats { .noteWifiMulticastDisabledLocked(elapsedRealtimeMs); } + @GuardedBy("this") public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) { noteFullWifiLockAcquiredFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); @@ -6836,11 +7040,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) { noteFullWifiLockReleasedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); @@ -6859,10 +7065,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiScanStartedFromSourceLocked(WorkSource ws) { noteWifiScanStartedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiScanStartedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); @@ -6881,10 +7089,12 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) { noteWifiScanStoppedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); @@ -6903,11 +7113,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) { noteWifiBatchedScanStartedFromSourceLocked(ws, csph, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + @GuardedBy("this") public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); @@ -6924,10 +7136,13 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) { noteWifiBatchedScanStoppedFromSourceLocked(ws, mClock.elapsedRealtime(), mClock.uptimeMillis()); } + + @GuardedBy("this") public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); @@ -7454,36 +7669,43 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") @Override public long getBluetoothMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH); } + @GuardedBy("this") @Override public long getCpuMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU); } + @GuardedBy("this") @Override public long getGnssMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS); } + @GuardedBy("this") @Override public long getMobileRadioMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO); } + @GuardedBy("this") @Override public long getScreenOnMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON); } + @GuardedBy("this") @Override public long getScreenDozeMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE); } + @GuardedBy("this") @Override public long getWifiMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI); @@ -7496,6 +7718,7 @@ public class BatteryStatsImpl extends BatteryStats { * @param bucket standard power bucket of interest * @return charge (in microcoulombs) used for this power bucket */ + @GuardedBy("this") private long getPowerBucketConsumptionUC(@StandardPowerBucket int bucket) { if (mGlobalMeasuredEnergyStats == null) { return POWER_DATA_UNAVAILABLE; @@ -7503,6 +7726,7 @@ public class BatteryStatsImpl extends BatteryStats { return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket); } + @GuardedBy("this") @Override public @Nullable long[] getCustomConsumerMeasuredBatteryConsumptionUC() { if (mGlobalMeasuredEnergyStats == null) { @@ -7514,12 +7738,13 @@ public class BatteryStatsImpl extends BatteryStats { /** * Returns the names of custom power components. */ + @GuardedBy("this") @Override public @NonNull String[] getCustomEnergyConsumerNames() { - if (mGlobalMeasuredEnergyStats == null) { + if (mMeasuredEnergyStatsConfig == null) { return new String[0]; } - final String[] names = mGlobalMeasuredEnergyStats.getCustomBucketNames(); + final String[] names = mMeasuredEnergyStatsConfig.getCustomBucketNames(); for (int i = 0; i < names.length; i++) { if (TextUtils.isEmpty(names[i])) { names[i] = "CUSTOM_" + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i; @@ -7528,6 +7753,7 @@ public class BatteryStatsImpl extends BatteryStats { return names; } + @GuardedBy("this") @Override public long getStartClockTime() { final long currentTimeMs = mClock.currentTimeMillis(); if ((currentTimeMs > MILLISECONDS_IN_YEAR @@ -7954,11 +8180,18 @@ public class BatteryStatsImpl extends BatteryStats { mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length]; } + @GuardedBy("mBsi") @VisibleForTesting public void setProcessStateForTest(int procState, long elapsedTimeMs) { mProcessState = procState; getProcStateTimeCounter().setState(procState, elapsedTimeMs); getProcStateScreenOffTimeCounter().setState(procState, elapsedTimeMs); + final MeasuredEnergyStats energyStats = + getOrCreateMeasuredEnergyStatsIfSupportedLocked(); + if (energyStats != null) { + energyStats.setState(mapUidProcessStateToBatteryConsumerProcessState(procState), + elapsedTimeMs); + } } @Override @@ -7981,6 +8214,7 @@ public class BatteryStatsImpl extends BatteryStats { return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED); } + @GuardedBy("mBsi") @Override public long[] getCpuFreqTimes(int which, int procState) { if (procState < 0 || procState >= NUM_PROCESS_STATE) { @@ -7997,6 +8231,7 @@ public class BatteryStatsImpl extends BatteryStats { return mProcStateTimeMs.getCountsLocked(which, procState); } + @GuardedBy("mBsi") @Override public long[] getScreenOffCpuFreqTimes(int which, int procState) { if (procState < 0 || procState >= NUM_PROCESS_STATE) { @@ -8026,6 +8261,7 @@ public class BatteryStatsImpl extends BatteryStats { return mProportionalSystemServiceUsage; } + @GuardedBy("mBsi") public void addIsolatedUid(int isolatedUid) { if (mChildUids == null) { mChildUids = new SparseArray<>(); @@ -8312,23 +8548,37 @@ public class BatteryStatsImpl extends BatteryStats { return mModemControllerActivity; } + @GuardedBy("mBsi") private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsLocked() { if (mUidMeasuredEnergyStats == null) { - mUidMeasuredEnergyStats = - MeasuredEnergyStats.createFromTemplate(mBsi.mGlobalMeasuredEnergyStats); + mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig); + } + return mUidMeasuredEnergyStats; + } + + @GuardedBy("mBsi") + private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsIfSupportedLocked() { + if (mUidMeasuredEnergyStats == null && mBsi.mMeasuredEnergyStatsConfig != null) { + mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig); } return mUidMeasuredEnergyStats; } /** Adds the given charge to the given standard power bucket for this uid. */ + @GuardedBy("mBsi") private void addChargeToStandardBucketLocked(long chargeDeltaUC, @StandardPowerBucket int powerBucket) { - getOrCreateMeasuredEnergyStatsLocked().updateStandardBucket(powerBucket, chargeDeltaUC); + final MeasuredEnergyStats measuredEnergyStats = + getOrCreateMeasuredEnergyStatsLocked(); + measuredEnergyStats.updateStandardBucket(powerBucket, chargeDeltaUC, + mBsi.mClock.elapsedRealtime()); } /** Adds the given charge to the given custom power bucket for this uid. */ + @GuardedBy("mBsi") private void addChargeToCustomBucketLocked(long chargeDeltaUC, int powerBucket) { - getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC); + getOrCreateMeasuredEnergyStatsLocked().updateCustomBucket(powerBucket, chargeDeltaUC, + mBsi.mClock.elapsedRealtime()); } /** @@ -8337,6 +8587,7 @@ public class BatteryStatsImpl extends BatteryStats { * @param bucket standard power bucket of interest * @return consumption (in microcolombs) used by this uid for this power bucket */ + @GuardedBy("mBsi") public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket) { if (mBsi.mGlobalMeasuredEnergyStats == null || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) { @@ -8348,6 +8599,7 @@ public class BatteryStatsImpl extends BatteryStats { return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket); } + @GuardedBy("mBsi") @Override public long[] getCustomConsumerMeasuredBatteryConsumptionUC() { if (mBsi.mGlobalMeasuredEnergyStats == null) { @@ -8360,31 +8612,37 @@ public class BatteryStatsImpl extends BatteryStats { return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges(); } + @GuardedBy("mBsi") @Override public long getBluetoothMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH); } + @GuardedBy("mBsi") @Override public long getCpuMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU); } + @GuardedBy("mBsi") @Override public long getGnssMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS); } + @GuardedBy("mBsi") @Override public long getMobileRadioMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO); } + @GuardedBy("mBsi") @Override public long getScreenOnMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON); } + @GuardedBy("mBsi") @Override public long getWifiMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI); @@ -9678,6 +9936,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("mBsi") void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) { mOnBatteryBackgroundTimeBase.readFromParcel(in); mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in); @@ -9917,7 +10176,8 @@ public class BatteryStatsImpl extends BatteryStats { } if (in.readInt() != 0) { - mUidMeasuredEnergyStats = new MeasuredEnergyStats(in); + mUidMeasuredEnergyStats = new MeasuredEnergyStats(mBsi.mMeasuredEnergyStatsConfig, + in); } mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in); @@ -10801,6 +11061,7 @@ public class BatteryStatsImpl extends BatteryStats { mBsi.mClock.elapsedRealtime(), mBsi.mClock.uptimeMillis()); } + @GuardedBy("mBsi") public void updateUidProcessStateLocked(int procState, long elapsedRealtimeMs, long uptimeMs) { int uidRunningState; @@ -10845,6 +11106,14 @@ public class BatteryStatsImpl extends BatteryStats { updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000); updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000); + + final MeasuredEnergyStats energyStats = + getOrCreateMeasuredEnergyStatsIfSupportedLocked(); + if (energyStats != null) { + energyStats.setState( + mapUidProcessStateToBatteryConsumerProcessState(mProcessState), + elapsedRealtimeMs); + } } if (userAwareService != mInForegroundService) { @@ -11485,6 +11754,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void readDailyStatsLocked() { Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile()); mDailyItems.clear(); @@ -11659,6 +11929,7 @@ public class BatteryStatsImpl extends BatteryStats { return mNextMaxDailyDeadlineMs; } + @GuardedBy("this") public int getHistoryTotalSize() { return mConstants.MAX_HISTORY_BUFFER * mConstants.MAX_HISTORY_FILES; } @@ -11779,6 +12050,7 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryResetListener = batteryResetListener; } + @GuardedBy("this") public void resetAllStatsCmdLocked() { final long mSecUptime = mClock.uptimeMillis(); long uptimeUs = mSecUptime * 1000; @@ -11813,6 +12085,7 @@ public class BatteryStatsImpl extends BatteryStats { initActiveHistoryEventsLocked(mSecRealtime, mSecUptime); } + @GuardedBy("this") private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis, int resetReason) { if (mBatteryResetListener != null) { @@ -11971,6 +12244,7 @@ public class BatteryStatsImpl extends BatteryStats { mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS); } + @GuardedBy("this") private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) { for (int i=0; iAll uids in ratioNumerators must exist in mUidStats already. */ + @GuardedBy("this") + @SuppressWarnings("GuardedBy") // errorprone false positive on u.addChargeToStandardBucketLocked private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket, long totalConsumedChargeUC, SparseDoubleArray ratioNumerators, double minRatioDenominator) { @@ -14256,6 +14545,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs, boolean reset) { mRecordingHistory = true; @@ -14269,6 +14559,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void recordCurrentTimeChangeLocked(final long currentTimeMs, final long elapsedRealtimeMs, final long uptimeMs) { if (mRecordingHistory) { @@ -14278,6 +14569,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) { if (mRecordingHistory) { mHistoryCur.currentTime = currentTimeMs; @@ -14304,6 +14596,7 @@ public class BatteryStatsImpl extends BatteryStats { mClock.elapsedRealtime(), mClock.uptimeMillis(), mClock.currentTimeMillis()); } + @GuardedBy("this") public void setBatteryStateLocked(final int status, final int health, final int plugType, final int level, /* not final */ int temp, final int voltageMv, final int chargeUah, final int chargeFullUah, final long chargeTimeToFullSeconds, @@ -14987,6 +15280,7 @@ public class BatteryStatsImpl extends BatteryStats { return u; } + @GuardedBy("this") public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) { final int firstUidForUser = UserHandle.getUid(userId, 0); final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1); @@ -14994,6 +15288,7 @@ public class BatteryStatsImpl extends BatteryStats { new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs)); } + @GuardedBy("this") public void onUserRemovedLocked(int userId) { if (mExternalSync != null) { // Clear out the removed user's UIDs after a short delay. The delay is needed @@ -15006,6 +15301,7 @@ public class BatteryStatsImpl extends BatteryStats { /** * Removes battery stats for UIDs corresponding to a removed user. */ + @GuardedBy("this") public void clearRemovedUserUidsLocked(int userId) { final int firstUidForUser = UserHandle.getUid(userId, 0); final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1); @@ -15027,6 +15323,7 @@ public class BatteryStatsImpl extends BatteryStats { * Remove the statistics object for a particular uid. */ @UnsupportedAppUsage + @GuardedBy("this") public void removeUidStatsLocked(int uid) { removeUidStatsLocked(uid, mClock.elapsedRealtime()); } @@ -15034,6 +15331,7 @@ public class BatteryStatsImpl extends BatteryStats { /** * @see #removeUidStatsLocked(int) */ + @GuardedBy("this") public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) { final Uid u = mUidStats.get(uid); if (u != null) { @@ -15131,21 +15429,25 @@ public class BatteryStatsImpl extends BatteryStats { return u.getServiceStatsLocked(pkg, name); } + @GuardedBy("this") public void shutdownLocked() { recordShutdownLocked(mClock.currentTimeMillis(), mClock.elapsedRealtime()); writeSyncLocked(); mShuttingDown = true; } + @GuardedBy("this") @Override public boolean isProcessStateDataAvailable() { return trackPerProcStateCpuTimes(); } + @GuardedBy("this") public boolean trackPerProcStateCpuTimes() { return mConstants.TRACK_CPU_TIMES_BY_PROC_STATE && mPerProcStateCpuTimesAvailable; } + @GuardedBy("this") public void systemServicesReady(Context context) { mConstants.startObserving(context.getContentResolver()); registerUsbStateReceiver(context); @@ -15162,28 +15464,28 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void initMeasuredEnergyStatsLocked(@Nullable boolean[] supportedStandardBuckets, String[] customBucketNames) { - boolean supportedBucketMismatch = false; - final int numDisplays = mPerDisplayBatteryStats.length; for (int i = 0; i < numDisplays; i++) { final int screenState = mPerDisplayBatteryStats[i].screenState; mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState; } - if (supportedStandardBuckets == null) { - if (mGlobalMeasuredEnergyStats != null) { - // Measured energy no longer supported, wipe out the existing data. - supportedBucketMismatch = true; - } - } else { - if (mGlobalMeasuredEnergyStats == null) { - mGlobalMeasuredEnergyStats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + final boolean compatibleConfig; + if (supportedStandardBuckets != null) { + final MeasuredEnergyStats.Config config = new MeasuredEnergyStats.Config( + supportedStandardBuckets, customBucketNames, + SUPPORTED_PER_PROCESS_STATE_STANDARD_ENERGY_BUCKETS, + getBatteryConsumerProcessStateNames()); + + if (mMeasuredEnergyStatsConfig == null) { + compatibleConfig = true; } else { - supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo( - supportedStandardBuckets, customBucketNames); + compatibleConfig = mMeasuredEnergyStatsConfig.isCompatible(config); } + mMeasuredEnergyStatsConfig = config; + mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(config); + if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH]) { mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile); } @@ -15196,11 +15498,14 @@ public class BatteryStatsImpl extends BatteryStats { if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_WIFI]) { mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile); } + } else { + compatibleConfig = (mMeasuredEnergyStatsConfig == null); + // Measured energy no longer supported, wipe out the existing data. + mMeasuredEnergyStatsConfig = null; + mGlobalMeasuredEnergyStats = null; } - if (supportedBucketMismatch) { - mGlobalMeasuredEnergyStats = supportedStandardBuckets == null - ? null : new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + if (!compatibleConfig) { // Supported power buckets changed since last boot. // Existing data is no longer reliable. resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(), @@ -15208,6 +15513,16 @@ public class BatteryStatsImpl extends BatteryStats { } } + @NonNull + private static String[] getBatteryConsumerProcessStateNames() { + String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT]; + for (int procState = 0; procState < BatteryConsumer.PROCESS_STATE_COUNT; procState++) { + procStateNames[procState] = BatteryConsumer.processStateToString(procState); + } + procStateNames[BatteryConsumer.PROCESS_STATE_ANY] = "untracked"; + return procStateNames; + } + /** Get the last known Battery voltage (in millivolts), returns -1 if unknown */ @GuardedBy("this") public int getBatteryVoltageMvLocked() { @@ -15373,6 +15688,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("BatteryStatsImpl.this") private void updateProcStateCpuTimesReadDelayMs(long oldDelayMillis, long newDelayMillis) { PROC_STATE_CPU_TIMES_READ_DELAY_MS = newDelayMillis; if (oldDelayMillis != newDelayMillis) { @@ -15393,6 +15709,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("BatteryStatsImpl.this") private void updateUidRemoveDelay(long newTimeMs) { UID_REMOVE_DELAY_MS = newTimeMs; clearPendingRemovedUidsLocked(); @@ -15530,16 +15847,19 @@ public class BatteryStatsImpl extends BatteryStats { final ReentrantLock mWriteLock = new ReentrantLock(); + @GuardedBy("this") public void writeAsyncLocked() { writeStatsLocked(false); writeHistoryLocked(false); } + @GuardedBy("this") public void writeSyncLocked() { writeStatsLocked(true); writeHistoryLocked(true); } + @GuardedBy("this") void writeStatsLocked(boolean sync) { if (mStatsFile == null) { Slog.w(TAG, @@ -15621,6 +15941,7 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage + @GuardedBy("this") public void readLocked() { if (mDailyFile != null) { readDailyStatsLocked(); @@ -15705,6 +16026,7 @@ public class BatteryStatsImpl extends BatteryStats { return 0; } + @GuardedBy("this") void readHistoryBuffer(Parcel in) throws ParcelFormatException { final int version = in.readInt(); if (version != VERSION) { @@ -15784,6 +16106,7 @@ public class BatteryStatsImpl extends BatteryStats { out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize()); } + @GuardedBy("this") public void readSummaryFromParcel(Parcel in) throws ParcelFormatException { final int version = in.readInt(); if (version != VERSION) { @@ -15870,11 +16193,14 @@ public class BatteryStatsImpl extends BatteryStats { mNextMaxDailyDeadlineMs = in.readLong(); mBatteryTimeToFullSeconds = in.readLong(); + mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in); + /** * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled * later when {@link #initMeasuredEnergyStatsLocked} is called. */ - mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in); + mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel( + mMeasuredEnergyStatsConfig, in); mStartCount++; @@ -16191,8 +16517,8 @@ public class BatteryStatsImpl extends BatteryStats { u.mWifiRadioApWakeupCount = null; } - u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in, - /* template */ mGlobalMeasuredEnergyStats); + u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel( + mMeasuredEnergyStatsConfig, in); int NW = in.readInt(); if (NW > (MAX_WAKELOCKS_PER_UID+1)) { @@ -16304,6 +16630,7 @@ public class BatteryStatsImpl extends BatteryStats { * * @param out the Parcel to be written to. */ + @GuardedBy("this") public void writeSummaryToParcel(Parcel out, boolean inclHistory) { pullPendingStateUpdatesLocked(); @@ -16377,7 +16704,8 @@ public class BatteryStatsImpl extends BatteryStats { out.writeLong(mNextMaxDailyDeadlineMs); out.writeLong(mBatteryTimeToFullSeconds); - MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out, false, false); + MeasuredEnergyStats.Config.writeToParcel(mMeasuredEnergyStatsConfig, out); + MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out); mScreenOnTimer.writeSummaryFromParcelLocked(out, nowRealtime); mScreenDozeTimer.writeSummaryFromParcelLocked(out, nowRealtime); @@ -16700,7 +17028,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } - MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out, true, true); + MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out); final ArrayMap wakeStats = u.mWakelockStats.getMap(); int NW = wakeStats.size(); @@ -16822,10 +17150,13 @@ public class BatteryStatsImpl extends BatteryStats { LongSamplingCounterArray.writeSummaryToParcelLocked(out, mBinderThreadCpuTimesUs); } + @GuardedBy("this") public void readFromParcel(Parcel in) { readFromParcelLocked(in); } + @GuardedBy("this") + @SuppressWarnings("GuardedBy") // errorprone false positive on u.readFromParcelLocked void readFromParcelLocked(Parcel in) { int magic = in.readInt(); if (magic != MAGIC) { @@ -16966,9 +17297,9 @@ public class BatteryStatsImpl extends BatteryStats { mLastWriteTimeMs = in.readLong(); mBatteryTimeToFullSeconds = in.readLong(); - if (in.readInt() != 0) { - mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(in); - } + mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in); + mGlobalMeasuredEnergyStats = + MeasuredEnergyStats.createFromParcel(mMeasuredEnergyStatsConfig, in); mRpmStats.clear(); int NRPMS = in.readInt(); @@ -17039,22 +17370,26 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < numUids; i++) { int uid = in.readInt(); Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs); - u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in); + u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, + in); mUidStats.append(uid, u); } mBinderThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase); } + @GuardedBy("this") public void writeToParcel(Parcel out, int flags) { writeToParcelLocked(out, true, flags); } + @GuardedBy("this") public void writeToParcelWithoutUids(Parcel out, int flags) { writeToParcelLocked(out, false, flags); } @SuppressWarnings("unused") + @GuardedBy("this") void writeToParcelLocked(Parcel out, boolean inclUids, int flags) { // Need to update with current kernel wake lock counts. pullPendingStateUpdatesLocked(); @@ -17170,6 +17505,8 @@ public class BatteryStatsImpl extends BatteryStats { out.writeLong(mLastWriteTimeMs); out.writeLong(mBatteryTimeToFullSeconds); + MeasuredEnergyStats.Config.writeToParcel(mMeasuredEnergyStatsConfig, out); + if (mGlobalMeasuredEnergyStats != null) { out.writeInt(1); mGlobalMeasuredEnergyStats.writeToParcel(out); @@ -17332,6 +17669,7 @@ public class BatteryStatsImpl extends BatteryStats { } }; + @GuardedBy("this") public void prepareForDumpLocked() { // Need to retrieve current kernel wake lock stats before printing. pullPendingStateUpdatesLocked(); @@ -17343,6 +17681,7 @@ public class BatteryStatsImpl extends BatteryStats { updateSystemServiceCallStats(); } + @GuardedBy("this") public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) { if (DEBUG) { pw.println("mOnBatteryTimeBase:"); diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java index 72b57ab1d468c..072376638f894 100644 --- a/core/java/com/android/internal/power/MeasuredEnergyStats.java +++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java @@ -29,6 +29,7 @@ import android.util.Slog; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.LongMultiStateCounter; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -75,6 +76,147 @@ public class MeasuredEnergyStats { public @interface StandardPowerBucket { } + private static final int INVALID_STATE = -1; + + /** + * Configuration of measured energy stats: which power rails (buckets) are supported on + * this device, what custom power drains are supported etc. + */ + public static class Config { + private final boolean[] mSupportedStandardBuckets; + @NonNull + private final String[] mCustomBucketNames; + private final boolean[] mSupportedMultiStateBuckets; + @NonNull + private final String[] mStateNames; + + public Config(@NonNull boolean[] supportedStandardBuckets, + @Nullable String[] customBucketNames, + @NonNull int[] supportedMultiStateBuckets, + @Nullable String[] stateNames) { + mSupportedStandardBuckets = supportedStandardBuckets; + mCustomBucketNames = customBucketNames != null ? customBucketNames : new String[0]; + mSupportedMultiStateBuckets = + new boolean[supportedStandardBuckets.length + mCustomBucketNames.length]; + for (int bucket : supportedMultiStateBuckets) { + if (mSupportedStandardBuckets[bucket]) { + mSupportedMultiStateBuckets[bucket] = true; + } + } + mStateNames = stateNames != null ? stateNames : new String[] {""}; + } + + /** + * Returns true if the supplied Config is compatible with this one and therefore + * data collected with one of them will work with the other. + */ + public boolean isCompatible(Config other) { + return Arrays.equals(mSupportedStandardBuckets, other.mSupportedStandardBuckets) + && Arrays.equals(mCustomBucketNames, other.mCustomBucketNames) + && Arrays.equals(mSupportedMultiStateBuckets, + other.mSupportedMultiStateBuckets) + && Arrays.equals(mStateNames, other.mStateNames); + } + + /** + * Writes the Config object into the supplied Parcel. + */ + public static void writeToParcel(@Nullable Config config, Parcel out) { + if (config == null) { + out.writeBoolean(false); + return; + } + + out.writeBoolean(true); + out.writeInt(config.mSupportedStandardBuckets.length); + out.writeBooleanArray(config.mSupportedStandardBuckets); + out.writeStringArray(config.mCustomBucketNames); + int multiStateBucketCount = 0; + for (boolean supported : config.mSupportedMultiStateBuckets) { + if (supported) { + multiStateBucketCount++; + } + } + final int[] supportedMultiStateBuckets = new int[multiStateBucketCount]; + int index = 0; + for (int bucket = 0; bucket < config.mSupportedMultiStateBuckets.length; bucket++) { + if (config.mSupportedMultiStateBuckets[bucket]) { + supportedMultiStateBuckets[index++] = bucket; + } + } + out.writeInt(multiStateBucketCount); + out.writeIntArray(supportedMultiStateBuckets); + out.writeStringArray(config.mStateNames); + } + + /** + * Reads a Config object from the supplied Parcel. + */ + @Nullable + public static Config createFromParcel(Parcel in) { + if (!in.readBoolean()) { + return null; + } + + final int supportedStandardBucketCount = in.readInt(); + final boolean[] supportedStandardBuckets = new boolean[supportedStandardBucketCount]; + in.readBooleanArray(supportedStandardBuckets); + final String[] customBucketNames = in.readStringArray(); + final int supportedMultiStateBucketCount = in.readInt(); + final int[] supportedMultiStateBuckets = new int[supportedMultiStateBucketCount]; + in.readIntArray(supportedMultiStateBuckets); + final String[] stateNames = in.readStringArray(); + return new Config(supportedStandardBuckets, customBucketNames, + supportedMultiStateBuckets, stateNames); + } + + /** Get number of possible buckets, including both standard and custom ones. */ + private int getNumberOfBuckets() { + return mSupportedStandardBuckets.length + mCustomBucketNames.length; + } + + /** + * Returns true if the specified charge bucket is tracked. + */ + public boolean isSupportedBucket(int index) { + return mSupportedStandardBuckets[index]; + } + + @NonNull + public String[] getCustomBucketNames() { + return mCustomBucketNames; + } + + /** + * Returns true if the specified charge bucket is tracked on a per-state basis. + */ + public boolean isSupportedMultiStateBucket(int index) { + return mSupportedMultiStateBuckets[index]; + } + + public String[] getStateNames() { + return mStateNames; + } + + /** + * If the index is a standard bucket, returns its name; otherwise returns its prefixed + * custom bucket number. + */ + private String getBucketName(int index) { + if (isValidStandardBucket(index)) { + return DebugUtils.valueToString(MeasuredEnergyStats.class, "POWER_BUCKET_", index); + } + final int customBucket = indexToCustomBucket(index); + StringBuilder name = new StringBuilder().append("CUSTOM_").append(customBucket); + if (!TextUtils.isEmpty(mCustomBucketNames[customBucket])) { + name.append('(').append(mCustomBucketNames[customBucket]).append(')'); + } + return name.toString(); + } + } + + private final Config mConfig; + /** * Total charge (in microcoulombs) that a power bucket (including both * {@link StandardPowerBucket} and custom buckets) has accumulated since the last reset. @@ -90,74 +232,76 @@ public class MeasuredEnergyStats { */ private final long[] mAccumulatedChargeMicroCoulomb; - private final String[] mCustomBucketNames; + private LongMultiStateCounter[] mAccumulatedMultiStateChargeMicroCoulomb; + private int mState = INVALID_STATE; + private long mStateChangeTimestampMs; /** * Creates a MeasuredEnergyStats set to support the provided power buckets. * supportedStandardBuckets must be of size {@link #NUMBER_STANDARD_POWER_BUCKETS}. * numCustomBuckets >= 0 is the number of (non-standard) custom power buckets on the device. */ - public MeasuredEnergyStats(@NonNull boolean[] supportedStandardBuckets, - @Nullable String[] customBucketNames) { - mCustomBucketNames = customBucketNames == null ? new String[0] : customBucketNames; - final int numTotalBuckets = NUMBER_STANDARD_POWER_BUCKETS + mCustomBucketNames.length; + public MeasuredEnergyStats(MeasuredEnergyStats.Config config) { + mConfig = config; + final int numTotalBuckets = config.getNumberOfBuckets(); mAccumulatedChargeMicroCoulomb = new long[numTotalBuckets]; // Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE. // All custom buckets are, by definition, supported, so their values stay at 0. for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) { - if (!supportedStandardBuckets[stdBucket]) { + if (!mConfig.mSupportedStandardBuckets[stdBucket]) { mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE; } } } /** - * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are - * supported. This certainly does NOT produce an exact clone of the template. + * Reads a MeasuredEnergyStats from the supplied Parcel. */ - private MeasuredEnergyStats(MeasuredEnergyStats template) { - final int numIndices = template.getNumberOfIndices(); - mAccumulatedChargeMicroCoulomb = new long[numIndices]; - // Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE. - // All custom buckets are, by definition, supported, so their values stay at 0. - for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) { - if (!template.isIndexSupported(stdBucket)) { - mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE; - } + @Nullable + public static MeasuredEnergyStats createFromParcel(Config config, Parcel in) { + if (!in.readBoolean()) { + return null; } - mCustomBucketNames = template.getCustomBucketNames(); - } - - /** - * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are - * supported. - */ - public static MeasuredEnergyStats createFromTemplate(MeasuredEnergyStats template) { - return new MeasuredEnergyStats(template); - } - - /** - * Constructor for creating a temp MeasuredEnergyStats. - * See {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}. - */ - private MeasuredEnergyStats(int numIndices) { - mAccumulatedChargeMicroCoulomb = new long[numIndices]; - mCustomBucketNames = new String[numIndices - NUMBER_STANDARD_POWER_BUCKETS]; + return new MeasuredEnergyStats(config, in); } /** Construct from parcel. */ - public MeasuredEnergyStats(Parcel in) { + public MeasuredEnergyStats(MeasuredEnergyStats.Config config, Parcel in) { + mConfig = config; + final int size = in.readInt(); mAccumulatedChargeMicroCoulomb = new long[size]; in.readLongArray(mAccumulatedChargeMicroCoulomb); - mCustomBucketNames = in.readStringArray(); + if (in.readBoolean()) { + mAccumulatedMultiStateChargeMicroCoulomb = new LongMultiStateCounter[size]; + for (int i = 0; i < size; i++) { + if (in.readBoolean()) { + mAccumulatedMultiStateChargeMicroCoulomb[i] = + LongMultiStateCounter.CREATOR.createFromParcel(in); + } + } + } else { + mAccumulatedMultiStateChargeMicroCoulomb = null; + } } /** Write to parcel */ public void writeToParcel(Parcel out) { out.writeInt(mAccumulatedChargeMicroCoulomb.length); out.writeLongArray(mAccumulatedChargeMicroCoulomb); - out.writeStringArray(mCustomBucketNames); + if (mAccumulatedMultiStateChargeMicroCoulomb != null) { + out.writeBoolean(true); + for (LongMultiStateCounter counter : mAccumulatedMultiStateChargeMicroCoulomb) { + if (counter != null) { + out.writeBoolean(true); + counter.writeToParcel(out, 0); + } else { + out.writeBoolean(false); + } + } + } else { + out.writeBoolean(false); + } } /** @@ -167,17 +311,27 @@ public class MeasuredEnergyStats { * Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary * parceling changes. * - * Corresponding write performed by {@link #writeSummaryToParcel(Parcel, boolean)}. + * Corresponding write performed by {@link #writeSummaryToParcel(Parcel)}. */ - private void readSummaryFromParcel(Parcel in, boolean overwriteAvailability) { + private void readSummaryFromParcel(Parcel in) { final int numWrittenEntries = in.readInt(); for (int entry = 0; entry < numWrittenEntries; entry++) { final int index = in.readInt(); final long chargeUC = in.readLong(); - if (overwriteAvailability) { - mAccumulatedChargeMicroCoulomb[index] = chargeUC; - } else { + LongMultiStateCounter multiStateCounter = null; + if (in.readBoolean()) { + multiStateCounter = LongMultiStateCounter.CREATOR.createFromParcel(in); + } + + if (index < mAccumulatedChargeMicroCoulomb.length) { setValueIfSupported(index, chargeUC); + if (multiStateCounter != null) { + if (mAccumulatedMultiStateChargeMicroCoulomb == null) { + mAccumulatedMultiStateChargeMicroCoulomb = + new LongMultiStateCounter[numWrittenEntries]; + } + mAccumulatedMultiStateChargeMicroCoulomb[index] = multiStateCounter; + } } } } @@ -186,20 +340,26 @@ public class MeasuredEnergyStats { * Write to summary parcel. * Note: Measured subsystem availability may be different when the summary parcel is read. * - * Corresponding read performed by {@link #readSummaryFromParcel(Parcel, boolean)}. + * Corresponding read performed by {@link #readSummaryFromParcel(Parcel)}. */ - private void writeSummaryToParcel(Parcel out, boolean skipZero) { + private void writeSummaryToParcel(Parcel out) { final int posOfNumWrittenEntries = out.dataPosition(); out.writeInt(0); int numWrittenEntries = 0; // Write only the supported buckets (with non-zero charge, if applicable). for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) { final long charge = mAccumulatedChargeMicroCoulomb[index]; - if (charge < 0) continue; - if (charge == 0 && skipZero) continue; + if (charge <= 0) continue; out.writeInt(index); out.writeLong(charge); + if (mAccumulatedMultiStateChargeMicroCoulomb != null + && mAccumulatedMultiStateChargeMicroCoulomb[index] != null) { + out.writeBoolean(true); + mAccumulatedMultiStateChargeMicroCoulomb[index].writeToParcel(out, 0); + } else { + out.writeBoolean(false); + } numWrittenEntries++; } final int currPos = out.dataPosition(); @@ -208,39 +368,86 @@ public class MeasuredEnergyStats { out.setDataPosition(currPos); } - /** Get number of possible buckets, including both standard and custom ones. */ - private int getNumberOfIndices() { - return mAccumulatedChargeMicroCoulomb.length; - } - - /** Updates the given standard power bucket with the given charge if accumulate is true. */ public void updateStandardBucket(@StandardPowerBucket int bucket, long chargeDeltaUC) { + updateStandardBucket(bucket, chargeDeltaUC, 0); + } + + /** + * Updates the given standard power bucket with the given charge if supported. + * @param timestampMs elapsed realtime in milliseconds + */ + public void updateStandardBucket(@StandardPowerBucket int bucket, long chargeDeltaUC, + long timestampMs) { checkValidStandardBucket(bucket); - updateEntry(bucket, chargeDeltaUC); + updateEntry(bucket, chargeDeltaUC, timestampMs); } /** Updates the given custom power bucket with the given charge if accumulate is true. */ public void updateCustomBucket(int customBucket, long chargeDeltaUC) { + updateCustomBucket(customBucket, chargeDeltaUC, 0); + } + + /** + * Updates the given custom power bucket with the given charge if supported. + * @param timestampMs elapsed realtime in milliseconds + */ + public void updateCustomBucket(int customBucket, long chargeDeltaUC, long timestampMs) { if (!isValidCustomBucket(customBucket)) { Slog.e(TAG, "Attempted to update invalid custom bucket " + customBucket); return; } final int index = customBucketToIndex(customBucket); - updateEntry(index, chargeDeltaUC); + updateEntry(index, chargeDeltaUC, timestampMs); } - /** Updates the given index with the given charge if accumulate is true. */ - private void updateEntry(int index, long chargeDeltaUC) { + /** Updates the given bucket with the given charge delta. */ + private void updateEntry(int index, long chargeDeltaUC, long timestampMs) { if (mAccumulatedChargeMicroCoulomb[index] >= 0L) { mAccumulatedChargeMicroCoulomb[index] += chargeDeltaUC; + if (mState != INVALID_STATE && mConfig.isSupportedMultiStateBucket(index)) { + if (mAccumulatedMultiStateChargeMicroCoulomb == null) { + mAccumulatedMultiStateChargeMicroCoulomb = + new LongMultiStateCounter[mAccumulatedChargeMicroCoulomb.length]; + } + LongMultiStateCounter counter = + mAccumulatedMultiStateChargeMicroCoulomb[index]; + if (counter == null) { + counter = new LongMultiStateCounter(mConfig.mStateNames.length); + mAccumulatedMultiStateChargeMicroCoulomb[index] = counter; + counter.setState(mState, mStateChangeTimestampMs); + counter.updateValue(0, mStateChangeTimestampMs); + } + counter.updateValue(mAccumulatedChargeMicroCoulomb[index], timestampMs); + } } else { Slog.wtf(TAG, "Attempting to add " + chargeDeltaUC + " to unavailable bucket " - + getBucketName(index) + " whose value was " + + mConfig.getBucketName(index) + " whose value was " + mAccumulatedChargeMicroCoulomb[index]); } } + /** + * Updates the "state" on all multi-state counters used by this MeasuredEnergyStats. Further + * accumulated charge updates will assign the deltas to this state, until the state changes. + * + * If setState is never called on a MeasuredEnergyStats object, then it does not track + * per-state usage. + */ + public void setState(int state, long timestampMs) { + mState = state; + mStateChangeTimestampMs = timestampMs; + if (mAccumulatedMultiStateChargeMicroCoulomb == null) { + return; + } + for (int i = 0; i < mAccumulatedMultiStateChargeMicroCoulomb.length; i++) { + LongMultiStateCounter counter = mAccumulatedMultiStateChargeMicroCoulomb[i]; + if (counter != null) { + counter.setState(state, timestampMs); + } + } + } + /** * Return accumulated charge (in microcouloumb) for a standard power bucket since last reset. * Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable. @@ -251,6 +458,26 @@ public class MeasuredEnergyStats { return mAccumulatedChargeMicroCoulomb[bucket]; } + /** + * Returns the accumulated charge (in microcouloumb) for the standard power bucket and + * the specified state since last reset. + * + * Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable. + */ + public long getAccumulatedStandardBucketCharge(@StandardPowerBucket int bucket, int state) { + if (!mConfig.isSupportedMultiStateBucket(bucket)) { + return POWER_DATA_UNAVAILABLE; + } + if (mAccumulatedMultiStateChargeMicroCoulomb == null) { + return 0; + } + final LongMultiStateCounter counter = mAccumulatedMultiStateChargeMicroCoulomb[bucket]; + if (counter == null) { + return 0; + } + return counter.getCount(state); + } + /** * Return accumulated charge (in microcoulomb) for the a custom power bucket since last * reset. @@ -288,32 +515,6 @@ public class MeasuredEnergyStats { return POWER_BUCKET_SCREEN_OTHER; } - /** - * Create a MeasuredEnergyStats object from a summary parcel. - * - * Corresponding write performed by - * {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean, boolean)}. - * - * @return a new MeasuredEnergyStats object as described. - * Returns null if the parcel indicates there is no data to populate. - */ - public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in) { - final int arraySize = in.readInt(); - // Check if any MeasuredEnergyStats exists on the parcel - if (arraySize == 0) return null; - - final String[] customBucketNames; - if (in.readBoolean()) { - customBucketNames = in.readStringArray(); - } else { - customBucketNames = new String[0]; - } - final MeasuredEnergyStats stats = new MeasuredEnergyStats( - new boolean[NUMBER_STANDARD_POWER_BUCKETS], customBucketNames); - stats.readSummaryFromParcel(in, true); - return stats; - } - /** * Create a MeasuredEnergyStats using the template to determine which buckets are supported, * and populate this new object from the given parcel. @@ -322,44 +523,37 @@ public class MeasuredEnergyStats { * possible (not necessarily supported) standard and custom buckets. * * Corresponding write performed by - * {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean, boolean)}. + * {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel)}. * * @return a new MeasuredEnergyStats object as described. * Returns null if the stats contain no non-0 information (such as if template is null * or if the parcel indicates there is no data to populate). - * - * @see #createFromTemplate */ - public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in, - @Nullable MeasuredEnergyStats template) { + public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel( + @Nullable Config config, Parcel in) { final int arraySize = in.readInt(); // Check if any MeasuredEnergyStats exists on the parcel if (arraySize == 0) return null; - boolean includesCustomBucketNames = in.readBoolean(); - if (includesCustomBucketNames) { - // Consume the array of custom bucket names. They are already included in the - // template. - in.readStringArray(); - } - if (template == null) { + if (config == null) { // Nothing supported anymore. Create placeholder object just to consume the parcel data. - final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize); - mes.readSummaryFromParcel(in, false); + final MeasuredEnergyStats mes = new MeasuredEnergyStats( + new Config(new boolean[arraySize], null, new int[0], new String[]{""})); + mes.readSummaryFromParcel(in); return null; } - if (arraySize != template.getNumberOfIndices()) { + if (arraySize != config.getNumberOfBuckets()) { Slog.wtf(TAG, "Size of MeasuredEnergyStats parcel (" + arraySize - + ") does not match template (" + template.getNumberOfIndices() + ")."); + + ") does not match config (" + config.getNumberOfBuckets() + ")."); // Something is horribly wrong. Just consume the parcel and return null. - final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize); - mes.readSummaryFromParcel(in, false); + final MeasuredEnergyStats mes = new MeasuredEnergyStats(config); + mes.readSummaryFromParcel(in); return null; } - final MeasuredEnergyStats stats = createFromTemplate(template); - stats.readSummaryFromParcel(in, false); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); + stats.readSummaryFromParcel(in); if (stats.containsInterestingData()) { return stats; } else { @@ -379,28 +573,20 @@ public class MeasuredEnergyStats { /** * Write a MeasuredEnergyStats to a parcel. If the stats is null, just write a 0. * - * Corresponding read performed by {@link #createAndReadSummaryFromParcel(Parcel)} - * and {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}. + * Corresponding read performed by {@link #createAndReadSummaryFromParcel}. */ - public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats, - Parcel dest, boolean skipZero, boolean skipCustomBucketNames) { + public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats, Parcel dest) { if (stats == null) { dest.writeInt(0); return; } - dest.writeInt(stats.getNumberOfIndices()); - if (!skipCustomBucketNames) { - dest.writeBoolean(true); - dest.writeStringArray(stats.getCustomBucketNames()); - } else { - dest.writeBoolean(false); - } - stats.writeSummaryToParcel(dest, skipZero); + dest.writeInt(stats.mConfig.getNumberOfBuckets()); + stats.writeSummaryToParcel(dest); } /** Reset accumulated charges. */ private void reset() { - final int numIndices = getNumberOfIndices(); + final int numIndices = mConfig.getNumberOfBuckets(); for (int index = 0; index < numIndices; index++) { setValueIfSupported(index, 0L); } @@ -431,46 +617,32 @@ public class MeasuredEnergyStats { return mAccumulatedChargeMicroCoulomb[index] != POWER_DATA_UNAVAILABLE; } - /** Check if the supported power buckets are precisely those given. */ - public boolean isSupportEqualTo( - @NonNull boolean[] queriedStandardBuckets, @Nullable String[] customBucketNames) { - if (customBucketNames == null) { - //In practice customBucketNames should never be null, but sanitize it just to be sure. - customBucketNames = new String[0]; - } - - final int numBuckets = getNumberOfIndices(); - final int numCustomBuckets = customBucketNames == null ? 0 : customBucketNames.length; - if (numBuckets != NUMBER_STANDARD_POWER_BUCKETS + numCustomBuckets) { - return false; - } - - if (!Arrays.equals(mCustomBucketNames, customBucketNames)) { - return false; - } - - for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) { - if (isStandardBucketSupported(stdBucket) != queriedStandardBuckets[stdBucket]) { - return false; - } - } - return true; - } - - public String[] getCustomBucketNames() { - return mCustomBucketNames; - } - /** Dump debug data. */ public void dump(PrintWriter pw) { pw.print(" "); for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) { - pw.print(getBucketName(index)); + pw.print(mConfig.getBucketName(index)); pw.print(" : "); pw.print(mAccumulatedChargeMicroCoulomb[index]); if (!isIndexSupported(index)) { pw.print(" (unsupported)"); } + if (mAccumulatedMultiStateChargeMicroCoulomb != null) { + final LongMultiStateCounter counter = + mAccumulatedMultiStateChargeMicroCoulomb[index]; + if (counter != null) { + pw.print(" ["); + for (int i = 0; i < mConfig.mStateNames.length; i++) { + if (i != 0) { + pw.print(" "); + } + pw.print(mConfig.mStateNames[i]); + pw.print(": "); + pw.print(counter.getCount(i)); + } + pw.print("]"); + } + } if (index != mAccumulatedChargeMicroCoulomb.length - 1) { pw.print(", "); } @@ -478,22 +650,6 @@ public class MeasuredEnergyStats { pw.println(); } - /** - * If the index is a standard bucket, returns its name; otherwise returns its prefixed custom - * bucket number. - */ - private String getBucketName(int index) { - if (isValidStandardBucket(index)) { - return DebugUtils.valueToString(MeasuredEnergyStats.class, "POWER_BUCKET_", index); - } - final int customBucket = indexToCustomBucket(index); - StringBuilder name = new StringBuilder().append("CUSTOM_").append(customBucket); - if (mCustomBucketNames != null && !TextUtils.isEmpty(mCustomBucketNames[customBucket])) { - name.append('(').append(mCustomBucketNames[customBucket]).append(')'); - } - return name.toString(); - } - /** Get the number of custom power buckets on this device. */ public int getNumberCustomPowerBuckets() { return mAccumulatedChargeMicroCoulomb.length - NUMBER_STANDARD_POWER_BUCKETS; diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java index c24dc67291ae9..d16689cfc5601 100644 --- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java @@ -65,8 +65,9 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { final boolean[] supportedStandardBuckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; Arrays.fill(supportedStandardBuckets, true); - mGlobalMeasuredEnergyStats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + mMeasuredEnergyStatsConfig = new MeasuredEnergyStats.Config(supportedStandardBuckets, + customBucketNames, new int[0], new String[]{""}); + mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(mMeasuredEnergyStatsConfig); } public TimeBase getOnBatteryTimeBase() { diff --git a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java index a70033bf3e1f8..dc5bc9708f6ac 100644 --- a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java @@ -19,9 +19,12 @@ package com.android.internal.power; import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; import static com.android.internal.power.MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS; +import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH; +import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_CPU; import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE; import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON; import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_OTHER; +import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_WIFI; import static com.google.common.truth.Truth.assertThat; @@ -56,55 +59,32 @@ public class MeasuredEnergyStatsTest { supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_WIFI}, + new String[]{"state0", "state1", "state3"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); - for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { - if (supportedStandardBuckets[i]) { - assertTrue(stats.isStandardBucketSupported(i)); - assertEquals(0L, stats.getAccumulatedStandardBucketCharge(i)); + for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) { + if (supportedStandardBuckets[bucket]) { + assertTrue(stats.isStandardBucketSupported(bucket)); + assertEquals(0L, stats.getAccumulatedStandardBucketCharge(bucket)); } else { - assertFalse(stats.isStandardBucketSupported(i)); - assertEquals(POWER_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketCharge(i)); + assertFalse(stats.isStandardBucketSupported(bucket)); + assertEquals(POWER_DATA_UNAVAILABLE, + stats.getAccumulatedStandardBucketCharge(bucket)); + } + if (bucket == POWER_BUCKET_SCREEN_ON) { + assertThat(config.isSupportedMultiStateBucket(bucket)).isTrue(); + } else { + assertThat(config.isSupportedMultiStateBucket(bucket)).isFalse(); } } for (int i = 0; i < customBucketNames.length; i++) { assertEquals(0L, stats.getAccumulatedCustomBucketCharge(i)); } - assertThat(stats.getCustomBucketNames()).asList().containsExactly("A", "B"); - } - - @Test - public void testCreateFromTemplate() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; - final String[] customBucketNames = {"A", "B"}; - supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; - supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; - supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); - stats.updateCustomBucket(0, 50); - stats.updateCustomBucket(1, 60); - - final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats); - - for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { - if (supportedStandardBuckets[i]) { - assertTrue(newStats.isStandardBucketSupported(i)); - assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i)); - } else { - assertFalse(newStats.isStandardBucketSupported(i)); - assertEquals(POWER_DATA_UNAVAILABLE, - newStats.getAccumulatedStandardBucketCharge(i)); - } - } - for (int i = 0; i < customBucketNames.length; i++) { - assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(i)); - } + assertThat(config.getCustomBucketNames()).asList().containsExactly("A", "B"); + assertThat(config.getStateNames()).asList().containsExactly("state0", "state1", "state3"); } @Test @@ -115,23 +95,32 @@ public class MeasuredEnergyStatsTest { supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); - stats.updateCustomBucket(0, 50); - stats.updateCustomBucket(1, 60); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[]{POWER_BUCKET_SCREEN_ON}, new String[]{"s0", "s1"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); + + stats.setState(0, 1000); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10, 2000); + stats.setState(1, 3000); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5, 4000); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40, 5000); + stats.updateCustomBucket(0, 50, 6000); + stats.updateCustomBucket(1, 60, 7000); final Parcel parcel = Parcel.obtain(); stats.writeToParcel(parcel); parcel.setDataPosition(0); - MeasuredEnergyStats newStats = new MeasuredEnergyStats(parcel); + MeasuredEnergyStats newStats = new MeasuredEnergyStats(config, parcel); - for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { - assertEquals(stats.getAccumulatedStandardBucketCharge(i), - newStats.getAccumulatedStandardBucketCharge(i)); + for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) { + assertEquals(stats.getAccumulatedStandardBucketCharge(bucket), + newStats.getAccumulatedStandardBucketCharge(bucket)); + for (int state = 0; state < 2; state++) { + assertEquals(stats.getAccumulatedStandardBucketCharge(bucket, state), + newStats.getAccumulatedStandardBucketCharge(bucket, state)); + } } for (int i = 0; i < customBucketNames.length; i++) { assertEquals(stats.getAccumulatedCustomBucketCharge(i), @@ -142,6 +131,57 @@ public class MeasuredEnergyStatsTest { parcel.recycle(); } + @Test + public void testCreateAndReadConfigFromParcel() { + final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; + final String[] customBucketNames = {"A", "B"}; + supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; + supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; + + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_WIFI}, + new String[] {"state0", "state1", "state2"}); + + final Parcel parcel = Parcel.obtain(); + MeasuredEnergyStats.Config.writeToParcel(config, parcel); + + parcel.setDataPosition(0); + + final MeasuredEnergyStats.Config newConfig = MeasuredEnergyStats.Config.createFromParcel( + parcel); + + assertThat(newConfig).isNotNull(); + for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) { + if (bucket == POWER_BUCKET_SCREEN_ON || bucket == POWER_BUCKET_SCREEN_OTHER) { + assertThat(newConfig.isSupportedBucket(bucket)).isTrue(); + } else { + assertThat(newConfig.isSupportedBucket(bucket)).isFalse(); + } + if (bucket == POWER_BUCKET_SCREEN_ON) { + assertThat(newConfig.isSupportedMultiStateBucket(bucket)).isTrue(); + } else { + assertThat(newConfig.isSupportedMultiStateBucket(bucket)).isFalse(); + } + } + assertThat(newConfig.getCustomBucketNames()).isEqualTo(new String[]{"A", "B"}); + assertThat(newConfig.getStateNames()).isEqualTo(new String[]{"state0", "state1", "state2"}); + } + + @Test + public void testCreateAndReadConfigFromParcel_nullConfig() { + final Parcel parcel = Parcel.obtain(); + MeasuredEnergyStats.Config.writeToParcel(null, parcel); + + parcel.setDataPosition(0); + + final MeasuredEnergyStats.Config newConfig = MeasuredEnergyStats.Config.createFromParcel( + parcel); + + assertThat(newConfig).isNull(); + } + @Test public void testCreateAndReadSummaryFromParcel() { final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; @@ -150,8 +190,11 @@ public class MeasuredEnergyStatsTest { supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); @@ -159,9 +202,12 @@ public class MeasuredEnergyStatsTest { stats.updateCustomBucket(1, 60); final Parcel parcel = Parcel.obtain(); - MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, false); + MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); + parcel.setDataPosition(0); - MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel); + + MeasuredEnergyStats newStats = + MeasuredEnergyStats.createAndReadSummaryFromParcel(config, parcel); for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { assertEquals(stats.isStandardBucketSupported(i), @@ -175,48 +221,44 @@ public class MeasuredEnergyStatsTest { } assertEquals(POWER_DATA_UNAVAILABLE, newStats.getAccumulatedCustomBucketCharge(customBucketNames.length + 1)); - assertThat(newStats.getCustomBucketNames()).asList().containsExactly("A", "B"); parcel.recycle(); } @Test - public void testCreateAndReadSummaryFromParcel_existingTemplate() { + public void testCreateAndReadSummaryFromParcel_configChange() { final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final String[] customBucketNames = {"A", "B"}; supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats template = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); - template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); - template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); - template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); - template.updateCustomBucket(0, 50); - - final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 7); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 63); - stats.updateCustomBucket(0, 315); - stats.updateCustomBucket(1, 316); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); + stats.updateCustomBucket(0, 50); final Parcel parcel = Parcel.obtain(); - MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true); - - final boolean[] newsupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; - newsupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; - newsupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true - newsupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false - final MeasuredEnergyStats newTemplate = - new MeasuredEnergyStats(newsupportedStandardBuckets, customBucketNames); + MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); parcel.setDataPosition(0); + final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; + newSupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; + newSupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true + newSupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false + + final MeasuredEnergyStats.Config newConfig = + new MeasuredEnergyStats.Config(newSupportedStandardBuckets, customBucketNames, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats newStats = - MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate); + MeasuredEnergyStats.createAndReadSummaryFromParcel(newConfig, parcel); for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { - if (!newsupportedStandardBuckets[i]) { + if (!newSupportedStandardBuckets[i]) { assertFalse(newStats.isStandardBucketSupported(i)); assertEquals(POWER_DATA_UNAVAILABLE, newStats.getAccumulatedStandardBucketCharge(i)); @@ -235,81 +277,22 @@ public class MeasuredEnergyStatsTest { } assertEquals(POWER_DATA_UNAVAILABLE, newStats.getAccumulatedCustomBucketCharge(customBucketNames.length + 1)); - assertThat(newStats.getCustomBucketNames()).asList().containsExactly("A", "B"); parcel.recycle(); } @Test - public void testCreateAndReadSummaryFromParcel_skipZero() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; - final String[] customBucketNames = {"A", "B"}; - Arrays.fill(supportedStandardBuckets, true); - - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); - // Accumulate charge in one bucket and one custom bucket, the rest should be zero - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200); - stats.updateCustomBucket(1, 60); - - // Let's try parcelling with including zeros - final Parcel includeZerosParcel = Parcel.obtain(); - MeasuredEnergyStats.writeSummaryToParcel(stats, includeZerosParcel, false, false); - includeZerosParcel.setDataPosition(0); - - MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel( - includeZerosParcel); - - for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { - if (i == POWER_BUCKET_SCREEN_ON) { - assertEquals(stats.isStandardBucketSupported(i), - newStats.isStandardBucketSupported(i)); - assertEquals(stats.getAccumulatedStandardBucketCharge(i), - newStats.getAccumulatedStandardBucketCharge(i)); - } else { - assertTrue(newStats.isStandardBucketSupported(i)); - assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i)); - } - } - assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0)); - assertEquals(stats.getAccumulatedCustomBucketCharge(1), - newStats.getAccumulatedCustomBucketCharge(1)); - includeZerosParcel.recycle(); - - // Now let's try parcelling with skipping zeros - final Parcel skipZerosParcel = Parcel.obtain(); - MeasuredEnergyStats.writeSummaryToParcel(stats, skipZerosParcel, true, false); - skipZerosParcel.setDataPosition(0); - - newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(skipZerosParcel); - - for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) { - if (i == POWER_BUCKET_SCREEN_ON) { - assertEquals(stats.isStandardBucketSupported(i), - newStats.isStandardBucketSupported(i)); - assertEquals(stats.getAccumulatedStandardBucketCharge(i), - newStats.getAccumulatedStandardBucketCharge(i)); - } else { - assertFalse(newStats.isStandardBucketSupported(i)); - assertEquals(POWER_DATA_UNAVAILABLE, - newStats.getAccumulatedStandardBucketCharge(i)); - } - } - assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0)); - assertEquals(stats.getAccumulatedCustomBucketCharge(1), - newStats.getAccumulatedCustomBucketCharge(1)); - skipZerosParcel.recycle(); - } - - @Test - public void testCreateAndReadSummaryFromParcel_nullTemplate() { + public void testCreateAndReadSummaryFromParcel_nullConfig() { final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; final String[] customBucketNames = {"A", "B"}; supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); @@ -317,11 +300,11 @@ public class MeasuredEnergyStatsTest { stats.updateCustomBucket(1, 60); final Parcel parcel = Parcel.obtain(); - MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true); + MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); parcel.setDataPosition(0); MeasuredEnergyStats newStats = - MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, null); + MeasuredEnergyStats.createAndReadSummaryFromParcel(null, parcel); assertNull(newStats); parcel.recycle(); } @@ -334,30 +317,30 @@ public class MeasuredEnergyStatsTest { supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats template = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); - template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); - template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); - template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); - template.updateCustomBucket(0, 50); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); - final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 0L); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 7L); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 0); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); final Parcel parcel = Parcel.obtain(); - MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true); + MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; newSupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true; newSupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true newSupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false - final MeasuredEnergyStats newTemplate = - new MeasuredEnergyStats(newSupportedStandardBuckets, customBucketNames); + final MeasuredEnergyStats.Config newConfig = + new MeasuredEnergyStats.Config(newSupportedStandardBuckets, customBucketNames, + new int[0], new String[]{"s"}); + parcel.setDataPosition(0); final MeasuredEnergyStats newStats = - MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate); + MeasuredEnergyStats.createAndReadSummaryFromParcel(newConfig, parcel); + // The only non-0 entry in stats is no longer supported, so now there's no interesting data. assertNull(newStats); assertEquals("Parcel was not properly consumed", 0, parcel.dataAvail()); @@ -372,30 +355,47 @@ public class MeasuredEnergyStatsTest { supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_DOZE, 30); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); - stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_SCREEN_OTHER}, + new String[]{"s0", "s1"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); - stats.updateCustomBucket(0, 50); - stats.updateCustomBucket(1, 60); - stats.updateCustomBucket(0, 3); + stats.setState(0, 1000); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10, 2000); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_DOZE, 30, 3000); + stats.setState(1, 4000); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40, 5000); + stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 6, 6000); - assertEquals(15, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON)); + stats.updateCustomBucket(0, 50, 7000); + stats.updateCustomBucket(1, 60, 8000); + stats.updateCustomBucket(0, 3, 9000); + + assertEquals(16, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON)); assertEquals(POWER_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_DOZE)); assertEquals(40, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER)); assertEquals(50 + 3, stats.getAccumulatedCustomBucketCharge(0)); assertEquals(60, stats.getAccumulatedCustomBucketCharge(1)); + + // 10 + 6 * (4000-2000)/(6000-2000) + assertEquals(13, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON, 0)); + // 6 * (6000-4000)/(6000-2000) + assertEquals(3, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON, 1)); + + // POWER_BUCKET_SCREEN_OTHER was only present along with state=1 + assertEquals(0, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER, 0)); + assertEquals(40, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER, 1)); } @Test public void testIsValidCustomBucket() { - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], - new String[]{"A", "B", "C"}); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS], + new String[]{"A", "B", "C"}, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); assertFalse(stats.isValidCustomBucket(-1)); assertTrue(stats.isValidCustomBucket(0)); assertTrue(stats.isValidCustomBucket(1)); @@ -403,8 +403,10 @@ public class MeasuredEnergyStatsTest { assertFalse(stats.isValidCustomBucket(3)); assertFalse(stats.isValidCustomBucket(4)); - final MeasuredEnergyStats boringStats = - new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0]); + final MeasuredEnergyStats.Config boringConfig = + new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS], + new String[0], new int[0], new String[]{"s"}); + final MeasuredEnergyStats boringStats = new MeasuredEnergyStats(boringConfig); assertFalse(boringStats.isValidCustomBucket(-1)); assertFalse(boringStats.isValidCustomBucket(0)); assertFalse(boringStats.isValidCustomBucket(1)); @@ -412,9 +414,11 @@ public class MeasuredEnergyStatsTest { @Test public void testGetAccumulatedCustomBucketCharges() { - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], - new String[]{"A", "B", "C"}); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS], + new String[]{"A", "B", "C"}, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); stats.updateCustomBucket(0, 50); stats.updateCustomBucket(1, 60); stats.updateCustomBucket(2, 13); @@ -430,8 +434,10 @@ public class MeasuredEnergyStatsTest { @Test public void testGetAccumulatedCustomBucketCharges_empty() { - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0]); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS], + new String[0], new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); final long[] output = stats.getAccumulatedCustomBucketCharges(); assertEquals(0, output.length); @@ -440,10 +446,15 @@ public class MeasuredEnergyStatsTest { @Test public void testGetNumberCustomChargeBuckets() { assertEquals(0, - new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0]) + new MeasuredEnergyStats( + new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS], + new String[0], new int[0], new String[]{"s"})) + .getNumberCustomPowerBuckets()); + assertEquals(3, + new MeasuredEnergyStats( + new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS], + new String[]{"A", "B", "C"}, new int[0], new String[]{"s"})) .getNumberCustomPowerBuckets()); - assertEquals(3, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], - new String[]{"A", "B", "C"}).getNumberCustomPowerBuckets()); } @Test @@ -454,8 +465,10 @@ public class MeasuredEnergyStatsTest { supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false; supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true; - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + final MeasuredEnergyStats.Config config = + new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames, + new int[0], new String[]{"s"}); + final MeasuredEnergyStats stats = new MeasuredEnergyStats(config); stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10); stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5); stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40); @@ -500,83 +513,62 @@ public class MeasuredEnergyStatsTest { assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_DOZE_SUSPEND)); } - /** Test MeasuredEnergyStats#isSupportEqualTo */ @Test - public void testIsSupportEqualTo() { + public void testConfig_isCompatible() { final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; Arrays.fill(supportedStandardBuckets, true); final String[] customBucketNames = {"A", "B"}; + final int[] supportedMultiStateBuckets = {POWER_BUCKET_CPU, POWER_BUCKET_WIFI}; + final String[] stateNames = {"s"}; - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets.clone(), - customBucketNames.clone()); - + final MeasuredEnergyStats.Config config = new MeasuredEnergyStats.Config( + supportedStandardBuckets, + customBucketNames, + supportedMultiStateBuckets, + stateNames); assertTrue( "All standard and custom bucket supports match", - stats.isSupportEqualTo(supportedStandardBuckets, customBucketNames)); + config.isCompatible( + new MeasuredEnergyStats.Config( + supportedStandardBuckets, + customBucketNames, + supportedMultiStateBuckets, + stateNames))); boolean[] differentSupportedStandardBuckets = supportedStandardBuckets.clone(); differentSupportedStandardBuckets[0] = !differentSupportedStandardBuckets[0]; + assertFalse( "Standard bucket support mismatch", - stats.isSupportEqualTo(differentSupportedStandardBuckets, customBucketNames)); - + config.isCompatible( + new MeasuredEnergyStats.Config( + differentSupportedStandardBuckets, + customBucketNames, + supportedMultiStateBuckets, + stateNames))); assertFalse( "Custom bucket support mismatch", - stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"C", "B"})); - + config.isCompatible( + new MeasuredEnergyStats.Config( + supportedStandardBuckets, + new String[]{"C", "B"}, + supportedMultiStateBuckets, + stateNames))); assertFalse( - "Fewer custom buckets supported", - stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A"})); - + "Multi-state bucket mismatch", + config.isCompatible( + new MeasuredEnergyStats.Config( + supportedStandardBuckets, + new String[]{"A"}, + new int[] {POWER_BUCKET_CPU, POWER_BUCKET_BLUETOOTH}, + stateNames))); assertFalse( - "More custom bucket supported", - stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B", "C"})); - - assertFalse( - "Custom bucket support order changed", - stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"B", "A"})); - } - - /** Test MeasuredEnergyStats#isSupportEqualTo when holding a null array of custom buckets */ - @Test - public void testIsSupportEqualTo_nullCustomBuckets() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; - - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets.clone(), null); - - assertTrue( - "Null custom bucket name lists should match", - stats.isSupportEqualTo(supportedStandardBuckets, null)); - - assertTrue( - "Null and empty custom buckets should match", - stats.isSupportEqualTo(supportedStandardBuckets, new String[0])); - - assertFalse( - "Null custom buckets should not match populated list", - stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"})); - } - - /** Test MeasuredEnergyStats#isSupportEqualTo when holding an empty array of custom buckets */ - @Test - public void testIsSupportEqualTo_emptyCustomBuckets() { - final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS]; - - final MeasuredEnergyStats stats = - new MeasuredEnergyStats(supportedStandardBuckets.clone(), new String[0]); - - assertTrue( - "Empty custom buckets should match", - stats.isSupportEqualTo(supportedStandardBuckets, new String[0])); - - assertTrue( - "Empty and null custom buckets should match", - stats.isSupportEqualTo(supportedStandardBuckets, null)); - - assertFalse( - "Empty custom buckets should not match populated list", - stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"})); + "Multi-state bucket state list mismatch", + config.isCompatible( + new MeasuredEnergyStats.Config( + supportedStandardBuckets, + new String[]{"A"}, + supportedMultiStateBuckets, + new String[]{"s1", "s2"}))); } }