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

Commit 91467df8 authored by Milo Sredkov's avatar Milo Sredkov
Browse files

Add measured camera stats to BatteryUsageStats

Implement POWER_MODEL_ENERGY_CONSUMPTION in CameraPowerCalculator by
using the camera energy consumption from BatteryStatsImpl.

Per-UID stats are will be supported in a follow-up change.

Bug: 258319905
Test: atest BatteryStatsTests
Test: Use the camera while not charging, observe usage in Battery Stats
Change-Id: I9df6c2d2300fdebc516d7b674c311e9be36b0d44
parent 259d5d2c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -2920,6 +2920,15 @@ public abstract class BatteryStats {
     */
    public abstract long getWifiEnergyConsumptionUC();

    /**
     * Returns the battery consumption (in microcoulombs) of camera, derived from on
     * device power measurement data.
     * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
     *
     * {@hide}
     */
    public abstract long getCameraEnergyConsumptionUC();

    /**
     * Returns the battery consumption (in microcoulombs) that each
     * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
+6 −0
Original line number Diff line number Diff line
@@ -7423,6 +7423,12 @@ public class BatteryStatsImpl extends BatteryStats {
        return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
    }
    @GuardedBy("this")
    @Override
    public long getCameraEnergyConsumptionUC() {
        return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
    }
    /**
     * Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
     * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
+16 −7
Original line number Diff line number Diff line
@@ -48,17 +48,26 @@ public class CameraPowerCalculator extends PowerCalculator {
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
        super.calculate(builder, batteryStats, rawRealtimeUs, rawUptimeUs, query);

        final long durationMs = batteryStats.getCameraOnTime(rawRealtimeUs,
                BatteryStats.STATS_SINCE_CHARGED) / 1000;
        final double powerMah = mPowerEstimator.calculatePower(durationMs);
        long consumptionUc = batteryStats.getCameraEnergyConsumptionUC();
        int powerModel = getPowerModel(consumptionUc, query);
        long durationMs =
                batteryStats.getCameraOnTime(
                        rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000;
        double powerMah;
        if (powerModel == BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION) {
            powerMah = uCtoMah(consumptionUc);
        } else {
            powerMah = mPowerEstimator.calculatePower(durationMs);
        }

        builder.getAggregateBatteryConsumerBuilder(
                        BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
                .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA, durationMs)
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah);
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah, powerModel);
        builder.getAggregateBatteryConsumerBuilder(
                        BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
                .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA, durationMs)
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah);
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah, powerModel);
    }

    @Override
+56 −4
Original line number Diff line number Diff line
@@ -40,24 +40,29 @@ public class CameraPowerCalculatorTest {

    @Rule
    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
            .setAveragePower(PowerProfile.POWER_CAMERA, 360.0);
            .setAveragePower(PowerProfile.POWER_CAMERA, 360.0)
            .initMeasuredEnergyStatsLocked();

    @Test
    public void testTimerBasedModel() {
        BatteryStatsImpl stats = mStatsRule.getBatteryStats();
        synchronized (stats) { // To keep the GuardedBy check happy
            stats.noteCameraOnLocked(APP_UID, 1000, 1000);
            stats.noteCameraOffLocked(APP_UID, 2000, 2000);
        }

        CameraPowerCalculator calculator =
                new CameraPowerCalculator(mStatsRule.getPowerProfile());

        mStatsRule.apply(calculator);
        mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);

        UidBatteryConsumer consumer = mStatsRule.getUidBatteryConsumer(APP_UID);
        assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(1000);
        assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isWithin(PRECISION).of(0.1);
        assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);

        final BatteryConsumer deviceBatteryConsumer = mStatsRule.getDeviceBatteryConsumer();
        assertThat(deviceBatteryConsumer
@@ -65,6 +70,8 @@ public class CameraPowerCalculatorTest {
                .isEqualTo(1000);
        assertThat(deviceBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isWithin(PRECISION).of(0.1);
        assertThat(deviceBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);

        final BatteryConsumer appsBatteryConsumer = mStatsRule.getAppsBatteryConsumer();
        assertThat(appsBatteryConsumer
@@ -72,5 +79,50 @@ public class CameraPowerCalculatorTest {
                .isEqualTo(1000);
        assertThat(appsBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isWithin(PRECISION).of(0.1);
        assertThat(appsBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
    }

    @Test
    public void testEnergyConsumptionBasedModel() {
        BatteryStatsImpl stats = mStatsRule.getBatteryStats();
        synchronized (stats) { // To keep the GuardedBy check happy
            stats.noteCameraOnLocked(APP_UID, 1000, 1000);
            stats.noteCameraOffLocked(APP_UID, 2000, 2000);
            stats.updateCameraEnergyConsumerStatsLocked(720_000, 6000); // 0.72C == 0.2mAh
        }

        CameraPowerCalculator calculator =
                new CameraPowerCalculator(mStatsRule.getPowerProfile());

        mStatsRule.apply(calculator);

        UidBatteryConsumer consumer = mStatsRule.getUidBatteryConsumer(APP_UID);
        assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(1000);
        assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isWithin(PRECISION).of(0.1);
        // Per-UID energy consumer model is not implemented yet, so the result will be based on the
        // power profile
        assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);

        final BatteryConsumer deviceBatteryConsumer = mStatsRule.getDeviceBatteryConsumer();
        assertThat(deviceBatteryConsumer
                .getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(1000);
        assertThat(deviceBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isWithin(PRECISION).of(0.2);
        assertThat(deviceBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);

        final BatteryConsumer appsBatteryConsumer = mStatsRule.getAppsBatteryConsumer();
        assertThat(appsBatteryConsumer
                .getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(1000);
        assertThat(appsBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isWithin(PRECISION).of(0.2);
        assertThat(appsBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
                .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
    }
}