Measured energy for Ambient Display in BatteryUsageStats

Bug: 178140704
Test: atest FrameworksCoreTests:com.android.internal.os.AmbientDisplayPowerCalculatorTest

Change-Id: I1a573c3e380777637b7c0466aa78a4cab4c05887
This commit is contained in:
Dmitri Plotnikov
2021-02-11 16:37:50 -08:00
parent 8093735b62
commit 8c2e375c1f
6 changed files with 74 additions and 28 deletions

View File

@@ -79,6 +79,14 @@ public final class BatteryUsageStatsQuery implements Parcelable {
return mUserIds;
}
/**
* Returns true if the power calculations must be based on the PowerProfile constants,
* even if measured energy data is available.
*/
public boolean shouldForceUsePowerProfileModel() {
return (mFlags & FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0;
}
private BatteryUsageStatsQuery(Parcel in) {
mFlags = in.readInt();
mUserIds = new int[in.readInt()];

View File

@@ -46,14 +46,12 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
final double powerMah = mPowerEstimator.calculatePower(durationMs);
if (powerMah > 0) {
builder.getOrCreateSystemBatteryConsumerBuilder(
SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, durationMs);
}
// TODO(b/178140704): Attribute *measured* total usage for BatteryUsageStats.
final double powerMah = getMeasuredOrEstimatedPower(batteryStats.getScreenDozeEnergy(),
mPowerEstimator, durationMs, query.shouldForceUsePowerProfileModel());
builder.getOrCreateSystemBatteryConsumerBuilder(
SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, durationMs);
}
/**
@@ -66,8 +64,8 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator {
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs, statsType);
final double powerMah = getMeasuredOrEstimatedPower(
batteryStats.getScreenDozeEnergy(), durationMs);
final double powerMah = getMeasuredOrEstimatedPower(batteryStats.getScreenDozeEnergy(),
mPowerEstimator, durationMs, false);
if (powerMah > 0) {
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.AMBIENT_DISPLAY, null, 0);
bs.usagePowerMah = powerMah;
@@ -81,11 +79,4 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator {
return batteryStats.getScreenDozeTime(rawRealtimeUs, statsType) / 1000;
}
private double getMeasuredOrEstimatedPower(long measuredEnergyUJ, long durationMs) {
if (measuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) {
return uJtoMah(measuredEnergyUJ);
} else {
return mPowerEstimator.calculatePower(durationMs);
}
}
}

View File

@@ -112,6 +112,19 @@ public abstract class PowerCalculator {
public void reset() {
}
/**
* Returns either the measured energy converted to mAh or a usage-based estimate.
*/
protected static double getMeasuredOrEstimatedPower(long measuredEnergyUj,
UsageBasedPowerEstimator powerEstimator, long durationMs,
boolean forceUsePowerProfileModel) {
if (measuredEnergyUj != BatteryStats.ENERGY_DATA_UNAVAILABLE
&& !forceUsePowerProfileModel) {
return uJtoMah(measuredEnergyUj);
}
return powerEstimator.calculatePower(durationMs);
}
/**
* Converts charge in mAh to string.
*/

View File

@@ -61,12 +61,10 @@ public class ScreenPowerCalculator extends PowerCalculator {
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final PowerAndDuration totalPowerAndDuration = new PowerAndDuration();
final boolean forceUsePowerProfileModel = (query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0;
final boolean useEnergyData = calculateTotalDurationAndPower(totalPowerAndDuration,
batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED,
forceUsePowerProfileModel);
query.shouldForceUsePowerProfileModel());
builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_SCREEN)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE,

View File

@@ -19,6 +19,7 @@ package com.android.internal.os;
import static com.google.common.truth.Truth.assertThat;
import android.os.BatteryConsumer;
import android.os.BatteryUsageStatsQuery;
import android.os.SystemBatteryConsumer;
import android.view.Display;
@@ -33,18 +34,29 @@ import org.junit.runner.RunWith;
@SmallTest
public class AmbientDisplayPowerCalculatorTest {
private static final double PRECISION = 0.00001;
private static final long MINUTE_IN_MS = 60 * 1000;
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
.setAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY, 360.0);
.setAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY, 10.0);
@Test
public void testTimerBasedModel() {
public void testMeasuredEnergyBasedModel() {
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
stats.noteScreenStateLocked(Display.STATE_ON, 1000, 1000, 1000);
stats.noteScreenStateLocked(Display.STATE_DOZE, 2000, 2000, 2000);
stats.noteScreenStateLocked(Display.STATE_OFF, 3000, 3000, 3000);
stats.updateDisplayEnergyLocked(300_000_000, Display.STATE_ON, 0);
stats.noteScreenStateLocked(Display.STATE_DOZE, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS,
30 * MINUTE_IN_MS);
stats.updateDisplayEnergyLocked(200_000_000, Display.STATE_DOZE,
30 * MINUTE_IN_MS);
stats.noteScreenStateLocked(Display.STATE_OFF, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS,
120 * MINUTE_IN_MS);
stats.updateDisplayEnergyLocked(100_000_000, Display.STATE_OFF,
120 * MINUTE_IN_MS);
AmbientDisplayPowerCalculator calculator =
new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
@@ -55,8 +67,32 @@ public class AmbientDisplayPowerCalculatorTest {
mStatsRule.getSystemBatteryConsumer(
SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY);
assertThat(consumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE))
.isEqualTo(1000);
.isEqualTo(90 * MINUTE_IN_MS);
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
.isWithin(PRECISION).of(0.1);
.isWithin(PRECISION).of(7.5075075);
}
@Test
public void testPowerProfileBasedModel() {
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
stats.noteScreenStateLocked(Display.STATE_DOZE, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS,
30 * MINUTE_IN_MS);
stats.noteScreenStateLocked(Display.STATE_OFF, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS,
120 * MINUTE_IN_MS);
AmbientDisplayPowerCalculator calculator =
new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
calculator);
SystemBatteryConsumer consumer =
mStatsRule.getSystemBatteryConsumer(
SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY);
assertThat(consumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE))
.isEqualTo(90 * MINUTE_IN_MS);
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
.isWithin(PRECISION).of(15.0);
}
}

View File

@@ -48,7 +48,7 @@ public class ScreenPowerCalculatorTest {
.setAveragePower(PowerProfile.POWER_SCREEN_FULL, 48.0);
@Test
public void testEnergyBasedModel() {
public void testMeasuredEnergyBasedModel() {
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
batteryStats.noteScreenStateLocked(Display.STATE_ON, 0, 0, 0);