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
This commit is contained in:
Michael Wachenschwanz
2021-02-12 00:08:30 -08:00
parent 750d5df6c6
commit 0726d59bc5
3 changed files with 57 additions and 21 deletions

View File

@@ -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<Integer> 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<Integer> 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<Integer> uidsToRemove = new ArrayList<>();
mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
mCpuUidClusterTimeReader.readDelta(false, (uid, cpuClusterTimesMs) -> {
uid = mapUid(uid);
if (Process.isIsolated(uid)) {
uidsToRemove.add(uid);

View File

@@ -91,15 +91,24 @@ public abstract class KernelCpuUidTimeReader<T> {
* 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<T> 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<T> 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");
}

View File

@@ -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]));
}