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

Commit c076e711 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Add stats session end timestamp and duration to BatteryUsageStats

Bug: 187223764
Test: atest FrameworksCoreTests:BatteryStatsTests
Change-Id: Iba97050c067cae7945276798273dd328fe040ef9
parent 15dd7654
Loading
Loading
Loading
Loading
+50 −1
Original line number Original line Diff line number Diff line
@@ -75,8 +75,10 @@ public final class BatteryUsageStats implements Parcelable {
    public static final int AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT = 2;
    public static final int AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT = 2;


    private final int mDischargePercentage;
    private final int mDischargePercentage;
    private final long mStatsStartTimestampMs;
    private final double mBatteryCapacityMah;
    private final double mBatteryCapacityMah;
    private final long mStatsStartTimestampMs;
    private final long mStatsEndTimestampMs;
    private final long mStatsDurationMs;
    private final double mDischargedPowerLowerBound;
    private final double mDischargedPowerLowerBound;
    private final double mDischargedPowerUpperBound;
    private final double mDischargedPowerUpperBound;
    private final long mBatteryTimeRemainingMs;
    private final long mBatteryTimeRemainingMs;
@@ -90,6 +92,12 @@ public final class BatteryUsageStats implements Parcelable {


    private BatteryUsageStats(@NonNull Builder builder) {
    private BatteryUsageStats(@NonNull Builder builder) {
        mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
        mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
        mStatsEndTimestampMs = builder.mStatsEndTimestampMs;
        if (builder.mStatsDurationMs != -1) {
            mStatsDurationMs = builder.mStatsDurationMs;
        } else {
            mStatsDurationMs = mStatsEndTimestampMs - mStatsStartTimestampMs;
        }
        mBatteryCapacityMah = builder.mBatteryCapacityMah;
        mBatteryCapacityMah = builder.mBatteryCapacityMah;
        mDischargePercentage = builder.mDischargePercentage;
        mDischargePercentage = builder.mDischargePercentage;
        mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
        mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
@@ -140,6 +148,24 @@ public final class BatteryUsageStats implements Parcelable {
        return mStatsStartTimestampMs;
        return mStatsStartTimestampMs;
    }
    }


    /**
     * Timestamp (as returned by System.currentTimeMillis()) of when the stats snapshot was taken,
     * in milliseconds.
     */
    public long getStatsEndTimestamp() {
        return mStatsEndTimestampMs;
    }

    /**
     * Returns the duration of the stats session captured by this BatteryUsageStats.
     * In rare cases, statsDuration != statsEndTimestamp - statsStartTimestamp.  This may
     * happen when BatteryUsageStats represents an accumulation of data across multiple
     * non-contiguous sessions.
     */
    public long getStatsDuration() {
        return mStatsDurationMs;
    }

    /**
    /**
     * Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully
     * Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully
     * charged), in mAh
     * charged), in mAh
@@ -229,6 +255,8 @@ public final class BatteryUsageStats implements Parcelable {


    private BatteryUsageStats(@NonNull Parcel source) {
    private BatteryUsageStats(@NonNull Parcel source) {
        mStatsStartTimestampMs = source.readLong();
        mStatsStartTimestampMs = source.readLong();
        mStatsEndTimestampMs = source.readLong();
        mStatsDurationMs = source.readLong();
        mBatteryCapacityMah = source.readDouble();
        mBatteryCapacityMah = source.readDouble();
        mDischargePercentage = source.readInt();
        mDischargePercentage = source.readInt();
        mDischargedPowerLowerBound = source.readDouble();
        mDischargedPowerLowerBound = source.readDouble();
@@ -287,6 +315,8 @@ public final class BatteryUsageStats implements Parcelable {
    @Override
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeLong(mStatsStartTimestampMs);
        dest.writeLong(mStatsStartTimestampMs);
        dest.writeLong(mStatsEndTimestampMs);
        dest.writeLong(mStatsDurationMs);
        dest.writeDouble(mBatteryCapacityMah);
        dest.writeDouble(mBatteryCapacityMah);
        dest.writeInt(mDischargePercentage);
        dest.writeInt(mDischargePercentage);
        dest.writeDouble(mDischargedPowerLowerBound);
        dest.writeDouble(mDischargedPowerLowerBound);
@@ -441,6 +471,8 @@ public final class BatteryUsageStats implements Parcelable {
        private final String[] mCustomPowerComponentNames;
        private final String[] mCustomPowerComponentNames;
        private final boolean mIncludePowerModels;
        private final boolean mIncludePowerModels;
        private long mStatsStartTimestampMs;
        private long mStatsStartTimestampMs;
        private long mStatsEndTimestampMs;
        private long mStatsDurationMs = -1;
        private double mBatteryCapacityMah;
        private double mBatteryCapacityMah;
        private int mDischargePercentage;
        private int mDischargePercentage;
        private double mDischargedPowerLowerBoundMah;
        private double mDischargedPowerLowerBoundMah;
@@ -493,6 +525,23 @@ public final class BatteryUsageStats implements Parcelable {
            return this;
            return this;
        }
        }


        /**
         * Sets the timestamp of when the battery stats snapshot was taken, in milliseconds.
         */
        public Builder setStatsEndTimestamp(long statsEndTimestampMs) {
            mStatsEndTimestampMs = statsEndTimestampMs;
            return this;
        }

        /**
         * Sets the duration of the stats session.  The default value of this field is
         * statsEndTimestamp - statsStartTimestamp.
         */
        public Builder setStatsDuration(long statsDurationMs) {
            mStatsDurationMs = statsDurationMs;
            return this;
        }

        /**
        /**
         * Sets the battery discharge amount since BatteryStats reset as percentage of the full
         * Sets the battery discharge amount since BatteryStats reset as percentage of the full
         * charge.
         * charge.
+29 −15
Original line number Original line Diff line number Diff line
@@ -610,18 +610,32 @@ public class BatteryStatsImpl extends BatteryStats {
    }
    }
    public interface Clocks {
    public interface Clocks {
        public long elapsedRealtime();
        /** Elapsed Realtime, see SystemClock.elapsedRealtime() */
        public long uptimeMillis();
        long elapsedRealtime();
        /** Uptime, see SystemClock.uptimeMillis() */
        long uptimeMillis();
        /** Wall-clock time as per System.currentTimeMillis() */
        long currentTimeMillis();
    }
    }
    public static class SystemClocks implements Clocks {
    public static class SystemClocks implements Clocks {
        @Override
        public long elapsedRealtime() {
        public long elapsedRealtime() {
            return SystemClock.elapsedRealtime();
            return SystemClock.elapsedRealtime();
        }
        }
        @Override
        public long uptimeMillis() {
        public long uptimeMillis() {
            return SystemClock.uptimeMillis();
            return SystemClock.uptimeMillis();
        }
        }
        @Override
        public long currentTimeMillis() {
            return System.currentTimeMillis();
        }
    }
    }
    public interface ExternalStatsSync {
    public interface ExternalStatsSync {
@@ -1163,7 +1177,7 @@ public class BatteryStatsImpl extends BatteryStats {
    public BatteryStatsImpl(Clocks clocks) {
    public BatteryStatsImpl(Clocks clocks) {
        init(clocks);
        init(clocks);
        mStartClockTimeMs = System.currentTimeMillis();
        mStartClockTimeMs = clocks.currentTimeMillis();
        mStatsFile = null;
        mStatsFile = null;
        mCheckinFile = null;
        mCheckinFile = null;
        mDailyFile = null;
        mDailyFile = null;
@@ -3694,7 +3708,7 @@ public class BatteryStatsImpl extends BatteryStats {
        if (dataSize == 0) {
        if (dataSize == 0) {
            // The history is currently empty; we need it to start with a time stamp.
            // The history is currently empty; we need it to start with a time stamp.
            cur.currentTime = System.currentTimeMillis();
            cur.currentTime = mClocks.currentTimeMillis();
            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
            addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_RESET, cur);
        }
        }
        addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
        addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, cur);
@@ -3914,7 +3928,7 @@ public class BatteryStatsImpl extends BatteryStats {
    }
    }
    public void noteCurrentTimeChangedLocked() {
    public void noteCurrentTimeChangedLocked() {
        final long currentTime = System.currentTimeMillis();
        final long currentTime = mClocks.currentTimeMillis();
        final long elapsedRealtime = mClocks.elapsedRealtime();
        final long elapsedRealtime = mClocks.elapsedRealtime();
        final long uptime = mClocks.uptimeMillis();
        final long uptime = mClocks.uptimeMillis();
        noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
        noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime);
@@ -4237,7 +4251,7 @@ public class BatteryStatsImpl extends BatteryStats {
        if (mPretendScreenOff != pretendScreenOff) {
        if (mPretendScreenOff != pretendScreenOff) {
            mPretendScreenOff = pretendScreenOff;
            mPretendScreenOff = pretendScreenOff;
            noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON,
            noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON,
                    mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
                    mClocks.elapsedRealtime(), mClocks.uptimeMillis(), mClocks.currentTimeMillis());
        }
        }
    }
    }
@@ -4827,7 +4841,7 @@ public class BatteryStatsImpl extends BatteryStats {
    @GuardedBy("this")
    @GuardedBy("this")
    public void noteScreenStateLocked(int state) {
    public void noteScreenStateLocked(int state) {
        noteScreenStateLocked(state, mClocks.elapsedRealtime(), mClocks.uptimeMillis(),
        noteScreenStateLocked(state, mClocks.elapsedRealtime(), mClocks.uptimeMillis(),
                System.currentTimeMillis());
                mClocks.currentTimeMillis());
    }
    }
    @GuardedBy("this")
    @GuardedBy("this")
@@ -6972,7 +6986,7 @@ public class BatteryStatsImpl extends BatteryStats {
    }
    }
    @Override public long getStartClockTime() {
    @Override public long getStartClockTime() {
        final long currentTimeMs = System.currentTimeMillis();
        final long currentTimeMs = mClocks.currentTimeMillis();
        if ((currentTimeMs > MILLISECONDS_IN_YEAR
        if ((currentTimeMs > MILLISECONDS_IN_YEAR
                && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
                && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR))
                || (mStartClockTimeMs > currentTimeMs)) {
                || (mStartClockTimeMs > currentTimeMs)) {
@@ -10735,7 +10749,7 @@ public class BatteryStatsImpl extends BatteryStats {
    public void updateDailyDeadlineLocked() {
    public void updateDailyDeadlineLocked() {
        // Get the current time.
        // Get the current time.
        long currentTimeMs = mDailyStartTimeMs = System.currentTimeMillis();
        long currentTimeMs = mDailyStartTimeMs = mClocks.currentTimeMillis();
        Calendar calDeadline = Calendar.getInstance();
        Calendar calDeadline = Calendar.getInstance();
        calDeadline.setTimeInMillis(currentTimeMs);
        calDeadline.setTimeInMillis(currentTimeMs);
@@ -10763,7 +10777,7 @@ public class BatteryStatsImpl extends BatteryStats {
    public void recordDailyStatsLocked() {
    public void recordDailyStatsLocked() {
        DailyItem item = new DailyItem();
        DailyItem item = new DailyItem();
        item.mStartTime = mDailyStartTimeMs;
        item.mStartTime = mDailyStartTimeMs;
        item.mEndTime = System.currentTimeMillis();
        item.mEndTime = mClocks.currentTimeMillis();
        boolean hasData = false;
        boolean hasData = false;
        if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
        if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
            hasData = true;
            hasData = true;
@@ -11128,7 +11142,7 @@ public class BatteryStatsImpl extends BatteryStats {
    }
    }
    void initTimes(long uptimeUs, long realtimeUs) {
    void initTimes(long uptimeUs, long realtimeUs) {
        mStartClockTimeMs = System.currentTimeMillis();
        mStartClockTimeMs = mClocks.currentTimeMillis();
        mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
        mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
        mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
        mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
        mRealtimeUs = 0;
        mRealtimeUs = 0;
@@ -13562,7 +13576,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
    private void startRecordingHistory(final long elapsedRealtimeMs, final long uptimeMs,
            boolean reset) {
            boolean reset) {
        mRecordingHistory = true;
        mRecordingHistory = true;
        mHistoryCur.currentTime = System.currentTimeMillis();
        mHistoryCur.currentTime = mClocks.currentTimeMillis();
        addHistoryBufferLocked(elapsedRealtimeMs,
        addHistoryBufferLocked(elapsedRealtimeMs,
                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
                mHistoryCur);
                mHistoryCur);
@@ -13604,7 +13618,7 @@ public class BatteryStatsImpl extends BatteryStats {
            final int chargeFullUah, final long chargeTimeToFullSeconds) {
            final int chargeFullUah, final long chargeTimeToFullSeconds) {
        setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
        setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
                chargeFullUah, chargeTimeToFullSeconds,
                chargeFullUah, chargeTimeToFullSeconds,
                mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
                mClocks.elapsedRealtime(), mClocks.uptimeMillis(), mClocks.currentTimeMillis());
    }
    }
    public void setBatteryStateLocked(final int status, final int health, final int plugType,
    public void setBatteryStateLocked(final int status, final int health, final int plugType,
@@ -14389,7 +14403,7 @@ public class BatteryStatsImpl extends BatteryStats {
    }
    }
    public void shutdownLocked() {
    public void shutdownLocked() {
        recordShutdownLocked(System.currentTimeMillis(), mClocks.elapsedRealtime());
        recordShutdownLocked(mClocks.currentTimeMillis(), mClocks.elapsedRealtime());
        writeSyncLocked();
        writeSyncLocked();
        mShuttingDown = true;
        mShuttingDown = true;
    }
    }
@@ -14938,7 +14952,7 @@ public class BatteryStatsImpl extends BatteryStats {
            startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
            startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
        }
        }
        recordDailyStatsIfNeededLocked(false, System.currentTimeMillis());
        recordDailyStatsIfNeededLocked(false, mClocks.currentTimeMillis());
    }
    }
    public int describeContents() {
    public int describeContents() {
+18 −2
Original line number Original line Diff line number Diff line
@@ -108,9 +108,9 @@ public class BatteryUsageStatsProvider {
        ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
        ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
        synchronized (mStats) {
        synchronized (mStats) {
            mStats.prepareForDumpLocked();
            mStats.prepareForDumpLocked();

            final long currentTimeMillis = currentTimeMillis();
            for (int i = 0; i < queries.size(); i++) {
            for (int i = 0; i < queries.size(); i++) {
                results.add(getBatteryUsageStats(queries.get(i)));
                results.add(getBatteryUsageStats(queries.get(i), currentTimeMillis));
            }
            }
        }
        }
        return results;
        return results;
@@ -121,6 +121,11 @@ public class BatteryUsageStatsProvider {
     */
     */
    @VisibleForTesting
    @VisibleForTesting
    public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
    public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
        return getBatteryUsageStats(query, currentTimeMillis());
    }

    private BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query,
            long currentTimeMs) {
        final long realtimeUs = elapsedRealtime() * 1000;
        final long realtimeUs = elapsedRealtime() * 1000;
        final long uptimeUs = uptimeMillis() * 1000;
        final long uptimeUs = uptimeMillis() * 1000;


@@ -129,7 +134,10 @@ public class BatteryUsageStatsProvider {


        final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
        final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
                mStats.getCustomEnergyConsumerNames(), includePowerModels);
                mStats.getCustomEnergyConsumerNames(), includePowerModels);
        // TODO(b/188068523): use a monotonic clock to ensure resilience of order and duration
        // of stats sessions to wall-clock adjustments
        batteryUsageStatsBuilder.setStatsStartTimestamp(mStats.getStartClockTime());
        batteryUsageStatsBuilder.setStatsStartTimestamp(mStats.getStartClockTime());
        batteryUsageStatsBuilder.setStatsEndTimestamp(currentTimeMs);


        SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
        SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
        for (int i = uidStats.size() - 1; i >= 0; i--) {
        for (int i = uidStats.size() - 1; i >= 0; i--) {
@@ -217,4 +225,12 @@ public class BatteryUsageStatsProvider {
            return SystemClock.uptimeMillis();
            return SystemClock.uptimeMillis();
        }
        }
    }
    }

    private long currentTimeMillis() {
        if (mStats instanceof BatteryStatsImpl) {
            return ((BatteryStatsImpl) mStats).mClocks.currentTimeMillis();
        } else {
            return System.currentTimeMillis();
        }
    }
}
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -45,7 +45,7 @@ public class BatteryUsageStatsProviderTest {
    private static final long MINUTE_IN_MS = 60 * 1000;
    private static final long MINUTE_IN_MS = 60 * 1000;


    @Rule
    @Rule
    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345);


    @Test
    @Test
    public void test_getBatteryUsageStats() {
    public void test_getBatteryUsageStats() {
@@ -62,6 +62,8 @@ public class BatteryUsageStatsProviderTest {
        batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
        batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                40 * MINUTE_IN_MS, 40 * MINUTE_IN_MS);
                40 * MINUTE_IN_MS, 40 * MINUTE_IN_MS);


        mStatsRule.setCurrentTime(54321);

        Context context = InstrumentationRegistry.getContext();
        Context context = InstrumentationRegistry.getContext();
        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
        BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);


@@ -75,6 +77,9 @@ public class BatteryUsageStatsProviderTest {
                .isEqualTo(20 * MINUTE_IN_MS);
                .isEqualTo(20 * MINUTE_IN_MS);
        assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
        assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
                .isEqualTo(10 * MINUTE_IN_MS);
                .isEqualTo(10 * MINUTE_IN_MS);

        assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(12345);
        assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(54321);
    }
    }


    @Test
    @Test
+9 −0
Original line number Original line Diff line number Diff line
@@ -57,8 +57,13 @@ public class BatteryUsageStatsRule implements TestRule {
    private boolean mScreenOn;
    private boolean mScreenOn;


    public BatteryUsageStatsRule() {
    public BatteryUsageStatsRule() {
        this(0);
    }

    public BatteryUsageStatsRule(long currentTime) {
        Context context = InstrumentationRegistry.getContext();
        Context context = InstrumentationRegistry.getContext();
        mPowerProfile = spy(new PowerProfile(context, true /* forTest */));
        mPowerProfile = spy(new PowerProfile(context, true /* forTest */));
        mMockClocks.currentTime = currentTime;
        mBatteryStats = new MockBatteryStatsImpl(mMockClocks);
        mBatteryStats = new MockBatteryStatsImpl(mMockClocks);
        mBatteryStats.setPowerProfile(mPowerProfile);
        mBatteryStats.setPowerProfile(mPowerProfile);
    }
    }
@@ -164,6 +169,10 @@ public class BatteryUsageStatsRule implements TestRule {
        mMockClocks.uptime = uptimeMs;
        mMockClocks.uptime = uptimeMs;
    }
    }


    public void setCurrentTime(long currentTimeMs) {
        mMockClocks.currentTime = currentTimeMs;
    }

    BatteryUsageStats apply(PowerCalculator... calculators) {
    BatteryUsageStats apply(PowerCalculator... calculators) {
        return apply(new BatteryUsageStatsQuery.Builder().includePowerModels().build(),
        return apply(new BatteryUsageStatsQuery.Builder().includePowerModels().build(),
                calculators);
                calculators);
Loading