summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dmitri Plotnikov <dplotnikov@google.com> 2024-01-29 18:32:16 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-01-29 18:32:16 +0000
commit0aad2b7abfed297f7495c89516b90f17f7f4fd48 (patch)
treea05e5a5e2f5febe3c1cd5e32a02551f90c1f254f
parent5748db0dd15c467ba8ca00409a9dd888b2a1f044 (diff)
parent820f9d71d4292706a4550bd29131c556aea473f6 (diff)
Merge "Synchronize access to BatteryStatsHistory" into main
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistory.java591
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryStatsImpl.java2
-rw-r--r--services/core/java/com/android/server/power/stats/PowerStatsAggregator.java3
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java30
4 files changed, 375 insertions, 251 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 7a79e0f7cfea..aa60cc9e672c 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -490,7 +490,7 @@ public class BatteryStatsHistory {
* Returns true if this instance only supports reading history.
*/
public boolean isReadOnly() {
- return mActiveFile == null || mHistoryDir == null;
+ return !mMutable || mActiveFile == null || mHistoryDir == null;
}
/**
@@ -508,6 +508,13 @@ public class BatteryStatsHistory {
* create next history file.
*/
public void startNextFile(long elapsedRealtimeMs) {
+ synchronized (this) {
+ startNextFileLocked(elapsedRealtimeMs);
+ }
+ }
+
+ @GuardedBy("this")
+ private void startNextFileLocked(long elapsedRealtimeMs) {
if (mMaxHistoryFiles == 0) {
Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history");
return;
@@ -548,10 +555,7 @@ public class BatteryStatsHistory {
}
mWrittenPowerStatsDescriptors.clear();
-
- synchronized (this) {
- cleanupLocked();
- }
+ cleanupLocked();
}
@GuardedBy("this")
@@ -599,27 +603,31 @@ public class BatteryStatsHistory {
* number 0 again.
*/
public void reset() {
- if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!");
- for (BatteryHistoryFile file : mHistoryFiles) {
- file.atomicFile.delete();
- }
- mHistoryFiles.clear();
+ synchronized (this) {
+ if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!");
+ for (BatteryHistoryFile file : mHistoryFiles) {
+ file.atomicFile.delete();
+ }
+ mHistoryFiles.clear();
- BatteryHistoryFile name = makeBatteryHistoryFile();
- mHistoryFiles.add(name);
- setActiveFile(name);
+ BatteryHistoryFile name = makeBatteryHistoryFile();
+ mHistoryFiles.add(name);
+ setActiveFile(name);
- initHistoryBuffer();
+ initHistoryBuffer();
+ }
}
/**
* Returns the monotonic clock time when the available battery history collection started.
*/
public long getStartTime() {
- if (!mHistoryFiles.isEmpty()) {
- return mHistoryFiles.get(0).monotonicTimeMs;
- } else {
- return mHistoryBufferStartTime;
+ synchronized (this) {
+ if (!mHistoryFiles.isEmpty()) {
+ return mHistoryFiles.get(0).monotonicTimeMs;
+ } else {
+ return mHistoryBufferStartTime;
+ }
}
}
@@ -633,11 +641,14 @@ public class BatteryStatsHistory {
*/
@NonNull
public BatteryStatsHistoryIterator iterate(long startTimeMs, long endTimeMs) {
+ if (mMutable) {
+ return copy().iterate(startTimeMs, endTimeMs);
+ }
+
mCurrentFileIndex = 0;
mCurrentParcel = null;
mCurrentParcelEnd = 0;
mParcelIndex = 0;
- mMutable = false;
if (mWritableHistory != null) {
synchronized (mWritableHistory) {
mWritableHistory.setCleanupEnabledLocked(false);
@@ -650,14 +661,11 @@ public class BatteryStatsHistory {
* Finish iterating history files and history buffer.
*/
void iteratorFinished() {
- // setDataPosition so mHistoryBuffer Parcel can be written.
mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
if (mWritableHistory != null) {
synchronized (mWritableHistory) {
mWritableHistory.setCleanupEnabledLocked(true);
}
- } else {
- mMutable = true;
}
}
@@ -671,6 +679,8 @@ public class BatteryStatsHistory {
*/
@Nullable
public Parcel getNextParcel(long startTimeMs, long endTimeMs) {
+ checkImmutable();
+
// First iterate through all records in current parcel.
if (mCurrentParcel != null) {
if (mCurrentParcel.dataPosition() < mCurrentParcelEnd) {
@@ -754,6 +764,12 @@ public class BatteryStatsHistory {
return mCurrentParcel;
}
+ private void checkImmutable() {
+ if (mMutable) {
+ throw new IllegalStateException("Iterating over a mutable battery history");
+ }
+ }
+
/**
* Read history file into a parcel.
*
@@ -863,8 +879,10 @@ public class BatteryStatsHistory {
* @param out the output parcel
*/
public void writeToParcel(Parcel out) {
- writeHistoryBuffer(out);
- writeToParcel(out, false /* useBlobs */);
+ synchronized (this) {
+ writeHistoryBuffer(out);
+ writeToParcel(out, false /* useBlobs */);
+ }
}
/**
@@ -874,8 +892,10 @@ public class BatteryStatsHistory {
* @param out the output parcel
*/
public void writeToBatteryUsageStatsParcel(Parcel out) {
- out.writeBlob(mHistoryBuffer.marshall());
- writeToParcel(out, true /* useBlobs */);
+ synchronized (this) {
+ out.writeBlob(mHistoryBuffer.marshall());
+ writeToParcel(out, true /* useBlobs */);
+ }
}
private void writeToParcel(Parcel out, boolean useBlobs) {
@@ -1022,14 +1042,18 @@ public class BatteryStatsHistory {
* Enables/disables recording of history. When disabled, all "record*" calls are a no-op.
*/
public void setHistoryRecordingEnabled(boolean enabled) {
- mRecordingHistory = enabled;
+ synchronized (this) {
+ mRecordingHistory = enabled;
+ }
}
/**
* Returns true if history recording is enabled.
*/
public boolean isRecordingHistory() {
- return mRecordingHistory;
+ synchronized (this) {
+ return mRecordingHistory;
+ }
}
/**
@@ -1037,8 +1061,10 @@ public class BatteryStatsHistory {
*/
@VisibleForTesting
public void forceRecordAllHistory() {
- mHaveBatteryLevel = true;
- mRecordingHistory = true;
+ synchronized (this) {
+ mHaveBatteryLevel = true;
+ mRecordingHistory = true;
+ }
}
/**
@@ -1046,37 +1072,43 @@ public class BatteryStatsHistory {
*/
public void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
boolean reset) {
- mRecordingHistory = true;
- mHistoryCur.currentTime = mClock.currentTimeMillis();
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur,
- reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME);
- mHistoryCur.currentTime = 0;
+ synchronized (this) {
+ mRecordingHistory = true;
+ mHistoryCur.currentTime = mClock.currentTimeMillis();
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur,
+ reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME);
+ mHistoryCur.currentTime = 0;
+ }
}
/**
* Prepares to continue recording after restoring previous history from persistent storage.
*/
public void continueRecordingHistory() {
- if (mHistoryBuffer.dataPosition() <= 0 && mHistoryFiles.size() <= 1) {
- return;
- }
+ synchronized (this) {
+ if (mHistoryBuffer.dataPosition() <= 0 && mHistoryFiles.size() <= 1) {
+ return;
+ }
- mRecordingHistory = true;
- final long elapsedRealtimeMs = mClock.elapsedRealtime();
- final long uptimeMs = mClock.uptimeMillis();
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_START);
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
+ mRecordingHistory = true;
+ final long elapsedRealtimeMs = mClock.elapsedRealtime();
+ final long uptimeMs = mClock.uptimeMillis();
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_START);
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
+ }
}
/**
* Notes the current battery state to be reflected in the next written history item.
*/
public void setBatteryState(boolean charging, int status, int level, int chargeUah) {
- mHaveBatteryLevel = true;
- setChargingState(charging);
- mHistoryCur.batteryStatus = (byte) status;
- mHistoryCur.batteryLevel = (byte) level;
- mHistoryCur.batteryChargeUah = chargeUah;
+ synchronized (this) {
+ mHaveBatteryLevel = true;
+ setChargingState(charging);
+ mHistoryCur.batteryStatus = (byte) status;
+ mHistoryCur.batteryLevel = (byte) level;
+ mHistoryCur.batteryChargeUah = chargeUah;
+ }
}
/**
@@ -1084,24 +1116,28 @@ public class BatteryStatsHistory {
*/
public void setBatteryState(int status, int level, int health, int plugType, int temperature,
int voltageMv, int chargeUah) {
- mHaveBatteryLevel = true;
- mHistoryCur.batteryStatus = (byte) status;
- mHistoryCur.batteryLevel = (byte) level;
- mHistoryCur.batteryHealth = (byte) health;
- mHistoryCur.batteryPlugType = (byte) plugType;
- mHistoryCur.batteryTemperature = (short) temperature;
- mHistoryCur.batteryVoltage = (char) voltageMv;
- mHistoryCur.batteryChargeUah = chargeUah;
+ synchronized (this) {
+ mHaveBatteryLevel = true;
+ mHistoryCur.batteryStatus = (byte) status;
+ mHistoryCur.batteryLevel = (byte) level;
+ mHistoryCur.batteryHealth = (byte) health;
+ mHistoryCur.batteryPlugType = (byte) plugType;
+ mHistoryCur.batteryTemperature = (short) temperature;
+ mHistoryCur.batteryVoltage = (char) voltageMv;
+ mHistoryCur.batteryChargeUah = chargeUah;
+ }
}
/**
* Notes the current power plugged-in state to be reflected in the next written history item.
*/
public void setPluggedInState(boolean pluggedIn) {
- if (pluggedIn) {
- mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- } else {
- mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
+ synchronized (this) {
+ if (pluggedIn) {
+ mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
+ } else {
+ mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
+ }
}
}
@@ -1109,10 +1145,12 @@ public class BatteryStatsHistory {
* Notes the current battery charging state to be reflected in the next written history item.
*/
public void setChargingState(boolean charging) {
- if (charging) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
- } else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
+ synchronized (this) {
+ if (charging) {
+ mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
+ } else {
+ mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
+ }
}
}
@@ -1121,38 +1159,44 @@ public class BatteryStatsHistory {
*/
public void recordEvent(long elapsedRealtimeMs, long uptimeMs, int code, String name,
int uid) {
- mHistoryCur.eventCode = code;
- mHistoryCur.eventTag = mHistoryCur.localEventTag;
- mHistoryCur.eventTag.string = name;
- mHistoryCur.eventTag.uid = uid;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.eventCode = code;
+ mHistoryCur.eventTag = mHistoryCur.localEventTag;
+ mHistoryCur.eventTag.string = name;
+ mHistoryCur.eventTag.uid = uid;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
* Records a time change event.
*/
public void recordCurrentTimeChange(long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
- if (!mRecordingHistory) {
- return;
- }
+ synchronized (this) {
+ if (!mRecordingHistory) {
+ return;
+ }
- mHistoryCur.currentTime = currentTimeMs;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur,
- HistoryItem.CMD_CURRENT_TIME);
- mHistoryCur.currentTime = 0;
+ mHistoryCur.currentTime = currentTimeMs;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur,
+ HistoryItem.CMD_CURRENT_TIME);
+ mHistoryCur.currentTime = 0;
+ }
}
/**
* Records a system shutdown event.
*/
public void recordShutdownEvent(long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
- if (!mRecordingHistory) {
- return;
- }
+ synchronized (this) {
+ if (!mRecordingHistory) {
+ return;
+ }
- mHistoryCur.currentTime = currentTimeMs;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_SHUTDOWN);
- mHistoryCur.currentTime = 0;
+ mHistoryCur.currentTime = currentTimeMs;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_SHUTDOWN);
+ mHistoryCur.currentTime = 0;
+ }
}
/**
@@ -1160,13 +1204,15 @@ public class BatteryStatsHistory {
*/
public void recordBatteryState(long elapsedRealtimeMs, long uptimeMs, int batteryLevel,
boolean isPlugged) {
- mHistoryCur.batteryLevel = (byte) batteryLevel;
- setPluggedInState(isPlugged);
- if (DEBUG) {
- Slog.v(TAG, "Battery unplugged to: "
- + Integer.toHexString(mHistoryCur.states));
+ synchronized (this) {
+ mHistoryCur.batteryLevel = (byte) batteryLevel;
+ setPluggedInState(isPlugged);
+ if (DEBUG) {
+ Slog.v(TAG, "Battery unplugged to: "
+ + Integer.toHexString(mHistoryCur.states));
+ }
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
/**
@@ -1174,9 +1220,11 @@ public class BatteryStatsHistory {
*/
public void recordPowerStats(long elapsedRealtimeMs, long uptimeMs,
PowerStats powerStats) {
- mHistoryCur.powerStats = powerStats;
- mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.powerStats = powerStats;
+ mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1184,11 +1232,13 @@ public class BatteryStatsHistory {
*/
public void recordProcessStateChange(long elapsedRealtimeMs, long uptimeMs,
int uid, @BatteryConsumer.ProcessState int processState) {
- mHistoryCur.processStateChange = mHistoryCur.localProcessStateChange;
- mHistoryCur.processStateChange.uid = uid;
- mHistoryCur.processStateChange.processState = processState;
- mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.processStateChange = mHistoryCur.localProcessStateChange;
+ mHistoryCur.processStateChange.uid = uid;
+ mHistoryCur.processStateChange.processState = processState;
+ mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1197,8 +1247,10 @@ public class BatteryStatsHistory {
*/
public void recordWifiConsumedCharge(long elapsedRealtimeMs, long uptimeMs,
double monitoredRailChargeMah) {
- mHistoryCur.wifiRailChargeMah += monitoredRailChargeMah;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.wifiRailChargeMah += monitoredRailChargeMah;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1206,10 +1258,12 @@ public class BatteryStatsHistory {
*/
public void recordWakelockStartEvent(long elapsedRealtimeMs, long uptimeMs, String historyName,
int uid) {
- mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName;
- mHistoryCur.wakelockTag.uid = uid;
- recordStateStartEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_WAKE_LOCK_FLAG);
+ synchronized (this) {
+ mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
+ mHistoryCur.wakelockTag.string = historyName;
+ mHistoryCur.wakelockTag.uid = uid;
+ recordStateStartEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_WAKE_LOCK_FLAG);
+ }
}
/**
@@ -1217,18 +1271,20 @@ public class BatteryStatsHistory {
*/
public boolean maybeUpdateWakelockTag(long elapsedRealtimeMs, long uptimeMs, String historyName,
int uid) {
- if (mHistoryLastWritten.cmd != HistoryItem.CMD_UPDATE) {
- return false;
- }
- if (mHistoryLastWritten.wakelockTag != null) {
- // We'll try to update the last tag.
- mHistoryLastWritten.wakelockTag = null;
- mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName;
- mHistoryCur.wakelockTag.uid = uid;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ if (mHistoryLastWritten.cmd != HistoryItem.CMD_UPDATE) {
+ return false;
+ }
+ if (mHistoryLastWritten.wakelockTag != null) {
+ // We'll try to update the last tag.
+ mHistoryLastWritten.wakelockTag = null;
+ mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
+ mHistoryCur.wakelockTag.string = historyName;
+ mHistoryCur.wakelockTag.uid = uid;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+ return true;
}
- return true;
}
/**
@@ -1236,26 +1292,32 @@ public class BatteryStatsHistory {
*/
public void recordWakelockStopEvent(long elapsedRealtimeMs, long uptimeMs, String historyName,
int uid) {
- mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName != null ? historyName : "";
- mHistoryCur.wakelockTag.uid = uid;
- recordStateStopEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_WAKE_LOCK_FLAG);
+ synchronized (this) {
+ mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
+ mHistoryCur.wakelockTag.string = historyName != null ? historyName : "";
+ mHistoryCur.wakelockTag.uid = uid;
+ recordStateStopEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.STATE_WAKE_LOCK_FLAG);
+ }
}
/**
* Records an event when some state flag changes to true.
*/
public void recordStateStartEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states |= stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states |= stateFlags;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
* Records an event when some state flag changes to false.
*/
public void recordStateStopEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states &= ~stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states &= ~stateFlags;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1263,34 +1325,42 @@ public class BatteryStatsHistory {
*/
public void recordStateChangeEvent(long elapsedRealtimeMs, long uptimeMs, int stateStartFlags,
int stateStopFlags) {
- mHistoryCur.states = (mHistoryCur.states | stateStartFlags) & ~stateStopFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states = (mHistoryCur.states | stateStartFlags) & ~stateStopFlags;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
* Records an event when some state2 flag changes to true.
*/
public void recordState2StartEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states2 |= stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states2 |= stateFlags;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
* Records an event when some state2 flag changes to false.
*/
public void recordState2StopEvent(long elapsedRealtimeMs, long uptimeMs, int stateFlags) {
- mHistoryCur.states2 &= ~stateFlags;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states2 &= ~stateFlags;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
* Records an wakeup event.
*/
public void recordWakeupEvent(long elapsedRealtimeMs, long uptimeMs, String reason) {
- mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
- mHistoryCur.wakeReasonTag.string = reason;
- mHistoryCur.wakeReasonTag.uid = 0;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+ mHistoryCur.wakeReasonTag.string = reason;
+ mHistoryCur.wakeReasonTag.uid = 0;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1298,10 +1368,12 @@ public class BatteryStatsHistory {
*/
public void recordScreenBrightnessEvent(long elapsedRealtimeMs, long uptimeMs,
int brightnessBin) {
- mHistoryCur.states = setBitField(mHistoryCur.states, brightnessBin,
- HistoryItem.STATE_BRIGHTNESS_SHIFT,
- HistoryItem.STATE_BRIGHTNESS_MASK);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states = setBitField(mHistoryCur.states, brightnessBin,
+ HistoryItem.STATE_BRIGHTNESS_SHIFT,
+ HistoryItem.STATE_BRIGHTNESS_MASK);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1309,20 +1381,24 @@ public class BatteryStatsHistory {
*/
public void recordGpsSignalQualityEvent(long elapsedRealtimeMs, long uptimeMs,
int signalLevel) {
- mHistoryCur.states2 = setBitField(mHistoryCur.states2, signalLevel,
- HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT,
- HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states2 = setBitField(mHistoryCur.states2, signalLevel,
+ HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT,
+ HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
* Records a device idle mode change event.
*/
public void recordDeviceIdleEvent(long elapsedRealtimeMs, long uptimeMs, int mode) {
- mHistoryCur.states2 = setBitField(mHistoryCur.states2, mode,
- HistoryItem.STATE2_DEVICE_IDLE_SHIFT,
- HistoryItem.STATE2_DEVICE_IDLE_MASK);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states2 = setBitField(mHistoryCur.states2, mode,
+ HistoryItem.STATE2_DEVICE_IDLE_SHIFT,
+ HistoryItem.STATE2_DEVICE_IDLE_MASK);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1330,20 +1406,22 @@ public class BatteryStatsHistory {
*/
public void recordPhoneStateChangeEvent(long elapsedRealtimeMs, long uptimeMs, int addStateFlag,
int removeStateFlag, int state, int signalStrength) {
- mHistoryCur.states = (mHistoryCur.states | addStateFlag) & ~removeStateFlag;
- if (state != -1) {
- mHistoryCur.states =
- setBitField(mHistoryCur.states, state,
- HistoryItem.STATE_PHONE_STATE_SHIFT,
- HistoryItem.STATE_PHONE_STATE_MASK);
- }
- if (signalStrength != -1) {
- mHistoryCur.states =
- setBitField(mHistoryCur.states, signalStrength,
- HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT,
- HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK);
+ synchronized (this) {
+ mHistoryCur.states = (mHistoryCur.states | addStateFlag) & ~removeStateFlag;
+ if (state != -1) {
+ mHistoryCur.states =
+ setBitField(mHistoryCur.states, state,
+ HistoryItem.STATE_PHONE_STATE_SHIFT,
+ HistoryItem.STATE_PHONE_STATE_MASK);
+ }
+ if (signalStrength != -1) {
+ mHistoryCur.states =
+ setBitField(mHistoryCur.states, signalStrength,
+ HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT,
+ HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK);
+ }
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
/**
@@ -1351,10 +1429,12 @@ public class BatteryStatsHistory {
*/
public void recordDataConnectionTypeChangeEvent(long elapsedRealtimeMs, long uptimeMs,
int dataConnectionType) {
- mHistoryCur.states = setBitField(mHistoryCur.states, dataConnectionType,
- HistoryItem.STATE_DATA_CONNECTION_SHIFT,
- HistoryItem.STATE_DATA_CONNECTION_MASK);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states = setBitField(mHistoryCur.states, dataConnectionType,
+ HistoryItem.STATE_DATA_CONNECTION_SHIFT,
+ HistoryItem.STATE_DATA_CONNECTION_MASK);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1362,10 +1442,12 @@ public class BatteryStatsHistory {
*/
public void recordNrStateChangeEvent(long elapsedRealtimeMs, long uptimeMs,
int nrState) {
- mHistoryCur.states2 = setBitField(mHistoryCur.states2, nrState,
- HistoryItem.STATE2_NR_STATE_SHIFT,
- HistoryItem.STATE2_NR_STATE_MASK);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states2 = setBitField(mHistoryCur.states2, nrState,
+ HistoryItem.STATE2_NR_STATE_SHIFT,
+ HistoryItem.STATE2_NR_STATE_MASK);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1373,11 +1455,13 @@ public class BatteryStatsHistory {
*/
public void recordWifiSupplicantStateChangeEvent(long elapsedRealtimeMs, long uptimeMs,
int supplState) {
- mHistoryCur.states2 =
- setBitField(mHistoryCur.states2, supplState,
- HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT,
- HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states2 =
+ setBitField(mHistoryCur.states2, supplState,
+ HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT,
+ HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1385,11 +1469,13 @@ public class BatteryStatsHistory {
*/
public void recordWifiSignalStrengthChangeEvent(long elapsedRealtimeMs, long uptimeMs,
int strengthBin) {
- mHistoryCur.states2 =
- setBitField(mHistoryCur.states2, strengthBin,
- HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT,
- HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK);
- writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ synchronized (this) {
+ mHistoryCur.states2 =
+ setBitField(mHistoryCur.states2, strengthBin,
+ HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT,
+ HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
}
/**
@@ -1446,25 +1532,30 @@ public class BatteryStatsHistory {
* Writes the current history item to history.
*/
public void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs) {
- if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
- final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
- final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
- if (diffUptimeMs < (diffElapsedMs - 20)) {
- final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
- mHistoryAddTmp.setTo(mHistoryLastWritten);
- mHistoryAddTmp.wakelockTag = null;
- mHistoryAddTmp.wakeReasonTag = null;
- mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
- mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
- writeHistoryItem(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
+ synchronized (this) {
+ if (mTrackRunningHistoryElapsedRealtimeMs != 0) {
+ final long diffElapsedMs =
+ elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs;
+ final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs;
+ if (diffUptimeMs < (diffElapsedMs - 20)) {
+ final long wakeElapsedTimeMs =
+ elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs);
+ mHistoryAddTmp.setTo(mHistoryLastWritten);
+ mHistoryAddTmp.wakelockTag = null;
+ mHistoryAddTmp.wakeReasonTag = null;
+ mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE;
+ mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG;
+ writeHistoryItem(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
+ }
}
+ mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
+ mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
+ mTrackRunningHistoryUptimeMs = uptimeMs;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur);
}
- mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
- mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
- mTrackRunningHistoryUptimeMs = uptimeMs;
- writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur);
}
+ @GuardedBy("this")
private void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
if (mTracer != null && mTracer.tracingEnabled()) {
recordTraceEvents(cur.eventCode, cur.eventTag);
@@ -1591,6 +1682,7 @@ public class BatteryStatsHistory {
writeHistoryItem(elapsedRealtimeMs, uptimeMs, cur, HistoryItem.CMD_UPDATE);
}
+ @GuardedBy("this")
private void writeHistoryItem(long elapsedRealtimeMs,
@SuppressWarnings("UnusedVariable") long uptimeMs, HistoryItem cur, byte cmd) {
if (!mMutable) {
@@ -1701,7 +1793,8 @@ public class BatteryStatsHistory {
/**
* Writes the delta between the previous and current history items into history buffer.
*/
- public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
+ @GuardedBy("this")
+ private void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
dest.writeInt(BatteryStatsHistory.DELTA_TIME_ABS);
cur.writeToParcel(dest, 0);
@@ -1921,6 +2014,7 @@ public class BatteryStatsHistory {
* while writing the current history buffer, the method returns
* <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
*/
+ @GuardedBy("this")
private int writeHistoryTag(HistoryTag tag) {
if (tag.string == null) {
Slog.wtfStack(TAG, "writeHistoryTag called with null name");
@@ -1964,33 +2058,37 @@ public class BatteryStatsHistory {
* Don't allow any more batching in to the current history event.
*/
public void commitCurrentHistoryBatchLocked() {
- mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
+ synchronized (this) {
+ mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
+ }
}
/**
* Saves the accumulated history buffer in the active file, see {@link #getActiveFile()} .
*/
public void writeHistory() {
- if (isReadOnly()) {
- Slog.w(TAG, "writeHistory: this instance instance is read-only");
- return;
- }
+ synchronized (this) {
+ if (isReadOnly()) {
+ Slog.w(TAG, "writeHistory: this instance instance is read-only");
+ return;
+ }
- // Save the monotonic time first, so that even if the history write below fails,
- // we still wouldn't end up with overlapping history timelines.
- mMonotonicClock.write();
+ // Save the monotonic time first, so that even if the history write below fails,
+ // we still wouldn't end up with overlapping history timelines.
+ mMonotonicClock.write();
- Parcel p = Parcel.obtain();
- try {
- final long start = SystemClock.uptimeMillis();
- writeHistoryBuffer(p);
- if (DEBUG) {
- Slog.d(TAG, "writeHistoryBuffer duration ms:"
- + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
+ Parcel p = Parcel.obtain();
+ try {
+ final long start = SystemClock.uptimeMillis();
+ writeHistoryBuffer(p);
+ if (DEBUG) {
+ Slog.d(TAG, "writeHistoryBuffer duration ms:"
+ + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
+ }
+ writeParcelToFileLocked(p, mActiveFile);
+ } finally {
+ p.recycle();
}
- writeParcelToFileLocked(p, mActiveFile);
- } finally {
- p.recycle();
}
}
@@ -1998,35 +2096,38 @@ public class BatteryStatsHistory {
* Reads history buffer from a persisted Parcel.
*/
public void readHistoryBuffer(Parcel in) throws ParcelFormatException {
- final int version = in.readInt();
- if (version != BatteryStatsHistory.VERSION) {
- Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
- + ", expected " + BatteryStatsHistory.VERSION + "; erasing old stats");
- return;
- }
-
- mHistoryBufferStartTime = in.readLong();
- mHistoryBuffer.setDataSize(0);
- mHistoryBuffer.setDataPosition(0);
+ synchronized (this) {
+ final int version = in.readInt();
+ if (version != BatteryStatsHistory.VERSION) {
+ Slog.w("BatteryStats", "readHistoryBuffer: version got " + version
+ + ", expected " + BatteryStatsHistory.VERSION + "; erasing old stats");
+ return;
+ }
- int bufSize = in.readInt();
- int curPos = in.dataPosition();
- if (bufSize >= (mMaxHistoryBufferSize * 100)) {
- throw new ParcelFormatException(
- "File corrupt: history data buffer too large " + bufSize);
- } else if ((bufSize & ~3) != bufSize) {
- throw new ParcelFormatException(
- "File corrupt: history data buffer not aligned " + bufSize);
- } else {
- if (DEBUG) {
- Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
- + " bytes at " + curPos);
+ mHistoryBufferStartTime = in.readLong();
+ mHistoryBuffer.setDataSize(0);
+ mHistoryBuffer.setDataPosition(0);
+
+ int bufSize = in.readInt();
+ int curPos = in.dataPosition();
+ if (bufSize >= (mMaxHistoryBufferSize * 100)) {
+ throw new ParcelFormatException(
+ "File corrupt: history data buffer too large " + bufSize);
+ } else if ((bufSize & ~3) != bufSize) {
+ throw new ParcelFormatException(
+ "File corrupt: history data buffer not aligned " + bufSize);
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
+ + " bytes at " + curPos);
+ }
+ mHistoryBuffer.appendFrom(in, curPos, bufSize);
+ in.setDataPosition(curPos + bufSize);
}
- mHistoryBuffer.appendFrom(in, curPos, bufSize);
- in.setDataPosition(curPos + bufSize);
}
}
+ @GuardedBy("this")
private void writeHistoryBuffer(Parcel out) {
out.writeInt(BatteryStatsHistory.VERSION);
out.writeLong(mHistoryBufferStartTime);
@@ -2038,6 +2139,7 @@ public class BatteryStatsHistory {
out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
}
+ @GuardedBy("this")
private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
FileOutputStream fos = null;
mWriteLock.lock();
@@ -2066,34 +2168,43 @@ public class BatteryStatsHistory {
* Returns the total number of history tags in the tag pool.
*/
public int getHistoryStringPoolSize() {
- return mHistoryTagPool.size();
+ synchronized (this) {
+ return mHistoryTagPool.size();
+ }
}
/**
* Returns the total number of bytes occupied by the history tag pool.
*/
public int getHistoryStringPoolBytes() {
- return mNumHistoryTagChars;
+ synchronized (this) {
+ return mNumHistoryTagChars;
+ }
}
/**
* Returns the string held by the requested history tag.
*/
public String getHistoryTagPoolString(int index) {
- ensureHistoryTagArray();
- HistoryTag historyTag = mHistoryTags.get(index);
- return historyTag != null ? historyTag.string : null;
+ synchronized (this) {
+ ensureHistoryTagArray();
+ HistoryTag historyTag = mHistoryTags.get(index);
+ return historyTag != null ? historyTag.string : null;
+ }
}
/**
* Returns the UID held by the requested history tag.
*/
public int getHistoryTagPoolUid(int index) {
- ensureHistoryTagArray();
- HistoryTag historyTag = mHistoryTags.get(index);
- return historyTag != null ? historyTag.uid : Process.INVALID_UID;
+ synchronized (this) {
+ ensureHistoryTagArray();
+ HistoryTag historyTag = mHistoryTags.get(index);
+ return historyTag != null ? historyTag.uid : Process.INVALID_UID;
+ }
}
+ @GuardedBy("this")
private void ensureHistoryTagArray() {
if (mHistoryTags != null) {
return;
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 09b19e6196a1..01b464fd8c7b 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -11459,7 +11459,7 @@ public class BatteryStatsImpl extends BatteryStats {
@Override
public BatteryStatsHistoryIterator iterateBatteryStatsHistory(long startTimeMs,
long endTimeMs) {
- return mHistory.copy().iterate(startTimeMs, endTimeMs);
+ return mHistory.iterate(startTimeMs, endTimeMs);
}
@Override
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
index cd3db36662d6..ba4c127ac3d0 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
@@ -74,8 +74,7 @@ public class PowerStatsAggregator {
boolean clockUpdateAdded = false;
long baseTime = startTimeMs > 0 ? startTimeMs : UNINITIALIZED;
long lastTime = 0;
- try (BatteryStatsHistoryIterator iterator =
- mHistory.copy().iterate(startTimeMs, endTimeMs)) {
+ try (BatteryStatsHistoryIterator iterator = mHistory.iterate(startTimeMs, endTimeMs)) {
while (iterator.hasNext()) {
BatteryStats.HistoryItem item = iterator.next();
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index bb70080362b1..92513760fa4a 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
@@ -21,6 +21,9 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -96,18 +99,11 @@ public class BatteryStatsHistoryTest {
mClock.realtime = 123;
mHistory = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
- mStepDetailsCalculator, mClock, mMonotonicClock, mTracer) {
- @Override
- public boolean readFileToParcel(Parcel out, AtomicFile file) {
- mReadFiles.add(file.getBaseFile().getName());
- return super.readFileToParcel(out, file);
- }
- };
+ mStepDetailsCalculator, mClock, mMonotonicClock, mTracer);
when(mStepDetailsCalculator.getHistoryStepDetails())
.thenReturn(new BatteryStats.HistoryStepDetails());
-
mHistoryPrinter = new BatteryStats.HistoryPrinter();
}
@@ -276,6 +272,15 @@ public class BatteryStatsHistoryTest {
mReadFiles.clear();
+ // Make an immutable copy and spy on it
+ mHistory = spy(mHistory.copy());
+
+ doAnswer(invocation -> {
+ AtomicFile file = invocation.getArgument(1);
+ mReadFiles.add(file.getBaseFile().getName());
+ return invocation.callRealMethod();
+ }).when(mHistory).readFileToParcel(any(), any());
+
// Prepare history for iteration
mHistory.iterate(0, MonotonicClock.UNDEFINED);
@@ -309,6 +314,15 @@ public class BatteryStatsHistoryTest {
mReadFiles.clear();
+ // Make an immutable copy and spy on it
+ mHistory = spy(mHistory.copy());
+
+ doAnswer(invocation -> {
+ AtomicFile file = invocation.getArgument(1);
+ mReadFiles.add(file.getBaseFile().getName());
+ return invocation.callRealMethod();
+ }).when(mHistory).readFileToParcel(any(), any());
+
// Prepare history for iteration
mHistory.iterate(1000, 3000);