Loading core/java/com/android/internal/os/BatteryStatsImpl.java +95 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.LogWriter; import android.util.LongSparseArray; import android.util.LongSparseLongArray; import android.util.MutableInt; import android.util.PrintWriterPrinter; import android.util.Printer; Loading Loading @@ -99,6 +101,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final boolean DEBUG = false; public static final boolean DEBUG_ENERGY = false; private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY; private static final boolean DEBUG_MEMORY = false; private static final boolean DEBUG_HISTORY = false; private static final boolean USE_OLD_HISTORY = false; // for debugging. Loading Loading @@ -144,6 +147,13 @@ public class BatteryStatsImpl extends BatteryStats { private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader(); private KernelCpuSpeedReader[] mKernelCpuSpeedReaders; private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats = new KernelMemoryBandwidthStats(); private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>(); public LongSparseArray<SamplingTimer> getKernelMemoryStats() { return mKernelMemoryStats; } public interface BatteryCallback { public void batteryNeedsCpuUpdate(); public void batteryPowerChanged(boolean onBattery); Loading Loading @@ -2082,6 +2092,15 @@ public class BatteryStatsImpl extends BatteryStats { return kwlt; } public SamplingTimer getKernelMemoryTimerLocked(long bucket) { SamplingTimer kmt = mKernelMemoryStats.get(bucket); if (kmt == null) { kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase); mKernelMemoryStats.put(bucket, kmt); } return kmt; } private int writeHistoryTag(HistoryTag tag) { Integer idxObj = mHistoryTagPool.get(tag); int idx; Loading Loading @@ -7698,7 +7717,6 @@ public class BatteryStatsImpl extends BatteryStats { NUM_BT_TX_LEVELS); mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, ModemActivityInfo.TX_POWER_LEVELS); mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase); mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null, mOnBatteryTimeBase); Loading Loading @@ -8395,6 +8413,13 @@ public class BatteryStatsImpl extends BatteryStats { mKernelWakelockStats.clear(); } if (mKernelMemoryStats.size() > 0) { for (int i = 0; i < mKernelMemoryStats.size(); i++) { mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i)); } mKernelMemoryStats.clear(); } if (mWakeupReasonStats.size() > 0) { for (SamplingTimer timer : mWakeupReasonStats.values()) { mOnBatteryTimeBase.remove(timer); Loading Loading @@ -9092,6 +9117,33 @@ public class BatteryStatsImpl extends BatteryStats { long mTempTotalCpuUserTimeUs; long mTempTotalCpuSystemTimeUs; /** * Reads the newest memory stats from the kernel. */ public void updateKernelMemoryBandwidthLocked() { mKernelMemoryBandwidthStats.updateStats(); LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries(); final int bandwidthEntryCount = bandwidthEntries.size(); int index; for (int i = 0; i < bandwidthEntryCount; i++) { SamplingTimer timer; if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) { timer = mKernelMemoryStats.valueAt(index); } else { timer = new SamplingTimer(mClocks, mOnBatteryTimeBase); mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer); } timer.update(bandwidthEntries.valueAt(i), 1); if (DEBUG_MEMORY) { Slog.d(TAG, String.format("Added entry %d and updated timer to: " + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i), mKernelMemoryStats.get( bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime, mKernelMemoryStats.size())); } } } /** * Read and distribute CPU usage across apps. If their are partial wakelocks being held * and we are on battery with screen off, we give more of the cpu time to those apps holding Loading Loading @@ -10372,6 +10424,14 @@ public class BatteryStatsImpl extends BatteryStats { } } int NMS = in.readInt(); for (int ims = 0; ims < NMS; ims++) { if (in.readInt() != 0) { long kmstName = in.readLong(); getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in); } } final int NU = in.readInt(); if (NU > 10000) { throw new ParcelFormatException("File corrupt: too many uids " + NU); Loading Loading @@ -10727,6 +10787,18 @@ public class BatteryStatsImpl extends BatteryStats { } } out.writeInt(mKernelMemoryStats.size()); for (int i = 0; i < mKernelMemoryStats.size(); i++) { Timer kmt = mKernelMemoryStats.valueAt(i); if (kmt != null) { out.writeInt(1); out.writeLong(mKernelMemoryStats.keyAt(i)); kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } } final int NU = mUidStats.size(); out.writeInt(NU); for (int iu = 0; iu < NU; iu++) { Loading Loading @@ -11129,6 +11201,16 @@ public class BatteryStatsImpl extends BatteryStats { } } mKernelMemoryStats.clear(); int nmt = in.readInt(); for (int imt = 0; imt < nmt; imt++) { if (in.readInt() != 0) { Long bucket = in.readLong(); SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in); mKernelMemoryStats.put(bucket, kmt); } } mPartialTimers.clear(); mFullTimers.clear(); mWindowTimers.clear(); Loading Loading @@ -11287,6 +11369,18 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } out.writeInt(mKernelMemoryStats.size()); for (int i = 0; i < mKernelMemoryStats.size(); i++) { SamplingTimer kmt = mKernelMemoryStats.valueAt(i); if (kmt != null) { out.writeInt(1); out.writeLong(mKernelMemoryStats.keyAt(i)); kmt.writeToParcel(out, uSecRealtime); } else { out.writeInt(0); } } if (inclUids) { int size = mUidStats.size(); out.writeInt(size); Loading core/java/com/android/internal/os/KernelMemoryBandwidthStats.java 0 → 100644 +72 −0 Original line number Diff line number Diff line package com.android.internal.os; import android.os.StrictMode; import android.text.TextUtils; import android.util.LongSparseLongArray; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /** * Reads DDR time spent at various frequencies and stores the data. Supports diff comparison with * other KernelMemoryBandwidthStats objects. The sysfs file has the format: * * freq time_in_bucket ... time_in_bucket * ... * freq time_in_bucket ... time_in_bucket * * where time is measured in nanoseconds. */ public class KernelMemoryBandwidthStats { private static final String TAG = "KernelMemoryBandwidthStats"; final protected LongSparseLongArray mBandwidthEntries = new LongSparseLongArray(); private static final String mSysfsFile = "/sys/kernel/memory_state_time/show_stat"; private static final boolean DEBUG = false; public void updateStats() { StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads(); try (BufferedReader reader = new BufferedReader(new FileReader(mSysfsFile))) { parseStats(reader); } catch (IOException e) { Slog.e(TAG, "Failed to read memory bandwidth: " + e.getMessage()); mBandwidthEntries.clear(); } finally { StrictMode.setThreadPolicy(policy); } } @VisibleForTesting public void parseStats(BufferedReader reader) throws IOException { String line; TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); mBandwidthEntries.clear(); while ((line = reader.readLine()) != null) { splitter.setString(line); splitter.next(); int bandwidth = 0; int index; do { if ((index = mBandwidthEntries.indexOfKey(bandwidth)) >= 0) { mBandwidthEntries.put(bandwidth, mBandwidthEntries.valueAt(index) + Long.parseLong(splitter.next()) / 1000000); } else { mBandwidthEntries.put(bandwidth, Long.parseLong(splitter.next()) / 1000000); } if (DEBUG) { Slog.d(TAG, String.format("bandwidth: %s time: %s", bandwidth, mBandwidthEntries.get(bandwidth))); } bandwidth++; } while(splitter.hasNext()); } } public LongSparseLongArray getBandwidthEntries() { return mBandwidthEntries; } } core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java 0 → 100644 +80 −0 Original line number Diff line number Diff line package com.android.internal.os; import android.support.test.filters.SmallTest; import android.util.LongSparseLongArray; import junit.framework.TestCase; import org.junit.Assert; import org.mockito.Mockito; import java.io.BufferedReader; /** * Tests for KernelMemoryBandwidthStats parsing and delta calculation, based on memory_state_time. */ public class KernelMemoryBandwidthStatsTest extends TestCase { /** * Standard example of parsing stats. * @throws Exception */ @SmallTest public void testParseStandard() throws Exception { KernelMemoryBandwidthStats stats = new KernelMemoryBandwidthStats(); BufferedReader mockStandardReader = Mockito.mock(BufferedReader.class); Mockito.when(mockStandardReader.readLine()).thenReturn( "99000000 0 0 0 0 0 0 0 0 0 0 0 0", "149000000 0 0 0 0 0 0 0 0 0 0 0 0", "199884800 7301000000 0 2000000 1000000 0 0 0 0 0 0 0 0", "299892736 674000000 0 21000000 0 0 0 0 0 0 0 0 0", "411959296 1146000000 0 221000000 1000000 0 0 0 0 0 0 0 0", "546963456 744000000 0 420000000 0 0 0 1000000 0 0 0 0 0", "680919040 182000000 0 1839000000 207000000 1000000 1000000 0 0 0 0 0 0", "767950848 0 0 198000000 33000000 4000000 0 1000000 0 0 0 0 0", "1016987648 0 0 339000000 362000000 3000000 0 0 0 0 0 0 16000000", "1295908864 0 0 20000000 870000000 244000000 0 0 0 0 0 0 33000000", "1554907136 0 0 6000000 32000000 631000000 115000000 0 0 0 1000000 0 0", "1803943936 2496000000 0 17000000 2000000 377000000 1505000000 278000000 183000000 141000000 486000000 154000000 113000000", null); stats.parseStats(mockStandardReader); long[] expected = new long[] {12543L, 0L, 3083L, 1508L, 1260L, 1621L, 280L, 183L, 141L, 487L, 154L, 162L}; LongSparseLongArray array = stats.getBandwidthEntries(); for (int i = 2; i < array.size(); i++) { assertEquals(i, array.keyAt(i)); assertEquals(expected[i], array.valueAt(i)); } Mockito.verify(mockStandardReader, Mockito.times(13)).readLine(); } /** * When the stats are populated with zeroes (unsupported device), checks that the stats are * zero. * @throws Exception */ @SmallTest public void testParseBackwards() throws Exception { KernelMemoryBandwidthStats zeroStats = new KernelMemoryBandwidthStats(); BufferedReader mockZeroReader = Mockito.mock(BufferedReader.class); Mockito.when(mockZeroReader.readLine()).thenReturn( "99000000 0 0 0 0 0 0 0 0 0 0 0 0", "149000000 0 0 0 0 0 0 0 0 0 0 0 0", "199884800 0 0 0 0 0 0 0 0 0 0 0 0", "299892736 0 0 0 0 0 0 0 0 0 0 0 0", "411959296 0 0 0 0 0 0 0 0 0 0 0 0", "546963456 0 0 0 0 0 0 0 0 0 0 0 0", "680919040 0 0 0 0 0 0 0 0 0 0 0 0", "767950848 0 0 0 0 0 0 0 0 0 0 0 0", "1016987648 0 0 0 0 0 0 0 0 0 0 0 0", "1295908864 0 0 0 0 0 0 0 0 0 0 0 0", "1554907136 0 0 0 0 0 0 0 0 0 0 0 0", "1803943936 0 0 0 0 0 0 0 0 0 0 0 0", null); zeroStats.parseStats(mockZeroReader); long[] expected = new long[] {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}; LongSparseLongArray array = zeroStats.getBandwidthEntries(); for (int i = 0; i < array.size(); i++) { assertEquals(expected[i], array.valueAt(i)); } Mockito.verify(mockZeroReader, Mockito.times(13)).readLine(); } } Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +95 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.LogWriter; import android.util.LongSparseArray; import android.util.LongSparseLongArray; import android.util.MutableInt; import android.util.PrintWriterPrinter; import android.util.Printer; Loading Loading @@ -99,6 +101,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final boolean DEBUG = false; public static final boolean DEBUG_ENERGY = false; private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY; private static final boolean DEBUG_MEMORY = false; private static final boolean DEBUG_HISTORY = false; private static final boolean USE_OLD_HISTORY = false; // for debugging. Loading Loading @@ -144,6 +147,13 @@ public class BatteryStatsImpl extends BatteryStats { private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader(); private KernelCpuSpeedReader[] mKernelCpuSpeedReaders; private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats = new KernelMemoryBandwidthStats(); private final LongSparseArray<SamplingTimer> mKernelMemoryStats = new LongSparseArray<>(); public LongSparseArray<SamplingTimer> getKernelMemoryStats() { return mKernelMemoryStats; } public interface BatteryCallback { public void batteryNeedsCpuUpdate(); public void batteryPowerChanged(boolean onBattery); Loading Loading @@ -2082,6 +2092,15 @@ public class BatteryStatsImpl extends BatteryStats { return kwlt; } public SamplingTimer getKernelMemoryTimerLocked(long bucket) { SamplingTimer kmt = mKernelMemoryStats.get(bucket); if (kmt == null) { kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase); mKernelMemoryStats.put(bucket, kmt); } return kmt; } private int writeHistoryTag(HistoryTag tag) { Integer idxObj = mHistoryTagPool.get(tag); int idx; Loading Loading @@ -7698,7 +7717,6 @@ public class BatteryStatsImpl extends BatteryStats { NUM_BT_TX_LEVELS); mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, ModemActivityInfo.TX_POWER_LEVELS); mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase); mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null, mOnBatteryTimeBase); Loading Loading @@ -8395,6 +8413,13 @@ public class BatteryStatsImpl extends BatteryStats { mKernelWakelockStats.clear(); } if (mKernelMemoryStats.size() > 0) { for (int i = 0; i < mKernelMemoryStats.size(); i++) { mOnBatteryTimeBase.remove(mKernelMemoryStats.valueAt(i)); } mKernelMemoryStats.clear(); } if (mWakeupReasonStats.size() > 0) { for (SamplingTimer timer : mWakeupReasonStats.values()) { mOnBatteryTimeBase.remove(timer); Loading Loading @@ -9092,6 +9117,33 @@ public class BatteryStatsImpl extends BatteryStats { long mTempTotalCpuUserTimeUs; long mTempTotalCpuSystemTimeUs; /** * Reads the newest memory stats from the kernel. */ public void updateKernelMemoryBandwidthLocked() { mKernelMemoryBandwidthStats.updateStats(); LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries(); final int bandwidthEntryCount = bandwidthEntries.size(); int index; for (int i = 0; i < bandwidthEntryCount; i++) { SamplingTimer timer; if ((index = mKernelMemoryStats.indexOfKey(bandwidthEntries.keyAt(i))) >= 0) { timer = mKernelMemoryStats.valueAt(index); } else { timer = new SamplingTimer(mClocks, mOnBatteryTimeBase); mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer); } timer.update(bandwidthEntries.valueAt(i), 1); if (DEBUG_MEMORY) { Slog.d(TAG, String.format("Added entry %d and updated timer to: " + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i), mKernelMemoryStats.get( bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime, mKernelMemoryStats.size())); } } } /** * Read and distribute CPU usage across apps. If their are partial wakelocks being held * and we are on battery with screen off, we give more of the cpu time to those apps holding Loading Loading @@ -10372,6 +10424,14 @@ public class BatteryStatsImpl extends BatteryStats { } } int NMS = in.readInt(); for (int ims = 0; ims < NMS; ims++) { if (in.readInt() != 0) { long kmstName = in.readLong(); getKernelMemoryTimerLocked(kmstName).readSummaryFromParcelLocked(in); } } final int NU = in.readInt(); if (NU > 10000) { throw new ParcelFormatException("File corrupt: too many uids " + NU); Loading Loading @@ -10727,6 +10787,18 @@ public class BatteryStatsImpl extends BatteryStats { } } out.writeInt(mKernelMemoryStats.size()); for (int i = 0; i < mKernelMemoryStats.size(); i++) { Timer kmt = mKernelMemoryStats.valueAt(i); if (kmt != null) { out.writeInt(1); out.writeLong(mKernelMemoryStats.keyAt(i)); kmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } } final int NU = mUidStats.size(); out.writeInt(NU); for (int iu = 0; iu < NU; iu++) { Loading Loading @@ -11129,6 +11201,16 @@ public class BatteryStatsImpl extends BatteryStats { } } mKernelMemoryStats.clear(); int nmt = in.readInt(); for (int imt = 0; imt < nmt; imt++) { if (in.readInt() != 0) { Long bucket = in.readLong(); SamplingTimer kmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in); mKernelMemoryStats.put(bucket, kmt); } } mPartialTimers.clear(); mFullTimers.clear(); mWindowTimers.clear(); Loading Loading @@ -11287,6 +11369,18 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } out.writeInt(mKernelMemoryStats.size()); for (int i = 0; i < mKernelMemoryStats.size(); i++) { SamplingTimer kmt = mKernelMemoryStats.valueAt(i); if (kmt != null) { out.writeInt(1); out.writeLong(mKernelMemoryStats.keyAt(i)); kmt.writeToParcel(out, uSecRealtime); } else { out.writeInt(0); } } if (inclUids) { int size = mUidStats.size(); out.writeInt(size); Loading
core/java/com/android/internal/os/KernelMemoryBandwidthStats.java 0 → 100644 +72 −0 Original line number Diff line number Diff line package com.android.internal.os; import android.os.StrictMode; import android.text.TextUtils; import android.util.LongSparseLongArray; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /** * Reads DDR time spent at various frequencies and stores the data. Supports diff comparison with * other KernelMemoryBandwidthStats objects. The sysfs file has the format: * * freq time_in_bucket ... time_in_bucket * ... * freq time_in_bucket ... time_in_bucket * * where time is measured in nanoseconds. */ public class KernelMemoryBandwidthStats { private static final String TAG = "KernelMemoryBandwidthStats"; final protected LongSparseLongArray mBandwidthEntries = new LongSparseLongArray(); private static final String mSysfsFile = "/sys/kernel/memory_state_time/show_stat"; private static final boolean DEBUG = false; public void updateStats() { StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads(); try (BufferedReader reader = new BufferedReader(new FileReader(mSysfsFile))) { parseStats(reader); } catch (IOException e) { Slog.e(TAG, "Failed to read memory bandwidth: " + e.getMessage()); mBandwidthEntries.clear(); } finally { StrictMode.setThreadPolicy(policy); } } @VisibleForTesting public void parseStats(BufferedReader reader) throws IOException { String line; TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); mBandwidthEntries.clear(); while ((line = reader.readLine()) != null) { splitter.setString(line); splitter.next(); int bandwidth = 0; int index; do { if ((index = mBandwidthEntries.indexOfKey(bandwidth)) >= 0) { mBandwidthEntries.put(bandwidth, mBandwidthEntries.valueAt(index) + Long.parseLong(splitter.next()) / 1000000); } else { mBandwidthEntries.put(bandwidth, Long.parseLong(splitter.next()) / 1000000); } if (DEBUG) { Slog.d(TAG, String.format("bandwidth: %s time: %s", bandwidth, mBandwidthEntries.get(bandwidth))); } bandwidth++; } while(splitter.hasNext()); } } public LongSparseLongArray getBandwidthEntries() { return mBandwidthEntries; } }
core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java 0 → 100644 +80 −0 Original line number Diff line number Diff line package com.android.internal.os; import android.support.test.filters.SmallTest; import android.util.LongSparseLongArray; import junit.framework.TestCase; import org.junit.Assert; import org.mockito.Mockito; import java.io.BufferedReader; /** * Tests for KernelMemoryBandwidthStats parsing and delta calculation, based on memory_state_time. */ public class KernelMemoryBandwidthStatsTest extends TestCase { /** * Standard example of parsing stats. * @throws Exception */ @SmallTest public void testParseStandard() throws Exception { KernelMemoryBandwidthStats stats = new KernelMemoryBandwidthStats(); BufferedReader mockStandardReader = Mockito.mock(BufferedReader.class); Mockito.when(mockStandardReader.readLine()).thenReturn( "99000000 0 0 0 0 0 0 0 0 0 0 0 0", "149000000 0 0 0 0 0 0 0 0 0 0 0 0", "199884800 7301000000 0 2000000 1000000 0 0 0 0 0 0 0 0", "299892736 674000000 0 21000000 0 0 0 0 0 0 0 0 0", "411959296 1146000000 0 221000000 1000000 0 0 0 0 0 0 0 0", "546963456 744000000 0 420000000 0 0 0 1000000 0 0 0 0 0", "680919040 182000000 0 1839000000 207000000 1000000 1000000 0 0 0 0 0 0", "767950848 0 0 198000000 33000000 4000000 0 1000000 0 0 0 0 0", "1016987648 0 0 339000000 362000000 3000000 0 0 0 0 0 0 16000000", "1295908864 0 0 20000000 870000000 244000000 0 0 0 0 0 0 33000000", "1554907136 0 0 6000000 32000000 631000000 115000000 0 0 0 1000000 0 0", "1803943936 2496000000 0 17000000 2000000 377000000 1505000000 278000000 183000000 141000000 486000000 154000000 113000000", null); stats.parseStats(mockStandardReader); long[] expected = new long[] {12543L, 0L, 3083L, 1508L, 1260L, 1621L, 280L, 183L, 141L, 487L, 154L, 162L}; LongSparseLongArray array = stats.getBandwidthEntries(); for (int i = 2; i < array.size(); i++) { assertEquals(i, array.keyAt(i)); assertEquals(expected[i], array.valueAt(i)); } Mockito.verify(mockStandardReader, Mockito.times(13)).readLine(); } /** * When the stats are populated with zeroes (unsupported device), checks that the stats are * zero. * @throws Exception */ @SmallTest public void testParseBackwards() throws Exception { KernelMemoryBandwidthStats zeroStats = new KernelMemoryBandwidthStats(); BufferedReader mockZeroReader = Mockito.mock(BufferedReader.class); Mockito.when(mockZeroReader.readLine()).thenReturn( "99000000 0 0 0 0 0 0 0 0 0 0 0 0", "149000000 0 0 0 0 0 0 0 0 0 0 0 0", "199884800 0 0 0 0 0 0 0 0 0 0 0 0", "299892736 0 0 0 0 0 0 0 0 0 0 0 0", "411959296 0 0 0 0 0 0 0 0 0 0 0 0", "546963456 0 0 0 0 0 0 0 0 0 0 0 0", "680919040 0 0 0 0 0 0 0 0 0 0 0 0", "767950848 0 0 0 0 0 0 0 0 0 0 0 0", "1016987648 0 0 0 0 0 0 0 0 0 0 0 0", "1295908864 0 0 0 0 0 0 0 0 0 0 0 0", "1554907136 0 0 0 0 0 0 0 0 0 0 0 0", "1803943936 0 0 0 0 0 0 0 0 0 0 0 0", null); zeroStats.parseStats(mockZeroReader); long[] expected = new long[] {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}; LongSparseLongArray array = zeroStats.getBandwidthEntries(); for (int i = 0; i < array.size(); i++) { assertEquals(expected[i], array.valueAt(i)); } Mockito.verify(mockZeroReader, Mockito.times(13)).readLine(); } }