diff options
| author | 2022-08-22 21:54:00 +0000 | |
|---|---|---|
| committer | 2022-08-22 21:54:00 +0000 | |
| commit | a7ee33e7a7593fd306914ea8171694d6a22dff7f (patch) | |
| tree | 5bafe9ebc894fd5a330c35411ae80325d5236269 | |
| parent | 62242bdca32c0b519ad11b035b990f17e9974a3f (diff) | |
Revert "Breaking history writing out of BatteryStatsImpl"
This reverts commit 62242bdca32c0b519ad11b035b990f17e9974a3f.
Reason for revert: ramdumps on ToT related to battersystats parcel parsing
Bug: 243434675
Change-Id: I18522929f5a1499f56a0cc19606c28a2ed9fc26d
8 files changed, 1406 insertions, 1768 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index da206268917e..09a52e452f9a 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -2326,6 +2326,11 @@ public abstract class BatteryStats { 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(); @@ -7610,6 +7615,8 @@ public abstract class BatteryStats { 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 6909965edcd8..962870e733f7 100644 --- a/core/java/com/android/internal/os/BatteryStatsHistory.java +++ b/core/java/com/android/internal/os/BatteryStatsHistory.java @@ -17,35 +17,25 @@ package com.android.internal.os; import android.annotation.Nullable; -import android.os.BatteryManager; -import android.os.BatteryStats.HistoryItem; -import android.os.BatteryStats.HistoryStepDetails; -import android.os.BatteryStats.HistoryTag; +import android.os.BatteryStats; 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.concurrent.locks.ReentrantLock; +import java.util.function.Supplier; /** * BatteryStatsHistory encapsulates battery history files. @@ -66,62 +56,57 @@ import java.util.concurrent.locks.ReentrantLock; * 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 - private static final int VERSION = 208; + public static final int VERSION = 208; - private static final String HISTORY_DIR = "battery-history"; - private static final String FILE_SUFFIX = ".bin"; + public static final String HISTORY_DIR = "battery-history"; + public 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. - 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. + 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. // Flag in delta int: a new battery level int follows. - static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000; + public static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000; // Flag in delta int: a new full state and battery status int follows. - static final int DELTA_STATE_FLAG = 0x00100000; + public static final int DELTA_STATE_FLAG = 0x00100000; // Flag in delta int: a new full state2 int follows. - static final int DELTA_STATE2_FLAG = 0x00200000; + public static final int DELTA_STATE2_FLAG = 0x00200000; // Flag in delta int: contains a wakelock or wakeReason tag. - static final int DELTA_WAKELOCK_FLAG = 0x00400000; + public static final int DELTA_WAKELOCK_FLAG = 0x00400000; // Flag in delta int: contains an event description. - static final int DELTA_EVENT_FLAG = 0x00800000; + public static final int DELTA_EVENT_FLAG = 0x00800000; // Flag in delta int: contains the battery charge count in uAh. - static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000; + public static final int DELTA_BATTERY_CHARGE_FLAG = 0x01000000; // These upper bits are the frequently changing state bits. - static final int DELTA_STATE_MASK = 0xfe000000; + public 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. - 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; + 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; // We use the low bit of the battery state int to indicate that we have full details // from a battery level change. - static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001; + public 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 - static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000; + public 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. */ @@ -159,77 +144,19 @@ public class BatteryStatsHistory { */ 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 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 + * @param historyBuffer The in-memory history buffer. + * @param systemDir typically /data/system + * @param maxHistoryFiles the largest number of history buffer files to keep */ - 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) { + Supplier<Integer> maxHistoryFiles) { mHistoryBuffer = historyBuffer; - mSystemDir = systemDir; + mHistoryDir = new File(systemDir, HISTORY_DIR); 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()); @@ -265,81 +192,19 @@ public class BatteryStatsHistory { } } - public BatteryStatsHistory(HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) { - mStepDetailsCalculator = stepDetailsCalculator; - mClock = clock; - - mHistoryBuffer = Parcel.obtain(); - mSystemDir = null; - mHistoryDir = null; - initHistoryBuffer(); - } - /** * Used when BatteryStatsImpl object is created from deserialization of a parcel, - * such as a checkin file. + * such as Settings app or checkin file. + * @param historyBuffer the history buffer */ - private BatteryStatsHistory(Parcel historyBuffer, - HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) { - mHistoryBuffer = historyBuffer; - mClock = clock; - mSystemDir = null; + public BatteryStatsHistory(Parcel historyBuffer) { 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); + mHistoryBuffer = historyBuffer; + mMaxHistoryFiles = null; } - /** - * Returns true if this instance only supports reading history. - */ - public boolean isReadOnly() { - return mActiveFile == null; + public File getHistoryDirectory() { + return mHistoryDir; } /** @@ -356,13 +221,12 @@ public class BatteryStatsHistory { /** * 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)); } /** @@ -370,7 +234,7 @@ public class BatteryStatsHistory { * create next history file. */ public void startNextFile() { - if (mMaxHistoryFiles == 0) { + if (mMaxHistoryFiles == null) { Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history"); return; } @@ -400,7 +264,7 @@ public class BatteryStatsHistory { // 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) { + while (mFileNumbers.size() > mMaxHistoryFiles.get()) { int oldest = mFileNumbers.get(0); getFile(oldest).delete(); mFileNumbers.remove(0); @@ -408,43 +272,36 @@ public class BatteryStatsHistory { } /** - * Clear history buffer and delete all existing history files. Active history file start from - * number 0 again. + * Delete all existing history files. Active history file start from number 0 again. */ - public void reset() { - if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!"); + public void resetAllFiles() { 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 BatteryStatsHistoryIterator iterate() { + public boolean startIteratingHistory() { mRecordCount = 0; mCurrentFileIndex = 0; mCurrentParcel = null; mCurrentParcelEnd = 0; mParcelIndex = 0; - mBatteryStatsHistoryIterator = new BatteryStatsHistoryIterator(this); - return mBatteryStatsHistoryIterator; + return true; } /** * Finish iterating history files and history buffer. */ - void finishIteratingHistory() { + public 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); } @@ -454,12 +311,11 @@ public class BatteryStatsHistory { * 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(HistoryItem out) { + public Parcel getNextParcel(BatteryStats.HistoryItem out) { if (mRecordCount == 0) { // reset out if it is the first record. out.clear(); @@ -467,7 +323,8 @@ public class BatteryStatsHistory { ++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; @@ -532,8 +389,7 @@ public class BatteryStatsHistory { /** * 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. */ @@ -546,8 +402,8 @@ public class BatteryStatsHistory { 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); @@ -557,7 +413,6 @@ public class BatteryStatsHistory { /** * Skip the header part of history parcel. - * * @param p history parcel to skip head. * @return true if version match, false if not. */ @@ -573,68 +428,18 @@ public class BatteryStatsHistory { } /** - * 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) { @@ -645,13 +450,13 @@ public class BatteryStatsHistory { 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); @@ -675,55 +480,17 @@ public class BatteryStatsHistory { Parcel historyBuffer = Parcel.obtain(); historyBuffer.unmarshall(historyBlob, 0, historyBlob.length); - BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer, null, - Clock.SYSTEM_CLOCK); + BatteryStatsHistory history = new BatteryStatsHistory(historyBuffer); 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 */); } @@ -731,7 +498,7 @@ public class BatteryStatsHistory { 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; @@ -754,12 +521,10 @@ public class BatteryStatsHistory { return stats.getAvailableBytes() > MIN_FREE_SPACE; } - @VisibleForTesting public List<Integer> getFilesNumbers() { return mFileNumbers; } - @VisibleForTesting public AtomicFile getActiveFile() { return mActiveFile; } @@ -769,972 +534,15 @@ public class BatteryStatsHistory { */ 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 1bf878cb9119..de8b414c4b78 100644 --- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java +++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java @@ -36,6 +36,7 @@ public class BatteryStatsHistoryIterator { public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) { mBatteryStatsHistory = history; + mBatteryStatsHistory.startIteratingHistory(); } /** @@ -230,11 +231,4 @@ public class BatteryStatsHistoryIterator { 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 df902c2916ba..fe4aa534df6f 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 @@ public class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStat // Now that we have finally received all the data, we can tell mStats about it. synchronized (mStats) { - mStats.recordHistoryEventLocked( + mStats.addHistoryEventLocked( 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 968f9161b3c1..0c9ada8fa6db 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -108,7 +108,6 @@ import com.android.internal.annotations.GuardedBy; 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; @@ -174,6 +173,7 @@ public class BatteryStatsImpl extends BatteryStats { 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,11 +322,6 @@ public class BatteryStatsImpl extends BatteryStats { @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; @@ -418,7 +413,7 @@ public class BatteryStatsImpl extends BatteryStats { if (changed) { final long uptimeMs = mClock.uptimeMillis(); final long elapsedRealtimeMs = mClock.elapsedRealtime(); - mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } } @@ -673,16 +668,16 @@ public class BatteryStatsImpl extends BatteryStats { /** * Mapping isolated uids to the actual owning app uid. */ - private final SparseIntArray mIsolatedUids = new SparseIntArray(); + final SparseIntArray mIsolatedUids = new SparseIntArray(); /** * Internal reference count of isolated uids. */ - private final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray(); + final SparseIntArray mIsolatedUidRefCounts = new SparseIntArray(); /** * The statistics we have collected organized by uids. */ - private final SparseArray<BatteryStatsImpl.Uid> mUidStats = new SparseArray<>(); + 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. @@ -690,21 +685,20 @@ public class BatteryStatsImpl extends BatteryStats { // changes. @VisibleForTesting protected ArrayList<StopwatchTimer> mPartialTimers = 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<>(); + 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<>(); // Last partial timers we use for distributing CPU usage. @VisibleForTesting @@ -719,24 +713,69 @@ public class BatteryStatsImpl extends BatteryStats { protected final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(true); private boolean mSystemReady; - private boolean mShuttingDown; - - private final HistoryEventTracker mActiveEvents = new HistoryEventTracker(); - private final HistoryStepDetailsCalculatorImpl mStepDetailsCalculator = - new HistoryStepDetailsCalculatorImpl(); - - 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; + boolean mShuttingDown; + + final HistoryEventTracker mActiveEvents = new HistoryEventTracker(); + + 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; @NonNull - private final BatteryStatsHistory mHistory; + 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 BatteryStatsHistoryIterator mBatteryStatsHistoryIterator; @@ -1352,6 +1391,7 @@ public class BatteryStatsImpl extends BatteryStats { int mDischargeUnplugLevel; int mDischargePlugLevel; int mDischargeCurrentLevel; + int mCurrentBatteryLevel; int mLowDischargeAmountSinceCharge; int mHighDischargeAmountSinceCharge; int mDischargeScreenOnUnplugLevel; @@ -1403,6 +1443,7 @@ public class BatteryStatsImpl extends BatteryStats { private int mNumConnectivityChange; + private int mBatteryVoltageMv = -1; private int mEstimatedBatteryCapacityMah = -1; private int mLastLearnedBatteryCapacityUah = -1; @@ -1586,27 +1627,28 @@ public class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(Clock clock) { - this(clock, null); + this(clock, (File) 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; - mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock); + mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer); } else { mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin")); - mHistory = new BatteryStatsHistory(historyDirectory, mConstants.MAX_HISTORY_FILES, - mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock); + mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, historyDirectory, + this::getMaxHistoryFiles); } + mHandler = null; mPlatformIdleStateCallback = null; mMeasuredEnergyRetriever = null; mUserInfoProvider = null; + mConstants = new Constants(mHandler); + clearHistoryLocked(); } private void init(Clock clock) { @@ -3869,188 +3911,406 @@ public class BatteryStatsImpl extends BatteryStats { return kmt; } - private class HistoryStepDetailsCalculatorImpl implements HistoryStepDetailsCalculator { - private final HistoryStepDetails mDetails = new HistoryStepDetails(); - - private boolean mHasHistoryStepDetails; + /** + * 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; + } + } - private int mLastHistoryStepLevel; + /* + 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. + */ - /** - * 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; - } + @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; + } - // Perform a CPU update right after we do this collection, so we have started - // collecting good data for the next step. - requestImmediateCpuUpdate(); + final long deltaTime = cur.time - last.time; + final int lastBatteryLevelInt = buildBatteryLevelInt(last); + final int lastStateInt = buildStateInt(last); - if (mPlatformIdleStateCallback != null) { - mDetails.statSubsystemPowerState = - mPlatformIdleStateCallback.getSubsystemLowPowerStats(); - if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" + - mDetails.statSubsystemPowerState); - } - - 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(); + 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.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; + 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; } - - mHasHistoryStepDetails = mBatteryLevel <= mLastHistoryStepLevel; - mLastHistoryStepLevel = mBatteryLevel; - - return mDetails; } - - 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); + 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; } - mCurStepCpuUserTimeMs += totalUTimeMs; - mCurStepCpuSystemTimeMs += totalSTimeMs; - mCurStepStatUserTimeMs += statUserTimeMs; - mCurStepStatSystemTimeMs += statSystemTimeMs; - mCurStepStatIOWaitTimeMs += statIOWaitTimeMs; - mCurStepStatIrqTimeMs += statIrqTimeMs; - mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs; - mCurStepStatIdleTimeMs += statIdleTimeMs; + 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 = + mPlatformIdleStateCallback.getSubsystemLowPowerStats(); + if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" + + mCurHistoryStepDetails.statSubsystemPowerState); - @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; + } + 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; + } + } } + mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs; + mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs; + mLastStepStatUserTimeMs = mCurStepStatUserTimeMs; + mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs; + mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs; + mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs; + mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs; + mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs; } @GuardedBy("this") @Override public void commitCurrentHistoryBatchLocked() { - mHistory.commitCurrentHistoryBatchLocked(); + mHistoryLastWritten.cmd = HistoryItem.CMD_NULL; } @GuardedBy("this") @@ -4066,9 +4326,191 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") - public void recordHistoryEventLocked(long elapsedRealtimeMs, long uptimeMs, int code, + 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, String name, int uid) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, 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; } @GuardedBy("this") @@ -4221,13 +4663,13 @@ public class BatteryStatsImpl extends BatteryStats { if (!mActiveEvents.updateState(code, name, uid, 0)) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, code, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid); } @GuardedBy("this") public void noteCurrentTimeChangedLocked(long currentTimeMs, long elapsedRealtimeMs, long uptimeMs) { - mHistory.recordCurrentTimeChange(elapsedRealtimeMs, uptimeMs, currentTimeMs); + recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs); } @GuardedBy("this") @@ -4244,7 +4686,7 @@ public class BatteryStatsImpl extends BatteryStats { if (!mRecordAllHistory) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid); } @GuardedBy("this") @@ -4302,7 +4744,8 @@ public class BatteryStatsImpl extends BatteryStats { if (!mRecordAllHistory) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, + name, uid); } @GuardedBy("this") @@ -4318,7 +4761,7 @@ public class BatteryStatsImpl extends BatteryStats { if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid); } @GuardedBy("this") @@ -4334,7 +4777,8 @@ public class BatteryStatsImpl extends BatteryStats { if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, + name, uid); } @GuardedBy("this") @@ -4350,7 +4794,7 @@ public class BatteryStatsImpl extends BatteryStats { if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid); } @GuardedBy("this") @@ -4368,7 +4812,7 @@ public class BatteryStatsImpl extends BatteryStats { if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid); } @GuardedBy("this") @@ -4416,7 +4860,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workSource.size(); ++i) { uid = mapUid(workSource.getUid(i)); if (mActiveEvents.updateState(historyItem, name, uid, 0)) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); } } @@ -4425,7 +4869,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { uid = mapUid(workChains.get(i).getAttributionUid()); if (mActiveEvents.updateState(historyItem, name, uid, 0)) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); } } } @@ -4433,7 +4877,7 @@ public class BatteryStatsImpl extends BatteryStats { uid = mapUid(uid); if (mActiveEvents.updateState(historyItem, name, uid, 0)) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); } } } @@ -4508,7 +4952,7 @@ public class BatteryStatsImpl extends BatteryStats { for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) { SparseIntArray uids = ent.getValue(); for (int j=0; j<uids.size(); j++) { - mHistory.recordEvent(mSecRealtime, mSecUptime, + addHistoryEventLocked(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_FINISH, ent.getKey(), uids.keyAt(j)); } } @@ -4523,8 +4967,8 @@ public class BatteryStatsImpl extends BatteryStats { for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) { SparseIntArray uids = ent.getValue(); for (int j=0; j<uids.size(); j++) { - mHistory.recordEvent(mSecRealtime, mSecUptime, HistoryItem.EVENT_PROC_START, - ent.getKey(), uids.keyAt(j)); + addHistoryEventLocked(mSecRealtime, mSecUptime, + HistoryItem.EVENT_PROC_START, ent.getKey(), uids.keyAt(j)); } } } @@ -4567,19 +5011,30 @@ public class BatteryStatsImpl extends BatteryStats { if (mRecordAllHistory) { if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName, mappedUid, 0)) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, + addHistoryEventLocked(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; - mHistory.recordWakelockStartEvent(elapsedRealtimeMs, uptimeMs, historyName, - mappedUid); - } else if (!mWakeLockImportant && !unimportantForLogging) { - if (mHistory.maybeUpdateWakelockTag(elapsedRealtimeMs, uptimeMs, historyName, - mappedUid)) { - mWakeLockImportant = true; - } + 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); + } + mWakeLockImportant = true; } mWakeLockNesting++; } @@ -4632,13 +5087,15 @@ public class BatteryStatsImpl extends BatteryStats { } if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid, 0)) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, mappedUid); } } if (mWakeLockNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WAKE_LOCK_FLAG); + mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } if (mappedUid >= 0) { @@ -4829,7 +5286,7 @@ public class BatteryStatsImpl extends BatteryStats { mappedUid, 0)) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START, + addHistoryEventLocked(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 @@ -4882,7 +5339,7 @@ public class BatteryStatsImpl extends BatteryStats { mappedUid, 0)) { return; } - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, + addHistoryEventLocked(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. @@ -4904,10 +5361,15 @@ public class BatteryStatsImpl extends BatteryStats { @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); - mHistory.recordWakeupEvent(elapsedRealtimeMs, uptimeMs, reason); + mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag; + mHistoryCur.wakeReasonTag.string = reason; + mHistoryCur.wakeReasonTag.uid = 0; mLastWakeupReason = reason; mLastWakeupUptimeMs = uptimeMs; + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } @GuardedBy("this") @@ -4918,11 +5380,22 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, - int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, - int statSoftIrqTimeMs, int statIdleTimeMs) { - mStepDetailsCalculator.addCpuStats(totalUTimeMs, totalSTimeMs, statUserTimeMs, - statSystemTimeMs, statIOWaitTimeMs, statIrqTimeMs, - statSoftIrqTimeMs, statIdleTimeMs); + 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; } public void noteProcessDiedLocked(int uid, int pid) { @@ -4952,8 +5425,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mSensorNesting == 0) { - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_SENSOR_ON_FLAG); + mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mSensorNesting++; getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -4970,8 +5445,10 @@ public class BatteryStatsImpl extends BatteryStats { uid = mapUid(uid); mSensorNesting--; if (mSensorNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_SENSOR_ON_FLAG); + mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteStopSensor(sensor, elapsedRealtimeMs); @@ -5021,8 +5498,10 @@ public class BatteryStatsImpl extends BatteryStats { } final int mappedUid = mapUid(uid); if (mGpsNesting == 0) { - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_GPS_ON_FLAG); + mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mGpsNesting++; @@ -5047,8 +5526,10 @@ public class BatteryStatsImpl extends BatteryStats { final int mappedUid = mapUid(uid); mGpsNesting--; if (mGpsNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_GPS_ON_FLAG); + mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs); mGpsSignalQualityBin = -1; } @@ -5081,9 +5562,12 @@ public class BatteryStatsImpl extends BatteryStats { if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) { mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs); } - mHistory.recordGpsSignalQualityEvent(elapsedRealtimeMs, uptimeMs, signalLevel); + mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK) + | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mGpsSignalQualityBin = signalLevel; } + return; } @GuardedBy("this") @@ -5256,33 +5740,41 @@ public class BatteryStatsImpl extends BatteryStats { } } - int startStates = 0; - int stopStates = 0; + boolean updateHistory = false; if (Display.isDozeState(state) && !Display.isDozeState(oldState)) { - startStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG; + mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG; mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs); + updateHistory = true; } else if (Display.isDozeState(oldState) && !Display.isDozeState(state)) { - stopStates |= HistoryItem.STATE_SCREEN_DOZE_FLAG; + mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG; mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs); + updateHistory = true; } if (Display.isOnState(state)) { - startStates |= HistoryItem.STATE_SCREEN_ON_FLAG; + mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: " + + Integer.toHexString(mHistoryCur.states)); mScreenOnTimer.startRunningLocked(elapsedRealtimeMs); if (mScreenBrightnessBin >= 0) { mScreenBrightnessTimer[mScreenBrightnessBin] .startRunningLocked(elapsedRealtimeMs); } + updateHistory = true; } else if (Display.isOnState(oldState)) { - stopStates |= HistoryItem.STATE_SCREEN_ON_FLAG; + mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: " + + Integer.toHexString(mHistoryCur.states)); mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs); if (mScreenBrightnessBin >= 0) { mScreenBrightnessTimer[mScreenBrightnessBin] .stopRunningLocked(elapsedRealtimeMs); } + updateHistory = true; } - if (startStates != 0 || stopStates != 0) { - mHistory.recordStateChangeEvent(elapsedRealtimeMs, uptimeMs, startStates, - stopStates); + if (updateHistory) { + if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: " + + Display.stateToString(state)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } // Per screen state Cpu stats needed. Prepare to schedule an external sync. @@ -5396,7 +5888,13 @@ public class BatteryStatsImpl extends BatteryStats { long uptimeMs) { if (mScreenBrightnessBin != overallBin) { if (overallBin >= 0) { - mHistory.recordScreenBrightnessEvent(elapsedRealtimeMs, uptimeMs, overallBin); + 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); } if (mScreenState == Display.STATE_ON) { if (mScreenBrightnessBin >= 0) { @@ -5423,8 +5921,8 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteWakeUpLocked(String reason, int reasonUid, long elapsedRealtimeMs, long uptimeMs) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason, - reasonUid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, + reason, reasonUid); } @GuardedBy("this") @@ -5443,7 +5941,7 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteConnectivityChangedLocked(int type, String extra, long elapsedRealtimeMs, long uptimeMs) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED, extra, type); mNumConnectivityChange++; } @@ -5452,7 +5950,7 @@ public class BatteryStatsImpl extends BatteryStats { private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid) { uid = mapUid(uid); - mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", + addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", uid); getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked(); } @@ -5478,8 +5976,7 @@ public class BatteryStatsImpl extends BatteryStats { } mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000); - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG); + mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; } else { realElapsedRealtimeMs = timestampNs / (1000*1000); long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs; @@ -5491,9 +5988,11 @@ public class BatteryStatsImpl extends BatteryStats { mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs - realElapsedRealtimeMs); } - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG); + mHistoryCur.states &= ~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. @@ -5543,14 +6042,17 @@ public class BatteryStatsImpl extends BatteryStats { mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState; mPowerSaveModeEnabled = enabled; if (enabled) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_POWER_SAVE_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: " + + Integer.toHexString(mHistoryCur.states2)); mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs); } else { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_POWER_SAVE_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: " + + Integer.toHexString(mHistoryCur.states2)); mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs); } + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON @@ -5574,7 +6076,7 @@ public class BatteryStatsImpl extends BatteryStats { nowLightIdling = true; } if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE, activeReason, activeUid); } if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) { @@ -5604,7 +6106,11 @@ public class BatteryStatsImpl extends BatteryStats { } } if (mDeviceIdleMode != mode) { - mHistory.recordDeviceIdleEvent(elapsedRealtimeMs, uptimeMs, 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); long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs; mLastIdleTimeStartMs = elapsedRealtimeMs; if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) { @@ -5632,7 +6138,7 @@ public class BatteryStatsImpl extends BatteryStats { public void notePackageInstalledLocked(String pkgName, long versionCode, long elapsedRealtimeMs, long uptimeMs) { // XXX need to figure out what to do with long version codes. - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED, pkgName, (int)versionCode); PackageChange pc = new PackageChange(); pc.mPackageName = pkgName; @@ -5644,8 +6150,8 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void notePackageUninstalledLocked(String pkgName, long elapsedRealtimeMs, long uptimeMs) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_UNINSTALLED, - pkgName, 0); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, + HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0); PackageChange pc = new PackageChange(); pc.mPackageName = pkgName; pc.mUpdate = true; @@ -5674,8 +6180,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) { if (!mPhoneOn) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_PHONE_IN_CALL_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mPhoneOn = true; mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs); } @@ -5684,8 +6192,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) { if (mPhoneOn) { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_PHONE_IN_CALL_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mPhoneOn = false; mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs); } @@ -5723,12 +6233,11 @@ public class BatteryStatsImpl extends BatteryStats { if (mUsbDataState != newState) { mUsbDataState = newState; if (connected) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_USB_DATA_LINK_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_USB_DATA_LINK_FLAG; } else { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_USB_DATA_LINK_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG; } + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } @@ -5749,10 +6258,6 @@ public class BatteryStatsImpl extends BatteryStats { 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; @@ -5781,8 +6286,10 @@ public class BatteryStatsImpl extends BatteryStats { scanning = true; strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; if (!mPhoneSignalScanningTimer.isRunningLocked()) { - addStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG; + mHistoryCur.states |= 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); @@ -5792,7 +6299,9 @@ public class BatteryStatsImpl extends BatteryStats { if (!scanning) { // If we are no longer scanning, then stop the scanning timer. if (mPhoneSignalScanningTimer.isRunningLocked()) { - removeStateFlag = HistoryItem.STATE_PHONE_SCANNING_FLAG; + mHistoryCur.states &= ~HistoryItem.STATE_PHONE_SCANNING_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: " + + Integer.toHexString(mHistoryCur.states)); newHistory = true; mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs); FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state, @@ -5801,7 +6310,10 @@ public class BatteryStatsImpl extends BatteryStats { } if (mPhoneServiceState != state) { - newState = 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)); newHistory = true; mPhoneServiceState = state; } @@ -5815,7 +6327,11 @@ public class BatteryStatsImpl extends BatteryStats { if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) { mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs); } - newSignalStrength = strengthBin; + 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)); newHistory = true; FrameworkStatsLog.write( FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin); @@ -5826,8 +6342,7 @@ public class BatteryStatsImpl extends BatteryStats { } if (newHistory) { - mHistory.recordPhoneStateChangeEvent(elapsedRealtimeMs, uptimeMs, - addStateFlag, removeStateFlag, newState, newSignalStrength); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } @@ -5951,7 +6466,11 @@ public class BatteryStatsImpl extends BatteryStats { if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); if (mPhoneDataConnectionType != bin) { - mHistory.recordDataConnectionTypeChangeEvent(elapsedRealtimeMs, uptimeMs, 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); if (mPhoneDataConnectionType >= 0) { mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked( elapsedRealtimeMs); @@ -6024,8 +6543,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) { if (!mWifiOn) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_WIFI_ON_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mWifiOn = true; mWifiOnTimer.startRunningLocked(elapsedRealtimeMs); scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI); @@ -6035,8 +6556,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) { if (mWifiOn) { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_WIFI_ON_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mWifiOn = false; mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs); scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI); @@ -6047,8 +6570,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mAudioOnNesting == 0) { - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_AUDIO_ON_FLAG); + mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mAudioOnTimer.startRunningLocked(elapsedRealtimeMs); } mAudioOnNesting++; @@ -6063,8 +6588,10 @@ public class BatteryStatsImpl extends BatteryStats { } uid = mapUid(uid); if (--mAudioOnNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_AUDIO_ON_FLAG); + mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6075,8 +6602,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mVideoOnNesting == 0) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_VIDEO_ON_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mVideoOnTimer.startRunningLocked(elapsedRealtimeMs); } mVideoOnNesting++; @@ -6091,8 +6620,10 @@ public class BatteryStatsImpl extends BatteryStats { } uid = mapUid(uid); if (--mVideoOnNesting == 0) { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_VIDEO_ON_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6103,8 +6634,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) { if (mAudioOnNesting > 0) { mAudioOnNesting = 0; - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_AUDIO_ON_FLAG); + mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); @@ -6117,8 +6650,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) { if (mVideoOnNesting > 0) { mVideoOnNesting = 0; - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_VIDEO_ON_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); @@ -6170,8 +6705,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mFlashlightOnNesting++ == 0) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_FLASHLIGHT_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6185,8 +6722,10 @@ public class BatteryStatsImpl extends BatteryStats { } uid = mapUid(uid); if (--mFlashlightOnNesting == 0) { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_FLASHLIGHT_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6197,8 +6736,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mCameraOnNesting++ == 0) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_CAMERA_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mCameraOnTimer.startRunningLocked(elapsedRealtimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6212,8 +6753,10 @@ public class BatteryStatsImpl extends BatteryStats { } uid = mapUid(uid); if (--mCameraOnNesting == 0) { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_CAMERA_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6224,8 +6767,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) { if (mCameraOnNesting > 0) { mCameraOnNesting = 0; - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_CAMERA_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); @@ -6238,8 +6783,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) { if (mFlashlightOnNesting > 0) { mFlashlightOnNesting = 0; - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_FLASHLIGHT_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); @@ -6256,8 +6803,10 @@ public class BatteryStatsImpl extends BatteryStats { } uid = mapUid(uid); if (mBluetoothScanNesting == 0) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs); } mBluetoothScanNesting++; @@ -6298,8 +6847,10 @@ public class BatteryStatsImpl extends BatteryStats { uid = mapUid(uid); mBluetoothScanNesting--; if (mBluetoothScanNesting == 0) { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6334,8 +6885,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) { if (mBluetoothScanNesting > 0) { mBluetoothScanNesting = 0; - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: " + + Integer.toHexString(mHistoryCur.states2)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); @@ -6375,7 +6928,7 @@ public class BatteryStatsImpl extends BatteryStats { private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, final long uptimeMillis, int uid) { uid = mapUid(uid); - mHistory.recordEvent(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", + addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", uid); getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked(); } @@ -6391,14 +6944,15 @@ public class BatteryStatsImpl extends BatteryStats { if (uid > 0) { noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid); } - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG); + mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG; mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs); } else { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG); + mHistoryCur.states &= ~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; } } @@ -6406,8 +6960,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { if (!mGlobalWifiRunning) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_WIFI_RUNNING_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mGlobalWifiRunning = true; mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs); int N = ws.size(); @@ -6475,8 +7031,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { if (mGlobalWifiRunning) { - mHistory.recordState2StopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_WIFI_RUNNING_FLAG); + mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mGlobalWifiRunning = false; mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs); int N = ws.size(); @@ -6524,7 +7082,12 @@ public class BatteryStatsImpl extends BatteryStats { } mWifiSupplState = supplState; mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs); - mHistory.recordWifiSupplicantStateChangeEvent(elapsedRealtimeMs, uptimeMs, supplState); + 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); } } @@ -6553,8 +7116,12 @@ public class BatteryStatsImpl extends BatteryStats { if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) { mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs); } - mHistory.recordWifiSignalStrengthChangeEvent(elapsedRealtimeMs, uptimeMs, - strengthBin); + 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); } else { stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs); } @@ -6567,8 +7134,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mWifiFullLockNesting == 0) { - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_FULL_LOCK_FLAG); + 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); } mWifiFullLockNesting++; getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6579,8 +7148,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { mWifiFullLockNesting--; if (mWifiFullLockNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_FULL_LOCK_FLAG); + 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); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteFullWifiLockReleasedLocked(elapsedRealtimeMs); @@ -6596,8 +7167,10 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mWifiScanNesting == 0) { - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_SCAN_FLAG); + mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mWifiScanNesting++; getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) @@ -6613,8 +7186,10 @@ public class BatteryStatsImpl extends BatteryStats { public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { mWifiScanNesting--; if (mWifiScanNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_SCAN_FLAG); + mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: " + + Integer.toHexString(mHistoryCur.states)); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) .noteWifiScanStoppedLocked(elapsedRealtimeMs); @@ -6639,10 +7214,14 @@ public class BatteryStatsImpl extends BatteryStats { public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (mWifiMulticastNesting == 0) { - mHistory.recordStateStartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG); + 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); + // Start Wifi Multicast overall timer if (!mWifiMulticastWakelockTimer.isRunningLocked()) { + if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started"); mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs); } } @@ -6656,12 +7235,14 @@ public class BatteryStatsImpl extends BatteryStats { uid = mapUid(uid); mWifiMulticastNesting--; if (mWifiMulticastNesting == 0) { - mHistory.recordStateStopEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG); + 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); // Stop Wifi Multicast overall timer if (mWifiMulticastWakelockTimer.isRunningLocked()) { - if (DEBUG) Slog.v(TAG, "Multicast Overall Timer Stopped"); + if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped"); mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs); } } @@ -7413,9 +7994,8 @@ public class BatteryStatsImpl extends BatteryStats { // 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. - mHistory.recordCurrentTimeChange(mClock.elapsedRealtime(), mClock.uptimeMillis(), - currentTimeMs - ); + recordCurrentTimeChangeLocked(currentTimeMs, mClock.elapsedRealtime(), + mClock.uptimeMillis()); return currentTimeMs - (mClock.elapsedRealtime() - (mRealtimeStartUs / 1000)); } return mStartClockTimeMs; @@ -10647,19 +11227,18 @@ public class BatteryStatsImpl extends BatteryStats { UserInfoProvider userInfoProvider) { init(clock); - mHandler = new MyHandler(handler.getLooper()); - mConstants = new Constants(mHandler); - if (systemDir == null) { mStatsFile = null; - mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock); + mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer); } else { mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin")); - mHistory = new BatteryStatsHistory(systemDir, mConstants.MAX_HISTORY_FILES, - mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock); + mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer, systemDir, + this::getMaxHistoryFiles); } 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; @@ -10668,6 +11247,7 @@ public class BatteryStatsImpl extends BatteryStats { initTimes(uptimeUs, realtimeUs); mStartPlatformVersion = mEndPlatformVersion = Build.ID; initDischarge(realtimeUs); + clearHistoryLocked(); updateDailyDeadlineLocked(); mPlatformIdleStateCallback = cb; mMeasuredEnergyRetriever = energyStatsCb; @@ -10678,6 +11258,12 @@ public class BatteryStatsImpl extends BatteryStats { 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); @@ -10759,7 +11345,7 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeUnplugLevel = 0; mDischargePlugLevel = -1; mDischargeCurrentLevel = 0; - mBatteryLevel = 0; + mCurrentBatteryLevel = 0; } public void setPowerProfileLocked(PowerProfile profile) { @@ -11146,7 +11732,7 @@ public class BatteryStatsImpl extends BatteryStats { } public int getHistoryUsedSize() { - return mHistory.getHistoryUsedSize(); + return mBatteryStatsHistory.getHistoryUsedSize(); } @Override @@ -11160,27 +11746,43 @@ public class BatteryStatsImpl extends BatteryStats { */ @VisibleForTesting public BatteryStatsHistoryIterator createBatteryStatsHistoryIterator() { - return mHistory.iterate(); + return new BatteryStatsHistoryIterator(mBatteryStatsHistory); } @Override public int getHistoryStringPoolSize() { - return mHistory.getHistoryStringPoolSize(); + return mHistoryTagPool.size(); } @Override public int getHistoryStringPoolBytes() { - return mHistory.getHistoryStringPoolBytes(); + return mNumHistoryTagChars; } @Override public String getHistoryTagPoolString(int index) { - return mHistory.getHistoryTagPoolString(index); + ensureHistoryTagArray(); + HistoryTag historyTag = mHistoryTags.get(index); + return historyTag != null ? historyTag.string : null; } @Override public int getHistoryTagPoolUid(int index) { - return mHistory.getHistoryTagPoolUid(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()); + } } @Override @@ -11190,11 +11792,15 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void finishIteratingHistoryLocked() { - mBatteryStatsHistoryIterator.close(); mBatteryStatsHistoryIterator = null; } @Override + public long getHistoryBaseTime() { + return mHistoryBaseTimeMs; + } + + @Override public int getStartCount() { return mStartCount; } @@ -11247,23 +11853,24 @@ public class BatteryStatsImpl extends BatteryStats { long realtimeUs = mSecRealtime * 1000; resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND); pullPendingStateUpdatesLocked(); - mHistory.writeHistoryItem(mSecRealtime, mSecUptime); - mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel; + addHistoryRecordLocked(mSecRealtime, mSecUptime); + mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel + = mCurrentBatteryLevel = mHistoryCur.batteryLevel; mOnBatteryTimeBase.reset(uptimeUs, realtimeUs); mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs); - if (!mBatteryPluggedIn) { + if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) { if (Display.isOnState(mScreenState)) { - mDischargeScreenOnUnplugLevel = mBatteryLevel; + mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel; mDischargeScreenDozeUnplugLevel = 0; mDischargeScreenOffUnplugLevel = 0; } else if (Display.isDozeState(mScreenState)) { mDischargeScreenOnUnplugLevel = 0; - mDischargeScreenDozeUnplugLevel = mBatteryLevel; + mDischargeScreenDozeUnplugLevel = mHistoryCur.batteryLevel; mDischargeScreenOffUnplugLevel = 0; } else { mDischargeScreenOnUnplugLevel = 0; mDischargeScreenDozeUnplugLevel = 0; - mDischargeScreenOffUnplugLevel = mBatteryLevel; + mDischargeScreenOffUnplugLevel = mHistoryCur.batteryLevel; } mDischargeAmountScreenOn = 0; mDischargeAmountScreenOff = 0; @@ -11407,12 +12014,27 @@ public class BatteryStatsImpl extends BatteryStats { 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); - mHistory.reset(); + clearHistoryLocked(); + if (mBatteryStatsHistory != null) { + mBatteryStatsHistory.resetAllFiles(); + } // Flush external data, gathering snapshots, but don't process it since it is pre-reset data mIgnoreNextExternalStats = true; @@ -11435,7 +12057,7 @@ public class BatteryStatsImpl extends BatteryStats { for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) { SparseIntArray uids = ent.getValue(); for (int j=0; j<uids.size(); j++) { - mHistory.recordEvent(elapsedRealtimeMs, uptimeMs, i, ent.getKey(), + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(), uids.keyAt(j)); } } @@ -11860,8 +12482,9 @@ public class BatteryStatsImpl extends BatteryStats { (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt); mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked( monitoredRailChargeConsumedMaMs); - mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs, - (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR)); + mHistoryCur.wifiRailChargeMah += + (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mTmpRailStats.resetWifiTotalEnergyUsed(); if (uidEstimatedConsumptionMah != null) { @@ -11974,8 +12597,9 @@ public class BatteryStatsImpl extends BatteryStats { (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt); mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked( monitoredRailChargeConsumedMaMs); - mHistory.recordWifiConsumedCharge(elapsedRealtimeMs, uptimeMs, - (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR)); + mHistoryCur.modemRailChargeMah += + (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mTmpRailStats.resetCellularTotalEnergyUsed(); } @@ -12243,8 +12867,8 @@ public class BatteryStatsImpl extends BatteryStats { } } if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) { - mHistory.recordState2StartEvent(elapsedRealtimeMs, uptimeMs, - HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG); + mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG; + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } @@ -13677,7 +14301,11 @@ public class BatteryStatsImpl extends BatteryStats { mHandler.removeCallbacks(mDeferSetCharging); if (mCharging != charging) { mCharging = charging; - mHistory.setChargingState(charging); + if (charging) { + mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG; + } else { + mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG; + } mHandler.sendEmptyMessage(MSG_REPORT_CHARGING); return true; } @@ -13691,15 +14319,6 @@ public class BatteryStatsImpl extends BatteryStats { 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) { @@ -13783,12 +14402,15 @@ public class BatteryStatsImpl extends BatteryStats { 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) { - mHistory.startRecordingHistory(mSecRealtime, mSecUptime, reset); - initActiveHistoryEventsLocked(mSecRealtime, mSecUptime); + mRecordingHistory = true; + startRecordingHistory(mSecRealtime, mSecUptime, reset); } - mBatteryPluggedIn = false; - mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn); + addHistoryRecordLocked(mSecRealtime, mSecUptime); mDischargeCurrentLevel = mDischargeUnplugLevel = level; if (Display.isOnState(screenState)) { mDischargeScreenOnUnplugLevel = level; @@ -13810,8 +14432,11 @@ public class BatteryStatsImpl extends BatteryStats { } else { mOnBattery = mOnBatteryInternal = false; pullPendingStateUpdatesLocked(); - mBatteryPluggedIn = true; - mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn); + 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); mDischargeCurrentLevel = mDischargePlugLevel = level; if (level < mDischargeUnplugLevel) { mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1; @@ -13826,12 +14451,45 @@ public class BatteryStatsImpl extends BatteryStats { mModStepMode = 0; } if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) { - if (mStatsFile != null && !mHistory.isReadOnly()) { + if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) { 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); @@ -13849,7 +14507,8 @@ public class BatteryStatsImpl extends BatteryStats { // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0. temp = Math.max(0, temp); - reportChangesToStatsLog(status, plugType, level); + reportChangesToStatsLog(mHaveBatteryLevel ? mHistoryCur : null, + status, plugType, level); final boolean onBattery = isOnBattery(plugType, status); if (!mHaveBatteryLevel) { @@ -13859,47 +14518,52 @@ public class BatteryStatsImpl extends BatteryStats { // plugged in, then twiddle our state to correctly reflect that // since we won't be going through the full setOnBattery(). if (onBattery == mOnBattery) { - mHistory.setPluggedInState(!onBattery); + if (onBattery) { + mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; + } else { + mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; + } } - mBatteryStatus = status; - mBatteryLevel = level; - mBatteryChargeUah = chargeUah; - // Always start out assuming charging, that will be updated later. - mHistory.setBatteryState(true /* charging */, status, level, chargeUah); - + mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG; + mHistoryCur.batteryStatus = (byte)status; + mHistoryCur.batteryLevel = (byte)level; + mHistoryCur.batteryChargeUah = chargeUah; mMaxChargeStepLevel = mMinDischargeStepLevel = mLastChargeStepLevel = mLastDischargeStepLevel = level; - } else if (mBatteryLevel != level || mOnBattery != onBattery) { + } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) { recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs); } - int oldStatus = mBatteryStatus; + int oldStatus = mHistoryCur.batteryStatus; if (onBattery) { mDischargeCurrentLevel = level; - if (!mHistory.isRecordingHistory()) { - mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true); + if (!mRecordingHistory) { + mRecordingHistory = true; + startRecordingHistory(elapsedRealtimeMs, uptimeMs, true); } } else if (level < 96 && status != BatteryManager.BATTERY_STATUS_UNKNOWN) { - if (!mHistory.isRecordingHistory()) { - mHistory.startRecordingHistory(elapsedRealtimeMs, uptimeMs, true); + if (!mRecordingHistory) { + mRecordingHistory = true; + startRecordingHistory(elapsedRealtimeMs, uptimeMs, true); } } + mBatteryVoltageMv = voltageMv; + mCurrentBatteryLevel = level; if (mDischargePlugLevel < 0) { mDischargePlugLevel = level; } if (onBattery != mOnBattery) { - mBatteryLevel = level; - mBatteryStatus = status; - mBatteryHealth = health; - mBatteryPlugType = plugType; - mBatteryTemperature = temp; - mBatteryVoltageMv = voltageMv; - mHistory.setBatteryState(status, level, health, plugType, temp, voltageMv, chargeUah); - if (chargeUah < mBatteryChargeUah) { + 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) { // Only record discharges - final long chargeDiff = (long) mBatteryChargeUah - chargeUah; + final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah; mDischargeCounter.addCountLocked(chargeDiff); mDischargeScreenOffCounter.addCountLocked(chargeDiff); if (Display.isDozeState(mScreenState)) { @@ -13911,12 +14575,12 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeDeepDozeCounter.addCountLocked(chargeDiff); } } - mBatteryChargeUah = chargeUah; + mHistoryCur.batteryChargeUah = chargeUah; setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah); } else { boolean changed = false; - if (mBatteryLevel != level) { - mBatteryLevel = level; + if (mHistoryCur.batteryLevel != level) { + mHistoryCur.batteryLevel = (byte)level; changed = true; // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record @@ -13924,33 +14588,33 @@ public class BatteryStatsImpl extends BatteryStats { mExternalSync.scheduleSyncDueToBatteryLevelChange( mConstants.BATTERY_LEVEL_COLLECTION_DELAY_MS); } - if (mBatteryStatus != status) { - mBatteryStatus = status; + if (mHistoryCur.batteryStatus != status) { + mHistoryCur.batteryStatus = (byte)status; changed = true; } - if (mBatteryHealth != health) { - mBatteryHealth = health; + if (mHistoryCur.batteryHealth != health) { + mHistoryCur.batteryHealth = (byte)health; changed = true; } - if (mBatteryPlugType != plugType) { - mBatteryPlugType = plugType; + if (mHistoryCur.batteryPlugType != plugType) { + mHistoryCur.batteryPlugType = (byte)plugType; changed = true; } - if (temp >= (mBatteryTemperature + 10) - || temp <= (mBatteryTemperature - 10)) { - mBatteryTemperature = temp; + if (temp >= (mHistoryCur.batteryTemperature+10) + || temp <= (mHistoryCur.batteryTemperature-10)) { + mHistoryCur.batteryTemperature = (short)temp; changed = true; } - if (voltageMv > (mBatteryVoltageMv + 20) - || voltageMv < (mBatteryVoltageMv - 20)) { - mBatteryVoltageMv = voltageMv; + if (voltageMv > (mHistoryCur.batteryVoltage + 20) + || voltageMv < (mHistoryCur.batteryVoltage - 20)) { + mHistoryCur.batteryVoltage = (char) voltageMv; changed = true; } - if (chargeUah >= (mBatteryChargeUah + 10) - || chargeUah <= (mBatteryChargeUah - 10)) { - if (chargeUah < mBatteryChargeUah) { + if (chargeUah >= (mHistoryCur.batteryChargeUah + 10) + || chargeUah <= (mHistoryCur.batteryChargeUah - 10)) { + if (chargeUah < mHistoryCur.batteryChargeUah) { // Only record discharges - final long chargeDiff = (long) mBatteryChargeUah - chargeUah; + final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah; mDischargeCounter.addCountLocked(chargeDiff); mDischargeScreenOffCounter.addCountLocked(chargeDiff); if (Display.isDozeState(mScreenState)) { @@ -13962,10 +14626,9 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeDeepDozeCounter.addCountLocked(chargeDiff); } } - mBatteryChargeUah = chargeUah; + mHistoryCur.batteryChargeUah = 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); @@ -14023,10 +14686,7 @@ public class BatteryStatsImpl extends BatteryStats { mLastChargeStepLevel = level; } if (changed) { - mHistory.setBatteryState(mBatteryStatus, mBatteryLevel, mBatteryHealth, - mBatteryPlugType, mBatteryTemperature, mBatteryVoltageMv, - mBatteryChargeUah); - mHistory.writeHistoryItem(elapsedRealtimeMs, uptimeMs); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } if (!onBattery && @@ -14035,7 +14695,7 @@ public class BatteryStatsImpl extends BatteryStats { // 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. - mHistory.setHistoryRecordingEnabled(DEBUG); + mRecordingHistory = DEBUG; } mLastLearnedBatteryCapacityUah = chargeFullUah; @@ -14054,18 +14714,17 @@ public class BatteryStatsImpl extends BatteryStats { } // Inform StatsLog of setBatteryState changes. - private void reportChangesToStatsLog(final int status, final int plugType, final int level) { - if (!mHaveBatteryLevel) { - return; - } + // If this is the first reporting, pass in recentPast == null. + private void reportChangesToStatsLog(HistoryItem recentPast, + final int status, final int plugType, final int level) { - if (mBatteryStatus != status) { + if (recentPast == null || recentPast.batteryStatus != status) { FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status); } - if (mBatteryPlugType != plugType) { + if (recentPast == null || recentPast.batteryPlugType != plugType) { FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType); } - if (mBatteryLevel != level) { + if (recentPast == null || recentPast.batteryLevel != level) { FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level); } } @@ -14135,7 +14794,7 @@ public class BatteryStatsImpl extends BatteryStats { if (msPerLevel <= 0) { return -1; } - return (msPerLevel * mBatteryLevel) * 1000; + return (msPerLevel * mCurrentBatteryLevel) * 1000; } @Override @@ -14165,7 +14824,7 @@ public class BatteryStatsImpl extends BatteryStats { if (msPerLevel <= 0) { return -1; } - return (msPerLevel * (100 - mBatteryLevel)) * 1000; + return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000; } /*@hide */ @@ -14596,8 +15255,7 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void shutdownLocked() { - mHistory.recordShutdownEvent(mClock.elapsedRealtime(), mClock.uptimeMillis(), - mClock.currentTimeMillis()); + recordShutdownLocked(mClock.currentTimeMillis(), mClock.elapsedRealtime()); writeSyncLocked(); mShuttingDown = true; } @@ -14805,6 +15463,7 @@ public class BatteryStatsImpl extends BatteryStats { 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 @@ -14815,20 +15474,9 @@ public class BatteryStatsImpl extends BatteryStats { : 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, @@ -15049,11 +15697,27 @@ public class BatteryStatsImpl extends BatteryStats { } private void writeHistoryLocked() { + if (mBatteryStatsHistory.getActiveFile() == null) { + Slog.w(TAG, "writeHistoryLocked: no history file associated with this instance"); + return; + } + if (mShuttingDown) { return; } - mHistory.writeHistory(); + 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(); + } } private final ReentrantLock mWriteLock = new ReentrantLock(); @@ -15092,6 +15756,13 @@ public class BatteryStatsImpl extends BatteryStats { 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(); @@ -15104,7 +15775,7 @@ public class BatteryStatsImpl extends BatteryStats { readSummaryFromParcel(stats); if (DEBUG) { Slog.d(TAG, "readLocked stats file:" + mStatsFile.getBaseFile().getPath() - + " bytes:" + raw.length + " took ms:" + (SystemClock.uptimeMillis() + + " bytes:" + raw.length + " takes ms:" + (SystemClock.uptimeMillis() - start)); } } @@ -15116,19 +15787,126 @@ public class BatteryStatsImpl extends BatteryStats { stats.recycle(); } - if (!mHistory.readSummary()) { - resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime(), - RESET_REASON_CORRUPT_FILE); + 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(); } mEndPlatformVersion = Build.ID; - mHistory.continueRecordingHistory(); + 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); + } 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(); @@ -15138,7 +15916,31 @@ public class BatteryStatsImpl extends BatteryStats { return; } - mHistory.readSummaryFromParcel(in); + 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; + } mStartCount = in.readInt(); mUptimeUs = in.readLong(); @@ -15151,7 +15953,7 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeUnplugLevel = in.readInt(); mDischargePlugLevel = in.readInt(); mDischargeCurrentLevel = in.readInt(); - mBatteryLevel = in.readInt(); + mCurrentBatteryLevel = in.readInt(); mEstimatedBatteryCapacityMah = in.readInt(); mLastLearnedBatteryCapacityUah = in.readInt(); mMinLearnedBatteryCapacityUah = in.readInt(); @@ -15654,7 +16456,19 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(VERSION); - mHistory.writeSummaryToParcel(out, inclHistory); + 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); + } out.writeInt(mStartCount); out.writeLong(computeUptime(nowUptime, STATS_SINCE_CHARGED)); @@ -15667,7 +16481,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mDischargeUnplugLevel); out.writeInt(mDischargePlugLevel); out.writeInt(mDischargeCurrentLevel); - out.writeInt(mBatteryLevel); + out.writeInt(mCurrentBatteryLevel); 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 c36d950b6cf6..0cdd4d101459 100644 --- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java +++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java @@ -22,6 +22,7 @@ import android.os.BatteryConsumer; 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; @@ -31,8 +32,10 @@ import android.util.SparseArray; 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; @@ -217,7 +220,18 @@ public class BatteryUsageStatsProvider { } BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats; - batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.copyHistory()); + + // 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); } 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 5c9348525861..61a7f3853746 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,7 +28,6 @@ import androidx.test.InstrumentationRegistry; 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; @@ -50,14 +49,13 @@ public class BatteryStatsHistoryTest { 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, "battery-history"); + mHistoryDir = new File(mSystemDir, BatteryStatsHistory.HISTORY_DIR); String[] files = mHistoryDir.list(); if (files != null) { for (int i = 0; i < files.length; i++) { @@ -69,8 +67,8 @@ public class BatteryStatsHistoryTest { @Test public void testConstruct() { - BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024, - null, mClock); + BatteryStatsHistory history = + new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32); createActiveFile(history); verifyFileNumbers(history, Arrays.asList(0)); verifyActiveFile(history, "0.bin"); @@ -78,8 +76,8 @@ public class BatteryStatsHistoryTest { @Test public void testStartNextFile() { - BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024, - null, mClock); + BatteryStatsHistory history = + new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32); List<Integer> fileList = new ArrayList<>(); fileList.add(0); createActiveFile(history); @@ -116,13 +114,13 @@ public class BatteryStatsHistoryTest { assertEquals(0, history.getHistoryUsedSize()); // create a new BatteryStatsHistory object, it will pick up existing history files. - BatteryStatsHistory history2 = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024, - null, mClock); - // verify constructor can pick up all files from file system. + BatteryStatsHistory history2 = + new BatteryStatsHistory(mHistoryBuffer, mSystemDir, () -> 32); + // verify construct can pick up all files from file system. verifyFileNumbers(history2, fileList); verifyActiveFile(history2, "33.bin"); - history2.reset(); + history2.resetAllFiles(); 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 570b2ee617f5..713e78638b95 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,7 +63,6 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { MockBatteryStatsImpl(Clock clock, File historyDirectory) { super(clock, historyDirectory); initTimersAndCounters(); - setMaxHistoryBuffer(128 * 1024); setExternalStatsSyncLocked(mExternalStatsSync); informThatAllExternalStatsAreFlushed(); @@ -105,6 +104,12 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { return mForceOnBattery ? true : super.isOnBattery(); } + public void forceRecordAllHistory() { + mHaveBatteryLevel = true; + mRecordingHistory = true; + mRecordAllHistory = true; + } + public TimeBase getOnBatteryBackgroundTimeBase(int uid) { return getUidStatsLocked(uid).mOnBatteryBackgroundTimeBase; } @@ -196,14 +201,12 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { @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; } |