From 5f9c679caf00cea17c76788f22cb8e4a198f162d Mon Sep 17 00:00:00 2001 From: Dmitri Plotnikov Date: Fri, 21 Jan 2022 15:13:14 -0800 Subject: [PATCH] Add BatteryUsageStats.getDischargeDurationMs This method returns the total amount of time the battery was discharging during the current battery session. Also, fixing time units used in BatteryStats tests: they are supposed to be microseconds, not milliseconds. Bug: 214407774 Test: atest FrameworksCoreTests:BatteryChargeCalculatorTest Change-Id: I5b64a6bd8a577b558b90cb60a1db8c3774121921 --- core/java/android/os/BatteryUsageStats.java | 28 +++++++++++++++++++ .../internal/os/BatteryChargeCalculator.java | 3 +- core/proto/android/os/batteryusagestats.proto | 5 +++- .../os/BatteryUsageStatsPulledTest.java | 2 ++ .../os/BatteryChargeCalculatorTest.java | 3 ++ .../internal/os/BatteryUsageStatsRule.java | 4 +-- .../os/BatteryUsageStatsStoreTest.java | 7 +++++ .../internal/os/BatteryUsageStatsTest.java | 9 ++++-- .../internal/os/IdlePowerCalculatorTest.java | 2 +- .../os/MobileRadioPowerCalculatorTest.java | 4 +-- .../os/WakelockPowerCalculatorTest.java | 2 +- 11 files changed, 58 insertions(+), 11 deletions(-) diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index abe5f81088b12..d41a5fe084489 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -109,6 +109,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { static final String XML_ATTR_DISCHARGE_PERCENT = "discharge_pct"; static final String XML_ATTR_DISCHARGE_LOWER = "discharge_lower"; static final String XML_ATTR_DISCHARGE_UPPER = "discharge_upper"; + static final String XML_ATTR_DISCHARGE_DURATION = "discharge_duration"; static final String XML_ATTR_BATTERY_REMAINING = "battery_remaining"; static final String XML_ATTR_CHARGE_REMAINING = "charge_remaining"; static final String XML_ATTR_HIGHEST_DRAIN_PACKAGE = "highest_drain_package"; @@ -127,6 +128,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { private final long mStatsDurationMs; private final double mDischargedPowerLowerBound; private final double mDischargedPowerUpperBound; + private final long mDischargeDurationMs; private final long mBatteryTimeRemainingMs; private final long mChargeTimeRemainingMs; private final String[] mCustomPowerComponentNames; @@ -146,6 +148,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { mDischargePercentage = builder.mDischargePercentage; mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah; mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah; + mDischargeDurationMs = builder.mDischargeDurationMs; mBatteryStatsHistory = builder.mBatteryStatsHistory; mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs; mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs; @@ -245,6 +248,13 @@ public final class BatteryUsageStats implements Parcelable, Closeable { return Range.create(mDischargedPowerLowerBound, mDischargedPowerUpperBound); } + /** + * Returns the total amount of time the battery was discharging. + */ + public long getDischargeDurationMs() { + return mDischargeDurationMs; + } + /** * Returns an approximation for how much run time (in milliseconds) is remaining on * the battery. Returns -1 if no time can be computed: either there is not @@ -321,6 +331,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { mDischargePercentage = source.readInt(); mDischargedPowerLowerBound = source.readDouble(); mDischargedPowerUpperBound = source.readDouble(); + mDischargeDurationMs = source.readLong(); mBatteryTimeRemainingMs = source.readLong(); mChargeTimeRemainingMs = source.readLong(); mCustomPowerComponentNames = source.readStringArray(); @@ -378,6 +389,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { dest.writeInt(mDischargePercentage); dest.writeDouble(mDischargedPowerLowerBound); dest.writeDouble(mDischargedPowerUpperBound); + dest.writeLong(mDischargeDurationMs); dest.writeLong(mBatteryTimeRemainingMs); dest.writeLong(mChargeTimeRemainingMs); dest.writeStringArray(mCustomPowerComponentNames); @@ -447,6 +459,8 @@ public final class BatteryUsageStats implements Parcelable, Closeable { proto.write(BatteryUsageStatsAtomsProto.SESSION_DURATION_MILLIS, getStatsDuration()); proto.write(BatteryUsageStatsAtomsProto.SESSION_DISCHARGE_PERCENTAGE, getDischargePercentage()); + proto.write(BatteryUsageStatsAtomsProto.DISCHARGE_DURATION_MILLIS, + getDischargeDurationMs()); deviceBatteryConsumer.writeStatsProto(proto, BatteryUsageStatsAtomsProto.DEVICE_BATTERY_CONSUMER); writeUidBatteryConsumersProto(proto, maxRawSize); @@ -638,6 +652,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { serializer.attributeInt(null, XML_ATTR_DISCHARGE_PERCENT, mDischargePercentage); serializer.attributeDouble(null, XML_ATTR_DISCHARGE_LOWER, mDischargedPowerLowerBound); serializer.attributeDouble(null, XML_ATTR_DISCHARGE_UPPER, mDischargedPowerUpperBound); + serializer.attributeLong(null, XML_ATTR_DISCHARGE_DURATION, mDischargeDurationMs); serializer.attributeLong(null, XML_ATTR_BATTERY_REMAINING, mBatteryTimeRemainingMs); serializer.attributeLong(null, XML_ATTR_CHARGE_REMAINING, mChargeTimeRemainingMs); @@ -693,6 +708,8 @@ public final class BatteryUsageStats implements Parcelable, Closeable { builder.setDischargedPowerRange( parser.getAttributeDouble(null, XML_ATTR_DISCHARGE_LOWER), parser.getAttributeDouble(null, XML_ATTR_DISCHARGE_UPPER)); + builder.setDischargeDurationMs( + parser.getAttributeLong(null, XML_ATTR_DISCHARGE_DURATION)); builder.setBatteryTimeRemainingMs( parser.getAttributeLong(null, XML_ATTR_BATTERY_REMAINING)); builder.setChargeTimeRemainingMs( @@ -759,6 +776,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { private int mDischargePercentage; private double mDischargedPowerLowerBoundMah; private double mDischargedPowerUpperBoundMah; + private long mDischargeDurationMs; private long mBatteryTimeRemainingMs = -1; private long mChargeTimeRemainingMs = -1; private final AggregateBatteryConsumer.Builder[] mAggregateBatteryConsumersBuilders = @@ -868,6 +886,15 @@ public final class BatteryUsageStats implements Parcelable, Closeable { return this; } + /** + * Sets the total battery discharge time, in milliseconds. + */ + @NonNull + public Builder setDischargeDurationMs(long durationMs) { + mDischargeDurationMs = durationMs; + return this; + } + /** * Sets an approximation for how much time (in milliseconds) remains until the battery * is fully discharged. @@ -994,6 +1021,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { mDischargedPowerLowerBoundMah += stats.mDischargedPowerLowerBound; mDischargedPowerUpperBoundMah += stats.mDischargedPowerUpperBound; mDischargePercentage += stats.mDischargePercentage; + mDischargeDurationMs += stats.mDischargeDurationMs; mStatsDurationMs = getStatsDuration() + stats.getStatsDuration(); diff --git a/core/java/com/android/internal/os/BatteryChargeCalculator.java b/core/java/com/android/internal/os/BatteryChargeCalculator.java index 81785298f8282..0aade8fac53db 100644 --- a/core/java/com/android/internal/os/BatteryChargeCalculator.java +++ b/core/java/com/android/internal/os/BatteryChargeCalculator.java @@ -51,7 +51,8 @@ public class BatteryChargeCalculator extends PowerCalculator { builder.setDischargePercentage( batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)) .setDischargedPowerRange(dischargedPowerLowerBoundMah, - dischargedPowerUpperBoundMah); + dischargedPowerUpperBoundMah) + .setDischargeDurationMs(batteryStats.getBatteryRealtime(rawRealtimeUs) / 1000); final long batteryTimeRemainingMs = batteryStats.computeBatteryTimeRemaining(rawRealtimeUs); if (batteryTimeRemainingMs != -1) { diff --git a/core/proto/android/os/batteryusagestats.proto b/core/proto/android/os/batteryusagestats.proto index c0a9f0339d9e8..cc90e05de7448 100644 --- a/core/proto/android/os/batteryusagestats.proto +++ b/core/proto/android/os/batteryusagestats.proto @@ -98,4 +98,7 @@ message BatteryUsageStatsAtomsProto { // Sum of all discharge percentage point drops during the reported session. optional int32 session_discharge_percentage = 6; -} \ No newline at end of file + + // Total amount of time battery was discharging during the reported session + optional int64 discharge_duration_millis = 7; +} diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java index e230a54e261f9..23b12cf3ea4b9 100644 --- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java +++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java @@ -68,6 +68,7 @@ public class BatteryUsageStatsPulledTest { bus.getStatsEndTimestamp() - bus.getStatsStartTimestamp(), proto.sessionDurationMillis); assertEquals(bus.getDischargePercentage(), proto.sessionDischargePercentage); + assertEquals(bus.getDischargeDurationMs(), proto.dischargeDurationMillis); assertEquals(3, proto.deviceBatteryConsumer.powerComponents.length); // Only 3 are non-empty assertSameBatteryConsumer("For deviceBatteryConsumer", @@ -215,6 +216,7 @@ public class BatteryUsageStatsPulledTest { /* includeProcessStats */true) .setDischargePercentage(20) .setDischargedPowerRange(1000, 2000) + .setDischargeDurationMs(1234) .setStatsStartTimestamp(1000); final UidBatteryConsumer.Builder uidBuilder = builder.getOrCreateUidBatteryConsumerBuilder( batteryStatsUid0) diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java index 6457e3f96d1c1..96d6a7e84ee20 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java @@ -54,6 +54,7 @@ public class BatteryChargeCalculatorTest { /* plugType */ 0, 80, 72, 3700, 2_400_000, 4_000_000, 0, 2_000_000, 2_000_000, 2_000_000); + mStatsRule.setTime(5_000_000, 5_000_000); BatteryChargeCalculator calculator = new BatteryChargeCalculator(); BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator); @@ -64,6 +65,8 @@ public class BatteryChargeCalculatorTest { .isWithin(PRECISION).of(360.0); assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()) .isWithin(PRECISION).of(400.0); + // 5_000_000 (current time) - 1_000_000 (started discharging) + assertThat(batteryUsageStats.getDischargeDurationMs()).isEqualTo(4_000_000); assertThat(batteryUsageStats.getBatteryTimeRemainingMs()).isEqualTo(8_000_000); assertThat(batteryUsageStats.getChargeTimeRemainingMs()).isEqualTo(-1); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java index b3056e222477e..4f29863a7b0d4 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java @@ -212,8 +212,8 @@ public class BatteryUsageStatsRule implements TestRule { } for (PowerCalculator calculator : calculators) { - calculator.calculate(builder, mBatteryStats, mMockClock.realtime, mMockClock.uptime, - query); + calculator.calculate(builder, mBatteryStats, mMockClock.realtime * 1000, + mMockClock.uptime * 1000, query); } mBatteryUsageStats = builder.build(); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java index 51f20f380475e..21f6e7c82d7fb 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsStoreTest.java @@ -44,6 +44,7 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; @RunWith(AndroidJUnit4.class) +@SuppressWarnings("GuardedBy") public class BatteryUsageStatsStoreTest { private static final long MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES = 2 * 1024; @@ -76,8 +77,13 @@ public class BatteryUsageStatsStoreTest { @Test public void testStoreSnapshot() { mMockClock.currentTime = 1_600_000; + mMockClock.realtime = 1000; + mMockClock.uptime = 1000; prepareBatteryStats(); + + mMockClock.realtime = 1_000_000; + mMockClock.uptime = 1_000_000; mBatteryStats.resetAllStatsCmdLocked(); final long[] timestamps = mBatteryUsageStatsStore.listBatteryUsageStatsTimestamps(); @@ -90,6 +96,7 @@ public class BatteryUsageStatsStoreTest { assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(1_600_000); assertThat(batteryUsageStats.getBatteryCapacity()).isEqualTo(4000); assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(5); + assertThat(batteryUsageStats.getDischargeDurationMs()).isEqualTo(1_000_000 - 1_000); assertThat(batteryUsageStats.getAggregateBatteryConsumer( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE).getConsumedPower()) .isEqualTo(600); // (3_600_000 - 3_000_000) / 1000 diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java index 8cc4c348111c5..5adc9bdf0d008 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java @@ -183,7 +183,7 @@ public class BatteryUsageStatsTest { .add(stats2) .build(); - assertBatteryUsageStats(sum, 42345, 50, 2234, 4345, 1000, 5000, 5000); + assertBatteryUsageStats(sum, 42345, 50, 2234, 4345, 1234, 1000, 5000, 5000); final List uidBatteryConsumers = sum.getUidBatteryConsumers(); @@ -259,6 +259,7 @@ public class BatteryUsageStatsTest { .setBatteryCapacity(4000) .setDischargePercentage(20) .setDischargedPowerRange(1000, 2000) + .setDischargeDurationMs(1234) .setStatsStartTimestamp(1000) .setStatsEndTimestamp(3000); @@ -420,7 +421,7 @@ public class BatteryUsageStatsTest { public void assertBatteryUsageStats1(BatteryUsageStats batteryUsageStats, boolean includesUserBatteryConsumers) { - assertBatteryUsageStats(batteryUsageStats, 30000, 20, 1000, 2000, 1000, 3000, 2000); + assertBatteryUsageStats(batteryUsageStats, 30000, 20, 1000, 2000, 1234, 1000, 3000, 2000); final List uidBatteryConsumers = batteryUsageStats.getUidBatteryConsumers(); @@ -463,13 +464,15 @@ public class BatteryUsageStatsTest { private void assertBatteryUsageStats(BatteryUsageStats batteryUsageStats, int consumedPower, int dischargePercentage, int dischagePowerLower, int dischargePowerUpper, - int statsStartTimestamp, int statsEndTimestamp, int statsDuration) { + int dischargeDuration, int statsStartTimestamp, int statsEndTimestamp, + int statsDuration) { assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(consumedPower); assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(dischargePercentage); assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo( dischagePowerLower); assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo( dischargePowerUpper); + assertThat(batteryUsageStats.getDischargeDurationMs()).isEqualTo(dischargeDuration); assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(statsStartTimestamp); assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(statsEndTimestamp); assertThat(batteryUsageStats.getStatsDuration()).isEqualTo(statsDuration); diff --git a/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java index 67b1e516d7046..2b28031be6c57 100644 --- a/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/IdlePowerCalculatorTest.java @@ -39,7 +39,7 @@ public class IdlePowerCalculatorTest { @Test public void testTimerBasedModel() { - mStatsRule.setTime(3_000_000, 2_000_000); + mStatsRule.setTime(3_000, 2_000); IdlePowerCalculator calculator = new IdlePowerCalculator(mStatsRule.getPowerProfile()); diff --git a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java index ce2f76457422e..c20293b2443ba 100644 --- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java @@ -102,7 +102,7 @@ public class MobileRadioPowerCalculatorTest { stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000, mNetworkStatsManager); - mStatsRule.setTime(12_000_000, 12_000_000); + mStatsRule.setTime(12_000, 12_000); MobileRadioPowerCalculator calculator = new MobileRadioPowerCalculator(mStatsRule.getPowerProfile()); @@ -248,7 +248,7 @@ public class MobileRadioPowerCalculatorTest { new int[]{100, 200, 300, 400, 500}, 600); stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000, mNetworkStatsManager); - mStatsRule.setTime(12_000_000, 12_000_000); + mStatsRule.setTime(12_000, 12_000); MobileRadioPowerCalculator calculator = new MobileRadioPowerCalculator(mStatsRule.getPowerProfile()); diff --git a/core/tests/coretests/src/com/android/internal/os/WakelockPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WakelockPowerCalculatorTest.java index a7f4fb303b3da..f3456af3feb46 100644 --- a/core/tests/coretests/src/com/android/internal/os/WakelockPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/WakelockPowerCalculatorTest.java @@ -54,7 +54,7 @@ public class WakelockPowerCalculatorTest { batteryStats.noteStopWakeFromSourceLocked(new WorkSource(APP_UID), APP_PID, "awake", "", BatteryStats.WAKE_TYPE_PARTIAL, 2000, 2000); - mStatsRule.setTime(10_000_000, 6_000_000); + mStatsRule.setTime(10_000, 6_000); WakelockPowerCalculator calculator = new WakelockPowerCalculator(mStatsRule.getPowerProfile());