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

Commit c189595b authored by Sudheer Shanka's avatar Sudheer Shanka Committed by Android (Google) Code Review
Browse files

Merge "Log if there is malformed data in the proc file."

parents 907ebe9a 0085752b
Loading
Loading
Loading
Loading
+26 −3
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
package com.android.internal.os;

import android.annotation.Nullable;
import android.os.SystemClock;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;

import com.android.internal.annotations.VisibleForTesting;

@@ -50,6 +52,8 @@ public class KernelUidCpuFreqTimeReader {

    private long[] mCpuFreqs;
    private int mCpuFreqsCount;
    private long mLastTimeReadMs;
    private long mNowTimeMs;

    private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();

@@ -64,7 +68,9 @@ public class KernelUidCpuFreqTimeReader {
            return;
        }
        try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
            mNowTimeMs = SystemClock.elapsedRealtime();
            readDelta(reader, callback);
            mLastTimeReadMs = mNowTimeMs;
            mProcFileAvailable = true;
        } catch (IOException e) {
            mReadErrorCounter++;
@@ -115,18 +121,35 @@ public class KernelUidCpuFreqTimeReader {
            return;
        }
        final long[] deltaUidTimeMs = new long[size];
        final long[] curUidTimeMs = new long[size];
        boolean notify = false;
        for (int i = 0; i < size; ++i) {
            // Times read will be in units of 10ms
            final long totalTimeMs = Long.parseLong(timesStr[i], 10) * 10;
            deltaUidTimeMs[i] = totalTimeMs - uidTimeMs[i];
            uidTimeMs[i] = totalTimeMs;
            // If there is malformed data for any uid, then we just log about it and ignore
            // the data for that uid.
            if (deltaUidTimeMs[i] < 0 || totalTimeMs < 0) {
                final StringBuilder sb = new StringBuilder("Malformed cpu freq data for UID=")
                        .append(uid).append("\n");
                sb.append("data=").append("(").append(uidTimeMs[i]).append(",")
                        .append(totalTimeMs).append(")").append("\n");
                sb.append("times=").append("(")
                        .append(TimeUtils.formatForLogging(mLastTimeReadMs)).append(",")
                        .append(TimeUtils.formatForLogging(mNowTimeMs)).append(")");
                Slog.wtf(TAG, sb.toString());
                return;
            }
            curUidTimeMs[i] = totalTimeMs;
            notify = notify || (deltaUidTimeMs[i] > 0);
        }
        if (callback != null && notify) {
        if (notify) {
            System.arraycopy(curUidTimeMs, 0, uidTimeMs, 0, size);
            if (callback != null) {
                callback.onUidCpuFreqTime(uid, deltaUidTimeMs);
            }
        }
    }

    private void readCpuFreqs(String line, Callback callback) {
        if (mCpuFreqs == null) {
+93 −0
Original line number Diff line number Diff line
@@ -98,6 +98,14 @@ public class KernelUidCpuFreqTimeReaderTest {
        }
        verifyNoMoreInteractions(mCallback);

        // Verify that there won't be a callback if the proc file values didn't change.
        Mockito.reset(mCallback, mBufferedReader);
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
        verify(mCallback).onCpuFreqs(freqs);
        verifyNoMoreInteractions(mCallback);

        // Verify that calling with a null callback doesn't result in any crashes
        Mockito.reset(mCallback, mBufferedReader);
        final long[][] newTimes2 = new long[uids.length][freqs.length];
@@ -130,6 +138,91 @@ public class KernelUidCpuFreqTimeReaderTest {
        verifyNoMoreInteractions(mCallback);
    }

    @Test
    public void testReadDelta_malformedData() throws Exception {
        final long[] freqs = {1, 12, 123, 1234, 12345, 123456};
        final int[] uids = {1, 22, 333, 4444, 5555};
        final long[][] times = new long[uids.length][freqs.length];
        for (int i = 0; i < uids.length; ++i) {
            for (int j = 0; j < freqs.length; ++j) {
                times[i][j] = uids[i] * freqs[j] * 10;
            }
        }
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, times));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
        verify(mCallback).onCpuFreqs(freqs);
        for (int i = 0; i < uids.length; ++i) {
            verify(mCallback).onUidCpuFreqTime(uids[i], times[i]);
        }
        verifyNoMoreInteractions(mCallback);

        // Verify that there is no callback if any value in the proc file is -ve.
        Mockito.reset(mCallback, mBufferedReader);
        final long[][] newTimes1 = new long[uids.length][freqs.length];
        for (int i = 0; i < uids.length; ++i) {
            for (int j = 0; j < freqs.length; ++j) {
                newTimes1[i][j] = (times[i][j] + uids[i] + freqs[j]) * 10;
            }
        }
        newTimes1[uids.length - 1][freqs.length - 1] *= -1;
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
        verify(mCallback).onCpuFreqs(freqs);
        for (int i = 0; i < uids.length; ++i) {
            if (i == uids.length - 1) {
                continue;
            }
            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes1[i], times[i]));
        }
        verifyNoMoreInteractions(mCallback);

        // Verify that the internal state was not modified when the proc file had -ve value.
        Mockito.reset(mCallback, mBufferedReader);
        for (int i = 0; i < freqs.length; ++i) {
            newTimes1[uids.length - 1][i] = times[uids.length - 1][i];
        }
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
        verify(mCallback).onCpuFreqs(freqs);
        verifyNoMoreInteractions(mCallback);

        // Verify that there is no callback if the values in the proc file are decreased.
        Mockito.reset(mCallback, mBufferedReader);
        final long[][] newTimes2 = new long[uids.length][freqs.length];
        for (int i = 0; i < uids.length; ++i) {
            for (int j = 0; j < freqs.length; ++j) {
                newTimes2[i][j] = (newTimes1[i][j] + uids[i] * freqs[j]) * 10;
            }
        }
        newTimes2[uids.length - 1][freqs.length - 1] =
                newTimes1[uids.length - 1][freqs.length - 1] - 222;
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
        verify(mCallback).onCpuFreqs(freqs);
        for (int i = 0; i < uids.length; ++i) {
            if (i == uids.length - 1) {
                continue;
            }
            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes2[i], newTimes1[i]));
        }
        verifyNoMoreInteractions(mCallback);

        // Verify that the internal state was not modified when the proc file had decreasing values.
        Mockito.reset(mCallback, mBufferedReader);
        for (int i = 0; i < freqs.length; ++i) {
            newTimes2[uids.length - 1][i] = newTimes1[uids.length - 1][i];
        }
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
        verify(mCallback).onCpuFreqs(freqs);
        verifyNoMoreInteractions(mCallback);
    }

    private long[] subtract(long[] a1, long[] a2) {
        long[] val = new long[a1.length];
        for (int i = 0; i < val.length; ++i) {