diff options
6 files changed, 385 insertions, 228 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java index c5c17cffa48b..2a52264515fc 100644 --- a/core/java/com/android/internal/os/BatteryStatsHistory.java +++ b/core/java/com/android/internal/os/BatteryStatsHistory.java @@ -136,10 +136,8 @@ public class BatteryStatsHistory { 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; /** @@ -150,7 +148,7 @@ public class BatteryStatsHistory { /** * A list of history files with increasing timestamps. */ - private final List<BatteryHistoryFile> mHistoryFiles = new ArrayList<>(); + private final BatteryHistoryDirectory mHistoryDir; /** * A list of small history parcels, used when BatteryStatsImpl object is created from @@ -161,7 +159,8 @@ public class BatteryStatsHistory { /** * When iterating history files, the current file index. */ - private int mCurrentFileIndex; + private BatteryHistoryFile mCurrentFile; + /** * When iterating history files, the current file parcel. */ @@ -203,7 +202,6 @@ public class BatteryStatsHistory { private byte mLastHistoryStepLevel = 0; private boolean mMutable = true; private final BatteryStatsHistory mWritableHistory; - private boolean mCleanupEnabled = true; private static class BatteryHistoryFile implements Comparable<BatteryHistoryFile> { public final long monotonicTimeMs; @@ -235,6 +233,271 @@ public class BatteryStatsHistory { } } + private static class BatteryHistoryDirectory { + private final File mDirectory; + private final MonotonicClock mMonotonicClock; + private int mMaxHistoryFiles; + private final List<BatteryHistoryFile> mHistoryFiles = new ArrayList<>(); + private final ReentrantLock mLock = new ReentrantLock(); + private boolean mCleanupNeeded; + + BatteryHistoryDirectory(File directory, MonotonicClock monotonicClock, + int maxHistoryFiles) { + mDirectory = directory; + mMonotonicClock = monotonicClock; + mMaxHistoryFiles = maxHistoryFiles; + if (mMaxHistoryFiles == 0) { + Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history"); + } + } + + void setMaxHistoryFiles(int maxHistoryFiles) { + mMaxHistoryFiles = maxHistoryFiles; + cleanup(); + } + + void lock() { + mLock.lock(); + } + + void unlock() { + mLock.unlock(); + if (mCleanupNeeded) { + cleanup(); + } + } + + boolean isLocked() { + return mLock.isLocked(); + } + + void load() { + mDirectory.mkdirs(); + if (!mDirectory.exists()) { + Slog.wtf(TAG, "HistoryDir does not exist:" + mDirectory.getPath()); + } + + final List<File> toRemove = new ArrayList<>(); + final Set<BatteryHistoryFile> dedup = new ArraySet<>(); + mDirectory.listFiles((dir, name) -> { + final int b = name.lastIndexOf(FILE_SUFFIX); + if (b <= 0) { + toRemove.add(new File(dir, name)); + return false; + } + try { + long monotonicTime = Long.parseLong(name.substring(0, b)); + dedup.add(new BatteryHistoryFile(mDirectory, monotonicTime)); + } catch (NumberFormatException e) { + toRemove.add(new File(dir, name)); + return false; + } + return true; + }); + if (!dedup.isEmpty()) { + mHistoryFiles.addAll(dedup); + Collections.sort(mHistoryFiles); + } + if (!toRemove.isEmpty()) { + // Clear out legacy history files, which did not follow the X-Y.bin naming format. + BackgroundThread.getHandler().post(() -> { + lock(); + try { + for (File file : toRemove) { + file.delete(); + } + } finally { + unlock(); + } + }); + } + } + + List<String> getFileNames() { + lock(); + try { + List<String> names = new ArrayList<>(); + for (BatteryHistoryFile historyFile : mHistoryFiles) { + names.add(historyFile.atomicFile.getBaseFile().getName()); + } + return names; + } finally { + unlock(); + } + } + + @Nullable + BatteryHistoryFile getFirstFile() { + lock(); + try { + if (!mHistoryFiles.isEmpty()) { + return mHistoryFiles.get(0); + } + return null; + } finally { + unlock(); + } + } + + @Nullable + BatteryHistoryFile getLastFile() { + lock(); + try { + if (!mHistoryFiles.isEmpty()) { + return mHistoryFiles.get(mHistoryFiles.size() - 1); + } + return null; + } finally { + unlock(); + } + } + + @Nullable + BatteryHistoryFile getNextFile(BatteryHistoryFile current, long startTimeMs, + long endTimeMs) { + if (!mLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Iterating battery history without a lock"); + } + + int nextFileIndex = 0; + int firstFileIndex = 0; + // skip the last file because its data is in history buffer. + int lastFileIndex = mHistoryFiles.size() - 2; + for (int i = lastFileIndex; i >= 0; i--) { + BatteryHistoryFile file = mHistoryFiles.get(i); + if (current != null && file.monotonicTimeMs == current.monotonicTimeMs) { + nextFileIndex = i + 1; + } + if (file.monotonicTimeMs > endTimeMs) { + lastFileIndex = i - 1; + } + if (file.monotonicTimeMs <= startTimeMs) { + firstFileIndex = i; + break; + } + } + + if (nextFileIndex < firstFileIndex) { + nextFileIndex = firstFileIndex; + } + + if (nextFileIndex <= lastFileIndex) { + return mHistoryFiles.get(nextFileIndex); + } + + return null; + } + + BatteryHistoryFile makeBatteryHistoryFile() { + BatteryHistoryFile file = new BatteryHistoryFile(mDirectory, + mMonotonicClock.monotonicTime()); + lock(); + try { + mHistoryFiles.add(file); + } finally { + unlock(); + } + return file; + } + + void writeToParcel(Parcel out, boolean useBlobs) { + lock(); + try { + final long start = SystemClock.uptimeMillis(); + out.writeInt(mHistoryFiles.size() - 1); + for (int i = 0; i < mHistoryFiles.size() - 1; i++) { + AtomicFile file = mHistoryFiles.get(i).atomicFile; + byte[] raw = new byte[0]; + try { + raw = file.readFully(); + } catch (Exception e) { + Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e); + } + if (useBlobs) { + out.writeBlob(raw); + } else { + // Avoiding blobs in the check-in file for compatibility + out.writeByteArray(raw); + } + } + if (DEBUG) { + Slog.d(TAG, + "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start)); + } + } finally { + unlock(); + } + } + + int getFileCount() { + lock(); + try { + return mHistoryFiles.size(); + } finally { + unlock(); + } + } + + int getSize() { + lock(); + try { + int ret = 0; + for (int i = 0; i < mHistoryFiles.size() - 1; i++) { + ret += (int) mHistoryFiles.get(i).atomicFile.getBaseFile().length(); + } + return ret; + } finally { + unlock(); + } + } + + void reset() { + lock(); + try { + if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!"); + for (BatteryHistoryFile file : mHistoryFiles) { + file.atomicFile.delete(); + } + mHistoryFiles.clear(); + } finally { + unlock(); + } + } + + private void cleanup() { + if (mDirectory == null) { + return; + } + + if (isLocked()) { + mCleanupNeeded = true; + return; + } + + mCleanupNeeded = false; + + lock(); + try { + // if free disk space is less than 100MB, delete oldest history file. + if (!hasFreeDiskSpace(mDirectory)) { + BatteryHistoryFile oldest = mHistoryFiles.remove(0); + oldest.atomicFile.delete(); + } + + // if there are more history files than allowed, delete oldest history files. + // mMaxHistoryFiles comes from Constants.MAX_HISTORY_FILES and + // can be updated by DeviceConfig at run time. + while (mHistoryFiles.size() > mMaxHistoryFiles) { + BatteryHistoryFile oldest = mHistoryFiles.get(0); + oldest.atomicFile.delete(); + mHistoryFiles.remove(0); + } + } finally { + unlock(); + } + } + } + /** * A delegate responsible for computing additional details for a step in battery history. */ @@ -351,7 +614,6 @@ public class BatteryStatsHistory { BatteryStatsHistory writableHistory) { mHistoryBuffer = historyBuffer; mSystemDir = systemDir; - mMaxHistoryFiles = maxHistoryFiles; mMaxHistoryBufferSize = maxHistoryBufferSize; mStepDetailsCalculator = stepDetailsCalculator; mTracer = tracer; @@ -363,66 +625,32 @@ public class BatteryStatsHistory { mMutable = false; } - mHistoryDir = new File(systemDir, HISTORY_DIR); - mHistoryDir.mkdirs(); - if (!mHistoryDir.exists()) { - Slog.wtf(TAG, "HistoryDir does not exist:" + mHistoryDir.getPath()); - } - - final List<File> toRemove = new ArrayList<>(); - final Set<BatteryHistoryFile> dedup = new ArraySet<>(); - mHistoryDir.listFiles((dir, name) -> { - final int b = name.lastIndexOf(FILE_SUFFIX); - if (b <= 0) { - toRemove.add(new File(dir, name)); - return false; - } - try { - long monotonicTime = Long.parseLong(name.substring(0, b)); - dedup.add(new BatteryHistoryFile(mHistoryDir, monotonicTime)); - } catch (NumberFormatException e) { - toRemove.add(new File(dir, name)); - return false; + if (writableHistory != null) { + mHistoryDir = writableHistory.mHistoryDir; + } else { + mHistoryDir = new BatteryHistoryDirectory(new File(systemDir, HISTORY_DIR), + monotonicClock, maxHistoryFiles); + mHistoryDir.load(); + BatteryHistoryFile activeFile = mHistoryDir.getLastFile(); + if (activeFile == null) { + activeFile = mHistoryDir.makeBatteryHistoryFile(); } - return true; - }); - if (!dedup.isEmpty()) { - mHistoryFiles.addAll(dedup); - Collections.sort(mHistoryFiles); - setActiveFile(mHistoryFiles.get(mHistoryFiles.size() - 1)); - } else if (mMutable) { - // No file found, default to have the initial file. - BatteryHistoryFile name = makeBatteryHistoryFile(); - mHistoryFiles.add(name); - setActiveFile(name); - } - if (!toRemove.isEmpty()) { - // Clear out legacy history files, which did not follow the X-Y.bin naming format. - BackgroundThread.getHandler().post(() -> { - for (File file : toRemove) { - file.delete(); - } - }); + setActiveFile(activeFile); } } - private BatteryHistoryFile makeBatteryHistoryFile() { - return new BatteryHistoryFile(mHistoryDir, mMonotonicClock.monotonicTime()); - } - - public BatteryStatsHistory(int maxHistoryFiles, int maxHistoryBufferSize, + public BatteryStatsHistory(int maxHistoryBufferSize, HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock, MonotonicClock monotonicClock) { - this(maxHistoryFiles, maxHistoryBufferSize, stepDetailsCalculator, clock, monotonicClock, + this(maxHistoryBufferSize, stepDetailsCalculator, clock, monotonicClock, new TraceDelegate(), new EventLogger()); } @VisibleForTesting - public BatteryStatsHistory(int maxHistoryFiles, int maxHistoryBufferSize, + public BatteryStatsHistory(int maxHistoryBufferSize, HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock, MonotonicClock monotonicClock, TraceDelegate traceDelegate, EventLogger eventLogger) { - mMaxHistoryFiles = maxHistoryFiles; mMaxHistoryBufferSize = maxHistoryBufferSize; mStepDetailsCalculator = stepDetailsCalculator; mTracer = traceDelegate; @@ -484,7 +712,9 @@ public class BatteryStatsHistory { * Changes the maximum number of history files to be kept. */ public void setMaxHistoryFiles(int maxHistoryFiles) { - mMaxHistoryFiles = maxHistoryFiles; + if (mHistoryDir != null) { + mHistoryDir.setMaxHistoryFiles(maxHistoryFiles); + } } /** @@ -513,7 +743,7 @@ public class BatteryStatsHistory { * Returns true if this instance only supports reading history. */ public boolean isReadOnly() { - return !mMutable || mActiveFile == null || mHistoryDir == null; + return !mMutable || mActiveFile == null/* || mHistoryDir == null*/; } /** @@ -538,25 +768,13 @@ public class BatteryStatsHistory { @GuardedBy("this") private void startNextFileLocked(long elapsedRealtimeMs) { - if (mMaxHistoryFiles == 0) { - Slog.wtf(TAG, "mMaxHistoryFiles should not be zero when writing history"); - return; - } - - if (mHistoryFiles.isEmpty()) { - Slog.wtf(TAG, "mFileNumbers should never be empty"); - return; - } - final long start = SystemClock.uptimeMillis(); writeHistory(); if (DEBUG) { Slog.d(TAG, "writeHistory took ms:" + (SystemClock.uptimeMillis() - start)); } - final BatteryHistoryFile next = makeBatteryHistoryFile(); - mHistoryFiles.add(next); - setActiveFile(next); + setActiveFile(mHistoryDir.makeBatteryHistoryFile()); try { mActiveFile.getBaseFile().createNewFile(); } catch (IOException e) { @@ -578,37 +796,7 @@ public class BatteryStatsHistory { } mWrittenPowerStatsDescriptors.clear(); - cleanupLocked(); - } - - @GuardedBy("this") - private void setCleanupEnabledLocked(boolean enabled) { - mCleanupEnabled = enabled; - if (mCleanupEnabled) { - cleanupLocked(); - } - } - - @GuardedBy("this") - private void cleanupLocked() { - if (!mCleanupEnabled || mHistoryDir == null) { - return; - } - - // if free disk space is less than 100MB, delete oldest history file. - if (!hasFreeDiskSpace()) { - BatteryHistoryFile oldest = mHistoryFiles.remove(0); - oldest.atomicFile.delete(); - } - - // 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 (mHistoryFiles.size() > mMaxHistoryFiles) { - BatteryHistoryFile oldest = mHistoryFiles.get(0); - oldest.atomicFile.delete(); - mHistoryFiles.remove(0); - } + mHistoryDir.cleanup(); } /** @@ -616,9 +804,7 @@ public class BatteryStatsHistory { * currently being read. */ public boolean isResetEnabled() { - synchronized (this) { - return mCleanupEnabled; - } + return mHistoryDir == null || !mHistoryDir.isLocked(); } /** @@ -627,16 +813,10 @@ public class BatteryStatsHistory { */ public void reset() { synchronized (this) { - if (DEBUG) Slog.i(TAG, "********** CLEARING HISTORY!"); - for (BatteryHistoryFile file : mHistoryFiles) { - file.atomicFile.delete(); + if (mHistoryDir != null) { + mHistoryDir.reset(); + setActiveFile(mHistoryDir.makeBatteryHistoryFile()); } - mHistoryFiles.clear(); - - BatteryHistoryFile name = makeBatteryHistoryFile(); - mHistoryFiles.add(name); - setActiveFile(name); - initHistoryBuffer(); } } @@ -646,8 +826,9 @@ public class BatteryStatsHistory { */ public long getStartTime() { synchronized (this) { - if (!mHistoryFiles.isEmpty()) { - return mHistoryFiles.get(0).monotonicTimeMs; + BatteryHistoryFile file = mHistoryDir.getFirstFile(); + if (file != null) { + return file.monotonicTimeMs; } else { return mHistoryBufferStartTime; } @@ -668,15 +849,13 @@ public class BatteryStatsHistory { return copy().iterate(startTimeMs, endTimeMs); } - mCurrentFileIndex = 0; + if (mHistoryDir != null) { + mHistoryDir.lock(); + } + mCurrentFile = null; mCurrentParcel = null; mCurrentParcelEnd = 0; mParcelIndex = 0; - if (mWritableHistory != null) { - synchronized (mWritableHistory) { - mWritableHistory.setCleanupEnabledLocked(false); - } - } return new BatteryStatsHistoryIterator(this, startTimeMs, endTimeMs); } @@ -685,10 +864,8 @@ public class BatteryStatsHistory { */ void iteratorFinished() { mHistoryBuffer.setDataPosition(mHistoryBuffer.dataSize()); - if (mWritableHistory != null) { - synchronized (mWritableHistory) { - mWritableHistory.setCleanupEnabledLocked(true); - } + if (mHistoryDir != null) { + mHistoryDir.unlock(); } } @@ -719,39 +896,27 @@ public class BatteryStatsHistory { } } - int firstFileIndex = 0; - // skip the last file because its data is in history buffer. - int lastFileIndex = mHistoryFiles.size() - 1; - for (int i = mHistoryFiles.size() - 1; i >= 0; i--) { - BatteryHistoryFile file = mHistoryFiles.get(i); - if (file.monotonicTimeMs >= endTimeMs) { - lastFileIndex = i; - } - if (file.monotonicTimeMs <= startTimeMs) { - firstFileIndex = i; - break; - } - } - - if (mCurrentFileIndex < firstFileIndex) { - mCurrentFileIndex = firstFileIndex; - } - - while (mCurrentFileIndex < lastFileIndex) { - mCurrentParcel = null; - mCurrentParcelEnd = 0; - final Parcel p = Parcel.obtain(); - AtomicFile file = mHistoryFiles.get(mCurrentFileIndex++).atomicFile; - if (readFileToParcel(p, file)) { - int bufSize = p.readInt(); - int curPos = p.dataPosition(); - mCurrentParcelEnd = curPos + bufSize; - mCurrentParcel = p; - if (curPos < mCurrentParcelEnd) { - return mCurrentParcel; + if (mHistoryDir != null) { + BatteryHistoryFile nextFile = mHistoryDir.getNextFile(mCurrentFile, startTimeMs, + endTimeMs); + while (nextFile != null) { + mCurrentParcel = null; + mCurrentParcelEnd = 0; + final Parcel p = Parcel.obtain(); + AtomicFile file = nextFile.atomicFile; + if (readFileToParcel(p, file)) { + int bufSize = p.readInt(); + int curPos = p.dataPosition(); + mCurrentParcelEnd = curPos + bufSize; + mCurrentParcel = p; + if (curPos < mCurrentParcelEnd) { + mCurrentFile = nextFile; + return mCurrentParcel; + } + } else { + p.recycle(); } - } else { - p.recycle(); + nextFile = mHistoryDir.getNextFile(nextFile, startTimeMs, endTimeMs); } } @@ -922,25 +1087,8 @@ public class BatteryStatsHistory { } private void writeToParcel(Parcel out, boolean useBlobs) { - final long start = SystemClock.uptimeMillis(); - out.writeInt(mHistoryFiles.size() - 1); - for (int i = 0; i < mHistoryFiles.size() - 1; i++) { - AtomicFile file = mHistoryFiles.get(i).atomicFile; - byte[] raw = new byte[0]; - try { - raw = file.readFully(); - } catch (Exception e) { - Slog.e(TAG, "Error reading file " + file.getBaseFile().getPath(), e); - } - if (useBlobs) { - out.writeBlob(raw); - } else { - // Avoiding blobs in the check-in file for compatibility - out.writeByteArray(raw); - } - } - if (DEBUG) { - Slog.d(TAG, "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start)); + if (mHistoryDir != null) { + mHistoryDir.writeToParcel(out, useBlobs); } } @@ -1021,22 +1169,18 @@ public class BatteryStatsHistory { * @return true if there is more than 100MB free disk space left. */ @android.ravenwood.annotation.RavenwoodReplace - private boolean hasFreeDiskSpace() { - final StatFs stats = new StatFs(mHistoryDir.getAbsolutePath()); + private static boolean hasFreeDiskSpace(File systemDir) { + final StatFs stats = new StatFs(systemDir.getAbsolutePath()); return stats.getAvailableBytes() > MIN_FREE_SPACE; } - private boolean hasFreeDiskSpace$ravenwood() { + private static boolean hasFreeDiskSpace$ravenwood(File systemDir) { return true; } @VisibleForTesting public List<String> getFilesNames() { - List<String> names = new ArrayList<>(); - for (BatteryHistoryFile historyFile : mHistoryFiles) { - names.add(historyFile.atomicFile.getBaseFile().getName()); - } - return names; + return mHistoryDir.getFileNames(); } @VisibleForTesting @@ -1048,10 +1192,7 @@ public class BatteryStatsHistory { * @return the total size of all history files and history buffer. */ public int getHistoryUsedSize() { - int ret = 0; - for (int i = 0; i < mHistoryFiles.size() - 1; i++) { - ret += mHistoryFiles.get(i).atomicFile.getBaseFile().length(); - } + int ret = mHistoryDir.getSize(); ret += mHistoryBuffer.dataSize(); if (mHistoryParcels != null) { for (int i = 0; i < mHistoryParcels.size(); i++) { @@ -1109,7 +1250,7 @@ public class BatteryStatsHistory { */ public void continueRecordingHistory() { synchronized (this) { - if (mHistoryBuffer.dataPosition() <= 0 && mHistoryFiles.size() <= 1) { + if (mHistoryBuffer.dataPosition() <= 0 && mHistoryDir.getFileCount() <= 1) { return; } diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java index b2a6a934ba3f..83e9407fbdde 100644 --- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java +++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java @@ -44,6 +44,7 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor private BatteryStats.HistoryItem mHistoryItem = new BatteryStats.HistoryItem(); private boolean mNextItemReady; private boolean mTimeInitialized; + private boolean mClosed; public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history, long startTimeMs, long endTimeMs) { @@ -322,6 +323,9 @@ public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.Histor */ @Override public void close() { - mBatteryStatsHistory.iteratorFinished(); + if (!mClosed) { + mClosed = true; + mBatteryStatsHistory.iteratorFinished(); + } } } 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 af4da812d79e..b33412362639 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -1817,9 +1817,8 @@ public class BatteryStatsImpl extends BatteryStats { if (historyDirectory == null) { mCheckinFile = null; mStatsFile = null; - mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES, - mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock, mMonotonicClock, - traceDelegate, eventLogger); + mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_BUFFER, + mStepDetailsCalculator, mClock, mMonotonicClock, traceDelegate, eventLogger); } else { mCheckinFile = new AtomicFile(new File(historyDirectory, "batterystats-checkin.bin")); mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin")); @@ -10962,8 +10961,8 @@ public class BatteryStatsImpl extends BatteryStats { mStatsFile = null; mCheckinFile = null; mDailyFile = null; - mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES, - mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock, mMonotonicClock); + mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_BUFFER, + mStepDetailsCalculator, mClock, mMonotonicClock); } else { mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin")); mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin")); diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java index 6cd79bc09fb6..5102f3cd43c6 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java @@ -49,7 +49,6 @@ import org.junit.runner.RunWith; import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.util.List; @SmallTest @@ -64,11 +63,10 @@ public class BatteryUsageStatsProviderTest { private static final long MINUTE_IN_MS = 60 * 1000; private static final double PRECISION = 0.00001; - private File mHistoryDir; - @Rule(order = 1) public final BatteryUsageStatsRule mStatsRule = - new BatteryUsageStatsRule(12345, mHistoryDir) + new BatteryUsageStatsRule(12345) + .createTempDirectory() .setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0) .setAveragePower(PowerProfile.POWER_AUDIO, 720.0); @@ -77,9 +75,6 @@ public class BatteryUsageStatsProviderTest { @Before public void setup() throws IOException { - mHistoryDir = Files.createTempDirectory("BatteryUsageStatsProviderTest").toFile(); - clearDirectory(mHistoryDir); - if (RavenwoodRule.isUnderRavenwood()) { mContext = mock(Context.class); SensorManager sensorManager = mock(SensorManager.class); @@ -89,17 +84,6 @@ public class BatteryUsageStatsProviderTest { } } - private void clearDirectory(File dir) { - if (dir.exists()) { - for (File child : dir.listFiles()) { - if (child.isDirectory()) { - clearDirectory(child); - } - child.delete(); - } - } - } - @Test public void test_getBatteryUsageStats() { BatteryStatsImpl batteryStats = prepareBatteryStats(); @@ -417,7 +401,7 @@ public class BatteryUsageStatsProviderTest { } PowerStatsStore powerStatsStore = new PowerStatsStore( - new File(mHistoryDir, "powerstatsstore"), + new File(mStatsRule.getHistoryDir(), "powerstatsstore"), mStatsRule.getHandler(), null); powerStatsStore.reset(); diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java index 8bdb0292bf00..e9a1246fb244 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java @@ -32,7 +32,6 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.UidBatteryConsumer; import android.os.UserBatteryConsumer; -import android.platform.test.ravenwood.RavenwoodRule; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; @@ -47,6 +46,8 @@ import org.junit.runners.model.Statement; import org.mockito.stubbing.Answer; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.Arrays; @SuppressWarnings("SynchronizeOnNonFinalField") @@ -59,7 +60,9 @@ public class BatteryUsageStatsRule implements TestRule { private final PowerProfile mPowerProfile; private final MockClock mMockClock = new MockClock(); - private final File mHistoryDir; + private String mTestName; + private boolean mCreateTempDirectory; + private File mHistoryDir; private MockBatteryStatsImpl mBatteryStats; private Handler mHandler; @@ -76,32 +79,30 @@ public class BatteryUsageStatsRule implements TestRule { private String[] mCustomPowerComponentNames; public BatteryUsageStatsRule() { - this(0, null); + this(0); } public BatteryUsageStatsRule(long currentTime) { - this(currentTime, null); - } - - public BatteryUsageStatsRule(long currentTime, File historyDir) { mHandler = mock(Handler.class); mPowerProfile = spy(new PowerProfile()); mMockClock.currentTime = currentTime; - mHistoryDir = historyDir; - - if (!RavenwoodRule.isUnderRavenwood()) { - lateInitBatteryStats(); - } - mCpusByPolicy.put(0, new int[]{0, 1, 2, 3}); mCpusByPolicy.put(4, new int[]{4, 5, 6, 7}); mFreqsByPolicy.put(0, new int[]{300000, 1000000, 2000000}); mFreqsByPolicy.put(4, new int[]{300000, 1000000, 2500000, 3000000}); } - private void lateInitBatteryStats() { + private void initBatteryStats() { if (mBatteryStats != null) return; + if (mCreateTempDirectory) { + try { + mHistoryDir = Files.createTempDirectory(mTestName).toFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + clearDirectory(); + } mBatteryStats = new MockBatteryStatsImpl(mMockClock, mHistoryDir, mHandler); mBatteryStats.setPowerProfile(mPowerProfile); mBatteryStats.setCpuScalingPolicies(new CpuScalingPolicies(mCpusByPolicy, mFreqsByPolicy)); @@ -134,6 +135,15 @@ public class BatteryUsageStatsRule implements TestRule { return mHandler; } + public File getHistoryDir() { + return mHistoryDir; + } + + public BatteryUsageStatsRule createTempDirectory() { + mCreateTempDirectory = true; + return this; + } + public BatteryUsageStatsRule setTestPowerProfile(@XmlRes int xmlId) { mPowerProfile.forceInitForTesting(InstrumentationRegistry.getContext(), xmlId); return this; @@ -265,6 +275,7 @@ public class BatteryUsageStatsRule implements TestRule { @Override public Statement apply(Statement base, Description description) { + mTestName = description.getClassName() + "#" + description.getMethodName(); return new Statement() { @Override public void evaluate() throws Throwable { @@ -275,7 +286,7 @@ public class BatteryUsageStatsRule implements TestRule { } private void before() { - lateInitBatteryStats(); + initBatteryStats(); HandlerThread bgThread = new HandlerThread("bg thread"); bgThread.start(); mHandler = new Handler(bgThread.getLooper()); @@ -296,6 +307,9 @@ public class BatteryUsageStatsRule implements TestRule { } public MockBatteryStatsImpl getBatteryStats() { + if (mBatteryStats == null) { + initBatteryStats(); + } return mBatteryStats; } @@ -369,4 +383,19 @@ public class BatteryUsageStatsRule implements TestRule { } return null; } + + public void clearDirectory() { + clearDirectory(mHistoryDir); + } + + private void clearDirectory(File dir) { + if (dir.exists()) { + for (File child : dir.listFiles()) { + if (child.isDirectory()) { + clearDirectory(child); + } + child.delete(); + } + } + } } diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java index af5b462e017d..2ea86a4527eb 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java @@ -58,7 +58,7 @@ public class PowerStatsAggregatorTest { @Before public void setup() throws ParseException { - mHistory = new BatteryStatsHistory(32, 1024, + mHistory = new BatteryStatsHistory(1024, mock(BatteryStatsHistory.HistoryStepDetailsCalculator.class), mClock, mMonotonicClock, mock(BatteryStatsHistory.TraceDelegate.class), null); |