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

Commit 413b1352 authored by Joe Onorato's avatar Joe Onorato Committed by Android (Google) Code Review
Browse files

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

parents fe06de1f 8c6f3c50
Loading
Loading
Loading
Loading
+31 −24
Original line number Diff line number Diff line
@@ -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,25 +925,30 @@ 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() {
        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
        public void stepAtomic() {
            if (mTimeBase.isRunning()) {
                mCount.incrementAndGet();
            }
        }

        void addAtomic(int delta) {
            if (mTimeBase.isRunning()) {
                mCount.addAndGet(delta);
            }
        }

        /**
         * Clear state of this counter.
         */
        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,6 +1033,7 @@ public class BatteryStatsImpl extends BatteryStats {
            if (counts == null) {
                return;
            }
            if (mTimeBase.isRunning()) {
                if (mCounts == null) {
                    mCounts = new long[counts.length];
                }
@@ -1036,6 +1041,7 @@ public class BatteryStatsImpl extends BatteryStats {
                    mCounts[i] += counts[i];
                }
            }
        }

        /**
         * Clear state of this counter.
@@ -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,8 +1194,10 @@ public class BatteryStatsImpl extends BatteryStats {
        }

        void addCountLocked(long count) {
            if (mTimeBase.isRunning()) {
                mCount += count;
            }
        }

        /**
         * Clear state of this counter.
+148 −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 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));
    }
}
+4 −3
Original line number Diff line number Diff line
@@ -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 {
}