Merge "Revert "Revert "Breaking history writing out of BatteryStatsImpl"""
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 09a52e4..da20626 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2326,11 +2326,6 @@
public abstract void finishIteratingHistoryLocked();
/**
- * Return the base time offset for the battery history.
- */
- public abstract long getHistoryBaseTime();
-
- /**
* Returns the number of times the device has been started.
*/
public abstract int getStartCount();
@@ -7615,8 +7610,6 @@
CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
getEndPlatformVersion());
- long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
-
if ((flags & (DUMP_INCLUDE_HISTORY | DUMP_HISTORY_ONLY)) != 0) {
if (startIteratingHistoryLocked()) {
try {
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 962870e..6909965 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -17,25 +17,35 @@
package com.android.internal.os;
import android.annotation.Nullable;
-import android.os.BatteryStats;
+import android.os.BatteryManager;
+import android.os.BatteryStats.HistoryItem;
+import android.os.BatteryStats.HistoryStepDetails;
+import android.os.BatteryStats.HistoryTag;
import android.os.Parcel;
+import android.os.ParcelFormatException;
+import android.os.Process;
import android.os.StatFs;
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ParseUtils;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
-import java.util.function.Supplier;
+import java.util.concurrent.locks.ReentrantLock;
/**
* BatteryStatsHistory encapsulates battery history files.
@@ -56,57 +66,62 @@
* All interfaces in BatteryStatsHistory should only be called by BatteryStatsImpl and protected by
* locks on BatteryStatsImpl object.
*/
-@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class BatteryStatsHistory {
private static final boolean DEBUG = false;
private static final String TAG = "BatteryStatsHistory";
// Current on-disk Parcel version. Must be updated when the format of the parcelable changes
- public static final int VERSION = 208;
+ private static final int VERSION = 208;
- public static final String HISTORY_DIR = "battery-history";
- public static final String FILE_SUFFIX = ".bin";
+ private static final String HISTORY_DIR = "battery-history";
+ private static final String FILE_SUFFIX = ".bin";
private static final int MIN_FREE_SPACE = 100 * 1024 * 1024;
+
// Part of initial delta int that specifies the time delta.
- public static final int DELTA_TIME_MASK = 0x7ffff;
- public static final int DELTA_TIME_LONG = 0x7ffff; // The delta is a following long
- public static final int DELTA_TIME_INT = 0x7fffe; // The delta is a following int
- public static final int DELTA_TIME_ABS = 0x7fffd; // Following is an entire abs update.
+ static final int DELTA_TIME_MASK = 0x7ffff;
+ static final int DELTA_TIME_LONG = 0x7ffff; // The delta is a following long
+ static final int DELTA_TIME_INT = 0x7fffe; // The delta is a following int
+ static final int DELTA_TIME_ABS = 0x7fffd; // Following is an entire abs update.
// Flag in delta int: a new battery level int follows.
- public static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
+ static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
// Flag in delta int: a new full state and battery status int follows.
- public static final int DELTA_STATE_FLAG = 0x00100000;
+ static final int DELTA_STATE_FLAG = 0x00100000;
// Flag in delta int: a new full state2 int follows.
- public static final int DELTA_STATE2_FLAG = 0x00200000;
+ static final int DELTA_STATE2_FLAG = 0x00200000;
// Flag in delta int: contains a wakelock or wakeReason tag.
- public static final int DELTA_WAKELOCK_FLAG = 0x00400000;
+ static final int DELTA_WAKELOCK_FLAG = 0x00400000;
// Flag in delta int: contains an event description.
- public static final int DELTA_EVENT_FLAG = 0x00800000;
+ static final int DELTA_EVENT_FLAG = 0x00800000;
// Flag in delta int: contains the battery charge count in uAh.
- public static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000;
+ static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000;
// These upper bits are the frequently changing state bits.
- public static final int DELTA_STATE_MASK = 0xfe000000;
+ static final int DELTA_STATE_MASK = 0xfe000000;
// These are the pieces of battery state that are packed in to the upper bits of
// the state int that have been packed in to the first delta int. They must fit
// in STATE_BATTERY_MASK.
- public static final int STATE_BATTERY_MASK = 0xff000000;
- public static final int STATE_BATTERY_STATUS_MASK = 0x00000007;
- public static final int STATE_BATTERY_STATUS_SHIFT = 29;
- public static final int STATE_BATTERY_HEALTH_MASK = 0x00000007;
- public static final int STATE_BATTERY_HEALTH_SHIFT = 26;
- public static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
- public static final int STATE_BATTERY_PLUG_SHIFT = 24;
+ static final int STATE_BATTERY_MASK = 0xff000000;
+ static final int STATE_BATTERY_STATUS_MASK = 0x00000007;
+ static final int STATE_BATTERY_STATUS_SHIFT = 29;
+ static final int STATE_BATTERY_HEALTH_MASK = 0x00000007;
+ static final int STATE_BATTERY_HEALTH_SHIFT = 26;
+ static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
+ static final int STATE_BATTERY_PLUG_SHIFT = 24;
// We use the low bit of the battery state int to indicate that we have full details
// from a battery level change.
- public static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
+ static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
// Flag in history tag index: indicates that this is the first occurrence of this tag,
// therefore the tag value is written in the parcel
- public static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
+ static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
- @Nullable
- private final Supplier<Integer> mMaxHistoryFiles;
private final Parcel mHistoryBuffer;
+ private final File mSystemDir;
+ private final HistoryStepDetailsCalculator mStepDetailsCalculator;
private final File mHistoryDir;
+ private final Clock mClock;
+
+ private int mMaxHistoryFiles;
+ private int mMaxHistoryBufferSize;
+
/**
* The active history file that the history buffer is backed up into.
*/
@@ -144,19 +159,77 @@
*/
private int mParcelIndex = 0;
+ private final ReentrantLock mWriteLock = new ReentrantLock();
+
+ private final HistoryItem mHistoryCur = new HistoryItem();
+
+ private boolean mHaveBatteryLevel;
+ private boolean mRecordingHistory;
+
+ private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
+ private static final int MAX_HISTORY_TAG_STRING_LENGTH = 1024;
+
+ private final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
+ private SparseArray<HistoryTag> mHistoryTags;
+ private final HistoryItem mHistoryLastWritten = new HistoryItem();
+ private final HistoryItem mHistoryLastLastWritten = new HistoryItem();
+ private final HistoryItem mHistoryAddTmp = new HistoryItem();
+ private int mNextHistoryTagIdx = 0;
+ private int mNumHistoryTagChars = 0;
+ private int mHistoryBufferLastPos = -1;
+ private int mActiveHistoryStates = 0xffffffff;
+ private int mActiveHistoryStates2 = 0xffffffff;
+ private long mLastHistoryElapsedRealtimeMs = 0;
+ private long mTrackRunningHistoryElapsedRealtimeMs = 0;
+ private long mTrackRunningHistoryUptimeMs = 0;
+ private long mHistoryBaseTimeMs;
+
+ private byte mLastHistoryStepLevel = 0;
+
+ private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
+
+ /**
+ * A delegate responsible for computing additional details for a step in battery history.
+ */
+ public interface HistoryStepDetailsCalculator {
+ /**
+ * Returns additional details for the current history step or null.
+ */
+ @Nullable
+ HistoryStepDetails getHistoryStepDetails();
+
+ /**
+ * Resets the calculator to get ready for a new battery session
+ */
+ void clear();
+ }
+
/**
* Constructor
*
- * @param historyBuffer The in-memory history buffer.
- * @param systemDir typically /data/system
- * @param maxHistoryFiles the largest number of history buffer files to keep
+ * @param systemDir typically /data/system
+ * @param maxHistoryFiles the largest number of history buffer files to keep
+ * @param maxHistoryBufferSize the most amount of RAM to used for buffering of history steps
*/
- public BatteryStatsHistory(Parcel historyBuffer, File systemDir,
- Supplier<Integer> maxHistoryFiles) {
- mHistoryBuffer = historyBuffer;
- mHistoryDir = new File(systemDir, HISTORY_DIR);
- mMaxHistoryFiles = maxHistoryFiles;
+ public BatteryStatsHistory(File systemDir, int maxHistoryFiles, int maxHistoryBufferSize,
+ HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
+ this(Parcel.obtain(), systemDir, maxHistoryFiles, maxHistoryBufferSize,
+ stepDetailsCalculator, clock);
+ initHistoryBuffer();
+ }
+ @VisibleForTesting
+ public BatteryStatsHistory(Parcel historyBuffer, File systemDir,
+ int maxHistoryFiles, int maxHistoryBufferSize,
+ HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
+ mHistoryBuffer = historyBuffer;
+ mSystemDir = systemDir;
+ mMaxHistoryFiles = maxHistoryFiles;
+ mMaxHistoryBufferSize = maxHistoryBufferSize;
+ mStepDetailsCalculator = stepDetailsCalculator;
+ mClock = clock;
+
+ mHistoryDir = new File(systemDir, HISTORY_DIR);
mHistoryDir.mkdirs();
if (!mHistoryDir.exists()) {
Slog.wtf(TAG, "HistoryDir does not exist:" + mHistoryDir.getPath());
@@ -192,19 +265,81 @@
}
}
- /**
- * Used when BatteryStatsImpl object is created from deserialization of a parcel,
- * such as Settings app or checkin file.
- * @param historyBuffer the history buffer
- */
- public BatteryStatsHistory(Parcel historyBuffer) {
+ public BatteryStatsHistory(HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
+ mStepDetailsCalculator = stepDetailsCalculator;
+ mClock = clock;
+
+ mHistoryBuffer = Parcel.obtain();
+ mSystemDir = null;
mHistoryDir = null;
- mHistoryBuffer = historyBuffer;
- mMaxHistoryFiles = null;
+ initHistoryBuffer();
}
- public File getHistoryDirectory() {
- return mHistoryDir;
+ /**
+ * Used when BatteryStatsImpl object is created from deserialization of a parcel,
+ * such as a checkin file.
+ */
+ private BatteryStatsHistory(Parcel historyBuffer,
+ HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
+ mHistoryBuffer = historyBuffer;
+ mClock = clock;
+ mSystemDir = null;
+ mHistoryDir = null;
+ mStepDetailsCalculator = stepDetailsCalculator;
+ }
+
+ private void initHistoryBuffer() {
+ mHistoryBaseTimeMs = 0;
+ mLastHistoryElapsedRealtimeMs = 0;
+ mTrackRunningHistoryElapsedRealtimeMs = 0;
+ mTrackRunningHistoryUptimeMs = 0;
+
+ mHistoryBuffer.setDataSize(0);
+ mHistoryBuffer.setDataPosition(0);
+ mHistoryBuffer.setDataCapacity(mMaxHistoryBufferSize / 2);
+ mHistoryLastLastWritten.clear();
+ mHistoryLastWritten.clear();
+ mHistoryTagPool.clear();
+ mNextHistoryTagIdx = 0;
+ mNumHistoryTagChars = 0;
+ mHistoryBufferLastPos = -1;
+ mActiveHistoryStates = 0xffffffff;
+ mActiveHistoryStates2 = 0xffffffff;
+ if (mStepDetailsCalculator != null) {
+ mStepDetailsCalculator.clear();
+ }
+ }
+
+ /**
+ * Changes the maximum number of history files to be kept.
+ */
+ public void setMaxHistoryFiles(int maxHistoryFiles) {
+ mMaxHistoryFiles = maxHistoryFiles;
+ }
+
+ /**
+ * Changes the maximum size of the history buffer, in bytes.
+ */
+ public void setMaxHistoryBufferSize(int maxHistoryBufferSize) {
+ mMaxHistoryBufferSize = maxHistoryBufferSize;
+ }
+
+ /**
+ * Creates a read-only copy of the battery history. Does not copy the files stored
+ * in the system directory, so it is not safe while actively writing history.
+ */
+ public BatteryStatsHistory copy() {
+ // Make a copy of battery history to avoid concurrent modification.
+ Parcel historyBuffer = Parcel.obtain();
+ historyBuffer.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+ return new BatteryStatsHistory(historyBuffer, mSystemDir, 0, 0, null, null);
+ }
+
+ /**
+ * Returns true if this instance only supports reading history.
+ */
+ public boolean isReadOnly() {
+ return mActiveFile == null;
}
/**
@@ -221,12 +356,13 @@
/**
* Create history AtomicFile from file number.
+ *
* @param num file number.
* @return AtomicFile object.
*/
private AtomicFile getFile(int num) {
return new AtomicFile(
- new File(mHistoryDir, num + FILE_SUFFIX));
+ new File(mHistoryDir, num + FILE_SUFFIX));
}
/**
@@ -234,7 +370,7 @@
* create next history file.
*/
public void startNextFile() {
- if (mMaxHistoryFiles == null) {
+ if (mMaxHistoryFiles == 0) {
Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history");
return;
}
@@ -264,7 +400,7 @@
// if there are more history files than allowed, delete oldest history files.
// mMaxHistoryFiles comes from Constants.MAX_HISTORY_FILES and can be updated by GService
// config at run time.
- while (mFileNumbers.size() > mMaxHistoryFiles.get()) {
+ while (mFileNumbers.size() > mMaxHistoryFiles) {
int oldest = mFileNumbers.get(0);
getFile(oldest).delete();
mFileNumbers.remove(0);
@@ -272,36 +408,43 @@
}
/**
- * Delete all existing history files. Active history file start from number 0 again.
+ * Clear history buffer and delete all existing history files. Active history file start from
+ * number 0 again.
*/
- public void resetAllFiles() {
+ public void reset() {
+ if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!");
for (Integer i : mFileNumbers) {
getFile(i).delete();
}
mFileNumbers.clear();
mFileNumbers.add(0);
setActiveFile(0);
+
+ initHistoryBuffer();
}
/**
* Start iterating history files and history buffer.
+ *
* @return always return true.
*/
- public boolean startIteratingHistory() {
+ public BatteryStatsHistoryIterator iterate() {
mRecordCount = 0;
mCurrentFileIndex = 0;
mCurrentParcel = null;
mCurrentParcelEnd = 0;
mParcelIndex = 0;
- return true;
+ mBatteryStatsHistoryIterator = new BatteryStatsHistoryIterator(this);
+ return mBatteryStatsHistoryIterator;
}
/**
* Finish iterating history files and history buffer.
*/
- public void finishIteratingHistory() {
+ void finishIteratingHistory() {
// setDataPosition so mHistoryBuffer Parcel can be written.
mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize());
+ mBatteryStatsHistoryIterator = null;
if (DEBUG) {
Slog.d(TAG, "Battery history records iterated: " + mRecordCount);
}
@@ -311,11 +454,12 @@
* When iterating history files and history buffer, always start from the lowest numbered
* history file, when reached the mActiveFile (highest numbered history file), do not read from
* mActiveFile, read from history buffer instead because the buffer has more updated data.
+ *
* @param out a history item.
* @return The parcel that has next record. null if finished all history files and history
- * buffer
+ * buffer
*/
- public Parcel getNextParcel(BatteryStats.HistoryItem out) {
+ public Parcel getNextParcel(HistoryItem out) {
if (mRecordCount == 0) {
// reset out if it is the first record.
out.clear();
@@ -323,8 +467,7 @@
++mRecordCount;
// First iterate through all records in current parcel.
- if (mCurrentParcel != null)
- {
+ if (mCurrentParcel != null) {
if (mCurrentParcel.dataPosition() < mCurrentParcelEnd) {
// There are more records in current parcel.
return mCurrentParcel;
@@ -389,7 +532,8 @@
/**
* Read history file into a parcel.
- * @param out the Parcel read into.
+ *
+ * @param out the Parcel read into.
* @param file the File to read from.
* @return true if success, false otherwise.
*/
@@ -402,8 +546,8 @@
Slog.d(TAG, "readFileToParcel:" + file.getBaseFile().getPath()
+ " duration ms:" + (SystemClock.uptimeMillis() - start));
}
- } catch(Exception e) {
- Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e);
return false;
}
out.unmarshall(raw, 0, raw.length);
@@ -413,6 +557,7 @@
/**
* Skip the header part of history parcel.
+ *
* @param p history parcel to skip head.
* @return true if version match, false if not.
*/
@@ -428,18 +573,68 @@
}
/**
+ * Writes the battery history contents for persistence.
+ */
+ public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
+ out.writeBoolean(inclHistory);
+ if (inclHistory) {
+ writeToParcel(out);
+ }
+
+ out.writeInt(mHistoryTagPool.size());
+ for (Map.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
+ HistoryTag tag = ent.getKey();
+ out.writeInt(ent.getValue());
+ out.writeString(tag.string);
+ out.writeInt(tag.uid);
+ }
+ }
+
+ /**
+ * Reads battery history contents from a persisted parcel.
+ */
+ public void readSummaryFromParcel(Parcel in) {
+ boolean inclHistory = in.readBoolean();
+ if (inclHistory) {
+ readFromParcel(in);
+ }
+
+ mHistoryTagPool.clear();
+ mNextHistoryTagIdx = 0;
+ mNumHistoryTagChars = 0;
+
+ int numTags = in.readInt();
+ for (int i = 0; i < numTags; i++) {
+ int idx = in.readInt();
+ String str = in.readString();
+ int uid = in.readInt();
+ HistoryTag tag = new HistoryTag();
+ tag.string = str;
+ tag.uid = uid;
+ tag.poolIdx = idx;
+ mHistoryTagPool.put(tag, idx);
+ if (idx >= mNextHistoryTagIdx) {
+ mNextHistoryTagIdx = idx + 1;
+ }
+ mNumHistoryTagChars += tag.string.length() + 1;
+ }
+ }
+
+ /**
* Read all history files and serialize into a big Parcel.
* Checkin file calls this method.
*
* @param out the output parcel
*/
public void writeToParcel(Parcel out) {
+ writeHistoryBuffer(out);
writeToParcel(out, false /* useBlobs */);
}
/**
* This is for Settings app, when Settings app receives big history parcel, it call
* this method to parse it into list of parcels.
+ *
* @param out the output parcel
*/
public void writeToBatteryUsageStatsParcel(Parcel out) {
@@ -450,13 +645,13 @@
private void writeToParcel(Parcel out, boolean useBlobs) {
final long start = SystemClock.uptimeMillis();
out.writeInt(mFileNumbers.size() - 1);
- for(int i = 0; i < mFileNumbers.size() - 1; i++) {
+ for (int i = 0; i < mFileNumbers.size() - 1; i++) {
AtomicFile file = getFile(mFileNumbers.get(i));
byte[] raw = new byte[0];
try {
raw = file.readFully();
- } catch(Exception e) {
- Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e);
}
if (useBlobs) {
out.writeBlob(raw);
@@ -480,17 +675,55 @@
Parcel historyBuffer = Parcel.obtain();
historyBuffer.unmarshall(historyBlob, 0, historyBlob.length);
- BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer);
+ BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer, null,
+ Clock.SYSTEM_CLOCK);
history.readFromParcel(in, true /* useBlobs */);
return history;
}
/**
+ * Read history from a check-in file.
+ */
+ public boolean readSummary() {
+ if (mActiveFile == null) {
+ Slog.w(TAG, "readSummary: no history file associated with this instance");
+ return false;
+ }
+
+ Parcel parcel = Parcel.obtain();
+ try {
+ final long start = SystemClock.uptimeMillis();
+ if (mActiveFile.exists()) {
+ byte[] raw = mActiveFile.readFully();
+ if (raw.length > 0) {
+ parcel.unmarshall(raw, 0, raw.length);
+ parcel.setDataPosition(0);
+ readHistoryBuffer(parcel);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "read history file::"
+ + mActiveFile.getBaseFile().getPath()
+ + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
+ - start));
+ }
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error reading battery history", e);
+ reset();
+ return false;
+ } finally {
+ parcel.recycle();
+ }
+ return true;
+ }
+
+ /**
* This is for the check-in file, which has all history files embedded.
*
* @param in the input parcel.
*/
public void readFromParcel(Parcel in) {
+ readHistoryBuffer(in);
readFromParcel(in, false /* useBlobs */);
}
@@ -498,7 +731,7 @@
final long start = SystemClock.uptimeMillis();
mHistoryParcels = new ArrayList<>();
final int count = in.readInt();
- for(int i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
byte[] temp = useBlobs ? in.readBlob() : in.createByteArray();
if (temp == null || temp.length == 0) {
continue;
@@ -521,10 +754,12 @@
return stats.getAvailableBytes() > MIN_FREE_SPACE;
}
+ @VisibleForTesting
public List<Integer> getFilesNumbers() {
return mFileNumbers;
}
+ @VisibleForTesting
public AtomicFile getActiveFile() {
return mActiveFile;
}
@@ -534,15 +769,972 @@
*/
public int getHistoryUsedSize() {
int ret = 0;
- for(int i = 0; i < mFileNumbers.size() - 1; i++) {
+ for (int i = 0; i < mFileNumbers.size() - 1; i++) {
ret += getFile(mFileNumbers.get(i)).getBaseFile().length();
}
ret += mHistoryBuffer.dataSize();
if (mHistoryParcels != null) {
- for(int i = 0; i < mHistoryParcels.size(); i++) {
+ for (int i = 0; i < mHistoryParcels.size(); i++) {
ret += mHistoryParcels.get(i).dataSize();
}
}
return ret;
}
+
+ /**
+ * Enables/disables recording of history. When disabled, all "record*" calls are a no-op.
+ */
+ public void setHistoryRecordingEnabled(boolean enabled) {
+ mRecordingHistory = enabled;
+ }
+
+ /**
+ * Returns true if history recording is enabled.
+ */
+ public boolean isRecordingHistory() {
+ return mRecordingHistory;
+ }
+
+ /**
+ * Forces history recording regardless of charging state.
+ */
+ @VisibleForTesting
+ public void forceRecordAllHistory() {
+ mHaveBatteryLevel = true;
+ mRecordingHistory = true;
+ }
+
+ /**
+ * Starts a history buffer by recording the current wall-clock time.
+ */
+ 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;
+ }
+
+ /**
+ * Prepares to continue recording after restoring previous history from persistent storage.
+ */
+ public void continueRecordingHistory() {
+ if (mHistoryBuffer.dataPosition() <= 0 && mFileNumbers.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);
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Notes the current battery state to be reflected in the next written history item.
+ */
+ 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;
+ }
+
+ /**
+ * 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;
+ }
+ }
+
+ /**
+ * 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;
+ }
+ }
+
+ /**
+ * Records a history event with the given code, name and UID.
+ */
+ 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);
+ }
+
+ /**
+ * Records a time change event.
+ */
+ public void recordCurrentTimeChange(long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) {
+ if (!mRecordingHistory) {
+ return;
+ }
+
+ 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;
+ }
+
+ mHistoryCur.currentTime = currentTimeMs;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur, HistoryItem.CMD_SHUTDOWN);
+ mHistoryCur.currentTime = 0;
+ }
+
+ /**
+ * Records a battery state change event.
+ */
+ 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));
+ }
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a history item with the amount of charge consumed by WiFi. Used on certain devices
+ * equipped with on-device power metering.
+ */
+ public void recordWifiConsumedCharge(long elapsedRealtimeMs, long uptimeMs,
+ double monitoredRailChargeMah) {
+ mHistoryCur.wifiRailChargeMah += monitoredRailChargeMah;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a wakelock start event.
+ */
+ 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);
+ }
+
+ /**
+ * Updates the previous history event with a wakelock name and UID.
+ */
+ 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);
+ }
+ return true;
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Records an event when some state flags change to true and some to false.
+ */
+ public void recordStateChangeEvent(long elapsedRealtimeMs, long uptimeMs, int stateStartFlags,
+ int stateStopFlags) {
+ 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);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Records a screen brightness change event.
+ */
+ public void recordScreenBrightnessEvent(long elapsedRealtimeMs, long uptimeMs,
+ int brightnessBin) {
+ mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_BRIGHTNESS_MASK)
+ | (brightnessBin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a GNSS signal level change event.
+ */
+ public void recordGpsSignalQualityEvent(long elapsedRealtimeMs, long uptimeMs,
+ int signalLevel) {
+ mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
+ | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a device idle mode change event.
+ */
+ public void recordDeviceIdleEvent(long elapsedRealtimeMs, long uptimeMs, int mode) {
+ mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
+ | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a telephony state change event.
+ */
+ 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 =
+ (mHistoryCur.states & ~HistoryItem.STATE_PHONE_STATE_MASK)
+ | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
+ }
+ if (signalStrength != -1) {
+ mHistoryCur.states =
+ (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
+ | (signalStrength << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
+ }
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a data connection type change event.
+ */
+ public void recordDataConnectionTypeChangeEvent(long elapsedRealtimeMs, long uptimeMs,
+ int dataConnectionType) {
+ mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_DATA_CONNECTION_MASK)
+ | (dataConnectionType << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a WiFi supplicant state change event.
+ */
+ public void recordWifiSupplicantStateChangeEvent(long elapsedRealtimeMs, long uptimeMs,
+ int supplState) {
+ mHistoryCur.states2 =
+ (mHistoryCur.states2 & ~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
+ | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Records a WiFi signal strength change event.
+ */
+ public void recordWifiSignalStrengthChangeEvent(long elapsedRealtimeMs, long uptimeMs,
+ int strengthBin) {
+ mHistoryCur.states2 =
+ (mHistoryCur.states2 & ~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
+ | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * 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);
+ }
+ }
+ mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
+ mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
+ mTrackRunningHistoryUptimeMs = uptimeMs;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, mHistoryCur);
+ }
+
+ private void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
+ if (!mHaveBatteryLevel || !mRecordingHistory) {
+ return;
+ }
+
+ final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
+ final int diffStates = mHistoryLastWritten.states ^ (cur.states & mActiveHistoryStates);
+ final int diffStates2 = mHistoryLastWritten.states2 ^ (cur.states2 & mActiveHistoryStates2);
+ final int lastDiffStates = mHistoryLastWritten.states ^ mHistoryLastLastWritten.states;
+ final int lastDiffStates2 = mHistoryLastWritten.states2 ^ mHistoryLastLastWritten.states2;
+ if (DEBUG) {
+ Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
+ + Integer.toHexString(diffStates) + " lastDiff="
+ + Integer.toHexString(lastDiffStates) + " diff2="
+ + Integer.toHexString(diffStates2) + " lastDiff2="
+ + Integer.toHexString(lastDiffStates2));
+ }
+ if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
+ && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
+ && (diffStates2 & lastDiffStates2) == 0
+ && (!mHistoryLastWritten.tagsFirstOccurrence && !cur.tagsFirstOccurrence)
+ && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
+ && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
+ && mHistoryLastWritten.stepDetails == null
+ && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
+ || cur.eventCode == HistoryItem.EVENT_NONE)
+ && mHistoryLastWritten.batteryLevel == cur.batteryLevel
+ && mHistoryLastWritten.batteryStatus == cur.batteryStatus
+ && mHistoryLastWritten.batteryHealth == cur.batteryHealth
+ && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
+ && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
+ && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
+ // We can merge this new change in with the last one. Merging is
+ // allowed as long as only the states have changed, and within those states
+ // as long as no bit has changed both between now and the last entry, as
+ // well as the last entry and the one before it (so we capture any toggles).
+ if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
+ mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
+ mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
+ mHistoryBufferLastPos = -1;
+ elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
+ // If the last written history had a wakelock tag, we need to retain it.
+ // Note that the condition above made sure that we aren't in a case where
+ // both it and the current history item have a wakelock tag.
+ if (mHistoryLastWritten.wakelockTag != null) {
+ cur.wakelockTag = cur.localWakelockTag;
+ cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
+ }
+ // If the last written history had a wake reason tag, we need to retain it.
+ // Note that the condition above made sure that we aren't in a case where
+ // both it and the current history item have a wakelock tag.
+ if (mHistoryLastWritten.wakeReasonTag != null) {
+ cur.wakeReasonTag = cur.localWakeReasonTag;
+ cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
+ }
+ // If the last written history had an event, we need to retain it.
+ // Note that the condition above made sure that we aren't in a case where
+ // both it and the current history item have an event.
+ if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
+ cur.eventCode = mHistoryLastWritten.eventCode;
+ cur.eventTag = cur.localEventTag;
+ cur.eventTag.setTo(mHistoryLastWritten.eventTag);
+ }
+ mHistoryLastWritten.setTo(mHistoryLastLastWritten);
+ }
+ final int dataSize = mHistoryBuffer.dataSize();
+
+ if (dataSize >= mMaxHistoryBufferSize) {
+ if (mMaxHistoryBufferSize == 0) {
+ Slog.wtf(TAG, "mMaxHistoryBufferSize should not be zero when writing history");
+ mMaxHistoryBufferSize = 1024;
+ }
+
+ //open a new history file.
+ final long start = SystemClock.uptimeMillis();
+ writeHistory();
+ if (DEBUG) {
+ Slog.d(TAG, "addHistoryBufferLocked writeHistory took ms:"
+ + (SystemClock.uptimeMillis() - start));
+ }
+ startNextFile();
+ mHistoryBuffer.setDataSize(0);
+ mHistoryBuffer.setDataPosition(0);
+ mHistoryBuffer.setDataCapacity(mMaxHistoryBufferSize / 2);
+ mHistoryBufferLastPos = -1;
+ mHistoryLastWritten.clear();
+ mHistoryLastLastWritten.clear();
+
+ // Mark every entry in the pool with a flag indicating that the tag
+ // has not yet been encountered while writing the current history buffer.
+ for (Map.Entry<HistoryTag, Integer> entry : mHistoryTagPool.entrySet()) {
+ entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
+ }
+ // Make a copy of mHistoryCur.
+ HistoryItem copy = new HistoryItem();
+ copy.setTo(cur);
+ // startRecordingHistory will reset mHistoryCur.
+ startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
+ // Add the copy into history buffer.
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, copy, HistoryItem.CMD_UPDATE);
+ return;
+ }
+
+ if (dataSize == 0) {
+ // The history is currently empty; we need it to start with a time stamp.
+ cur.currentTime = mClock.currentTimeMillis();
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, cur, HistoryItem.CMD_RESET);
+ }
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs, cur, HistoryItem.CMD_UPDATE);
+ }
+
+ private void writeHistoryItem(long elapsedRealtimeMs,
+ @SuppressWarnings("UnusedVariable") long uptimeMs, HistoryItem cur, byte cmd) {
+ if (mBatteryStatsHistoryIterator != null) {
+ throw new IllegalStateException("Can't do this while iterating history!");
+ }
+ mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
+ mHistoryLastLastWritten.setTo(mHistoryLastWritten);
+ final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
+ mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
+ mHistoryLastWritten.tagsFirstOccurrence = hasTags;
+ mHistoryLastWritten.states &= mActiveHistoryStates;
+ mHistoryLastWritten.states2 &= mActiveHistoryStates2;
+ writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
+ mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
+ cur.wakelockTag = null;
+ cur.wakeReasonTag = null;
+ cur.eventCode = HistoryItem.EVENT_NONE;
+ cur.eventTag = null;
+ cur.tagsFirstOccurrence = false;
+ if (DEBUG) {
+ Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
+ + " now " + mHistoryBuffer.dataPosition()
+ + " size is now " + mHistoryBuffer.dataSize());
+ }
+ }
+
+ /*
+ The history delta format uses flags to denote further data in subsequent ints in the parcel.
+
+ There is always the first token, which may contain the delta time, or an indicator of
+ the length of the time (int or long) following this token.
+
+ First token: always present,
+ 31 23 15 7 0
+ â–ˆM|L|K|J|I|H|G|Fâ–ˆE|D|C|B|A|T|T|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆ
+
+ T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
+ follows containing the time, and 0x7ffff indicates a long immediately follows with the
+ delta time.
+ A: battery level changed and an int follows with battery data.
+ B: state changed and an int follows with state change data.
+ C: state2 has changed and an int follows with state2 change data.
+ D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
+ E: event data has changed and an event struct follows.
+ F: battery charge in coulombs has changed and an int with the charge follows.
+ G: state flag denoting that the mobile radio was active.
+ H: state flag denoting that the wifi radio was active.
+ I: state flag denoting that a wifi scan occurred.
+ J: state flag denoting that a wifi full lock was held.
+ K: state flag denoting that the gps was on.
+ L: state flag denoting that a wakelock was held.
+ M: state flag denoting that the cpu was running.
+
+ Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
+ with the time delta.
+
+ Battery level int: if A in the first token is set,
+ 31 23 15 7 0
+ â–ˆL|L|L|L|L|L|L|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆT|V|V|V|V|V|V|Vâ–ˆV|V|V|V|V|V|V|Dâ–ˆ
+
+ D: indicates that extra history details follow.
+ V: the battery voltage.
+ T: the battery temperature.
+ L: the battery level (out of 100).
+
+ State change int: if B in the first token is set,
+ 31 23 15 7 0
+ â–ˆS|S|S|H|H|H|P|Pâ–ˆF|E|D|C|B| | |Aâ–ˆ | | | | | | | â–ˆ | | | | | | | â–ˆ
+
+ A: wifi multicast was on.
+ B: battery was plugged in.
+ C: screen was on.
+ D: phone was scanning for signal.
+ E: audio was on.
+ F: a sensor was active.
+
+ State2 change int: if C in the first token is set,
+ 31 23 15 7 0
+ â–ˆM|L|K|J|I|H|H|Gâ–ˆF|E|D|C| | | | â–ˆ | | | | | | | â–ˆ |B|B|B|A|A|A|Aâ–ˆ
+
+ A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
+ B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
+ C: a bluetooth scan was active.
+ D: the camera was active.
+ E: bluetooth was on.
+ F: a phone call was active.
+ G: the device was charging.
+ H: 2 bits indicating the device-idle (doze) state: off, light, full
+ I: the flashlight was on.
+ J: wifi was on.
+ K: wifi was running.
+ L: video was playing.
+ M: power save mode was on.
+
+ Wakelock/wakereason struct: if D in the first token is set,
+ Event struct: if E in the first token is set,
+ History step details struct: if D in the battery level int is set,
+
+ Battery charge int: if F in the first token is set, an int representing the battery charge
+ in coulombs follows.
+ */
+ /**
+ * Writes the delta between the previous and current history items into history buffer.
+ */
+ public 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);
+ return;
+ }
+
+ final long deltaTime = cur.time - last.time;
+ final int lastBatteryLevelInt = buildBatteryLevelInt(last);
+ final int lastStateInt = buildStateInt(last);
+
+ int deltaTimeToken;
+ if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
+ deltaTimeToken = BatteryStatsHistory.DELTA_TIME_LONG;
+ } else if (deltaTime >= BatteryStatsHistory.DELTA_TIME_ABS) {
+ deltaTimeToken = BatteryStatsHistory.DELTA_TIME_INT;
+ } else {
+ deltaTimeToken = (int) deltaTime;
+ }
+ int firstToken = deltaTimeToken | (cur.states & BatteryStatsHistory.DELTA_STATE_MASK);
+ final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
+ ? BatteryStatsHistory.BATTERY_DELTA_LEVEL_FLAG : 0;
+ mLastHistoryStepLevel = cur.batteryLevel;
+ final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
+ final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
+ if (batteryLevelIntChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_BATTERY_LEVEL_FLAG;
+ }
+ final int stateInt = buildStateInt(cur);
+ final boolean stateIntChanged = stateInt != lastStateInt;
+ if (stateIntChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_STATE_FLAG;
+ }
+ final boolean state2IntChanged = cur.states2 != last.states2;
+ if (state2IntChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_STATE2_FLAG;
+ }
+ if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
+ firstToken |= BatteryStatsHistory.DELTA_WAKELOCK_FLAG;
+ }
+ if (cur.eventCode != HistoryItem.EVENT_NONE) {
+ firstToken |= BatteryStatsHistory.DELTA_EVENT_FLAG;
+ }
+
+ final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
+ if (batteryChargeChanged) {
+ firstToken |= BatteryStatsHistory.DELTA_BATTERY_CHARGE_FLAG;
+ }
+ dest.writeInt(firstToken);
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
+ + " deltaTime=" + deltaTime);
+ }
+
+ if (deltaTimeToken >= BatteryStatsHistory.DELTA_TIME_INT) {
+ if (deltaTimeToken == BatteryStatsHistory.DELTA_TIME_INT) {
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int) deltaTime);
+ dest.writeInt((int) deltaTime);
+ } else {
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
+ dest.writeLong(deltaTime);
+ }
+ }
+ if (batteryLevelIntChanged) {
+ dest.writeInt(batteryLevelInt);
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
+ + Integer.toHexString(batteryLevelInt)
+ + " batteryLevel=" + cur.batteryLevel
+ + " batteryTemp=" + cur.batteryTemperature
+ + " batteryVolt=" + (int) cur.batteryVoltage);
+ }
+ }
+ if (stateIntChanged) {
+ dest.writeInt(stateInt);
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: stateToken=0x"
+ + Integer.toHexString(stateInt)
+ + " batteryStatus=" + cur.batteryStatus
+ + " batteryHealth=" + cur.batteryHealth
+ + " batteryPlugType=" + cur.batteryPlugType
+ + " states=0x" + Integer.toHexString(cur.states));
+ }
+ }
+ if (state2IntChanged) {
+ dest.writeInt(cur.states2);
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: states2=0x"
+ + Integer.toHexString(cur.states2));
+ }
+ }
+ if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
+ int wakeLockIndex;
+ int wakeReasonIndex;
+ if (cur.wakelockTag != null) {
+ wakeLockIndex = writeHistoryTag(cur.wakelockTag);
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+ + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+ }
+ } else {
+ wakeLockIndex = 0xffff;
+ }
+ if (cur.wakeReasonTag != null) {
+ wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+ + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+ }
+ } else {
+ wakeReasonIndex = 0xffff;
+ }
+ dest.writeInt((wakeReasonIndex << 16) | wakeLockIndex);
+ if (cur.wakelockTag != null
+ && (wakeLockIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ cur.wakelockTag.writeToParcel(dest, 0);
+ cur.tagsFirstOccurrence = true;
+ }
+ if (cur.wakeReasonTag != null
+ && (wakeReasonIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ cur.wakeReasonTag.writeToParcel(dest, 0);
+ cur.tagsFirstOccurrence = true;
+ }
+ }
+ if (cur.eventCode != HistoryItem.EVENT_NONE) {
+ final int index = writeHistoryTag(cur.eventTag);
+ final int codeAndIndex = (cur.eventCode & 0xffff) | (index << 16);
+ dest.writeInt(codeAndIndex);
+ if ((index & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ cur.eventTag.writeToParcel(dest, 0);
+ cur.tagsFirstOccurrence = true;
+ }
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
+ + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
+ + cur.eventTag.string);
+ }
+ }
+
+ cur.stepDetails = mStepDetailsCalculator.getHistoryStepDetails();
+ if (includeStepDetails != 0) {
+ cur.stepDetails.writeToParcel(dest);
+ }
+
+ if (batteryChargeChanged) {
+ if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
+ dest.writeInt(cur.batteryChargeUah);
+ }
+ dest.writeDouble(cur.modemRailChargeMah);
+ dest.writeDouble(cur.wifiRailChargeMah);
+ }
+
+ private int buildBatteryLevelInt(HistoryItem h) {
+ return ((((int) h.batteryLevel) << 25) & 0xfe000000)
+ | ((((int) h.batteryTemperature) << 15) & 0x01ff8000)
+ | ((((int) h.batteryVoltage) << 1) & 0x00007ffe);
+ }
+
+ private int buildStateInt(HistoryItem h) {
+ int plugType = 0;
+ if ((h.batteryPlugType & BatteryManager.BATTERY_PLUGGED_AC) != 0) {
+ plugType = 1;
+ } else if ((h.batteryPlugType & BatteryManager.BATTERY_PLUGGED_USB) != 0) {
+ plugType = 2;
+ } else if ((h.batteryPlugType & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
+ plugType = 3;
+ }
+ return ((h.batteryStatus & BatteryStatsHistory.STATE_BATTERY_STATUS_MASK)
+ << BatteryStatsHistory.STATE_BATTERY_STATUS_SHIFT)
+ | ((h.batteryHealth & BatteryStatsHistory.STATE_BATTERY_HEALTH_MASK)
+ << BatteryStatsHistory.STATE_BATTERY_HEALTH_SHIFT)
+ | ((plugType & BatteryStatsHistory.STATE_BATTERY_PLUG_MASK)
+ << BatteryStatsHistory.STATE_BATTERY_PLUG_SHIFT)
+ | (h.states & (~BatteryStatsHistory.STATE_BATTERY_MASK));
+ }
+
+ /**
+ * Returns the index for the specified tag. If this is the first time the tag is encountered
+ * while writing the current history buffer, the method returns
+ * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
+ */
+ private int writeHistoryTag(HistoryTag tag) {
+ if (tag.string == null) {
+ Slog.wtfStack(TAG, "writeHistoryTag called with null name");
+ }
+
+ final int stringLength = tag.string.length();
+ if (stringLength > MAX_HISTORY_TAG_STRING_LENGTH) {
+ Slog.e(TAG, "Long battery history tag: " + tag.string);
+ tag.string = tag.string.substring(0, MAX_HISTORY_TAG_STRING_LENGTH);
+ }
+
+ Integer idxObj = mHistoryTagPool.get(tag);
+ int idx;
+ if (idxObj != null) {
+ idx = idxObj;
+ if ((idx & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
+ mHistoryTagPool.put(tag, idx & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
+ }
+ return idx;
+ } else if (mNextHistoryTagIdx < HISTORY_TAG_INDEX_LIMIT) {
+ idx = mNextHistoryTagIdx;
+ HistoryTag key = new HistoryTag();
+ key.setTo(tag);
+ tag.poolIdx = idx;
+ mHistoryTagPool.put(key, idx);
+ mNextHistoryTagIdx++;
+
+ mNumHistoryTagChars += stringLength + 1;
+ if (mHistoryTags != null) {
+ mHistoryTags.put(idx, key);
+ }
+ return idx | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
+ } else {
+ // Tag pool overflow: include the tag itself in the parcel
+ return HISTORY_TAG_INDEX_LIMIT | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
+ }
+ }
+
+ /**
+ * Don't allow any more batching in to the current history event.
+ */
+ public void commitCurrentHistoryBatchLocked() {
+ mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
+ }
+
+ /**
+ * Saves the accumulated history buffer in the active file, see {@link #getActiveFile()} .
+ */
+ public void writeHistory() {
+ if (mActiveFile == null) {
+ Slog.w(TAG, "writeHistory: no history file associated with this instance");
+ return;
+ }
+
+ 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();
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+ final long historyBaseTime = 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);
+ }
+
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** OLD mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ mHistoryBaseTimeMs = historyBaseTime;
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** NEW mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+
+ // We are just arbitrarily going to insert 1 minute from the sample of
+ // the last run until samples in this run.
+ if (mHistoryBaseTimeMs > 0) {
+ long oldnow = mClock.elapsedRealtime();
+ mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ }
+ }
+
+ private void writeHistoryBuffer(Parcel out) {
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** WRITING mHistoryBaseTimeMs: ");
+ TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
+ sb.append(" mLastHistoryElapsedRealtimeMs: ");
+ TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ out.writeInt(BatteryStatsHistory.VERSION);
+ out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
+ out.writeInt(mHistoryBuffer.dataSize());
+ if (DEBUG) {
+ Slog.i(TAG, "***************** WRITING HISTORY: "
+ + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
+ }
+ out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+ }
+
+ private void writeParcelToFileLocked(Parcel p, AtomicFile file) {
+ FileOutputStream fos = null;
+ mWriteLock.lock();
+ try {
+ final long startTimeMs = SystemClock.uptimeMillis();
+ fos = file.startWrite();
+ fos.write(p.marshall());
+ fos.flush();
+ file.finishWrite(fos);
+ if (DEBUG) {
+ Slog.d(TAG, "writeParcelToFileLocked file:" + file.getBaseFile().getPath()
+ + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs)
+ + " bytes:" + p.dataSize());
+ }
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "batterystats", SystemClock.uptimeMillis() - startTimeMs);
+ } catch (IOException e) {
+ Slog.w(TAG, "Error writing battery statistics", e);
+ file.failWrite(fos);
+ } finally {
+ mWriteLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the total number of history tags in the tag pool.
+ */
+ public int getHistoryStringPoolSize() {
+ return mHistoryTagPool.size();
+ }
+
+ /**
+ * Returns the total number of bytes occupied by the history tag pool.
+ */
+ public int getHistoryStringPoolBytes() {
+ 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ private void ensureHistoryTagArray() {
+ if (mHistoryTags != null) {
+ return;
+ }
+
+ mHistoryTags = new SparseArray<>(mHistoryTagPool.size());
+ for (Map.Entry<HistoryTag, Integer> entry : mHistoryTagPool.entrySet()) {
+ mHistoryTags.put(entry.getValue() & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG,
+ entry.getKey());
+ }
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
index de8b414..1bf878cb 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -36,7 +36,6 @@
public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) {
mBatteryStatsHistory = history;
- mBatteryStatsHistory.startIteratingHistory();
}
/**
@@ -231,4 +230,11 @@
out.batteryTemperature = (short) ((batteryLevelInt & 0x01ff8000) >>> 15);
out.batteryVoltage = (char) ((batteryLevelInt & 0x00007ffe) >>> 1);
}
+
+ /**
+ * Should be called when iteration is complete.
+ */
+ public void close() {
+ mBatteryStatsHistory.finishIteratingHistory();
+ }
}
diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
index fe4aa53..df902c2 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -657,7 +657,7 @@
// Now that we have finally received all the data, we can tell mStats about it.
synchronized (mStats) {
- mStats.addHistoryEventLocked(
+ mStats.recordHistoryEventLocked(
elapsedRealtime,
uptime,
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
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 0c9ada8..968f916 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -108,6 +108,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.BatteryStatsHistory.HistoryStepDetailsCalculator;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderTransactionNameResolver;
@@ -173,7 +174,6 @@
private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
private static final boolean DEBUG_BINDER_STATS = false;
private static final boolean DEBUG_MEMORY = false;
- private static final boolean DEBUG_HISTORY = false;
// TODO: remove "tcp" from network methods, since we measure total stats.
@@ -322,6 +322,11 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected Queue<UidToRemove> mPendingRemovedUids = new LinkedList<>();
+ @NonNull
+ BatteryStatsHistory copyHistory() {
+ return mHistory.copy();
+ }
+
@VisibleForTesting
public final class UidToRemove {
private final int mStartUid;
@@ -413,7 +418,7 @@
if (changed) {
final long uptimeMs = mClock.uptimeMillis();
final long elapsedRealtimeMs = mClock.elapsedRealtime();
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
}
}
@@ -668,16 +673,16 @@
/**
* Mapping isolated uids to the actual owning app uid.
*/
- final SparseIntArray mIsolatedUids = new SparseIntArray();
+ private final SparseIntArray mIsolatedUids = new SparseIntArray();
/**
* Internal reference count of isolated uids.
*/
- final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
+ private final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray();
/**
* The statistics we have collected organized by uids.
*/
- final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
+ private final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>();
// A set of pools of currently active timers. When a timer is queried, we will divide the
// elapsed time by the number of active timers to arrive at that timer's share of the time.
@@ -685,20 +690,21 @@
// changes.
@VisibleForTesting
protected ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
- final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
- final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
- final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = new SparseArray<>();
- final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
- final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mDrawTimers = new ArrayList<>();
+ private final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers = new SparseArray<>();
+ private final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<>();
+ private final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
+ new SparseArray<>();
+ private final ArrayList<StopwatchTimer> mAudioTurnedOnTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
+ private final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
// Last partial timers we use for distributing CPU usage.
@VisibleForTesting
@@ -713,69 +719,24 @@
protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true);
private boolean mSystemReady;
- boolean mShuttingDown;
+ private boolean mShuttingDown;
- final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
+ private final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
+ private final HistoryStepDetailsCalculatorImpl mStepDetailsCalculator =
+ new HistoryStepDetailsCalculatorImpl();
- long mHistoryBaseTimeMs;
- protected boolean mHaveBatteryLevel = false;
- protected boolean mRecordingHistory = false;
- int mNumHistoryItems;
-
- private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
- private static final int MAX_HISTORY_TAG_STRING_LENGTH = 1024;
-
- final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
- private SparseArray<HistoryTag> mHistoryTags;
- final Parcel mHistoryBuffer = Parcel.obtain();
- final HistoryItem mHistoryLastWritten = new HistoryItem();
- final HistoryItem mHistoryLastLastWritten = new HistoryItem();
- final HistoryItem mHistoryAddTmp = new HistoryItem();
- int mNextHistoryTagIdx = 0;
- int mNumHistoryTagChars = 0;
- int mHistoryBufferLastPos = -1;
- int mActiveHistoryStates = 0xffffffff;
- int mActiveHistoryStates2 = 0xffffffff;
- long mLastHistoryElapsedRealtimeMs = 0;
- long mTrackRunningHistoryElapsedRealtimeMs = 0;
- long mTrackRunningHistoryUptimeMs = 0;
+ private boolean mHaveBatteryLevel = false;
+ private boolean mBatteryPluggedIn;
+ private int mBatteryStatus;
+ private int mBatteryLevel;
+ private int mBatteryPlugType;
+ private int mBatteryChargeUah;
+ private int mBatteryHealth;
+ private int mBatteryTemperature;
+ private int mBatteryVoltageMv = -1;
@NonNull
- final BatteryStatsHistory mBatteryStatsHistory;
-
- final HistoryItem mHistoryCur = new HistoryItem();
-
- // Used by computeHistoryStepDetails
- HistoryStepDetails mLastHistoryStepDetails = null;
- byte mLastHistoryStepLevel = 0;
- final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
- final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
-
- /**
- * Total time (in milliseconds) spent executing in user code.
- */
- long mLastStepCpuUserTimeMs;
- long mCurStepCpuUserTimeMs;
- /**
- * Total time (in milliseconds) spent executing in kernel code.
- */
- long mLastStepCpuSystemTimeMs;
- long mCurStepCpuSystemTimeMs;
- /**
- * Times from /proc/stat (but measured in milliseconds).
- */
- long mLastStepStatUserTimeMs;
- long mLastStepStatSystemTimeMs;
- long mLastStepStatIOWaitTimeMs;
- long mLastStepStatIrqTimeMs;
- long mLastStepStatSoftIrqTimeMs;
- long mLastStepStatIdleTimeMs;
- long mCurStepStatUserTimeMs;
- long mCurStepStatSystemTimeMs;
- long mCurStepStatIOWaitTimeMs;
- long mCurStepStatIrqTimeMs;
- long mCurStepStatSoftIrqTimeMs;
- long mCurStepStatIdleTimeMs;
+ private final BatteryStatsHistory mHistory;
private BatteryStatsHistoryIterator mBatteryStatsHistoryIterator;
@@ -1391,7 +1352,6 @@
int mDischargeUnplugLevel;
int mDischargePlugLevel;
int mDischargeCurrentLevel;
- int mCurrentBatteryLevel;
int mLowDischargeAmountSinceCharge;
int mHighDischargeAmountSinceCharge;
int mDischargeScreenOnUnplugLevel;
@@ -1443,7 +1403,6 @@
private int mNumConnectivityChange;
- private int mBatteryVoltageMv = -1;
private int mEstimatedBatteryCapacityMah = -1;
private int mLastLearnedBatteryCapacityUah = -1;
@@ -1627,28 +1586,27 @@
}
public BatteryStatsImpl(Clock clock) {
- this(clock, (File) null);
+ this(clock, null);
}
public BatteryStatsImpl(Clock clock, File historyDirectory) {
init(clock);
+ mHandler = null;
+ mConstants = new Constants(mHandler);
mStartClockTimeMs = clock.currentTimeMillis();
mCheckinFile = null;
mDailyFile = null;
if (historyDirectory == null) {
mStatsFile = null;
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+ mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
} else {
mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, historyDirectory,
- this::getMaxHistoryFiles);
+ mHistory = new BatteryStatsHistory(historyDirectory, mConstants.MAX_HISTORY_FILES,
+ mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
}
- mHandler = null;
mPlatformIdleStateCallback = null;
mMeasuredEnergyRetriever = null;
mUserInfoProvider = null;
- mConstants = new Constants(mHandler);
- clearHistoryLocked();
}
private void init(Clock clock) {
@@ -3911,406 +3869,188 @@
return kmt;
}
- /**
- * Returns the index for the specified tag. If this is the first time the tag is encountered
- * while writing the current history buffer, the method returns
- * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
- */
- private int writeHistoryTag(HistoryTag tag) {
- if (tag.string == null) {
- Slog.wtfStack(TAG, "writeHistoryTag called with null name");
- }
+ private class HistoryStepDetailsCalculatorImpl implements HistoryStepDetailsCalculator {
+ private final HistoryStepDetails mDetails = new HistoryStepDetails();
- final int stringLength = tag.string.length();
- if (stringLength > MAX_HISTORY_TAG_STRING_LENGTH) {
- Slog.e(TAG, "Long battery history tag: " + tag.string);
- tag.string = tag.string.substring(0, MAX_HISTORY_TAG_STRING_LENGTH);
- }
+ private boolean mHasHistoryStepDetails;
- Integer idxObj = mHistoryTagPool.get(tag);
- int idx;
- if (idxObj != null) {
- idx = idxObj;
- if ((idx & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- mHistoryTagPool.put(tag, idx & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
+ private int mLastHistoryStepLevel;
+
+ /**
+ * Total time (in milliseconds) spent executing in user code.
+ */
+ private long mLastStepCpuUserTimeMs;
+ private long mCurStepCpuUserTimeMs;
+ /**
+ * Total time (in milliseconds) spent executing in kernel code.
+ */
+ private long mLastStepCpuSystemTimeMs;
+ private long mCurStepCpuSystemTimeMs;
+ /**
+ * Times from /proc/stat (but measured in milliseconds).
+ */
+ private long mLastStepStatUserTimeMs;
+ private long mLastStepStatSystemTimeMs;
+ private long mLastStepStatIOWaitTimeMs;
+ private long mLastStepStatIrqTimeMs;
+ private long mLastStepStatSoftIrqTimeMs;
+ private long mLastStepStatIdleTimeMs;
+ private long mCurStepStatUserTimeMs;
+ private long mCurStepStatSystemTimeMs;
+ private long mCurStepStatIOWaitTimeMs;
+ private long mCurStepStatIrqTimeMs;
+ private long mCurStepStatSoftIrqTimeMs;
+ private long mCurStepStatIdleTimeMs;
+
+ @Override
+ public HistoryStepDetails getHistoryStepDetails() {
+ if (mBatteryLevel >= mLastHistoryStepLevel && mHasHistoryStepDetails) {
+ mLastHistoryStepLevel = mBatteryLevel;
+ return null;
}
- return idx;
- } else if (mNextHistoryTagIdx < HISTORY_TAG_INDEX_LIMIT) {
- idx = mNextHistoryTagIdx;
- HistoryTag key = new HistoryTag();
- key.setTo(tag);
- tag.poolIdx = idx;
- mHistoryTagPool.put(key, idx);
- mNextHistoryTagIdx++;
- mNumHistoryTagChars += stringLength + 1;
- if (mHistoryTags != null) {
- mHistoryTags.put(idx, key);
- }
- return idx | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
- } else {
- // Tag pool overflow: include the tag itself in the parcel
- return HISTORY_TAG_INDEX_LIMIT | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
- }
- }
+ // Perform a CPU update right after we do this collection, so we have started
+ // collecting good data for the next step.
+ requestImmediateCpuUpdate();
- /*
- The history delta format uses flags to denote further data in subsequent ints in the parcel.
-
- There is always the first token, which may contain the delta time, or an indicator of
- the length of the time (int or long) following this token.
-
- First token: always present,
- 31 23 15 7 0
- â–ˆM|L|K|J|I|H|G|Fâ–ˆE|D|C|B|A|T|T|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆ
-
- T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
- follows containing the time, and 0x7ffff indicates a long immediately follows with the
- delta time.
- A: battery level changed and an int follows with battery data.
- B: state changed and an int follows with state change data.
- C: state2 has changed and an int follows with state2 change data.
- D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
- E: event data has changed and an event struct follows.
- F: battery charge in coulombs has changed and an int with the charge follows.
- G: state flag denoting that the mobile radio was active.
- H: state flag denoting that the wifi radio was active.
- I: state flag denoting that a wifi scan occurred.
- J: state flag denoting that a wifi full lock was held.
- K: state flag denoting that the gps was on.
- L: state flag denoting that a wakelock was held.
- M: state flag denoting that the cpu was running.
-
- Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
- with the time delta.
-
- Battery level int: if A in the first token is set,
- 31 23 15 7 0
- â–ˆL|L|L|L|L|L|L|Tâ–ˆT|T|T|T|T|T|T|Tâ–ˆT|V|V|V|V|V|V|Vâ–ˆV|V|V|V|V|V|V|Dâ–ˆ
-
- D: indicates that extra history details follow.
- V: the battery voltage.
- T: the battery temperature.
- L: the battery level (out of 100).
-
- State change int: if B in the first token is set,
- 31 23 15 7 0
- â–ˆS|S|S|H|H|H|P|Pâ–ˆF|E|D|C|B| | |Aâ–ˆ | | | | | | | â–ˆ | | | | | | | â–ˆ
-
- A: wifi multicast was on.
- B: battery was plugged in.
- C: screen was on.
- D: phone was scanning for signal.
- E: audio was on.
- F: a sensor was active.
-
- State2 change int: if C in the first token is set,
- 31 23 15 7 0
- â–ˆM|L|K|J|I|H|H|Gâ–ˆF|E|D|C| | | | â–ˆ | | | | | | | â–ˆ |B|B|B|A|A|A|Aâ–ˆ
-
- A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
- B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
- C: a bluetooth scan was active.
- D: the camera was active.
- E: bluetooth was on.
- F: a phone call was active.
- G: the device was charging.
- H: 2 bits indicating the device-idle (doze) state: off, light, full
- I: the flashlight was on.
- J: wifi was on.
- K: wifi was running.
- L: video was playing.
- M: power save mode was on.
-
- Wakelock/wakereason struct: if D in the first token is set,
- TODO(adamlesinski): describe wakelock/wakereason struct.
-
- Event struct: if E in the first token is set,
- TODO(adamlesinski): describe the event struct.
-
- History step details struct: if D in the battery level int is set,
- TODO(adamlesinski): describe the history step details struct.
-
- Battery charge int: if F in the first token is set, an int representing the battery charge
- in coulombs follows.
- */
-
- @GuardedBy("this")
- public 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);
- return;
- }
-
- final long deltaTime = cur.time - last.time;
- final int lastBatteryLevelInt = buildBatteryLevelInt(last);
- final int lastStateInt = buildStateInt(last);
-
- int deltaTimeToken;
- if (deltaTime < 0 || deltaTime > Integer.MAX_VALUE) {
- deltaTimeToken = BatteryStatsHistory.DELTA_TIME_LONG;
- } else if (deltaTime >= BatteryStatsHistory.DELTA_TIME_ABS) {
- deltaTimeToken = BatteryStatsHistory.DELTA_TIME_INT;
- } else {
- deltaTimeToken = (int)deltaTime;
- }
- int firstToken = deltaTimeToken | (cur.states & BatteryStatsHistory.DELTA_STATE_MASK);
- final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
- ? BatteryStatsHistory.BATTERY_DELTA_LEVEL_FLAG : 0;
- final boolean computeStepDetails = includeStepDetails != 0
- || mLastHistoryStepDetails == null;
- final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
- final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
- if (batteryLevelIntChanged) {
- firstToken |= BatteryStatsHistory.DELTA_BATTERY_LEVEL_FLAG;
- }
- final int stateInt = buildStateInt(cur);
- final boolean stateIntChanged = stateInt != lastStateInt;
- if (stateIntChanged) {
- firstToken |= BatteryStatsHistory.DELTA_STATE_FLAG;
- }
- final boolean state2IntChanged = cur.states2 != last.states2;
- if (state2IntChanged) {
- firstToken |= BatteryStatsHistory.DELTA_STATE2_FLAG;
- }
- if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
- firstToken |= BatteryStatsHistory.DELTA_WAKELOCK_FLAG;
- }
- if (cur.eventCode != HistoryItem.EVENT_NONE) {
- firstToken |= BatteryStatsHistory.DELTA_EVENT_FLAG;
- }
-
- final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
- if (batteryChargeChanged) {
- firstToken |= BatteryStatsHistory.DELTA_BATTERY_CHARGE_FLAG;
- }
- dest.writeInt(firstToken);
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
- + " deltaTime=" + deltaTime);
-
- if (deltaTimeToken >= BatteryStatsHistory.DELTA_TIME_INT) {
- if (deltaTimeToken == BatteryStatsHistory.DELTA_TIME_INT) {
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: int deltaTime=" + (int)deltaTime);
- dest.writeInt((int)deltaTime);
- } else {
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: long deltaTime=" + deltaTime);
- dest.writeLong(deltaTime);
- }
- }
- if (batteryLevelIntChanged) {
- dest.writeInt(batteryLevelInt);
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryToken=0x"
- + Integer.toHexString(batteryLevelInt)
- + " batteryLevel=" + cur.batteryLevel
- + " batteryTemp=" + cur.batteryTemperature
- + " batteryVolt=" + (int)cur.batteryVoltage);
- }
- if (stateIntChanged) {
- dest.writeInt(stateInt);
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: stateToken=0x"
- + Integer.toHexString(stateInt)
- + " batteryStatus=" + cur.batteryStatus
- + " batteryHealth=" + cur.batteryHealth
- + " batteryPlugType=" + cur.batteryPlugType
- + " states=0x" + Integer.toHexString(cur.states));
- }
- if (state2IntChanged) {
- dest.writeInt(cur.states2);
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: states2=0x"
- + Integer.toHexString(cur.states2));
- }
- if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
- int wakeLockIndex;
- int wakeReasonIndex;
- if (cur.wakelockTag != null) {
- wakeLockIndex = writeHistoryTag(cur.wakelockTag);
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
- + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
- } else {
- wakeLockIndex = 0xffff;
- }
- if (cur.wakeReasonTag != null) {
- wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
- + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
- } else {
- wakeReasonIndex = 0xffff;
- }
- dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
- if (cur.wakelockTag != null
- && (wakeLockIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- cur.wakelockTag.writeToParcel(dest, 0);
- cur.tagsFirstOccurrence = true;
- }
- if (cur.wakeReasonTag != null
- && (wakeReasonIndex & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- cur.wakeReasonTag.writeToParcel(dest, 0);
- cur.tagsFirstOccurrence = true;
- }
- }
- if (cur.eventCode != HistoryItem.EVENT_NONE) {
- final int index = writeHistoryTag(cur.eventTag);
- final int codeAndIndex = (cur.eventCode & 0xffff) | (index << 16);
- dest.writeInt(codeAndIndex);
- if ((index & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
- cur.eventTag.writeToParcel(dest, 0);
- cur.tagsFirstOccurrence = true;
- }
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: event=" + cur.eventCode + " tag=#"
- + cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
- + cur.eventTag.string);
- }
- if (computeStepDetails) {
if (mPlatformIdleStateCallback != null) {
- mCurHistoryStepDetails.statSubsystemPowerState =
+ mDetails.statSubsystemPowerState =
mPlatformIdleStateCallback.getSubsystemLowPowerStats();
if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
- mCurHistoryStepDetails.statSubsystemPowerState);
-
+ mDetails.statSubsystemPowerState);
}
- computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
- if (includeStepDetails != 0) {
- mCurHistoryStepDetails.writeToParcel(dest);
- }
- cur.stepDetails = mCurHistoryStepDetails;
- mLastHistoryStepDetails = mCurHistoryStepDetails;
- } else {
- cur.stepDetails = null;
- }
- if (mLastHistoryStepLevel < cur.batteryLevel) {
- mLastHistoryStepDetails = null;
- }
- mLastHistoryStepLevel = cur.batteryLevel;
- if (batteryChargeChanged) {
- if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
- dest.writeInt(cur.batteryChargeUah);
- }
- dest.writeDouble(cur.modemRailChargeMah);
- dest.writeDouble(cur.wifiRailChargeMah);
- }
-
- private int buildBatteryLevelInt(HistoryItem h) {
- return ((((int)h.batteryLevel)<<25)&0xfe000000)
- | ((((int)h.batteryTemperature)<<15)&0x01ff8000)
- | ((((int)h.batteryVoltage)<<1)&0x00007ffe);
- }
-
- private int buildStateInt(HistoryItem h) {
- int plugType = 0;
- if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
- plugType = 1;
- } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
- plugType = 2;
- } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
- plugType = 3;
- }
- return ((h.batteryStatus & BatteryStatsHistory.STATE_BATTERY_STATUS_MASK)
- << BatteryStatsHistory.STATE_BATTERY_STATUS_SHIFT)
- | ((h.batteryHealth & BatteryStatsHistory.STATE_BATTERY_HEALTH_MASK)
- << BatteryStatsHistory.STATE_BATTERY_HEALTH_SHIFT)
- | ((plugType & BatteryStatsHistory.STATE_BATTERY_PLUG_MASK)
- << BatteryStatsHistory.STATE_BATTERY_PLUG_SHIFT)
- | (h.states & (~BatteryStatsHistory.STATE_BATTERY_MASK));
- }
-
- private void computeHistoryStepDetails(final HistoryStepDetails out,
- final HistoryStepDetails last) {
- final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
-
- // Perform a CPU update right after we do this collection, so we have started
- // collecting good data for the next step.
- requestImmediateCpuUpdate();
-
- if (last == null) {
- // We are not generating a delta, so all we need to do is reset the stats
- // we will later be doing a delta from.
- final int NU = mUidStats.size();
- for (int i=0; i<NU; i++) {
- final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
- uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
- }
- mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
- mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
- mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
- mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
- mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
- mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
- mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
- mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
- tmp.clear();
- return;
- }
- if (DEBUG) {
- Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
- + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
- + " irq=" + mLastStepStatIrqTimeMs + " sirq="
- + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
- Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
- + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
- + " irq=" + mCurStepStatIrqTimeMs + " sirq="
- + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
- }
- out.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
- out.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
- out.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
- out.statSystemTime = (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
- out.statIOWaitTime = (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
- out.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
- out.statSoftIrqTime = (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
- out.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
- out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
- out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
- out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
- final int NU = mUidStats.size();
- for (int i=0; i<NU; i++) {
- final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
- final int totalUTimeMs = (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
- final int totalSTimeMs = (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
- final int totalTimeMs = totalUTimeMs + totalSTimeMs;
- uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
- uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
- if (totalTimeMs <= (out.appCpuUTime3 + out.appCpuSTime3)) {
- continue;
- }
- if (totalTimeMs <= (out.appCpuUTime2 + out.appCpuSTime2)) {
- out.appCpuUid3 = uid.mUid;
- out.appCpuUTime3 = totalUTimeMs;
- out.appCpuSTime3 = totalSTimeMs;
- } else {
- out.appCpuUid3 = out.appCpuUid2;
- out.appCpuUTime3 = out.appCpuUTime2;
- out.appCpuSTime3 = out.appCpuSTime2;
- if (totalTimeMs <= (out.appCpuUTime1 + out.appCpuSTime1)) {
- out.appCpuUid2 = uid.mUid;
- out.appCpuUTime2 = totalUTimeMs;
- out.appCpuSTime2 = totalSTimeMs;
- } else {
- out.appCpuUid2 = out.appCpuUid1;
- out.appCpuUTime2 = out.appCpuUTime1;
- out.appCpuSTime2 = out.appCpuSTime1;
- out.appCpuUid1 = uid.mUid;
- out.appCpuUTime1 = totalUTimeMs;
- out.appCpuSTime1 = totalSTimeMs;
+ if (!mHasHistoryStepDetails) {
+ // We are not generating a delta, so all we need to do is reset the stats
+ // we will later be doing a delta from.
+ final int uidCount = mUidStats.size();
+ for (int i = 0; i < uidCount; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
+ uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
}
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
+ mDetails.clear();
+ } else {
+ if (DEBUG) {
+ Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys="
+ + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs
+ + " irq=" + mLastStepStatIrqTimeMs + " sirq="
+ + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs);
+ Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys="
+ + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs
+ + " irq=" + mCurStepStatIrqTimeMs + " sirq="
+ + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs);
+ }
+ mDetails.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs);
+ mDetails.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs);
+ mDetails.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs);
+ mDetails.statSystemTime =
+ (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs);
+ mDetails.statIOWaitTime =
+ (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs);
+ mDetails.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs);
+ mDetails.statSoftIrqTime =
+ (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs);
+ mDetails.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs);
+ mDetails.appCpuUid1 = mDetails.appCpuUid2 = mDetails.appCpuUid3 = -1;
+ mDetails.appCpuUTime1 = mDetails.appCpuUTime2 = mDetails.appCpuUTime3 = 0;
+ mDetails.appCpuSTime1 = mDetails.appCpuSTime2 = mDetails.appCpuSTime3 = 0;
+ final int uidCount = mUidStats.size();
+ for (int i = 0; i < uidCount; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ final int totalUTimeMs =
+ (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs);
+ final int totalSTimeMs =
+ (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs);
+ final int totalTimeMs = totalUTimeMs + totalSTimeMs;
+ uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs;
+ uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs;
+ if (totalTimeMs <= (mDetails.appCpuUTime3 + mDetails.appCpuSTime3)) {
+ continue;
+ }
+ if (totalTimeMs <= (mDetails.appCpuUTime2 + mDetails.appCpuSTime2)) {
+ mDetails.appCpuUid3 = uid.mUid;
+ mDetails.appCpuUTime3 = totalUTimeMs;
+ mDetails.appCpuSTime3 = totalSTimeMs;
+ } else {
+ mDetails.appCpuUid3 = mDetails.appCpuUid2;
+ mDetails.appCpuUTime3 = mDetails.appCpuUTime2;
+ mDetails.appCpuSTime3 = mDetails.appCpuSTime2;
+ if (totalTimeMs <= (mDetails.appCpuUTime1 + mDetails.appCpuSTime1)) {
+ mDetails.appCpuUid2 = uid.mUid;
+ mDetails.appCpuUTime2 = totalUTimeMs;
+ mDetails.appCpuSTime2 = totalSTimeMs;
+ } else {
+ mDetails.appCpuUid2 = mDetails.appCpuUid1;
+ mDetails.appCpuUTime2 = mDetails.appCpuUTime1;
+ mDetails.appCpuSTime2 = mDetails.appCpuSTime1;
+ mDetails.appCpuUid1 = uid.mUid;
+ mDetails.appCpuUTime1 = totalUTimeMs;
+ mDetails.appCpuSTime1 = totalSTimeMs;
+ }
+ }
+ }
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
}
+
+ mHasHistoryStepDetails = mBatteryLevel <= mLastHistoryStepLevel;
+ mLastHistoryStepLevel = mBatteryLevel;
+
+ return mDetails;
}
- mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs;
- mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs;
- mLastStepStatUserTimeMs = mCurStepStatUserTimeMs;
- mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs;
- mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs;
- mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs;
- mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs;
- mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs;
+
+ public void addCpuStats(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
+ int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
+ int statSoftIrqTimeMs, int statIdleTimeMs) {
+ if (DEBUG) {
+ Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
+ + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
+ + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
+ + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
+ }
+ mCurStepCpuUserTimeMs += totalUTimeMs;
+ mCurStepCpuSystemTimeMs += totalSTimeMs;
+ mCurStepStatUserTimeMs += statUserTimeMs;
+ mCurStepStatSystemTimeMs += statSystemTimeMs;
+ mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
+ mCurStepStatIrqTimeMs += statIrqTimeMs;
+ mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
+ mCurStepStatIdleTimeMs += statIdleTimeMs;
+ }
+
+ @Override
+ public void clear() {
+ mHasHistoryStepDetails = false;
+ mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
+ mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
+ mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
+ mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
+ mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
+ mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
+ mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
+ mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
+ }
}
@GuardedBy("this")
@Override
public void commitCurrentHistoryBatchLocked() {
- mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
+ mHistory.commitCurrentHistoryBatchLocked();
}
@GuardedBy("this")
@@ -4326,191 +4066,9 @@
}
@GuardedBy("this")
- void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
- if (!mHaveBatteryLevel || !mRecordingHistory) {
- return;
- }
-
- final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
- final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates);
- final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2);
- final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states;
- final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2;
- if (DEBUG) {
- Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff="
- + Integer.toHexString(diffStates) + " lastDiff="
- + Integer.toHexString(lastDiffStates) + " diff2="
- + Integer.toHexString(diffStates2) + " lastDiff2="
- + Integer.toHexString(lastDiffStates2));
- }
- if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
- && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
- && (diffStates2&lastDiffStates2) == 0
- && (!mHistoryLastWritten.tagsFirstOccurrence && !cur.tagsFirstOccurrence)
- && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
- && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
- && mHistoryLastWritten.stepDetails == null
- && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
- || cur.eventCode == HistoryItem.EVENT_NONE)
- && mHistoryLastWritten.batteryLevel == cur.batteryLevel
- && mHistoryLastWritten.batteryStatus == cur.batteryStatus
- && mHistoryLastWritten.batteryHealth == cur.batteryHealth
- && mHistoryLastWritten.batteryPlugType == cur.batteryPlugType
- && mHistoryLastWritten.batteryTemperature == cur.batteryTemperature
- && mHistoryLastWritten.batteryVoltage == cur.batteryVoltage) {
- // We can merge this new change in with the last one. Merging is
- // allowed as long as only the states have changed, and within those states
- // as long as no bit has changed both between now and the last entry, as
- // well as the last entry and the one before it (so we capture any toggles).
- if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos);
- mHistoryBuffer.setDataSize(mHistoryBufferLastPos);
- mHistoryBuffer.setDataPosition(mHistoryBufferLastPos);
- mHistoryBufferLastPos = -1;
- elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs;
- // If the last written history had a wakelock tag, we need to retain it.
- // Note that the condition above made sure that we aren't in a case where
- // both it and the current history item have a wakelock tag.
- if (mHistoryLastWritten.wakelockTag != null) {
- cur.wakelockTag = cur.localWakelockTag;
- cur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
- }
- // If the last written history had a wake reason tag, we need to retain it.
- // Note that the condition above made sure that we aren't in a case where
- // both it and the current history item have a wakelock tag.
- if (mHistoryLastWritten.wakeReasonTag != null) {
- cur.wakeReasonTag = cur.localWakeReasonTag;
- cur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
- }
- // If the last written history had an event, we need to retain it.
- // Note that the condition above made sure that we aren't in a case where
- // both it and the current history item have an event.
- if (mHistoryLastWritten.eventCode != HistoryItem.EVENT_NONE) {
- cur.eventCode = mHistoryLastWritten.eventCode;
- cur.eventTag = cur.localEventTag;
- cur.eventTag.setTo(mHistoryLastWritten.eventTag);
- }
- mHistoryLastWritten.setTo(mHistoryLastLastWritten);
- }
- final int dataSize = mHistoryBuffer.dataSize();
-
- if (dataSize >= mConstants.MAX_HISTORY_BUFFER) {
- //open a new history file.
- final long start = SystemClock.uptimeMillis();
- writeHistoryLocked();
- if (DEBUG) {
- Slog.d(TAG, "addHistoryBufferLocked writeHistoryLocked takes ms:"
- + (SystemClock.uptimeMillis() - start));
- }
- mBatteryStatsHistory.startNextFile();
- mHistoryBuffer.setDataSize(0);
- mHistoryBuffer.setDataPosition(0);
- mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
- mHistoryBufferLastPos = -1;
- mHistoryLastWritten.clear();
- mHistoryLastLastWritten.clear();
-
- // Mark every entry in the pool with a flag indicating that the tag
- // has not yet been encountered while writing the current history buffer.
- for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
- entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
- }
- // Make a copy of mHistoryCur.
- HistoryItem copy = new HistoryItem();
- copy.setTo(cur);
- // startRecordingHistory will reset mHistoryCur.
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
- // Add the copy into history buffer.
- addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, copy);
- return;
- }
-
- if (dataSize == 0) {
- // The history is currently empty; we need it to start with a time stamp.
- cur.currentTime = mClock.currentTimeMillis();
- addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
- }
- 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!");
- }
- mHistoryBufferLastPos = mHistoryBuffer.dataPosition();
- mHistoryLastLastWritten.setTo(mHistoryLastWritten);
- final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
- mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
- mHistoryLastWritten.tagsFirstOccurrence = hasTags;
- mHistoryLastWritten.states &= mActiveHistoryStates;
- mHistoryLastWritten.states2 &= mActiveHistoryStates2;
- writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
- mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
- cur.wakelockTag = null;
- cur.wakeReasonTag = null;
- cur.eventCode = HistoryItem.EVENT_NONE;
- cur.eventTag = null;
- cur.tagsFirstOccurrence = false;
- if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
- + " now " + mHistoryBuffer.dataPosition()
- + " size is now " + mHistoryBuffer.dataSize());
- }
-
- @GuardedBy("this")
- void addHistoryRecordLocked(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;
- addHistoryRecordInnerLocked(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp);
- }
- }
- mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG;
- mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs;
- mTrackRunningHistoryUptimeMs = uptimeMs;
- 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,
+ public void recordHistoryEventLocked(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;
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
- }
-
- @GuardedBy("this")
- void clearHistoryLocked() {
- if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
- mHistoryBaseTimeMs = 0;
- mLastHistoryElapsedRealtimeMs = 0;
- mTrackRunningHistoryElapsedRealtimeMs = 0;
- mTrackRunningHistoryUptimeMs = 0;
-
- mHistoryBuffer.setDataSize(0);
- mHistoryBuffer.setDataPosition(0);
- mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2);
- mHistoryLastLastWritten.clear();
- mHistoryLastWritten.clear();
- mHistoryTagPool.clear();
- mNextHistoryTagIdx = 0;
- mNumHistoryTagChars = 0;
- mHistoryBufferLastPos = -1;
- mActiveHistoryStates = 0xffffffff;
- mActiveHistoryStates2 = 0xffffffff;
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
}
@GuardedBy("this")
@@ -4663,13 +4221,13 @@
if (!mActiveEvents.updateState(code, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid);
}
@GuardedBy("this")
public void noteCurrentTimeChangedLocked(long currentTimeMs,
long elapsedRealtimeMs, long uptimeMs) {
- recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs);
+ mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs);
}
@GuardedBy("this")
@@ -4686,7 +4244,7 @@
if (!mRecordAllHistory) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid);
}
@GuardedBy("this")
@@ -4744,8 +4302,7 @@
if (!mRecordAllHistory) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH,
- name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid);
}
@GuardedBy("this")
@@ -4761,7 +4318,7 @@
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid);
}
@GuardedBy("this")
@@ -4777,8 +4334,7 @@
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH,
- name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid);
}
@GuardedBy("this")
@@ -4794,7 +4350,7 @@
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid);
}
@GuardedBy("this")
@@ -4812,7 +4368,7 @@
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid);
}
@GuardedBy("this")
@@ -4860,7 +4416,7 @@
for (int i = 0; i < workSource.size(); ++i) {
uid = mapUid(workSource.getUid(i));
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
@@ -4869,7 +4425,7 @@
for (int i = 0; i < workChains.size(); ++i) {
uid = mapUid(workChains.get(i).getAttributionUid());
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
@@ -4877,7 +4433,7 @@
uid = mapUid(uid);
if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid);
}
}
}
@@ -4952,7 +4508,7 @@
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
- addHistoryEventLocked(mSecRealtime, mSecUptime,
+ mHistory.recordEvent(mSecRealtime, mSecUptime,
HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j));
}
}
@@ -4967,8 +4523,8 @@
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
- addHistoryEventLocked(mSecRealtime, mSecUptime,
- HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j));
+ mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START,
+ ent.getKey(), uids.keyAt(j));
}
}
}
@@ -5011,30 +4567,19 @@
if (mRecordAllHistory) {
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
mappedUid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid);
}
}
if (mWakeLockNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
- + Integer.toHexString(mHistoryCur.states));
- mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
- mHistoryCur.wakelockTag.string = historyName;
- mHistoryCur.wakelockTag.uid = mappedUid;
mWakeLockImportant = !unimportantForLogging;
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
- } else if (!mWakeLockImportant && !unimportantForLogging
- && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
- 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 = mappedUid;
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName,
+ mappedUid);
+ } else if (!mWakeLockImportant && !unimportantForLogging) {
+ if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName,
+ mappedUid)) {
+ mWakeLockImportant = true;
}
- mWakeLockImportant = true;
}
mWakeLockNesting++;
}
@@ -5087,15 +4632,13 @@
}
if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
mappedUid, 0)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs,
HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid);
}
}
if (mWakeLockNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WAKE_LOCK_FLAG);
}
}
if (mappedUid >= 0) {
@@ -5286,7 +4829,7 @@
mappedUid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
historyName, mappedUid);
if (mappedUid != uid) {
// Prevent the isolated uid mapping from being removed while the wakelock is
@@ -5339,7 +4882,7 @@
mappedUid, 0)) {
return;
}
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
historyName, mappedUid);
if (mappedUid != uid) {
// Decrement the ref count for the isolated uid and delete the mapping if uneeded.
@@ -5361,15 +4904,10 @@
@GuardedBy("this")
public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) {
- if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
- + Integer.toHexString(mHistoryCur.states));
aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs);
- mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
- mHistoryCur.wakeReasonTag.string = reason;
- mHistoryCur.wakeReasonTag.uid = 0;
+ mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason);
mLastWakeupReason = reason;
mLastWakeupUptimeMs = uptimeMs;
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
@GuardedBy("this")
@@ -5380,22 +4918,11 @@
@GuardedBy("this")
public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs,
- int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
- int statSoftIrqTimeMs, int statIdleTimeMs) {
- if (DEBUG) {
- Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs
- + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs
- + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs
- + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs);
- }
- mCurStepCpuUserTimeMs += totalUTimeMs;
- mCurStepCpuSystemTimeMs += totalSTimeMs;
- mCurStepStatUserTimeMs += statUserTimeMs;
- mCurStepStatSystemTimeMs += statSystemTimeMs;
- mCurStepStatIOWaitTimeMs += statIOWaitTimeMs;
- mCurStepStatIrqTimeMs += statIrqTimeMs;
- mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs;
- mCurStepStatIdleTimeMs += statIdleTimeMs;
+ int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs,
+ int statSoftIrqTimeMs, int statIdleTimeMs) {
+ mStepDetailsCalculator.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs,
+ statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs,
+ statSoftIrqTimeMs, statIdleTimeMs);
}
public void noteProcessDiedLocked(int uid, int pid) {
@@ -5425,10 +4952,8 @@
public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mSensorNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_SENSOR_ON_FLAG);
}
mSensorNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -5445,10 +4970,8 @@
uid = mapUid(uid);
mSensorNesting--;
if (mSensorNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_SENSOR_ON_FLAG);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteStopSensor(sensor, elapsedRealtimeMs);
@@ -5498,10 +5021,8 @@
}
final int mappedUid = mapUid(uid);
if (mGpsNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_GPS_ON_FLAG);
}
mGpsNesting++;
@@ -5526,10 +5047,8 @@
final int mappedUid = mapUid(uid);
mGpsNesting--;
if (mGpsNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_GPS_ON_FLAG);
stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
mGpsSignalQualityBin = -1;
}
@@ -5562,12 +5081,9 @@
if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs);
}
- mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
- | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel);
mGpsSignalQualityBin = signalLevel;
}
- return;
}
@GuardedBy("this")
@@ -5740,41 +5256,33 @@
}
}
- boolean updateHistory = false;
+ int startStates = 0;
+ int stopStates = 0;
if (Display.isDozeState(state) && !Display.isDozeState(oldState)) {
- mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
+ startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs);
- updateHistory = true;
} else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) {
- mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG;
+ stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG;
mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs);
- updateHistory = true;
}
if (Display.isOnState(state)) {
- mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
- + Integer.toHexString(mHistoryCur.states));
+ startStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
mScreenOnTimer.startRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
mScreenBrightnessTimer[mScreenBrightnessBin]
.startRunningLocked(elapsedRealtimeMs);
}
- updateHistory = true;
} else if (Display.isOnState(oldState)) {
- mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
- + Integer.toHexString(mHistoryCur.states));
+ stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG;
mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs);
if (mScreenBrightnessBin >= 0) {
mScreenBrightnessTimer[mScreenBrightnessBin]
.stopRunningLocked(elapsedRealtimeMs);
}
- updateHistory = true;
}
- if (updateHistory) {
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: "
- + Display.stateToString(state));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ if (startStates != 0 || stopStates != 0) {
+ mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates,
+ stopStates);
}
// Per screen state Cpu stats needed. Prepare to schedule an external sync.
@@ -5888,13 +5396,7 @@
long uptimeMs) {
if (mScreenBrightnessBin != overallBin) {
if (overallBin >= 0) {
- mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_BRIGHTNESS_MASK)
- | (overallBin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
- if (DEBUG_HISTORY) {
- Slog.v(TAG, "Screen brightness " + overallBin + " to: "
- + Integer.toHexString(mHistoryCur.states));
- }
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin);
}
if (mScreenState == Display.STATE_ON) {
if (mScreenBrightnessBin >= 0) {
@@ -5921,8 +5423,8 @@
@GuardedBy("this")
public void noteWakeUpLocked(String reason, int reasonUid,
long elapsedRealtimeMs, long uptimeMs) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP,
- reason, reasonUid);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason,
+ reasonUid);
}
@GuardedBy("this")
@@ -5941,7 +5443,7 @@
@GuardedBy("this")
public void noteConnectivityChangedLocked(int type, String extra,
long elapsedRealtimeMs, long uptimeMs) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
extra, type);
mNumConnectivityChange++;
}
@@ -5950,7 +5452,7 @@
private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
- addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
+ mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked();
}
@@ -5976,7 +5478,8 @@
}
mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000);
- mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
} else {
realElapsedRealtimeMs = timestampNs / (1000*1000);
long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs;
@@ -5988,11 +5491,9 @@
mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs
- realElapsedRealtimeMs);
}
- mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG);
}
- if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mMobileRadioPowerState = powerState;
// Inform current RatBatteryStats that the modem active state might have changed.
@@ -6042,17 +5543,14 @@
mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
mPowerSaveModeEnabled = enabled;
if (enabled) {
- mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: "
- + Integer.toHexString(mHistoryCur.states2));
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_POWER_SAVE_FLAG);
mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: "
- + Integer.toHexString(mHistoryCur.states2));
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_POWER_SAVE_FLAG);
mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs);
}
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED,
enabled
? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON
@@ -6076,7 +5574,7 @@
nowLightIdling = true;
}
if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE,
activeReason, activeUid);
}
if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) {
@@ -6106,11 +5604,7 @@
}
}
if (mDeviceIdleMode != mode) {
- mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
- | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
- if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, mode);
long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs;
mLastIdleTimeStartMs = elapsedRealtimeMs;
if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
@@ -6138,7 +5632,7 @@
public void notePackageInstalledLocked(String pkgName, long versionCode,
long elapsedRealtimeMs, long uptimeMs) {
// XXX need to figure out what to do with long version codes.
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED,
pkgName, (int)versionCode);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
@@ -6150,8 +5644,8 @@
@GuardedBy("this")
public void notePackageUninstalledLocked(String pkgName,
long elapsedRealtimeMs, long uptimeMs) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs,
- HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0);
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
+ pkgName, 0);
PackageChange pc = new PackageChange();
pc.mPackageName = pkgName;
pc.mUpdate = true;
@@ -6180,10 +5674,8 @@
@GuardedBy("this")
public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mPhoneOn) {
- mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
mPhoneOn = true;
mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
}
@@ -6192,10 +5684,8 @@
@GuardedBy("this")
public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mPhoneOn) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
mPhoneOn = false;
mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
@@ -6233,11 +5723,12 @@
if (mUsbDataState != newState) {
mUsbDataState = newState;
if (connected) {
- mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG;
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_USB_DATA_LINK_FLAG);
} else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG;
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_USB_DATA_LINK_FLAG);
}
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
}
@@ -6258,6 +5749,10 @@
long elapsedRealtimeMs, long uptimeMs) {
boolean scanning = false;
boolean newHistory = false;
+ int addStateFlag = 0;
+ int removeStateFlag = 0;
+ int newState = -1;
+ int newSignalStrength = -1;
mPhoneServiceStateRaw = state;
mPhoneSimStateRaw = simState;
@@ -6286,10 +5781,8 @@
scanning = true;
strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
if (!mPhoneSignalScanningTimer.isRunningLocked()) {
- mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
+ addStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
newHistory = true;
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
- + Integer.toHexString(mHistoryCur.states));
mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
simState, strengthBin);
@@ -6299,9 +5792,7 @@
if (!scanning) {
// If we are no longer scanning, then stop the scanning timer.
if (mPhoneSignalScanningTimer.isRunningLocked()) {
- mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
- + Integer.toHexString(mHistoryCur.states));
+ removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG;
newHistory = true;
mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs);
FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state,
@@ -6310,10 +5801,7 @@
}
if (mPhoneServiceState != state) {
- mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_STATE_MASK)
- | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
- if (DEBUG_HISTORY) Slog.v(TAG, "Phone state " + state + " to: "
- + Integer.toHexString(mHistoryCur.states));
+ newState = state;
newHistory = true;
mPhoneServiceState = state;
}
@@ -6327,11 +5815,7 @@
if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
- mHistoryCur.states =
- (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
- | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
- if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: "
- + Integer.toHexString(mHistoryCur.states));
+ newSignalStrength = strengthBin;
newHistory = true;
FrameworkStatsLog.write(
FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin);
@@ -6342,7 +5826,8 @@
}
if (newHistory) {
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs,
+ addStateFlag, removeStateFlag, newState, newSignalStrength);
}
}
@@ -6466,11 +5951,7 @@
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
if (mPhoneDataConnectionType != bin) {
- mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
- | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
- if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, bin);
if (mPhoneDataConnectionType >= 0) {
mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
elapsedRealtimeMs);
@@ -6543,10 +6024,8 @@
@GuardedBy("this")
public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) {
if (!mWifiOn) {
- mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_ON_FLAG);
mWifiOn = true;
mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
@@ -6556,10 +6035,8 @@
@GuardedBy("this")
public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mWifiOn) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_ON_FLAG);
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
@@ -6570,10 +6047,8 @@
public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mAudioOnNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_AUDIO_ON_FLAG);
mAudioOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mAudioOnNesting++;
@@ -6588,10 +6063,8 @@
}
uid = mapUid(uid);
if (--mAudioOnNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_AUDIO_ON_FLAG);
mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6602,10 +6075,8 @@
public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mVideoOnNesting == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_VIDEO_ON_FLAG);
mVideoOnTimer.startRunningLocked(elapsedRealtimeMs);
}
mVideoOnNesting++;
@@ -6620,10 +6091,8 @@
}
uid = mapUid(uid);
if (--mVideoOnNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_VIDEO_ON_FLAG);
mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6634,10 +6103,8 @@
public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mAudioOnNesting > 0) {
mAudioOnNesting = 0;
- mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_AUDIO_ON_FLAG);
mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6650,10 +6117,8 @@
public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mVideoOnNesting > 0) {
mVideoOnNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_VIDEO_ON_FLAG);
mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6705,10 +6170,8 @@
public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mFlashlightOnNesting++ == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_FLASHLIGHT_FLAG);
mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6722,10 +6185,8 @@
}
uid = mapUid(uid);
if (--mFlashlightOnNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_FLASHLIGHT_FLAG);
mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6736,10 +6197,8 @@
public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mCameraOnNesting++ == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CAMERA_FLAG);
mCameraOnTimer.startRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6753,10 +6212,8 @@
}
uid = mapUid(uid);
if (--mCameraOnNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CAMERA_FLAG);
mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6767,10 +6224,8 @@
public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mCameraOnNesting > 0) {
mCameraOnNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CAMERA_FLAG);
mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6783,10 +6238,8 @@
public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mFlashlightOnNesting > 0) {
mFlashlightOnNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_FLASHLIGHT_FLAG);
mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6803,10 +6256,8 @@
}
uid = mapUid(uid);
if (mBluetoothScanNesting == 0) {
- mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs);
}
mBluetoothScanNesting++;
@@ -6847,10 +6298,8 @@
uid = mapUid(uid);
mBluetoothScanNesting--;
if (mBluetoothScanNesting == 0) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -6885,10 +6334,8 @@
public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) {
if (mBluetoothScanNesting > 0) {
mBluetoothScanNesting = 0;
- mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG);
mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
for (int i=0; i<mUidStats.size(); i++) {
BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
@@ -6928,7 +6375,7 @@
private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
final long uptimeMillis, int uid) {
uid = mapUid(uid);
- addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
+ mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "",
uid);
getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked();
}
@@ -6944,15 +6391,14 @@
if (uid > 0) {
noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid);
}
- mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs);
} else {
- mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG;
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG);
mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000));
}
- if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mWifiRadioPowerState = powerState;
}
}
@@ -6960,10 +6406,8 @@
@GuardedBy("this")
public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (!mGlobalWifiRunning) {
- mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_RUNNING_FLAG);
mGlobalWifiRunning = true;
mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
int N = ws.size();
@@ -7031,10 +6475,8 @@
@GuardedBy("this")
public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) {
if (mGlobalWifiRunning) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_WIFI_RUNNING_FLAG);
mGlobalWifiRunning = false;
mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
int N = ws.size();
@@ -7082,12 +6524,7 @@
}
mWifiSupplState = supplState;
mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs);
- mHistoryCur.states2 =
- (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
- | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
- if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState);
}
}
@@ -7116,12 +6553,8 @@
if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) {
mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs);
}
- mHistoryCur.states2 =
- (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
- | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
- if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: "
- + Integer.toHexString(mHistoryCur.states2));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs,
+ strengthBin);
} else {
stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs);
}
@@ -7134,10 +6567,8 @@
@GuardedBy("this")
public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiFullLockNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
}
mWifiFullLockNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -7148,10 +6579,8 @@
public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiFullLockNesting--;
if (mWifiFullLockNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_FULL_LOCK_FLAG);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteFullWifiLockReleasedLocked(elapsedRealtimeMs);
@@ -7167,10 +6596,8 @@
@GuardedBy("this")
public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
if (mWifiScanNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_SCAN_FLAG);
}
mWifiScanNesting++;
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -7186,10 +6613,8 @@
public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
mWifiScanNesting--;
if (mWifiScanNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_SCAN_FLAG);
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteWifiScanStoppedLocked(elapsedRealtimeMs);
@@ -7214,14 +6639,10 @@
public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
uid = mapUid(uid);
if (mWifiMulticastNesting == 0) {
- mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
-
+ mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
// Start Wifi Multicast overall timer
if (!mWifiMulticastWakelockTimer.isRunningLocked()) {
- if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started");
mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs);
}
}
@@ -7235,14 +6656,12 @@
uid = mapUid(uid);
mWifiMulticastNesting--;
if (mWifiMulticastNesting == 0) {
- mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG);
// Stop Wifi Multicast overall timer
if (mWifiMulticastWakelockTimer.isRunningLocked()) {
- if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped");
+ if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped");
mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
}
}
@@ -7994,8 +7413,9 @@
// If the start clock time has changed by more than a year, then presumably
// the previous time was completely bogus. So we are going to figure out a
// new time based on how much time has elapsed since we started counting.
- recordCurrentTimeChangeLocked(currentTimeMs, mClock.elapsedRealtime(),
- mClock.uptimeMillis());
+ mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(),
+ currentTimeMs
+ );
return currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000));
}
return mStartClockTimeMs;
@@ -11227,18 +10647,19 @@
UserInfoProvider userInfoProvider) {
init(clock);
+ mHandler = new MyHandler(handler.getLooper());
+ mConstants = new Constants(mHandler);
+
if (systemDir == null) {
mStatsFile = null;
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+ mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
} else {
mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, systemDir,
- this::getMaxHistoryFiles);
+ mHistory = new BatteryStatsHistory(systemDir, mConstants.MAX_HISTORY_FILES,
+ mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
}
mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
- mHandler = new MyHandler(handler.getLooper());
- mConstants = new Constants(mHandler);
mStartCount++;
initTimersAndCounters();
mOnBattery = mOnBatteryInternal = false;
@@ -11247,7 +10668,6 @@
initTimes(uptimeUs, realtimeUs);
mStartPlatformVersion = mEndPlatformVersion = Build.ID;
initDischarge(realtimeUs);
- clearHistoryLocked();
updateDailyDeadlineLocked();
mPlatformIdleStateCallback = cb;
mMeasuredEnergyRetriever = energyStatsCb;
@@ -11258,12 +10678,6 @@
FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
}
- private int getMaxHistoryFiles() {
- synchronized (this) {
- return mConstants.MAX_HISTORY_FILES;
- }
- }
-
@VisibleForTesting
protected void initTimersAndCounters() {
mScreenOnTimer = new StopwatchTimer(mClock, null, -1, null, mOnBatteryTimeBase);
@@ -11345,7 +10759,7 @@
mDischargeUnplugLevel = 0;
mDischargePlugLevel = -1;
mDischargeCurrentLevel = 0;
- mCurrentBatteryLevel = 0;
+ mBatteryLevel = 0;
}
public void setPowerProfileLocked(PowerProfile profile) {
@@ -11732,7 +11146,7 @@
}
public int getHistoryUsedSize() {
- return mBatteryStatsHistory.getHistoryUsedSize();
+ return mHistory.getHistoryUsedSize();
}
@Override
@@ -11746,43 +11160,27 @@
*/
@VisibleForTesting
public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() {
- return new BatteryStatsHistoryIterator(mBatteryStatsHistory);
+ return mHistory.iterate();
}
@Override
public int getHistoryStringPoolSize() {
- return mHistoryTagPool.size();
+ return mHistory.getHistoryStringPoolSize();
}
@Override
public int getHistoryStringPoolBytes() {
- return mNumHistoryTagChars;
+ return mHistory.getHistoryStringPoolBytes();
}
@Override
public String getHistoryTagPoolString(int index) {
- ensureHistoryTagArray();
- HistoryTag historyTag = mHistoryTags.get(index);
- return historyTag != null ? historyTag.string : null;
+ return mHistory.getHistoryTagPoolString(index);
}
@Override
public int getHistoryTagPoolUid(int index) {
- ensureHistoryTagArray();
- HistoryTag historyTag = mHistoryTags.get(index);
- return historyTag != null ? historyTag.uid : Process.INVALID_UID;
- }
-
- private void ensureHistoryTagArray() {
- if (mHistoryTags != null) {
- return;
- }
-
- mHistoryTags = new SparseArray<>(mHistoryTagPool.size());
- for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
- mHistoryTags.put(entry.getValue() & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG,
- entry.getKey());
- }
+ return mHistory.getHistoryTagPoolUid(index);
}
@Override
@@ -11792,15 +11190,11 @@
@Override
public void finishIteratingHistoryLocked() {
+ mBatteryStatsHistoryIterator.close();
mBatteryStatsHistoryIterator = null;
}
@Override
- public long getHistoryBaseTime() {
- return mHistoryBaseTimeMs;
- }
-
- @Override
public int getStartCount() {
return mStartCount;
}
@@ -11853,24 +11247,23 @@
long realtimeUs = mSecRealtime * 1000;
resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND);
pullPendingStateUpdatesLocked();
- addHistoryRecordLocked(mSecRealtime, mSecUptime);
- mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
- = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
+ mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
+ mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
mOnBatteryTimeBase.reset(uptimeUs, realtimeUs);
mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs);
- if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
+ if (!mBatteryPluggedIn) {
if (Display.isOnState(mScreenState)) {
- mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
+ mDischargeScreenOnUnplugLevel = mBatteryLevel;
mDischargeScreenDozeUnplugLevel = 0;
mDischargeScreenOffUnplugLevel = 0;
} else if (Display.isDozeState(mScreenState)) {
mDischargeScreenOnUnplugLevel = 0;
- mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel;
+ mDischargeScreenDozeUnplugLevel = mBatteryLevel;
mDischargeScreenOffUnplugLevel = 0;
} else {
mDischargeScreenOnUnplugLevel = 0;
mDischargeScreenDozeUnplugLevel = 0;
- mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel;
+ mDischargeScreenOffUnplugLevel = mBatteryLevel;
}
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenOff = 0;
@@ -12014,27 +11407,12 @@
resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
- mLastHistoryStepDetails = null;
- mLastStepCpuUserTimeMs = mLastStepCpuSystemTimeMs = 0;
- mCurStepCpuUserTimeMs = mCurStepCpuSystemTimeMs = 0;
- mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0;
- mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0;
- mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0;
- mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0;
- mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0;
- mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0;
- mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0;
- mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0;
-
mNumAllUidCpuTimeReads = 0;
mNumUidsRemoved = 0;
initDischarge(elapsedRealtimeUs);
- clearHistoryLocked();
- if (mBatteryStatsHistory != null) {
- mBatteryStatsHistory.resetAllFiles();
- }
+ mHistory.reset();
// Flush external data, gathering snapshots, but don't process it since it is pre-reset data
mIgnoreNextExternalStats = true;
@@ -12057,7 +11435,7 @@
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
- addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
+ mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
uids.keyAt(j));
}
}
@@ -12482,9 +11860,8 @@
(long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt);
mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
monitoredRailChargeConsumedMaMs);
- mHistoryCur.wifiRailChargeMah +=
- (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
+ (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
mTmpRailStats.resetWifiTotalEnergyUsed();
if (uidEstimatedConsumptionMah != null) {
@@ -12597,9 +11974,8 @@
(long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt);
mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked(
monitoredRailChargeConsumedMaMs);
- mHistoryCur.modemRailChargeMah +=
- (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs,
+ (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR));
mTmpRailStats.resetCellularTotalEnergyUsed();
}
@@ -12867,8 +12243,8 @@
}
}
if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs,
+ HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG);
}
}
@@ -14301,11 +13677,7 @@
mHandler.removeCallbacks(mDeferSetCharging);
if (mCharging != charging) {
mCharging = charging;
- if (charging) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
- } else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
- }
+ mHistory.setChargingState(charging);
mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
return true;
}
@@ -14319,6 +13691,15 @@
mSystemReady = true;
}
+ /**
+ * Force recording of all history events regardless of the "charging" state.
+ */
+ @VisibleForTesting
+ public void forceRecordAllHistory() {
+ mHistory.forceRecordAllHistory();
+ mRecordAllHistory = true;
+ }
+
@GuardedBy("this")
protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
@@ -14402,15 +13783,12 @@
mInitStepMode = mCurStepMode;
mModStepMode = 0;
pullPendingStateUpdatesLocked();
- mHistoryCur.batteryLevel = (byte)level;
- mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
- + Integer.toHexString(mHistoryCur.states));
if (reset) {
- mRecordingHistory = true;
- startRecordingHistory(mSecRealtime, mSecUptime, reset);
+ mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset);
+ initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
}
- addHistoryRecordLocked(mSecRealtime, mSecUptime);
+ mBatteryPluggedIn = false;
+ mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
mDischargeCurrentLevel = mDischargeUnplugLevel = level;
if (Display.isOnState(screenState)) {
mDischargeScreenOnUnplugLevel = level;
@@ -14432,11 +13810,8 @@
} else {
mOnBattery = mOnBatteryInternal = false;
pullPendingStateUpdatesLocked();
- mHistoryCur.batteryLevel = (byte)level;
- mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(mSecRealtime, mSecUptime);
+ mBatteryPluggedIn = true;
+ mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
mDischargeCurrentLevel = mDischargePlugLevel = level;
if (level < mDischargeUnplugLevel) {
mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
@@ -14451,45 +13826,12 @@
mModStepMode = 0;
}
if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
- if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) {
+ if (mStatsFile != null && !mHistory.isReadOnly()) {
writeAsyncLocked();
}
}
}
- @GuardedBy("this")
- private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
- boolean reset) {
- mRecordingHistory = true;
- mHistoryCur.currentTime = mClock.currentTimeMillis();
- addHistoryBufferLocked(elapsedRealtimeMs,
- reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
- mHistoryCur);
- mHistoryCur.currentTime = 0;
- if (reset) {
- initActiveHistoryEventsLocked(elapsedRealtimeMs, uptimeMs);
- }
- }
-
- @GuardedBy("this")
- private void recordCurrentTimeChangeLocked(final long currentTimeMs,
- final long elapsedRealtimeMs, final long uptimeMs) {
- if (mRecordingHistory) {
- mHistoryCur.currentTime = currentTimeMs;
- addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur);
- mHistoryCur.currentTime = 0;
- }
- }
-
- @GuardedBy("this")
- private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) {
- if (mRecordingHistory) {
- mHistoryCur.currentTime = currentTimeMs;
- addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur);
- mHistoryCur.currentTime = 0;
- }
- }
-
private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
if (mExternalSync != null) {
mExternalSync.scheduleSync(reason, updateFlags);
@@ -14507,8 +13849,7 @@
// Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
temp = Math.max(0, temp);
- reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null,
- status, plugType, level);
+ reportChangesToStatsLog(status, plugType, level);
final boolean onBattery = isOnBattery(plugType, status);
if (!mHaveBatteryLevel) {
@@ -14518,52 +13859,47 @@
// plugged in, then twiddle our state to correctly reflect that
// since we won't be going through the full setOnBattery().
if (onBattery == mOnBattery) {
- if (onBattery) {
- mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- } else {
- mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
- }
+ mHistory.setPluggedInState(!onBattery);
}
+ mBatteryStatus = status;
+ mBatteryLevel = level;
+ mBatteryChargeUah = chargeUah;
+
// Always start out assuming charging, that will be updated later.
- mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
- mHistoryCur.batteryStatus = (byte)status;
- mHistoryCur.batteryLevel = (byte)level;
- mHistoryCur.batteryChargeUah = chargeUah;
+ mHistory.setBatteryState(true /* charging */, status, level, chargeUah);
+
mMaxChargeStepLevel = mMinDischargeStepLevel =
mLastChargeStepLevel = mLastDischargeStepLevel = level;
- } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
+ } else if (mBatteryLevel != level || mOnBattery != onBattery) {
recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs);
}
- int oldStatus = mHistoryCur.batteryStatus;
+ int oldStatus = mBatteryStatus;
if (onBattery) {
mDischargeCurrentLevel = level;
- if (!mRecordingHistory) {
- mRecordingHistory = true;
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
+ if (!mHistory.isRecordingHistory()) {
+ mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
} else if (level < 96 &&
status != BatteryManager.BATTERY_STATUS_UNKNOWN) {
- if (!mRecordingHistory) {
- mRecordingHistory = true;
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
+ if (!mHistory.isRecordingHistory()) {
+ mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
}
- mBatteryVoltageMv = voltageMv;
- mCurrentBatteryLevel = level;
if (mDischargePlugLevel < 0) {
mDischargePlugLevel = level;
}
if (onBattery != mOnBattery) {
- mHistoryCur.batteryLevel = (byte)level;
- mHistoryCur.batteryStatus = (byte)status;
- mHistoryCur.batteryHealth = (byte)health;
- mHistoryCur.batteryPlugType = (byte)plugType;
- mHistoryCur.batteryTemperature = (short)temp;
- mHistoryCur.batteryVoltage = (char) voltageMv;
- if (chargeUah < mHistoryCur.batteryChargeUah) {
+ mBatteryLevel = level;
+ mBatteryStatus = status;
+ mBatteryHealth = health;
+ mBatteryPlugType = plugType;
+ mBatteryTemperature = temp;
+ mBatteryVoltageMv = voltageMv;
+ mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah);
+ if (chargeUah < mBatteryChargeUah) {
// Only record discharges
- final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
+ final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -14575,12 +13911,12 @@
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
- mHistoryCur.batteryChargeUah = chargeUah;
+ mBatteryChargeUah = chargeUah;
setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
} else {
boolean changed = false;
- if (mHistoryCur.batteryLevel != level) {
- mHistoryCur.batteryLevel = (byte)level;
+ if (mBatteryLevel != level) {
+ mBatteryLevel = level;
changed = true;
// TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
@@ -14588,33 +13924,33 @@
mExternalSync.scheduleSyncDueToBatteryLevelChange(
mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS);
}
- if (mHistoryCur.batteryStatus != status) {
- mHistoryCur.batteryStatus = (byte)status;
+ if (mBatteryStatus != status) {
+ mBatteryStatus = status;
changed = true;
}
- if (mHistoryCur.batteryHealth != health) {
- mHistoryCur.batteryHealth = (byte)health;
+ if (mBatteryHealth != health) {
+ mBatteryHealth = health;
changed = true;
}
- if (mHistoryCur.batteryPlugType != plugType) {
- mHistoryCur.batteryPlugType = (byte)plugType;
+ if (mBatteryPlugType != plugType) {
+ mBatteryPlugType = plugType;
changed = true;
}
- if (temp >= (mHistoryCur.batteryTemperature+10)
- || temp <= (mHistoryCur.batteryTemperature-10)) {
- mHistoryCur.batteryTemperature = (short)temp;
+ if (temp >= (mBatteryTemperature + 10)
+ || temp <= (mBatteryTemperature - 10)) {
+ mBatteryTemperature = temp;
changed = true;
}
- if (voltageMv > (mHistoryCur.batteryVoltage + 20)
- || voltageMv < (mHistoryCur.batteryVoltage - 20)) {
- mHistoryCur.batteryVoltage = (char) voltageMv;
+ if (voltageMv > (mBatteryVoltageMv + 20)
+ || voltageMv < (mBatteryVoltageMv - 20)) {
+ mBatteryVoltageMv = voltageMv;
changed = true;
}
- if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
- || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
- if (chargeUah < mHistoryCur.batteryChargeUah) {
+ if (chargeUah >= (mBatteryChargeUah + 10)
+ || chargeUah <= (mBatteryChargeUah - 10)) {
+ if (chargeUah < mBatteryChargeUah) {
// Only record discharges
- final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
+ final long chargeDiff = (long) mBatteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -14626,9 +13962,10 @@
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
- mHistoryCur.batteryChargeUah = chargeUah;
+ mBatteryChargeUah = chargeUah;
changed = true;
}
+
long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
| (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
| (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
@@ -14686,7 +14023,10 @@
mLastChargeStepLevel = level;
}
if (changed) {
- addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
+ mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth,
+ mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv,
+ mBatteryChargeUah);
+ mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
}
if (!onBattery &&
@@ -14695,7 +14035,7 @@
// We don't record history while we are plugged in and fully charged
// (or when battery is not present). The next time we are
// unplugged, history will be cleared.
- mRecordingHistory = DEBUG;
+ mHistory.setHistoryRecordingEnabled(DEBUG);
}
mLastLearnedBatteryCapacityUah = chargeFullUah;
@@ -14714,17 +14054,18 @@
}
// Inform StatsLog of setBatteryState changes.
- // If this is the first reporting, pass in recentPast == null.
- private void reportChangesToStatsLog(HistoryItem recentPast,
- final int status, final int plugType, final int level) {
+ private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
+ if (!mHaveBatteryLevel) {
+ return;
+ }
- if (recentPast == null || recentPast.batteryStatus != status) {
+ if (mBatteryStatus != status) {
FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
}
- if (recentPast == null || recentPast.batteryPlugType != plugType) {
+ if (mBatteryPlugType != plugType) {
FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
}
- if (recentPast == null || recentPast.batteryLevel != level) {
+ if (mBatteryLevel != level) {
FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
}
}
@@ -14794,7 +14135,7 @@
if (msPerLevel <= 0) {
return -1;
}
- return (msPerLevel * mCurrentBatteryLevel) * 1000;
+ return (msPerLevel * mBatteryLevel) * 1000;
}
@Override
@@ -14824,7 +14165,7 @@
if (msPerLevel <= 0) {
return -1;
}
- return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
+ return (msPerLevel * (100 - mBatteryLevel)) * 1000;
}
/*@hide */
@@ -15255,7 +14596,8 @@
@GuardedBy("this")
public void shutdownLocked() {
- recordShutdownLocked(mClock.currentTimeMillis(), mClock.elapsedRealtime());
+ mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(),
+ mClock.currentTimeMillis());
writeSyncLocked();
mShuttingDown = true;
}
@@ -15463,7 +14805,6 @@
PROC_STATE_CHANGE_COLLECTION_DELAY_MS = mParser.getLong(
KEY_PROC_STATE_CHANGE_COLLECTION_DELAY_MS,
DEFAULT_PROC_STATE_CHANGE_COLLECTION_DELAY_MS);
-
MAX_HISTORY_FILES = mParser.getInt(KEY_MAX_HISTORY_FILES,
ActivityManager.isLowRamDeviceStatic() ?
DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE
@@ -15474,9 +14815,20 @@
: DEFAULT_MAX_HISTORY_BUFFER_KB)
* 1024;
updateBatteryChargedDelayMsLocked();
+
+ onChange();
}
}
+ /**
+ * Propagates changes in constant values.
+ */
+ @VisibleForTesting
+ public void onChange() {
+ mHistory.setMaxHistoryFiles(MAX_HISTORY_FILES);
+ mHistory.setMaxHistoryBufferSize(MAX_HISTORY_BUFFER);
+ }
+
private void updateBatteryChargedDelayMsLocked() {
// a negative value indicates that we should ignore this override
final int delay = Settings.Global.getInt(mResolver,
@@ -15697,27 +15049,11 @@
}
private void writeHistoryLocked() {
- if (mBatteryStatsHistory.getActiveFile() == null) {
- Slog.w(TAG, "writeHistoryLocked: no history file associated with this instance");
- return;
- }
-
if (mShuttingDown) {
return;
}
- Parcel p = Parcel.obtain();
- try {
- final long start = SystemClock.uptimeMillis();
- writeHistoryBuffer(p, true);
- if (DEBUG) {
- Slog.d(TAG, "writeHistoryBuffer duration ms:"
- + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize());
- }
- writeParcelToFileLocked(p, mBatteryStatsHistory.getActiveFile());
- } finally {
- p.recycle();
- }
+ mHistory.writeHistory();
}
private final ReentrantLock mWriteLock = new ReentrantLock();
@@ -15756,13 +15092,6 @@
return;
}
- final AtomicFile activeHistoryFile = mBatteryStatsHistory.getActiveFile();
- if (activeHistoryFile == null) {
- Slog.w(TAG,
- "readLocked: no history file associated with this instance");
- return;
- }
-
mUidStats.clear();
Parcel stats = Parcel.obtain();
@@ -15775,7 +15104,7 @@
readSummaryFromParcel(stats);
if (DEBUG) {
Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath()
- + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
+ + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis()
- start));
}
}
@@ -15787,126 +15116,19 @@
stats.recycle();
}
- Parcel history = Parcel.obtain();
- try {
- final long start = SystemClock.uptimeMillis();
- if (activeHistoryFile.exists()) {
- byte[] raw = activeHistoryFile.readFully();
- if (raw.length > 0) {
- history.unmarshall(raw, 0, raw.length);
- history.setDataPosition(0);
- readHistoryBuffer(history);
- }
- if (DEBUG) {
- Slog.d(TAG, "readLocked history file::"
- + activeHistoryFile.getBaseFile().getPath()
- + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis()
- - start));
- }
- }
- } catch (Exception e) {
- Slog.e(TAG, "Error reading battery history", e);
- clearHistoryLocked();
- mBatteryStatsHistory.resetAllFiles();
- } finally {
- history.recycle();
+ if (!mHistory.readSummary()) {
+ resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(),
+ RESET_REASON_CORRUPT_FILE);
}
mEndPlatformVersion = Build.ID;
- if (mHistoryBuffer.dataPosition() > 0
- || mBatteryStatsHistory.getFilesNumbers().size() > 1) {
- mRecordingHistory = true;
- final long elapsedRealtimeMs = mClock.elapsedRealtime();
- final long uptimeMs = mClock.uptimeMillis();
- addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur);
- startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
- }
+ mHistory.continueRecordingHistory();
recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
}
@GuardedBy("this")
- 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;
- }
-
- final long historyBaseTime = in.readLong();
-
- mHistoryBuffer.setDataSize(0);
- mHistoryBuffer.setDataPosition(0);
-
- int bufSize = in.readInt();
- int curPos = in.dataPosition();
- if (bufSize >= (mConstants.MAX_HISTORY_BUFFER*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_HISTORY) Slog.i(TAG, "***************** READING NEW HISTORY: " + bufSize
- + " bytes at " + curPos);
- mHistoryBuffer.appendFrom(in, curPos, bufSize);
- in.setDataPosition(curPos + bufSize);
- }
-
- if (DEBUG_HISTORY) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** OLD mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
- mHistoryBaseTimeMs = historyBaseTime;
- if (DEBUG_HISTORY) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** NEW mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
-
- // We are just arbitrarily going to insert 1 minute from the sample of
- // the last run until samples in this run.
- if (mHistoryBaseTimeMs > 0) {
- long oldnow = mClock.elapsedRealtime();
- mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
- if (DEBUG_HISTORY) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
- }
- }
-
- void writeHistoryBuffer(Parcel out, boolean inclData) {
- if (DEBUG_HISTORY) {
- StringBuilder sb = new StringBuilder(128);
- sb.append("****************** WRITING mHistoryBaseTimeMs: ");
- TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
- sb.append(" mLastHistoryElapsedRealtimeMs: ");
- TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb);
- Slog.i(TAG, sb.toString());
- }
- out.writeInt(BatteryStatsHistory.VERSION);
- out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs);
- if (!inclData) {
- out.writeInt(0);
- out.writeInt(0);
- return;
- }
-
- out.writeInt(mHistoryBuffer.dataSize());
- if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
- + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
- out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
- }
-
- @GuardedBy("this")
public void readSummaryFromParcel(Parcel in) throws ParcelFormatException {
final int version = in.readInt();
@@ -15916,31 +15138,7 @@
return;
}
- boolean inclHistory = in.readBoolean();
- if (inclHistory) {
- readHistoryBuffer(in);
- mBatteryStatsHistory.readFromParcel(in);
- }
-
- mHistoryTagPool.clear();
- mNextHistoryTagIdx = 0;
- mNumHistoryTagChars = 0;
-
- int numTags = in.readInt();
- for (int i=0; i<numTags; i++) {
- int idx = in.readInt();
- String str = in.readString();
- int uid = in.readInt();
- HistoryTag tag = new HistoryTag();
- tag.string = str;
- tag.uid = uid;
- tag.poolIdx = idx;
- mHistoryTagPool.put(tag, idx);
- if (idx >= mNextHistoryTagIdx) {
- mNextHistoryTagIdx = idx+1;
- }
- mNumHistoryTagChars += tag.string.length() + 1;
- }
+ mHistory.readSummaryFromParcel(in);
mStartCount = in.readInt();
mUptimeUs = in.readLong();
@@ -15953,7 +15151,7 @@
mDischargeUnplugLevel = in.readInt();
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
- mCurrentBatteryLevel = in.readInt();
+ mBatteryLevel = in.readInt();
mEstimatedBatteryCapacityMah = in.readInt();
mLastLearnedBatteryCapacityUah = in.readInt();
mMinLearnedBatteryCapacityUah = in.readInt();
@@ -16456,19 +15654,7 @@
out.writeInt(VERSION);
- out.writeBoolean(inclHistory);
- if (inclHistory) {
- writeHistoryBuffer(out, true);
- mBatteryStatsHistory.writeToParcel(out);
- }
-
- out.writeInt(mHistoryTagPool.size());
- for (HashMap.Entry<HistoryTag, Integer> ent : mHistoryTagPool.entrySet()) {
- HistoryTag tag = ent.getKey();
- out.writeInt(ent.getValue());
- out.writeString(tag.string);
- out.writeInt(tag.uid);
- }
+ mHistory.writeSummaryToParcel(out, inclHistory);
out.writeInt(mStartCount);
out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED));
@@ -16481,7 +15667,7 @@
out.writeInt(mDischargeUnplugLevel);
out.writeInt(mDischargePlugLevel);
out.writeInt(mDischargeCurrentLevel);
- out.writeInt(mCurrentBatteryLevel);
+ out.writeInt(mBatteryLevel);
out.writeInt(mEstimatedBatteryCapacityMah);
out.writeInt(mLastLearnedBatteryCapacityUah);
out.writeInt(mMinLearnedBatteryCapacityUah);
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 0cdd4d1..c36d950 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -22,7 +22,6 @@
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
-import android.os.Parcel;
import android.os.Process;
import android.os.SystemClock;
import android.os.UidBatteryConsumer;
@@ -32,10 +31,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.PowerProfile;
-import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -220,18 +217,7 @@
}
BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats;
-
- // Make a copy of battery history to avoid concurrent modification.
- Parcel historyBuffer = Parcel.obtain();
- historyBuffer.appendFrom(batteryStatsImpl.mHistoryBuffer, 0,
- batteryStatsImpl.mHistoryBuffer.dataSize());
-
- final File systemDir =
- batteryStatsImpl.mBatteryStatsHistory.getHistoryDirectory().getParentFile();
- final BatteryStatsHistory batteryStatsHistory =
- new BatteryStatsHistory(historyBuffer, systemDir, null);
-
- batteryUsageStatsBuilder.setBatteryHistory(batteryStatsHistory);
+ batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.copyHistory());
}
BatteryUsageStats stats = batteryUsageStatsBuilder.build();
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index 61a7f38..5c934852 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
@@ -28,6 +28,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.Clock;
import org.junit.Before;
import org.junit.Test;
@@ -49,13 +50,14 @@
private final Parcel mHistoryBuffer = Parcel.obtain();
private File mSystemDir;
private File mHistoryDir;
+ private final Clock mClock = new MockClock();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Context context = InstrumentationRegistry.getContext();
mSystemDir = context.getDataDir();
- mHistoryDir = new File(mSystemDir, BatteryStatsHistory.HISTORY_DIR);
+ mHistoryDir = new File(mSystemDir, "battery-history");
String[] files = mHistoryDir.list();
if (files != null) {
for (int i = 0; i < files.length; i++) {
@@ -67,8 +69,8 @@
@Test
public void testConstruct() {
- BatteryStatsHistory history =
- new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
+ BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
+ null, mClock);
createActiveFile(history);
verifyFileNumbers(history, Arrays.asList(0));
verifyActiveFile(history, "0.bin");
@@ -76,8 +78,8 @@
@Test
public void testStartNextFile() {
- BatteryStatsHistory history =
- new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
+ BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
+ null, mClock);
List<Integer> fileList = new ArrayList<>();
fileList.add(0);
createActiveFile(history);
@@ -114,13 +116,13 @@
assertEquals(0, history.getHistoryUsedSize());
// create a new BatteryStatsHistory object, it will pick up existing history files.
- BatteryStatsHistory history2 =
- new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32);
- // verify construct can pick up all files from file system.
+ BatteryStatsHistory history2 = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
+ null, mClock);
+ // verify constructor can pick up all files from file system.
verifyFileNumbers(history2, fileList);
verifyActiveFile(history2, "33.bin");
- history2.resetAllFiles();
+ history2.reset();
createActiveFile(history2);
// verify all existing files are deleted.
for (int i = 2; i < 33; ++i) {
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index 713e786..570b2ee 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -63,6 +63,7 @@
MockBatteryStatsImpl(Clock clock, File historyDirectory) {
super(clock, historyDirectory);
initTimersAndCounters();
+ setMaxHistoryBuffer(128 * 1024);
setExternalStatsSyncLocked(mExternalStatsSync);
informThatAllExternalStatsAreFlushed();
@@ -104,12 +105,6 @@
return mForceOnBattery ? true : super.isOnBattery();
}
- public void forceRecordAllHistory() {
- mHaveBatteryLevel = true;
- mRecordingHistory = true;
- mRecordAllHistory = true;
- }
-
public TimeBase getOnBatteryBackgroundTimeBase(int uid) {
return getUidStatsLocked(uid).mOnBatteryBackgroundTimeBase;
}
@@ -201,12 +196,14 @@
@GuardedBy("this")
public MockBatteryStatsImpl setMaxHistoryFiles(int maxHistoryFiles) {
mConstants.MAX_HISTORY_FILES = maxHistoryFiles;
+ mConstants.onChange();
return this;
}
@GuardedBy("this")
public MockBatteryStatsImpl setMaxHistoryBuffer(int maxHistoryBuffer) {
mConstants.MAX_HISTORY_BUFFER = maxHistoryBuffer;
+ mConstants.onChange();
return this;
}