Merge "Fix batterystat Counter misreporting when charging" into oc-dev

This commit is contained in:
Joe Onorato
2017-05-31 19:26:45 +00:00
committed by Android (Google) Code Review
3 changed files with 183 additions and 27 deletions

View File

@@ -862,21 +862,19 @@ public class BatteryStatsImpl extends BatteryStats {
final AtomicInteger mCount = new AtomicInteger();
final TimeBase mTimeBase;
int mLoadedCount;
int mLastCount;
int mUnpluggedCount;
int mPluggedCount;
Counter(TimeBase timeBase, Parcel in) {
public Counter(TimeBase timeBase, Parcel in) {
mTimeBase = timeBase;
mPluggedCount = in.readInt();
mCount.set(mPluggedCount);
mLoadedCount = in.readInt();
mLastCount = 0;
mUnpluggedCount = in.readInt();
timeBase.add(this);
}
Counter(TimeBase timeBase) {
public Counter(TimeBase timeBase) {
mTimeBase = timeBase;
timeBase.add(this);
}
@@ -887,11 +885,12 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeInt(mUnpluggedCount);
}
@Override
public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
mUnpluggedCount = mPluggedCount;
mCount.set(mPluggedCount);
}
@Override
public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
mPluggedCount = mCount.get();
}
@@ -926,17 +925,22 @@ public class BatteryStatsImpl extends BatteryStats {
public void logState(Printer pw, String prefix) {
pw.println(prefix + "mCount=" + mCount.get()
+ " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
+ " mLoadedCount=" + mLoadedCount
+ " mUnpluggedCount=" + mUnpluggedCount
+ " mPluggedCount=" + mPluggedCount);
}
void stepAtomic() {
mCount.incrementAndGet();
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void stepAtomic() {
if (mTimeBase.isRunning()) {
mCount.incrementAndGet();
}
}
void addAtomic(int delta) {
mCount.addAndGet(delta);
if (mTimeBase.isRunning()) {
mCount.addAndGet(delta);
}
}
/**
@@ -944,7 +948,7 @@ public class BatteryStatsImpl extends BatteryStats {
*/
void reset(boolean detachIfReset) {
mCount.set(0);
mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
if (detachIfReset) {
detach();
}
@@ -954,15 +958,16 @@ public class BatteryStatsImpl extends BatteryStats {
mTimeBase.remove(this);
}
void writeSummaryFromParcelLocked(Parcel out) {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void writeSummaryFromParcelLocked(Parcel out) {
int count = mCount.get();
out.writeInt(count);
}
void readSummaryFromParcelLocked(Parcel in) {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void readSummaryFromParcelLocked(Parcel in) {
mLoadedCount = in.readInt();
mCount.set(mLoadedCount);
mLastCount = 0;
mUnpluggedCount = mPluggedCount = mLoadedCount;
}
}
@@ -998,7 +1003,6 @@ public class BatteryStatsImpl extends BatteryStats {
@Override
public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
mUnpluggedCounts = copyArray(mPluggedCounts, mUnpluggedCounts);
mCounts = copyArray(mPluggedCounts, mCounts);
}
@Override
@@ -1029,11 +1033,13 @@ public class BatteryStatsImpl extends BatteryStats {
if (counts == null) {
return;
}
if (mCounts == null) {
mCounts = new long[counts.length];
}
for (int i = 0; i < counts.length; ++i) {
mCounts[i] += counts[i];
if (mTimeBase.isRunning()) {
if (mCounts == null) {
mCounts = new long[counts.length];
}
for (int i = 0; i < counts.length; ++i) {
mCounts[i] += counts[i];
}
}
}
@@ -1104,13 +1110,13 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
private void fillArray(long[] a, long val) {
private static void fillArray(long[] a, long val) {
if (a != null) {
Arrays.fill(a, val);
}
}
private void subtract(@NonNull long[] val, long[] toSubtract) {
private static void subtract(@NonNull long[] val, long[] toSubtract) {
if (toSubtract == null) {
return;
}
@@ -1119,7 +1125,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
private long[] copyArray(long[] src, long[] dest) {
private static long[] copyArray(long[] src, long[] dest) {
if (src == null) {
return null;
} else {
@@ -1162,7 +1168,6 @@ public class BatteryStatsImpl extends BatteryStats {
@Override
public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
mUnpluggedCount = mPluggedCount;
mCount = mPluggedCount;
}
@Override
@@ -1189,7 +1194,9 @@ public class BatteryStatsImpl extends BatteryStats {
}
void addCountLocked(long count) {
mCount += count;
if (mTimeBase.isRunning()) {
mCount += count;
}
}
/**

View File

@@ -0,0 +1,148 @@
/*
* 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 android.os.BatteryStats;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
import junit.framework.TestCase;
/**
* Test BatteryStatsImpl.Counter.
*/
public class BatteryStatsCounterTest extends TestCase {
@SmallTest
public void testCounter() throws Exception {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
final BatteryStatsImpl.Counter counter = new BatteryStatsImpl.Counter(timeBase);
// timeBase off (i.e. plugged in)
timeBase.setRunning(false, 1, 1);
counter.stepAtomic();
counter.stepAtomic();
counter.stepAtomic();
counter.stepAtomic();
counter.stepAtomic();
assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(0, counter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// timeBase on (i.e. unplugged)
timeBase.setRunning(true, 2, 2);
counter.stepAtomic();
counter.stepAtomic();
counter.stepAtomic();
counter.stepAtomic();
assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// timeBase off (i.e. plugged in)
timeBase.setRunning(false, 3, 3);
counter.stepAtomic();
counter.stepAtomic();
counter.stepAtomic();
assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// timeBase on (i.e. unplugged)
timeBase.setRunning(true, 4, 4);
counter.stepAtomic();
counter.stepAtomic();
assertEquals(6, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(6, counter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(2, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
}
@SmallTest
public void testParceling() throws Exception {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
final BatteryStatsImpl.Counter origCounter = new BatteryStatsImpl.Counter(timeBase);
// timeBase on (i.e. unplugged)
timeBase.setRunning(true, 1, 1);
origCounter.stepAtomic(); origCounter.stepAtomic(); origCounter.stepAtomic(); // three times
assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// Test summary parcelling (from origCounter)
final Parcel summaryParcel = Parcel.obtain();
origCounter.writeSummaryFromParcelLocked(summaryParcel);
summaryParcel.setDataPosition(0);
final BatteryStatsImpl.Counter summaryCounter = new BatteryStatsImpl.Counter(timeBase);
summaryCounter.stepAtomic(); // occurs before reading the summary, so must not count later
summaryCounter.readSummaryFromParcelLocked(summaryParcel);
// timeBase still on (i.e. unplugged)
summaryCounter.stepAtomic(); // once
assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// timeBase off (i.e. plugged in)
timeBase.setRunning(false, 3, 3);
summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice
assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// timeBase on (i.e. unplugged)
timeBase.setRunning(true, 4, 4);
summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice
assertEquals(6, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(3, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(2, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// Test full parcelling (from summaryCounter)
final Parcel fullParcel = Parcel.obtain();
summaryCounter.writeToParcel(fullParcel);
fullParcel.setDataPosition(0);
final BatteryStatsImpl.Counter fullParcelCounter
= new BatteryStatsImpl.Counter(timeBase, fullParcel);
// timeBase still on (i.e. unplugged)
fullParcelCounter.stepAtomic(); // once
assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// timeBase off (i.e. plugged in)
timeBase.setRunning(false, 5, 5);
fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice
assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
// timeBase on (i.e. unplugged)
timeBase.setRunning(true, 6, 6);
fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice
assertEquals(9, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
assertEquals(6, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
assertEquals(2, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
}
}

View File

@@ -5,17 +5,18 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
BatteryStatsBackgroundStatsTest.class,
BatteryStatsCounterTest.class,
BatteryStatsDualTimerTest.class,
BatteryStatsDurationTimerTest.class,
BatteryStatsNoteTest.class,
BatteryStatsSamplingTimerTest.class,
BatteryStatsSensorTest.class,
BatteryStatsServTest.class,
BatteryStatsStopwatchTimerTest.class,
BatteryStatsTimeBaseTest.class,
BatteryStatsTimerTest.class,
BatteryStatsUidTest.class,
BatteryStatsSensorTest.class,
BatteryStatsBackgroundStatsTest.class,
BatteryStatsNoteTest.class,
})
public class BatteryStatsTests {
}