From cf2929ffe94c4c8c9ff7848f8e30efcc23030d38 Mon Sep 17 00:00:00 2001 From: Dmitri Plotnikov Date: Thu, 4 Mar 2021 17:29:38 -0800 Subject: Add batteryTimeRemaining and chargeTimeRemaining to BatteryUsageStats Bug: 158137862 Test: atest FrameworksCoreTests:com.android.internal.os.BatteryChargeCalculatorTest Change-Id: I247a593de242a2864eef16b7c9ea956209f60cbe --- core/java/android/os/BatteryUsageStats.java | 49 +++++++++++++ .../internal/os/BatteryChargeCalculator.java | 62 +++++++++++++++++ .../internal/os/BatteryUsageStatsProvider.java | 2 +- .../internal/os/DischargedPowerCalculator.java | 52 -------------- .../internal/os/BatteryChargeCalculatorTest.java | 80 ++++++++++++++++++++++ .../com/android/internal/os/BatteryStatsTests.java | 2 +- .../internal/os/DischargedPowerCalculatorTest.java | 66 ------------------ 7 files changed, 193 insertions(+), 120 deletions(-) create mode 100644 core/java/com/android/internal/os/BatteryChargeCalculator.java delete mode 100644 core/java/com/android/internal/os/DischargedPowerCalculator.java create mode 100644 core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java delete mode 100644 core/tests/coretests/src/com/android/internal/os/DischargedPowerCalculatorTest.java diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index de7b88575e98..f12eb8853c55 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -37,6 +37,8 @@ public final class BatteryUsageStats implements Parcelable { private final long mStatsStartRealtimeMs; private final double mDischargedPowerLowerBound; private final double mDischargedPowerUpperBound; + private final long mBatteryTimeRemainingMs; + private final long mChargeTimeRemainingMs; private final ArrayList mUidBatteryConsumers; private final ArrayList mSystemBatteryConsumers; private final ArrayList mUserBatteryConsumers; @@ -50,6 +52,8 @@ public final class BatteryUsageStats implements Parcelable { mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah; mHistoryBuffer = builder.mHistoryBuffer; mHistoryTagPool = builder.mHistoryTagPool; + mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs; + mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs; double totalPower = 0; @@ -109,6 +113,25 @@ public final class BatteryUsageStats implements Parcelable { return Range.create(mDischargedPowerLowerBound, mDischargedPowerUpperBound); } + /** + * 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 + * enough current data to make a decision, or the battery is currently + * charging. + */ + public long getBatteryTimeRemainingMs() { + return mBatteryTimeRemainingMs; + } + + /** + * Returns an approximation for how much time (in milliseconds) remains until the battery + * is fully charged. Returns -1 if no time can be computed: either there is not + * enough current data to make a decision, or the battery is currently discharging. + */ + public long getChargeTimeRemainingMs() { + return mChargeTimeRemainingMs; + } + /** * Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully * charged), in mAh @@ -156,6 +179,8 @@ public final class BatteryUsageStats implements Parcelable { mDischargePercentage = source.readInt(); mDischargedPowerLowerBound = source.readDouble(); mDischargedPowerUpperBound = source.readDouble(); + mBatteryTimeRemainingMs = source.readLong(); + mChargeTimeRemainingMs = source.readLong(); mUidBatteryConsumers = new ArrayList<>(); source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader()); mSystemBatteryConsumers = new ArrayList<>(); @@ -194,6 +219,8 @@ public final class BatteryUsageStats implements Parcelable { dest.writeInt(mDischargePercentage); dest.writeDouble(mDischargedPowerLowerBound); dest.writeDouble(mDischargedPowerUpperBound); + dest.writeLong(mBatteryTimeRemainingMs); + dest.writeLong(mChargeTimeRemainingMs); dest.writeParcelableList(mUidBatteryConsumers, flags); dest.writeParcelableList(mSystemBatteryConsumers, flags); dest.writeParcelableList(mUserBatteryConsumers, flags); @@ -237,6 +264,8 @@ public final class BatteryUsageStats implements Parcelable { private int mDischargePercentage; private double mDischargedPowerLowerBoundMah; private double mDischargedPowerUpperBoundMah; + private long mBatteryTimeRemainingMs = -1; + private long mChargeTimeRemainingMs = -1; private final SparseArray mUidBatteryConsumerBuilders = new SparseArray<>(); private final SparseArray mSystemBatteryConsumerBuilders = @@ -288,6 +317,26 @@ public final class BatteryUsageStats implements Parcelable { return this; } + /** + * Sets an approximation for how much time (in milliseconds) remains until the battery + * is fully discharged. + */ + @NonNull + public Builder setBatteryTimeRemainingMs(long batteryTimeRemainingMs) { + mBatteryTimeRemainingMs = batteryTimeRemainingMs; + return this; + } + + /** + * Sets an approximation for how much time (in milliseconds) remains until the battery + * is fully charged. + */ + @NonNull + public Builder setChargeTimeRemainingMs(long chargeTimeRemainingMs) { + mChargeTimeRemainingMs = chargeTimeRemainingMs; + return this; + } + /** * Sets the parceled recent history. */ diff --git a/core/java/com/android/internal/os/BatteryChargeCalculator.java b/core/java/com/android/internal/os/BatteryChargeCalculator.java new file mode 100644 index 000000000000..dc72f3267390 --- /dev/null +++ b/core/java/com/android/internal/os/BatteryChargeCalculator.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 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.BatteryUsageStats; +import android.os.BatteryUsageStatsQuery; +import android.os.UserHandle; +import android.util.SparseArray; + +import java.util.List; + +/** + * Estimates the battery discharge amounts. + */ +public class BatteryChargeCalculator extends PowerCalculator { + private final double mBatteryCapacity; + + public BatteryChargeCalculator(PowerProfile powerProfile) { + mBatteryCapacity = powerProfile.getBatteryCapacity(); + } + + @Override + public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, + long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { + builder.setDischargePercentage( + batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)) + .setDischargedPowerRange( + batteryStats.getLowDischargeAmountSinceCharge() * mBatteryCapacity / 100, + batteryStats.getHighDischargeAmountSinceCharge() * mBatteryCapacity / 100); + + final long batteryTimeRemainingMs = batteryStats.computeBatteryTimeRemaining(rawRealtimeUs); + if (batteryTimeRemainingMs != -1) { + builder.setBatteryTimeRemainingMs(batteryTimeRemainingMs / 1000); + } + + final long chargeTimeRemainingMs = batteryStats.computeChargeTimeRemaining(rawRealtimeUs); + if (chargeTimeRemainingMs != -1) { + builder.setChargeTimeRemainingMs(chargeTimeRemainingMs / 1000); + } + } + + @Override + public void calculate(List sippers, BatteryStats batteryStats, + long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray asUsers) { + // Not implemented. The computation is done by BatteryStatsHelper + } +} diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index 15b584d1fd06..619cd8e2fc27 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -55,7 +55,7 @@ public class BatteryUsageStatsProvider { mPowerCalculators = new ArrayList<>(); // Power calculators are applied in the order of registration - mPowerCalculators.add(new DischargedPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new BatteryChargeCalculator(mPowerProfile)); mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile)); mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile)); mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile)); diff --git a/core/java/com/android/internal/os/DischargedPowerCalculator.java b/core/java/com/android/internal/os/DischargedPowerCalculator.java deleted file mode 100644 index e94020cc4f18..000000000000 --- a/core/java/com/android/internal/os/DischargedPowerCalculator.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2021 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.BatteryUsageStats; -import android.os.BatteryUsageStatsQuery; -import android.os.UserHandle; -import android.util.SparseArray; - -import java.util.List; - -/** - * Estimates the battery discharge amounts. - */ -public class DischargedPowerCalculator extends PowerCalculator { - private final double mBatteryCapacity; - - public DischargedPowerCalculator(PowerProfile powerProfile) { - mBatteryCapacity = powerProfile.getBatteryCapacity(); - } - - @Override - public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, - long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { - builder.setDischargePercentage( - batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)) - .setDischargedPowerRange( - batteryStats.getLowDischargeAmountSinceCharge() * mBatteryCapacity / 100, - batteryStats.getHighDischargeAmountSinceCharge() * mBatteryCapacity / 100); - } - - @Override - public void calculate(List sippers, BatteryStats batteryStats, - long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray asUsers) { - // Not implemented. The computation is done by BatteryStatsHelper - } -} diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java new file mode 100644 index 000000000000..cf126c62dac7 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/BatteryChargeCalculatorTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2021 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 static com.google.common.truth.Truth.assertThat; + +import android.os.BatteryManager; +import android.os.BatteryUsageStats; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class BatteryChargeCalculatorTest { + private static final double PRECISION = 0.00001; + + @Rule + public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() + .setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 4000.0); + + @Test + public void testDischargeTotals() { + BatteryChargeCalculator calculator = + new BatteryChargeCalculator(mStatsRule.getPowerProfile()); + + final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); + + mStatsRule.setTime(1000, 1000); + batteryStats.resetAllStatsCmdLocked(); + batteryStats.setNoAutoReset(true); + batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100, + /* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, + 1_000_000, 1_000_000, 1_000_000); + batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100, + /* plugType */ 0, 85, 72, 3700, 3_000_000, 4_000_000, 0, + 1_500_000, 1_500_000, 1_500_000); + batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100, + /* plugType */ 0, 80, 72, 3700, 2_400_000, 4_000_000, 0, + 2_000_000, 2_000_000, 2_000_000); + + BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator); + + assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(10); + assertThat(batteryUsageStats.getDischargedPowerRange().getLower()) + .isWithin(PRECISION).of(360.0); + assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()) + .isWithin(PRECISION).of(400.0); + assertThat(batteryUsageStats.getBatteryTimeRemainingMs()).isEqualTo(8_000_000); + assertThat(batteryUsageStats.getChargeTimeRemainingMs()).isEqualTo(-1); + + // Plug in + batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_CHARGING, 100, + BatteryManager.BATTERY_PLUGGED_USB, 80, 72, 3700, 2_400_000, 4_000_000, 100, + 4_000_000, 4_000_000, 4_000_000); + + batteryUsageStats = mStatsRule.apply(calculator); + + assertThat(batteryUsageStats.getChargeTimeRemainingMs()).isEqualTo(100_000); + } +} diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java index 74c37ada2054..ee472880b79f 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java @@ -23,6 +23,7 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ AmbientDisplayPowerCalculatorTest.class, AudioPowerCalculatorTest.class, + BatteryChargeCalculatorTest.class, BatteryStatsCpuTimesTest.class, BatteryStatsBackgroundStatsTest.class, BatteryStatsBinderCallStatsTest.class, @@ -49,7 +50,6 @@ import org.junit.runners.Suite; CameraPowerCalculatorTest.class, CpuPowerCalculatorTest.class, CustomMeasuredPowerCalculatorTest.class, - DischargedPowerCalculatorTest.class, FlashlightPowerCalculatorTest.class, GnssPowerCalculatorTest.class, IdlePowerCalculatorTest.class, diff --git a/core/tests/coretests/src/com/android/internal/os/DischargedPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/DischargedPowerCalculatorTest.java deleted file mode 100644 index bec3d1644e81..000000000000 --- a/core/tests/coretests/src/com/android/internal/os/DischargedPowerCalculatorTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2021 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 static com.google.common.truth.Truth.assertThat; - -import android.os.BatteryManager; -import android.os.BatteryUsageStats; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class DischargedPowerCalculatorTest { - private static final double PRECISION = 0.00001; - - @Rule - public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() - .setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 4000.0); - - @Test - public void testDischargeTotals() { - final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); - - mStatsRule.setTime(1000, 1000); - batteryStats.resetAllStatsCmdLocked(); - batteryStats.setNoAutoReset(true); - batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100, - /* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, 1_000_000, - 1_000_000, 1_000_000); - batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100, - /* plugType */ 0, 80, 72, 3700, 2_400_000, 4_000_000, 0, 2_000_000, - 2_000_000, 2_000_000); - - DischargedPowerCalculator calculator = - new DischargedPowerCalculator(mStatsRule.getPowerProfile()); - - final BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator); - - assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(10); - assertThat(batteryUsageStats.getDischargedPowerRange().getLower()) - .isWithin(PRECISION).of(360.0); - assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()) - .isWithin(PRECISION).of(400.0); - } -} -- cgit v1.2.3-59-g8ed1b