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

Commit 59f5c00b authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

More unit tests for classes needed in reading uid times per cpu freq.

Bug: 34133340
Test: runtest -c com.android.internal.os.LongSamplingCounterArrayTest frameworks-core
      runtest -c com.android.internal.os.KernelUidCpuFreqTimeReaderTest frameworks-core
Change-Id: I4c64efd9b3d91a72c585b9e4b0e6b277297005a4
parent 7e08c7ec
Loading
Loading
Loading
Loading
+63 −60
Original line number Diff line number Diff line
@@ -967,14 +967,15 @@ public class BatteryStatsImpl extends BatteryStats {
        }
    }

    @VisibleForTesting
    public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
        final TimeBase mTimeBase;
        long[] mCounts;
        long[] mLoadedCounts;
        long[] mUnpluggedCounts;
        long[] mPluggedCounts;
        public long[] mCounts;
        public long[] mLoadedCounts;
        public long[] mUnpluggedCounts;
        public long[] mPluggedCounts;

        LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
        private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
            mTimeBase = timeBase;
            mPluggedCounts = in.createLongArray();
            mCounts = copyArray(mPluggedCounts, mCounts);
@@ -983,12 +984,12 @@ public class BatteryStatsImpl extends BatteryStats {
            timeBase.add(this);
        }

        LongSamplingCounterArray(TimeBase timeBase) {
        public LongSamplingCounterArray(TimeBase timeBase) {
            mTimeBase = timeBase;
            timeBase.add(this);
        }

        public void writeToParcel(Parcel out) {
        private void writeToParcel(Parcel out) {
            out.writeLongArray(mCounts);
            out.writeLongArray(mLoadedCounts);
            out.writeLongArray(mUnpluggedCounts);
@@ -1024,7 +1025,7 @@ public class BatteryStatsImpl extends BatteryStats {
                    + " mPluggedCounts=" + Arrays.toString(mPluggedCounts));
        }

        void addCountLocked(long[] counts) {
        public void addCountLocked(long[] counts) {
            if (counts == null) {
                return;
            }
@@ -1039,7 +1040,7 @@ public class BatteryStatsImpl extends BatteryStats {
        /**
         * Clear state of this counter.
         */
        void reset(boolean detachIfReset) {
        public void reset(boolean detachIfReset) {
            fillArray(mCounts, 0);
            fillArray(mLoadedCounts, 0);
            fillArray(mPluggedCounts, 0);
@@ -1049,21 +1050,60 @@ public class BatteryStatsImpl extends BatteryStats {
            }
        }

        void detach() {
        public void detach() {
            mTimeBase.remove(this);
        }

        void writeSummaryFromParcelLocked(Parcel out) {
        private void writeSummaryToParcelLocked(Parcel out) {
            out.writeLongArray(mCounts);
        }

        void readSummaryFromParcelLocked(Parcel in) {
        private void readSummaryFromParcelLocked(Parcel in) {
            mCounts = in.createLongArray();
            mLoadedCounts = copyArray(mCounts, mLoadedCounts);
            mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
            mPluggedCounts = copyArray(mCounts, mPluggedCounts);
        }

        public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
            if (counterArray != null) {
                out.writeInt(1);
                counterArray.writeToParcel(out);
            } else {
                out.writeInt(0);
            }
        }

        public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
            if (in.readInt() != 0) {
                return new LongSamplingCounterArray(timeBase, in);
            } else {
                return null;
            }
        }

        public static void writeSummaryToParcelLocked(Parcel out,
                LongSamplingCounterArray counterArray) {
            if (counterArray != null) {
                out.writeInt(1);
                counterArray.writeSummaryToParcelLocked(out);
            } else {
                out.writeInt(0);
            }
        }

        public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
                TimeBase timeBase) {
            if (in.readInt() != 0) {
                final LongSamplingCounterArray counterArray
                        = new LongSamplingCounterArray(timeBase);
                counterArray.readSummaryFromParcelLocked(in);
                return counterArray;
            } else {
                return null;
            }
        }

        private void fillArray(long[] a, long val) {
            if (a != null) {
                Arrays.fill(a, val);
@@ -6927,18 +6967,8 @@ public class BatteryStatsImpl extends BatteryStats {
                out.writeInt(0);
            }

            if (mCpuFreqTimeMs != null) {
                out.writeInt(1);
                mCpuFreqTimeMs.writeToParcel(out);
            } else {
                out.writeInt(0);
            }
            if (mScreenOffCpuFreqTimeMs != null) {
                out.writeInt(1);
                mScreenOffCpuFreqTimeMs.writeToParcel(out);
            } else {
                out.writeInt(0);
            }
            LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
            LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);

            if (mMobileRadioApWakeupCount != null) {
                out.writeInt(1);
@@ -7187,17 +7217,9 @@ public class BatteryStatsImpl extends BatteryStats {
                mCpuClusterSpeed = null;
            }

            if (in.readInt() != 0) {
                mCpuFreqTimeMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
            } else {
                mCpuFreqTimeMs = null;
            }
            if (in.readInt() != 0) {
                mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
                        mBsi.mOnBatteryScreenOffTimeBase, in);
            } else {
                mScreenOffCpuFreqTimeMs = null;
            }
            mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
            mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
                    in, mBsi.mOnBatteryScreenOffTimeBase);

            if (in.readInt() != 0) {
                mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
@@ -11355,19 +11377,10 @@ public class BatteryStatsImpl extends BatteryStats {
                u.mCpuClusterSpeed = null;
            }

            if (in.readInt() != 0) {
                u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
                u.mCpuFreqTimeMs.readSummaryFromParcelLocked(in);
            } else {
                u.mCpuFreqTimeMs = null;
            }
            if (in.readInt() != 0) {
                u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
                        mOnBatteryScreenOffTimeBase);
                u.mScreenOffCpuFreqTimeMs.readSummaryFromParcelLocked(in);
            } else {
                u.mScreenOffCpuFreqTimeMs = null;
            }
            u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
                    in, mOnBatteryTimeBase);
            u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
                    in, mOnBatteryScreenOffTimeBase);

            if (in.readInt() != 0) {
                u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
@@ -11765,18 +11778,8 @@ public class BatteryStatsImpl extends BatteryStats {
                out.writeInt(0);
            }

            if (u.mCpuFreqTimeMs != null) {
                out.writeInt(1);
                u.mCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
            } else {
                out.writeInt(0);
            }
            if (u.mScreenOffCpuFreqTimeMs != null) {
                out.writeInt(1);
                u.mScreenOffCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
            } else {
                out.writeInt(0);
            }
            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);

            if (u.mMobileRadioApWakeupCount != null) {
                out.writeInt(1);
+61 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.os;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.support.test.filters.SmallTest;
@@ -27,6 +28,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.io.BufferedReader;
@@ -70,18 +72,70 @@ public class KernelUidCpuFreqTimeReaderTest {
                times[i][j] = uids[i] * freqs[j] * 10;
            }
        }
        final String[] uidsTimesLines = getUidTimesLines(uids, times);
        final String[] lines = new String[uidsTimesLines.length + 1];
        System.arraycopy(uidsTimesLines, 0, lines, 0, uidsTimesLines.length);
        lines[uidsTimesLines.length] = null;
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), lines);
                .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 a second call will only return deltas.
        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;
            }
        }
        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) {
            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes1[i], times[i]));
        }
        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];
        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;
            }
        }
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, null);
        verifyZeroInteractions(mCallback);

        // Verify that the readDelta call will only return deltas when
        // the previous call had null callback.
        Mockito.reset(mCallback, mBufferedReader);
        final long[][] newTimes3 = new long[uids.length][freqs.length];
        for (int i = 0; i < uids.length; ++i) {
            for (int j = 0; j < freqs.length; ++j) {
                newTimes3[i][j] = (newTimes2[i][j] * (uids[i] + freqs[j])) * 10;
            }
        }
        when(mBufferedReader.readLine())
                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes3));
        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
        verify(mCallback).onCpuFreqs(freqs);
        for (int i = 0; i < uids.length; ++i) {
            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes3[i], newTimes2[i]));
        }
        verifyNoMoreInteractions(mCallback);
    }

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

    private String getFreqsLine(long[] freqs) {
@@ -94,7 +148,7 @@ public class KernelUidCpuFreqTimeReaderTest {
    }

    private String[] getUidTimesLines(int[] uids, long[][] times) {
        final String[] lines = new String[uids.length];
        final String[] lines = new String[uids.length + 1];
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < uids.length; ++i) {
            sb.setLength(0);
@@ -104,6 +158,7 @@ public class KernelUidCpuFreqTimeReaderTest {
            }
            lines[i] = sb.toString();
        }
        lines[uids.length] = null;
        return lines;
    }
}
+217 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.os;

import static android.os.BatteryStats.STATS_SINCE_CHARGED;

import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray;
import static com.android.internal.os.BatteryStatsImpl.TimeBase;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;

/**
 * Test class for {@link BatteryStatsImpl.LongSamplingCounterArray}.
 *
 * To run the tests, use
 *
 * runtest -c com.android.internal.os.LongSamplingCounterArrayTest frameworks-core
 *
 * or the following steps:
 *
 * Build: m FrameworksCoreTests
 * Install: adb install -r \
 *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
 * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \
 *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class LongSamplingCounterArrayTest {

    private static final long[] COUNTS = {1111, 2222, 3333, 4444};
    private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888};
    private static final long[] PLUGGED_COUNTS = {9999, 11111, 22222, 33333};
    private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777};
    private static final long[] ZEROES = {0, 0, 0, 0};

    @Mock private TimeBase mTimeBase;
    private LongSamplingCounterArray mCounterArray;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mCounterArray = new LongSamplingCounterArray(mTimeBase);
        Mockito.reset(mTimeBase);
    }

    @Test
    public void testReadWriteParcel() {
        final Parcel parcel = Parcel.obtain();
        initializeCounterArrayWithDefaultValues();
        LongSamplingCounterArray.writeToParcel(parcel, mCounterArray);
        parcel.setDataPosition(0);

        // Now clear counterArray and verify values are read from parcel correctly.
        updateCounts(null, null, null, null);
        mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
        parcel.recycle();
    }

    @Test
    public void testReadWriteSummaryParcel() {
        final Parcel parcel = Parcel.obtain();
        initializeCounterArrayWithDefaultValues();
        LongSamplingCounterArray.writeSummaryToParcelLocked(parcel, mCounterArray);
        parcel.setDataPosition(0);

        // Now clear counterArray and verify values are read from parcel correctly.
        updateCounts(null, null, null, null);
        mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
        parcel.recycle();
    }

    @Test
    public void testOnTimeStarted() {
        initializeCounterArrayWithDefaultValues();
        mCounterArray.onTimeStarted(0, 0, 0);
        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
    }

    @Test
    public void testOnTimeStopped() {
        initializeCounterArrayWithDefaultValues();
        mCounterArray.onTimeStopped(0, 0, 0);
        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
    }

    @Test
    public void testGetCountsLocked() {
        initializeCounterArrayWithDefaultValues();

        when(mTimeBase.isRunning()).thenReturn(false);
        long[] actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
        long[] expectedVal = PLUGGED_COUNTS;
        assertArrayEquals(expectedVal, actualVal, "Unexpected values");

        when(mTimeBase.isRunning()).thenReturn(true);
        actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
        expectedVal = COUNTS;
        assertArrayEquals(expectedVal, actualVal, "Unexpected values");
    }

    @Test
    public void testAddCountLocked() {
        final long[] deltas = {123, 234, 345, 456};
        mCounterArray.addCountLocked(deltas);
        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(null, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");

        initializeCounterArrayWithDefaultValues();
        final long[] newCounts = new long[deltas.length];
        for (int i = 0; i < deltas.length; ++i) {
            newCounts[i] = COUNTS[i] + deltas[i];
        }
        mCounterArray.addCountLocked(deltas);
        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
                "Unexpected unpluggedCounts");
    }

    @Test
    public void testReset() {
        initializeCounterArrayWithDefaultValues();
        // Test with detachIfReset=false
        mCounterArray.reset(false /* detachIfReset */);
        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
        verifyZeroInteractions(mTimeBase);

        initializeCounterArrayWithDefaultValues();
        // Test with detachIfReset=true
        mCounterArray.reset(true /* detachIfReset */);
        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
        assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
        verify(mTimeBase).remove(mCounterArray);
        verifyNoMoreInteractions(mTimeBase);
    }

    @Test
    public void testDetach() {
        mCounterArray.detach();
        verify(mTimeBase).remove(mCounterArray);
        verifyNoMoreInteractions(mTimeBase);
    }

    private void initializeCounterArrayWithDefaultValues() {
        updateCounts(COUNTS, LOADED_COUNTS, PLUGGED_COUNTS, UNPLUGGED_COUNTS);
    }

    private void assertArrayEquals(long[] expected, long[] actual, String msg) {
        assertTrue(msg + ", expected: " + Arrays.toString(expected)
                + ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual));
    }

    private void updateCounts(long[] counts, long[] loadedCounts,
            long[] pluggedCounts, long[] unpluggedCounts) {
        mCounterArray.mCounts = counts;
        mCounterArray.mLoadedCounts = loadedCounts;
        mCounterArray.mPluggedCounts = pluggedCounts;
        mCounterArray.mUnpluggedCounts = unpluggedCounts;
    }
}