From 0726d59bc541c1fd09553f0adb31793e7c8e258c Mon Sep 17 00:00:00 2001 From: Michael Wachenschwanz Date: Fri, 12 Feb 2021 00:08:30 -0800 Subject: [PATCH] Add cpu proc file read throttling enabling/disabling To properly attribute the new MeasureEnergy data for CPU, the cpu kernel uid file reads needs to occur everytime the CPU MeasuredEnergy is read. If throttling is necessary, it will need to be handled by BatteryExternalStatsWorker for both the cpu kernel file reads and the MeasuredEnergy read to make sure the data is in sync. Bug: 180079165 Test: atest FrameworksCoreTests:com.android.internal.os.KernelCpuUidUserSysTimeReaderTest Change-Id: I90ebad48d780872a611605689e0d25678da66f27 --- .../android/internal/os/BatteryStatsImpl.java | 16 +++--- .../internal/os/KernelCpuUidTimeReader.java | 13 ++++- .../os/KernelCpuUidUserSysTimeReaderTest.java | 49 ++++++++++++++----- 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 87820a89280c2..e599888c3bee4 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -12706,12 +12706,12 @@ public class BatteryStatsImpl extends BatteryStats { // When the battery is not on, we don't attribute the cpu times to any timers but we still // need to take the snapshots. if (!onBattery) { - mCpuUidUserSysTimeReader.readDelta(null); - mCpuUidFreqTimeReader.readDelta(null); + mCpuUidUserSysTimeReader.readDelta(false, null); + mCpuUidFreqTimeReader.readDelta(false, null); mNumAllUidCpuTimeReads += 2; if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) { - mCpuUidActiveTimeReader.readDelta(null); - mCpuUidClusterTimeReader.readDelta(null); + mCpuUidActiveTimeReader.readDelta(false, null); + mCpuUidClusterTimeReader.readDelta(false, null); mNumAllUidCpuTimeReads += 2; } for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) { @@ -12897,7 +12897,7 @@ public class BatteryStatsImpl extends BatteryStats { final long startTimeMs = mClocks.uptimeMillis(); final long elapsedRealtimeMs = mClocks.elapsedRealtime(); - mCpuUidUserSysTimeReader.readDelta((uid, timesUs) -> { + mCpuUidUserSysTimeReader.readDelta(false, (uid, timesUs) -> { long userTimeUs = timesUs[0], systemTimeUs = timesUs[1]; uid = mapUid(uid); @@ -13011,7 +13011,7 @@ public class BatteryStatsImpl extends BatteryStats { final long startTimeMs = mClocks.uptimeMillis(); final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final List uidsToRemove = new ArrayList<>(); - mCpuUidFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> { + mCpuUidFreqTimeReader.readDelta(false, (uid, cpuFreqTimeMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { uidsToRemove.add(uid); @@ -13129,7 +13129,7 @@ public class BatteryStatsImpl extends BatteryStats { final long startTimeMs = mClocks.uptimeMillis(); final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final List uidsToRemove = new ArrayList<>(); - mCpuUidActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> { + mCpuUidActiveTimeReader.readDelta(false, (uid, cpuActiveTimesMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { uidsToRemove.add(uid); @@ -13163,7 +13163,7 @@ public class BatteryStatsImpl extends BatteryStats { final long startTimeMs = mClocks.uptimeMillis(); final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final List uidsToRemove = new ArrayList<>(); - mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> { + mCpuUidClusterTimeReader.readDelta(false, (uid, cpuClusterTimesMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { uidsToRemove.add(uid); diff --git a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java index f7fad2c5bbaa1..4299f0936dae8 100644 --- a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java +++ b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java @@ -91,15 +91,24 @@ public abstract class KernelCpuUidTimeReader { * Reads the proc file, calling into the callback with a delta of time for each UID. * * @param cb The callback to invoke for each line of the proc file. If null,the data is - * consumed and subsequent calls to readDelta will provide a fresh delta. */ public void readDelta(@Nullable Callback cb) { + readDelta(false, cb); + } + + /** + * Reads the proc file, calling into the callback with a delta of time for each UID. + * + * @param force Ignore the throttling and force read the delta. + * @param cb The callback to invoke for each line of the proc file. If null,the data is + */ + public void readDelta(boolean force, @Nullable Callback cb) { if (!mThrottle) { readDeltaImpl(cb); return; } final long currTimeMs = SystemClock.elapsedRealtime(); - if (currTimeMs < mLastReadTimeMs + mMinTimeBetweenRead) { + if (!force && currTimeMs < mLastReadTimeMs + mMinTimeBetweenRead) { if (DEBUG) { Slog.d(mTag, "Throttle readDelta"); } diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java index 8f81ea237a15e..7dca0cb92f9d5 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java @@ -93,35 +93,62 @@ public class KernelCpuUidUserSysTimeReaderTest { mReader.setThrottle(500); writeToFile(uidLines(mUids, mInitialTimes)); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); assertEquals(6, mCallback.mData.size()); long[][] times1 = increaseTime(mInitialTimes); writeToFile(uidLines(mUids, times1)); mCallback.clear(); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); assertEquals(0, mCallback.mData.size()); + // TODO(b/180473895): Replace sleeps with injected simulated time. SystemClock.sleep(600); long[][] times2 = increaseTime(times1); writeToFile(uidLines(mUids, times2)); mCallback.clear(); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); assertEquals(6, mCallback.mData.size()); long[][] times3 = increaseTime(times2); writeToFile(uidLines(mUids, times3)); mCallback.clear(); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); assertEquals(0, mCallback.mData.size()); + + // Force the delta read, previously skipped increments should now be read + mCallback.clear(); + mReader.readDelta(true, mCallback); + assertEquals(6, mCallback.mData.size()); + + SystemClock.sleep(600); + + long[][] times4 = increaseTime(times3); + writeToFile(uidLines(mUids, times4)); + mCallback.clear(); + mReader.readDelta(true, mCallback); + assertEquals(6, mCallback.mData.size()); + + // Don't force the delta read, throttle should be set from last read. + long[][] times5 = increaseTime(times4); + writeToFile(uidLines(mUids, times5)); + mCallback.clear(); + mReader.readDelta(false, mCallback); + assertEquals(0, mCallback.mData.size()); + + SystemClock.sleep(600); + + mCallback.clear(); + mReader.readDelta(false, mCallback); + assertEquals(6, mCallback.mData.size()); } @Test public void testReadDelta() throws Exception { final long[][] times1 = mInitialTimes; writeToFile(uidLines(mUids, times1)); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], times1[i]); } @@ -131,7 +158,7 @@ public class KernelCpuUidUserSysTimeReaderTest { // Verify that a second call will only return deltas. final long[][] times2 = increaseTime(times1); writeToFile(uidLines(mUids, times2)); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], subtract(times2[i], times1[i])); } @@ -139,20 +166,20 @@ public class KernelCpuUidUserSysTimeReaderTest { mCallback.clear(); // Verify that there won't be a callback if the proc file values didn't change. - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); mCallback.verifyNoMoreInteractions(); mCallback.clear(); // Verify that calling with a null callback doesn't result in any crashes final long[][] times3 = increaseTime(times2); writeToFile(uidLines(mUids, times3)); - mReader.readDelta(null); + mReader.readDelta(false, null); // Verify that the readDelta call will only return deltas when // the previous call had null callback. final long[][] times4 = increaseTime(times3); writeToFile(uidLines(mUids, times4)); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], subtract(times4[i], times3[i])); } @@ -165,7 +192,7 @@ public class KernelCpuUidUserSysTimeReaderTest { public void testReadDeltaWrongData() throws Exception { final long[][] times1 = mInitialTimes; writeToFile(uidLines(mUids, times1)); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], times1[i]); } @@ -176,7 +203,7 @@ public class KernelCpuUidUserSysTimeReaderTest { final long[][] times2 = increaseTime(times1); times2[0][0] = 1000; writeToFile(uidLines(mUids, times2)); - mReader.readDelta(mCallback); + mReader.readDelta(false, mCallback); for (int i = 1; i < mUids.length; i++) { mCallback.verify(mUids[i], subtract(times2[i], times1[i])); }