Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0726d59b authored by Michael Wachenschwanz's avatar Michael Wachenschwanz
Browse files

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
parent 750d5df6
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -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);
+11 −2
Original line number Diff line number Diff line
@@ -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");
            }
+38 −11
Original line number Diff line number Diff line
@@ -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]));
        }