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

Commit d55f7e64 authored by Joe Onorato's avatar Joe Onorato Committed by android-build-merger
Browse files

Have BatteryStats track and report the running wakelocks.

am: adbee556

Change-Id: I02de7ade40163257d6d424b0ae37dba65d43a565
parents 899f65dc adbee556
Loading
Loading
Loading
Loading
+79 −6
Original line number Original line Diff line number Diff line
@@ -30,6 +30,8 @@ import android.content.pm.ApplicationInfo;
import android.telephony.SignalStrength;
import android.telephony.SignalStrength;
import android.text.format.DateFormat;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.MutableBoolean;
import android.util.MutableBoolean;
import android.util.Pair;
import android.util.Pair;
import android.util.Printer;
import android.util.Printer;
@@ -47,6 +49,7 @@ import com.android.internal.os.BatteryStatsHelper;
 * @hide
 * @hide
 */
 */
public abstract class BatteryStats implements Parcelable {
public abstract class BatteryStats implements Parcelable {
    private static final String TAG = "BatteryStats";


    private static final boolean LOCAL_LOGV = false;
    private static final boolean LOCAL_LOGV = false;


@@ -175,8 +178,11 @@ public abstract class BatteryStats implements Parcelable {


    /**
    /**
     * Current version of checkin data format.
     * Current version of checkin data format.
     *
     * New in version 19:
     *   - Wakelock data (wl) gets current and max times.
     */
     */
    static final String CHECKIN_VERSION = "18";
    static final String CHECKIN_VERSION = "19";


    /**
    /**
     * Old version, we hit 9 and ran out of room, need to remove.
     * Old version, we hit 9 and ran out of room, need to remove.
@@ -351,6 +357,32 @@ public abstract class BatteryStats implements Parcelable {
         */
         */
        public abstract long getTimeSinceMarkLocked(long elapsedRealtimeUs);
        public abstract long getTimeSinceMarkLocked(long elapsedRealtimeUs);


        /**
         * Returns the max duration if it is being tracked.
         * Not all Timer subclasses track the max duration and the current duration.

         */
        public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
            return -1;
        }

        /**
         * Returns the current time the timer has been active, if it is being tracked.
         * Not all Timer subclasses track the max duration and the current duration.
         */
        public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
            return -1;
        }

        /**
         * Returns whether the timer is currently running.  Some types of timers
         * (e.g. BatchTimers) don't know whether the event is currently active,
         * and report false.
         */
        public boolean isRunningLocked() {
            return false;
        }

        /**
        /**
         * Temporary for debugging.
         * Temporary for debugging.
         */
         */
@@ -2558,6 +2590,22 @@ public abstract class BatteryStats implements Parcelable {
                sb.append('(');
                sb.append('(');
                sb.append(count);
                sb.append(count);
                sb.append(" times)");
                sb.append(" times)");
                final long maxDurationMs = timer.getMaxDurationMsLocked(elapsedRealtimeUs/1000);
                if (maxDurationMs >= 0) {
                    sb.append(" max=");
                    sb.append(maxDurationMs);
                }
                if (timer.isRunningLocked()) {
                    final long currentMs = timer.getCurrentDurationMsLocked(elapsedRealtimeUs/1000);
                    if (currentMs >= 0) {
                        sb.append(" (running for ");
                        sb.append(currentMs);
                        sb.append("ms)");
                    } else {
                        sb.append(" (running)");
                    }
                }

                return ", ";
                return ", ";
            }
            }
        }
        }
@@ -2565,6 +2613,7 @@ public abstract class BatteryStats implements Parcelable {
    }
    }


    /**
    /**
     * Prints details about a timer, if its total time was greater than 0.
     *
     *
     * @param pw a PrintWriter object to print to.
     * @param pw a PrintWriter object to print to.
     * @param sb a StringBuilder object.
     * @param sb a StringBuilder object.
@@ -2573,24 +2622,40 @@ public abstract class BatteryStats implements Parcelable {
     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
     * @param prefix a String to be prepended to each line of output.
     * @param prefix a String to be prepended to each line of output.
     * @param type the name of the timer.
     * @param type the name of the timer.
     * @return true if anything was printed.
     */
     */
    private static final boolean printTimer(PrintWriter pw, StringBuilder sb, Timer timer,
    private static final boolean printTimer(PrintWriter pw, StringBuilder sb, Timer timer,
            long rawRealtime, int which, String prefix, String type) {
            long rawRealtimeUs, int which, String prefix, String type) {
        if (timer != null) {
        if (timer != null) {
            // Convert from microseconds to milliseconds with rounding
            // Convert from microseconds to milliseconds with rounding
            final long totalTime = (timer.getTotalTimeLocked(
            final long totalTimeMs = (timer.getTotalTimeLocked(
                    rawRealtime, which) + 500) / 1000;
                    rawRealtimeUs, which) + 500) / 1000;
            final int count = timer.getCountLocked(which);
            final int count = timer.getCountLocked(which);
            if (totalTime != 0) {
            if (totalTimeMs != 0) {
                sb.setLength(0);
                sb.setLength(0);
                sb.append(prefix);
                sb.append(prefix);
                sb.append("    ");
                sb.append("    ");
                sb.append(type);
                sb.append(type);
                sb.append(": ");
                sb.append(": ");
                formatTimeMs(sb, totalTime);
                formatTimeMs(sb, totalTimeMs);
                sb.append("realtime (");
                sb.append("realtime (");
                sb.append(count);
                sb.append(count);
                sb.append(" times)");
                sb.append(" times)");
                final long maxDurationMs = timer.getMaxDurationMsLocked(rawRealtimeUs/1000);
                if (maxDurationMs >= 0) {
                    sb.append(" max=");
                    sb.append(maxDurationMs);
                }
                if (timer.isRunningLocked()) {
                    final long currentMs = timer.getCurrentDurationMsLocked(rawRealtimeUs/1000);
                    if (currentMs >= 0) {
                        sb.append(" (running for ");
                        sb.append(currentMs);
                        sb.append("ms)");
                    } else {
                        sb.append(" (running)");
                    }
                }
                pw.println(sb.toString());
                pw.println(sb.toString());
                return true;
                return true;
            }
            }
@@ -2613,15 +2678,23 @@ public abstract class BatteryStats implements Parcelable {
            long elapsedRealtimeUs, String name, int which, String linePrefix) {
            long elapsedRealtimeUs, String name, int which, String linePrefix) {
        long totalTimeMicros = 0;
        long totalTimeMicros = 0;
        int count = 0;
        int count = 0;
        long max = -1;
        long current = -1;
        if (timer != null) {
        if (timer != null) {
            totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
            totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
            count = timer.getCountLocked(which); 
            count = timer.getCountLocked(which); 
            current = timer.getCurrentDurationMsLocked(elapsedRealtimeUs/1000);
            max = timer.getMaxDurationMsLocked(elapsedRealtimeUs/1000);
        }
        }
        sb.append(linePrefix);
        sb.append(linePrefix);
        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
        sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
        sb.append(',');
        sb.append(',');
        sb.append(name != null ? name + "," : "");
        sb.append(name != null ? name + "," : "");
        sb.append(count);
        sb.append(count);
        sb.append(',');
        sb.append(current);
        sb.append(',');
        sb.append(max);
        return ",";
        return ",";
    }
    }
    
    
+220 −18
Original line number Original line Diff line number Diff line
@@ -108,7 +108,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'


    // Current on-disk Parcel version
    // Current on-disk Parcel version
    private static final int VERSION = 148 + (USE_OLD_HISTORY ? 1000 : 0);
    private static final int VERSION = 149 + (USE_OLD_HISTORY ? 1000 : 0);


    // Maximum number of items we will record in the history.
    // Maximum number of items we will record in the history.
    private static final int MAX_HISTORY_ITEMS = 2000;
    private static final int MAX_HISTORY_ITEMS = 2000;
@@ -1566,6 +1566,186 @@ public class BatteryStatsImpl extends BatteryStats {
        }
        }
    }
    }



    /**
     * A StopwatchTimer that also tracks the total and max individual
     * time spent active according to the given timebase.  Whereas
     * StopwatchTimer apportions the time amongst all in the pool,
     * the total and max durations are not apportioned.
     */
    public static class DurationTimer extends StopwatchTimer {
        /**
         * The time (in ms) that the timer was last acquired or the time base
         * last (re-)started. Increasing the nesting depth does not reset this time.
         *
         * -1 if the timer is currently not running or the time base is not running.
         *
         * If written to a parcel, the start time is reset, as is mNesting in the base class
         * StopwatchTimer.
         */
        long mStartTimeMs = -1;

        /**
         * The longest time period (in ms) that the timer has been active.
         */
        long mMaxDurationMs;

        /**
         * The total time (in ms) that that the timer has been active since reset().
         */
        long mCurrentDurationMs;

        public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
                TimeBase timeBase, Parcel in) {
            super(clocks, uid, type, timerPool, timeBase, in);
            mMaxDurationMs = in.readLong();
        }

        public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
                TimeBase timeBase) {
            super(clocks, uid, type, timerPool, timeBase);
        }

        @Override
        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
            super.writeToParcel(out, elapsedRealtimeUs);
            out.writeLong(mMaxDurationMs);
        }

        /**
         * Write the summary to the parcel.
         *
         * Since the time base is probably meaningless after we come back, reading
         * from this will have the effect of stopping the timer. So here all we write
         * is the max duration.
         */
        @Override
        public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
            super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
            out.writeLong(mMaxDurationMs);
        }

        /**
         * Read the summary parcel.
         *
         * Has the side effect of stopping the timer.
         */
        @Override
        public void readSummaryFromParcelLocked(Parcel in) {
            super.readSummaryFromParcelLocked(in);
            mMaxDurationMs = in.readLong();
            mStartTimeMs = -1;
            mCurrentDurationMs = 0;
        }

        /**
         * The TimeBase time started (again).
         *
         * If the timer is also running, store the start time.
         */
        public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
            super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
            if (mNesting > 0) {
                mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
            }
        }

        /**
         * The TimeBase stopped running.
         *
         * If the timer is running, add the duration into mCurrentDurationMs.
         */
        @Override
        public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
            super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtime);
            if (mNesting > 0) {
                mCurrentDurationMs += (elapsedRealtimeUs / 1000) - mStartTimeMs;
            }
            mStartTimeMs = -1;
        }

        @Override
        public void logState(Printer pw, String prefix) {
            super.logState(pw, prefix);
        }

        @Override
        public void startRunningLocked(long elapsedRealtimeMs) {
            super.startRunningLocked(elapsedRealtimeMs);
            if (mNesting == 1 && mTimeBase.isRunning()) {
                // Just started
                mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
            }
        }

        /**
         * Decrements the mNesting ref-count on this timer.
         *
         * If it actually stopped (mNesting went to 0), then possibly update
         * mMaxDuration if the current duration was the longest ever.
         */
        @Override
        public void stopRunningLocked(long elapsedRealtimeMs) {
            super.stopRunningLocked(elapsedRealtimeMs);
            if (mNesting == 0) {
                final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
                if (durationMs > mMaxDurationMs) {
                    mMaxDurationMs = durationMs;
                }
                mStartTimeMs = -1;
                mCurrentDurationMs = 0;
            }
        }

        @Override
        public boolean reset(boolean detachIfReset) {
            boolean result = super.reset(detachIfReset);
            mMaxDurationMs = 0;
            mCurrentDurationMs = 0;
            if (mNesting > 0) {
                mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
            } else {
                mStartTimeMs = -1;
            }
            return result;
        }

        /**
         * Returns the max duration that this timer has ever seen.
         *
         * Note that this time is NOT split between the timers in the timer group that
         * this timer is attached to.  It is the TOTAL time.
         */
        @Override
        public long getMaxDurationMsLocked(long elapsedRealtimeMs) {
            if (mNesting > 0) {
                final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
                if (durationMs > mMaxDurationMs) {
                    return durationMs;
                }
            }
            return mMaxDurationMs;
        }

        /**
         * Returns the time since the timer was started.
         *
         * Note that this time is NOT split between the timers in the timer group that
         * this timer is attached to.  It is the TOTAL time.
         */
        @Override
        public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
            long durationMs = mCurrentDurationMs;
            if (mNesting > 0) {
                if (mTimeBase.isRunning()) {
                    durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
                            - mStartTimeMs;
                }
            }
            return durationMs;
        }
    }

    /**
    /**
     * State for keeping track of timing information.
     * State for keeping track of timing information.
     */
     */
@@ -6535,7 +6715,7 @@ public class BatteryStatsImpl extends BatteryStats {
            /**
            /**
             * How long (in ms) this uid has been keeping the device partially awake.
             * How long (in ms) this uid has been keeping the device partially awake.
             */
             */
            StopwatchTimer mTimerPartial;
            DurationTimer mTimerPartial;


            /**
            /**
             * How long (in ms) this uid has been keeping the device fully awake.
             * How long (in ms) this uid has been keeping the device fully awake.
@@ -6564,8 +6744,8 @@ public class BatteryStatsImpl extends BatteryStats {
             * @param in the Parcel to be read from.
             * @param in the Parcel to be read from.
             * return a new Timer, or null.
             * return a new Timer, or null.
             */
             */
            private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
            private StopwatchTimer readStopwatchTimerFromParcel(int type,
                    TimeBase timeBase, Parcel in) {
                    ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
                if (in.readInt() == 0) {
                if (in.readInt() == 0) {
                    return null;
                    return null;
                }
                }
@@ -6573,6 +6753,22 @@ public class BatteryStatsImpl extends BatteryStats {
                return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
                return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
            }
            }


            /**
             * Reads a possibly null Timer from a Parcel.  The timer is associated with the
             * proper timer pool from the given BatteryStatsImpl object.
             *
             * @param in the Parcel to be read from.
             * return a new Timer, or null.
             */
            private DurationTimer readDurationTimerFromParcel(int type,
                    ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
                if (in.readInt() == 0) {
                    return null;
                }

                return new DurationTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
            }

            boolean reset() {
            boolean reset() {
                boolean wlactive = false;
                boolean wlactive = false;
                if (mTimerFull != null) {
                if (mTimerFull != null) {
@@ -6609,11 +6805,14 @@ public class BatteryStatsImpl extends BatteryStats {
            }
            }


            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
                mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
                mTimerPartial = readDurationTimerFromParcel(WAKE_TYPE_PARTIAL,
                        mBsi.mPartialTimers, screenOffTimeBase, in);
                        mBsi.mPartialTimers, screenOffTimeBase, in);
                mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, mBsi.mFullTimers, timeBase, in);
                mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
                mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, mBsi.mWindowTimers, timeBase, in);
                        mBsi.mFullTimers, timeBase, in);
                mTimerDraw = readTimerFromParcel(WAKE_TYPE_DRAW, mBsi.mDrawTimers, timeBase, in);
                mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
                        mBsi.mWindowTimers, timeBase, in);
                mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW,
                        mBsi.mDrawTimers, timeBase, in);
            }
            }


            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
@@ -6635,40 +6834,43 @@ public class BatteryStatsImpl extends BatteryStats {
            }
            }


            public StopwatchTimer getStopwatchTimer(int type) {
            public StopwatchTimer getStopwatchTimer(int type) {
                StopwatchTimer t;
                switch (type) {
                switch (type) {
                    case WAKE_TYPE_PARTIAL:
                    case WAKE_TYPE_PARTIAL: {
                        t = mTimerPartial;
                        DurationTimer t = mTimerPartial;
                        if (t == null) {
                        if (t == null) {
                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL,
                            t = new DurationTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL,
                                    mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase);
                                    mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase);
                            mTimerPartial = t;
                            mTimerPartial = t;
                        }
                        }
                        return t;
                        return t;
                    case WAKE_TYPE_FULL:
                    }
                        t = mTimerFull;
                    case WAKE_TYPE_FULL: {
                        StopwatchTimer t = mTimerFull;
                        if (t == null) {
                        if (t == null) {
                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL,
                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL,
                                    mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
                                    mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
                            mTimerFull = t;
                            mTimerFull = t;
                        }
                        }
                        return t;
                        return t;
                    case WAKE_TYPE_WINDOW:
                    }
                        t = mTimerWindow;
                    case WAKE_TYPE_WINDOW: {
                        StopwatchTimer t = mTimerWindow;
                        if (t == null) {
                        if (t == null) {
                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW,
                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW,
                                    mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
                                    mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
                            mTimerWindow = t;
                            mTimerWindow = t;
                        }
                        }
                        return t;
                        return t;
                    case WAKE_TYPE_DRAW:
                    }
                        t = mTimerDraw;
                    case WAKE_TYPE_DRAW: {
                        StopwatchTimer t = mTimerDraw;
                        if (t == null) {
                        if (t == null) {
                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW,
                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW,
                                    mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
                                    mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
                            mTimerDraw = t;
                            mTimerDraw = t;
                        }
                        }
                        return t;
                        return t;
                    }
                    default:
                    default:
                        throw new IllegalArgumentException("type=" + type);
                        throw new IllegalArgumentException("type=" + type);
                }
                }
+151 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2016 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 android.util.Log;

import junit.framework.TestCase;

import org.mockito.Mockito;

/**
 * Test BatteryStatsImpl.DurationTimer.
 *
 * In these tests, unless otherwise commented, the time increments by
 * 2x + 100, to make the subtraction unlikely to alias to another time.
 */
public class BatteryStatsDurationTimerTest extends TestCase {

    @SmallTest
    public void testStartStop() throws Exception {
        final MockClocks clocks = new MockClocks();

        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());

        final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks, 
                null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);

        // TimeBase running, timer not running: current and max are 0
        timeBase.setRunning(true, /* uptimeUs */ 0, /* realtimeUs */ 100*1000);
        assertFalse(timer.isRunningLocked());
        assertEquals(0, timer.getCurrentDurationMsLocked(300));
        assertEquals(0, timer.getMaxDurationMsLocked(301));

        // Start timer: current and max advance
        timer.startRunningLocked(700);
        assertTrue(timer.isRunningLocked());
        assertEquals(800, timer.getCurrentDurationMsLocked(1500));
        assertEquals(801, timer.getMaxDurationMsLocked(1501));

        // Stop timer: current resets to 0, max remains
        timer.stopRunningLocked(3100);
        assertFalse(timer.isRunningLocked());
        assertEquals(0, timer.getCurrentDurationMsLocked(6300));
        assertEquals(2400, timer.getMaxDurationMsLocked(6301));

        // Start time again, but check with a short time, and make sure max doesn't
        // increment.
        timer.startRunningLocked(12700);
        assertTrue(timer.isRunningLocked());
        assertEquals(100, timer.getCurrentDurationMsLocked(12800));
        assertEquals(2400, timer.getMaxDurationMsLocked(12801));

        // And stop it again, but with a short time, and make sure it doesn't increment.
        timer.stopRunningLocked(12900);
        assertFalse(timer.isRunningLocked());
        assertEquals(0, timer.getCurrentDurationMsLocked(13000));
        assertEquals(2400, timer.getMaxDurationMsLocked(13001));

        // Now start and check that the time doesn't increase if the two times are the same.
        timer.startRunningLocked(27000);
        assertTrue(timer.isRunningLocked());
        assertEquals(0, timer.getCurrentDurationMsLocked(27000));
        assertEquals(2400, timer.getMaxDurationMsLocked(27000));

        // Stop the TimeBase. The values should be frozen.
        timeBase.setRunning(false, /* uptimeUs */ 10, /* realtimeUs */ 55000*1000);
        assertTrue(timer.isRunningLocked());
        assertEquals(28100, timer.getCurrentDurationMsLocked(110100)); // Why 28100 and not 28000?
        assertEquals(28100, timer.getMaxDurationMsLocked(110101));

        // Start the TimeBase. The values should be the old value plus the delta
        // between when the timer restarted and the current time
        timeBase.setRunning(true, /* uptimeUs */ 10, /* realtimeUs */ 220100*1000);
        assertTrue(timer.isRunningLocked());
        assertEquals(28300, timer.getCurrentDurationMsLocked(220300)); // extra 100 from above??
        assertEquals(28301, timer.getMaxDurationMsLocked(220301));
    }

    @SmallTest
    public void testReset() throws Exception {
    }

    @SmallTest
    public void testParceling() throws Exception {
        final MockClocks clocks = new MockClocks();

        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());

        final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks, 
                null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);

        // Start running on battery.
        clocks.realtime = 100;
        clocks.uptime = 10;
        timeBase.setRunning(true, clocks.uptimeMillis()*1000, clocks.elapsedRealtime()*1000);

        timer.startRunningLocked(300);

        // Check that it did start running
        assertEquals(400, timer.getMaxDurationMsLocked(700));
        assertEquals(401, timer.getCurrentDurationMsLocked(701));

        // Write summary
        final Parcel summaryParcel = Parcel.obtain();
        timer.writeSummaryFromParcelLocked(summaryParcel, 1500*1000);
        summaryParcel.setDataPosition(0);

        // Read summary
        final BatteryStatsImpl.DurationTimer summary = new BatteryStatsImpl.DurationTimer(clocks, 
                null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);
        summary.startRunningLocked(3100);
        summary.readSummaryFromParcelLocked(summaryParcel);
        // The new one shouldn't be running, and therefore 0 for current time
        assertFalse(summary.isRunningLocked());
        assertEquals(0, summary.getCurrentDurationMsLocked(6300));
        // The new one should have the max duration that we had when we wrote it
        assertEquals(1200, summary.getMaxDurationMsLocked(6301));

        // Write full
        final Parcel fullParcel = Parcel.obtain();
        timer.writeToParcel(fullParcel, 1500*1000);
        fullParcel.setDataPosition(0);
 
        // Read full - Should be the same as the summary as far as DurationTimer is concerned.
        final BatteryStatsImpl.DurationTimer full = new BatteryStatsImpl.DurationTimer(clocks, 
                null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase, fullParcel);
        // The new one shouldn't be running, and therefore 0 for current time
        assertFalse(full.isRunningLocked());
        assertEquals(0, full.getCurrentDurationMsLocked(6300));
        // The new one should have the max duration that we had when we wrote it
        assertEquals(1200, full.getMaxDurationMsLocked(6301));
    }
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -5,6 +5,7 @@ import org.junit.runners.Suite;


@RunWith(Suite.class)
@RunWith(Suite.class)
@Suite.SuiteClasses({
@Suite.SuiteClasses({
        BatteryStatsDurationTimerTest.class,
        BatteryStatsSamplingTimerTest.class,
        BatteryStatsSamplingTimerTest.class,
        BatteryStatsServTest.class,
        BatteryStatsServTest.class,
        BatteryStatsTimeBaseTest.class,
        BatteryStatsTimeBaseTest.class,