Merge "More unit tests for classes needed in reading uid times per cpu freq." into oc-dev

am: aff7c3c71e

Change-Id: Ie7691a19ef61668afd9200c9a3c77fa9fc5368f1
This commit is contained in:
Sudheer Shanka
2017-05-18 17:53:28 +00:00
committed by android-build-merger
3 changed files with 341 additions and 66 deletions

View File

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

View File

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

View File

@@ -0,0 +1,217 @@
/*
* 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;
}
}