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

Commit 79978c19 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Add process state to BatteryUsageStats atoms

Bug: 191921016
Test: atest BatteryUsageStatsProtoTests:BatteryUsageStatsPulledTest

Change-Id: Id047aa2e1fcf5318c3fd6620e6d41bcb172c6b31
parent 6b933776
Loading
Loading
Loading
Loading
+61 −17
Original line number Original line Diff line number Diff line
@@ -223,7 +223,8 @@ class PowerComponents {
        for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
        for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
                componentId++) {
                componentId++) {


            final BatteryConsumer.Key key = mData.getKey(componentId, PROCESS_STATE_ANY);
            final BatteryConsumer.Key[] keys = mData.getKeys(componentId);
            for (BatteryConsumer.Key key : keys) {
                final long powerDeciCoulombs = convertMahToDeciCoulombs(getConsumedPower(key));
                final long powerDeciCoulombs = convertMahToDeciCoulombs(getConsumedPower(key));
                final long durationMs = getUsageDurationMillis(key);
                final long durationMs = getUsageDurationMillis(key);


@@ -234,11 +235,20 @@ class PowerComponents {


                interestingData = true;
                interestingData = true;
                if (proto == null) {
                if (proto == null) {
                // We're just asked whether there is data, not to actually write it. And there is.
                    // We're just asked whether there is data, not to actually write it.
                    // And there is.
                    return true;
                    return true;
                }
                }


            writePowerComponent(proto, componentId, powerDeciCoulombs, durationMs);
                if (key.processState == PROCESS_STATE_ANY) {
                    writePowerComponentUsage(proto,
                            BatteryUsageStatsAtomsProto.BatteryConsumerData.POWER_COMPONENTS,
                            componentId, powerDeciCoulombs, durationMs);
                } else {
                    writePowerUsageSlice(proto, componentId, powerDeciCoulombs, durationMs,
                            key.processState);
                }
            }
        }
        }
        for (int idx = 0; idx < mData.layout.customPowerComponentCount; idx++) {
        for (int idx = 0; idx < mData.layout.customPowerComponentCount; idx++) {
            final int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + idx;
            final int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + idx;
@@ -257,15 +267,49 @@ class PowerComponents {
                return true;
                return true;
            }
            }


            writePowerComponent(proto, componentId, powerDeciCoulombs, durationMs);
            writePowerComponentUsage(proto,
                    BatteryUsageStatsAtomsProto.BatteryConsumerData.POWER_COMPONENTS,
                    componentId, powerDeciCoulombs, durationMs);
        }
        }
        return interestingData;
        return interestingData;
    }
    }


    private void writePowerComponent(ProtoOutputStream proto, int componentId,
    private void writePowerUsageSlice(ProtoOutputStream proto, int componentId,
            long powerDeciCoulombs, long durationMs, int processState) {
        final long slicesToken =
                proto.start(BatteryUsageStatsAtomsProto.BatteryConsumerData.SLICES);
        writePowerComponentUsage(proto,
                BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                        .POWER_COMPONENT,
                componentId, powerDeciCoulombs, durationMs);

        final int procState;
        switch (processState) {
            case BatteryConsumer.PROCESS_STATE_FOREGROUND:
                procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                        .FOREGROUND;
                break;
            case BatteryConsumer.PROCESS_STATE_BACKGROUND:
                procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                        .BACKGROUND;
                break;
            case BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE:
                procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                        .FOREGROUND_SERVICE;
                break;
            default:
                throw new IllegalArgumentException("Unknown process state: " + processState);
        }

        proto.write(BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                .PROCESS_STATE, procState);

        proto.end(slicesToken);
    }

    private void writePowerComponentUsage(ProtoOutputStream proto, long tag, int componentId,
            long powerDeciCoulombs, long durationMs) {
            long powerDeciCoulombs, long durationMs) {
        final long token =
        final long token = proto.start(tag);
                proto.start(BatteryUsageStatsAtomsProto.BatteryConsumerData.POWER_COMPONENTS);
        proto.write(
        proto.write(
                BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
                BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
                        .COMPONENT,
                        .COMPONENT,
+20 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,26 @@ message BatteryUsageStatsAtomsProto {
            optional int64 duration_millis = 3;
            optional int64 duration_millis = 3;
        }
        }
        repeated PowerComponentUsage power_components = 2;
        repeated PowerComponentUsage power_components = 2;

        // Represents a slice of power attribution, e.g. "cpu while in the background"
        // or "wifi when running a background service".  Queries that care about
        // PowerComponentUsage slices need to be aware of all supported dimensions.
        // There are no roll-ups included in the slices - it is up to the clients
        // of this data to aggregate values as needed.
        message PowerComponentUsageSlice {
            optional PowerComponentUsage power_component = 1;

            enum ProcessState {
                UNSPECIFIED = 0;
                FOREGROUND = 1;
                BACKGROUND = 2;
                FOREGROUND_SERVICE = 3;
            }

            optional ProcessState process_state = 2;
        }

        repeated PowerComponentUsageSlice slices = 3;
    }
    }


    // Total power usage for the device during this session.
    // Total power usage for the device during this session.
+59 −4
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;


import android.os.BatteryConsumer;
import android.os.BatteryConsumer;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStats;
import android.os.UidBatteryConsumer;
import android.os.nano.BatteryUsageStatsAtomsProto;
import android.os.nano.BatteryUsageStatsAtomsProto;
import android.os.nano.BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage;
import android.os.nano.BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage;


@@ -134,6 +135,43 @@ public class BatteryUsageStatsPulledTest {
                        componentProto.durationMillis);
                        componentProto.durationMillis);
            }
            }
        }
        }

        for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
                componentId++) {
            final BatteryConsumer.Key[] keys = consumer.getKeys(componentId);
            if (keys == null || keys.length <= 1) {
                continue;
            }

            for (BatteryConsumer.Key key : keys) {
                if (key.processState == 0) {
                    continue;
                }

                BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                        sliceProto = null;
                for (BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                        slice : consumerProto.slices) {
                    if (slice.powerComponent.component == componentId
                            && slice.processState == key.processState) {
                        sliceProto = slice;
                        break;
                    }
                }

                final long expectedPowerDc = convertMahToDc(consumer.getConsumedPower(key));
                final long expectedUsageDurationMillis = consumer.getUsageDurationMillis(key);
                if (expectedPowerDc == 0 && expectedUsageDurationMillis == 0) {
                    assertThat(sliceProto).isNull();
                } else {
                    assertThat(sliceProto).isNotNull();
                    assertThat(sliceProto.powerComponent.powerDeciCoulombs)
                            .isEqualTo(expectedPowerDc);
                    assertThat(sliceProto.powerComponent.durationMillis)
                            .isEqualTo(expectedUsageDurationMillis);
                }
            }
        }
    }
    }


    private void assertSameUidBatteryConsumer(
    private void assertSameUidBatteryConsumer(
@@ -172,14 +210,17 @@ public class BatteryUsageStatsPulledTest {
        final BatteryStatsImpl.Uid batteryStatsUid3 = batteryStats.getUidStatsLocked(UID_3);
        final BatteryStatsImpl.Uid batteryStatsUid3 = batteryStats.getUidStatsLocked(UID_3);


        final BatteryUsageStats.Builder builder =
        final BatteryUsageStats.Builder builder =
                new BatteryUsageStats.Builder(new String[]{"CustomConsumer1", "CustomConsumer2"})
                new BatteryUsageStats.Builder(new String[]{"CustomConsumer1", "CustomConsumer2"},
                        /* includePowerModels */ true,
                        /* includeProcessStats */true)
                        .setDischargePercentage(20)
                        .setDischargePercentage(20)
                        .setDischargedPowerRange(1000, 2000)
                        .setDischargedPowerRange(1000, 2000)
                        .setStatsStartTimestamp(1000);
                        .setStatsStartTimestamp(1000);
        builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid0)
        final UidBatteryConsumer.Builder uidBuilder = builder.getOrCreateUidBatteryConsumerBuilder(
                batteryStatsUid0)
                .setPackageWithHighestDrain("myPackage0")
                .setPackageWithHighestDrain("myPackage0")
                .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 1000)
                .setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND, 1000)
                .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND, 2000)
                .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND, 2000)
                .setConsumedPower(
                .setConsumedPower(
                        BatteryConsumer.POWER_COMPONENT_SCREEN, 300)
                        BatteryConsumer.POWER_COMPONENT_SCREEN, 300)
                .setConsumedPower(
                .setConsumedPower(
@@ -193,6 +234,20 @@ public class BatteryUsageStatsPulledTest {
                .setUsageDurationForCustomComponentMillis(
                .setUsageDurationForCustomComponentMillis(
                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 1, 800);
                        BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 1, 800);


        final BatteryConsumer.Key keyFg = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU,
                BatteryConsumer.PROCESS_STATE_FOREGROUND);
        final BatteryConsumer.Key keyBg = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU,
                BatteryConsumer.PROCESS_STATE_BACKGROUND);
        final BatteryConsumer.Key keyFgs = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU,
                BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);

        uidBuilder.setConsumedPower(keyFg, 9100, BatteryConsumer.POWER_MODEL_POWER_PROFILE)
                .setUsageDurationMillis(keyFg, 8100)
                .setConsumedPower(keyBg, 9200, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
                .setUsageDurationMillis(keyBg, 8200)
                .setConsumedPower(keyFgs, 9300, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
                .setUsageDurationMillis(keyFgs, 8300);

        builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid1)
        builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid1)
                .setPackageWithHighestDrain("myPackage1")
                .setPackageWithHighestDrain("myPackage1")
                .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 1234);
                .setTimeInStateMs(android.os.UidBatteryConsumer.STATE_FOREGROUND, 1234);