diff --git a/core/java/android/os/AggregateBatteryConsumer.java b/core/java/android/os/AggregateBatteryConsumer.java index e088f306cd980..068df22e222ba 100644 --- a/core/java/android/os/AggregateBatteryConsumer.java +++ b/core/java/android/os/AggregateBatteryConsumer.java @@ -19,6 +19,7 @@ package android.os; import android.annotation.NonNull; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; +import android.util.proto.ProtoOutputStream; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -97,6 +98,19 @@ public final class AggregateBatteryConsumer extends BatteryConsumer { } } + void writePowerComponentModelProto(@NonNull ProtoOutputStream proto) { + for (int i = 0; i < POWER_COMPONENT_COUNT; i++) { + final int powerModel = getPowerModel(i); + if (powerModel == BatteryConsumer.POWER_MODEL_UNDEFINED) continue; + + final long token = proto.start(BatteryUsageStatsAtomsProto.COMPONENT_MODELS); + proto.write(BatteryUsageStatsAtomsProto.PowerComponentModel.COMPONENT, i); + proto.write(BatteryUsageStatsAtomsProto.PowerComponentModel.POWER_MODEL, + powerModelToProtoEnum(powerModel)); + proto.end(token); + } + } + /** * Builder for DeviceBatteryConsumer. */ diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java index f4ca1b50fe865..de2dec779c991 100644 --- a/core/java/android/os/BatteryConsumer.java +++ b/core/java/android/os/BatteryConsumer.java @@ -478,6 +478,21 @@ public abstract class BatteryConsumer { } } + /** + * Returns the equivalent PowerModel enum for the specified power model. + * {@see BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage.PowerModel} + */ + public static int powerModelToProtoEnum(@BatteryConsumer.PowerModel int powerModel) { + switch (powerModel) { + case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY: + return BatteryUsageStatsAtomsProto.PowerComponentModel.MEASURED_ENERGY; + case BatteryConsumer.POWER_MODEL_POWER_PROFILE: + return BatteryUsageStatsAtomsProto.PowerComponentModel.POWER_PROFILE; + default: + return BatteryUsageStatsAtomsProto.PowerComponentModel.UNDEFINED; + } + } + /** * Returns the name of the specified process state. Intended for logging and debugging. */ diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index b76592d4be587..7105b1ad8b384 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -276,7 +276,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { /** * Returns a battery consumer for the specified battery consumer type. */ - public BatteryConsumer getAggregateBatteryConsumer( + public AggregateBatteryConsumer getAggregateBatteryConsumer( @AggregateBatteryConsumerScope int scope) { return mAggregateBatteryConsumers[scope]; } @@ -450,7 +450,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { @NonNull private void writeStatsProto(ProtoOutputStream proto, int maxRawSize) { - final BatteryConsumer deviceBatteryConsumer = getAggregateBatteryConsumer( + final AggregateBatteryConsumer deviceBatteryConsumer = getAggregateBatteryConsumer( AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); proto.write(BatteryUsageStatsAtomsProto.SESSION_START_MILLIS, getStatsStartTimestamp()); @@ -462,6 +462,9 @@ public final class BatteryUsageStats implements Parcelable, Closeable { getDischargeDurationMs()); deviceBatteryConsumer.writeStatsProto(proto, BatteryUsageStatsAtomsProto.DEVICE_BATTERY_CONSUMER); + if (mIncludesPowerModels) { + deviceBatteryConsumer.writePowerComponentModelProto(proto); + } writeUidBatteryConsumersProto(proto, maxRawSize); } diff --git a/core/proto/android/os/batteryusagestats.proto b/core/proto/android/os/batteryusagestats.proto index 856bc839aee5f..2b74220a14711 100644 --- a/core/proto/android/os/batteryusagestats.proto +++ b/core/proto/android/os/batteryusagestats.proto @@ -102,4 +102,21 @@ message BatteryUsageStatsAtomsProto { // Total amount of time battery was discharging during the reported session optional int64 discharge_duration_millis = 7; + + // Notes the power model used for a power component. + message PowerComponentModel { + // Holds android.os.PowerComponentEnum, or custom component value between 1000 and 9999. + optional int32 component = 1; + + enum PowerModel { + UNDEFINED = 0; + POWER_PROFILE = 1; + MEASURED_ENERGY = 2; + } + + optional PowerModel power_model = 2; + } + + // The power model used for each power component. + repeated PowerComponentModel component_models = 8; } 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 2ce305440ef57..f82523c5e3a12 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 @@ -24,6 +24,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; +import android.os.AggregateBatteryConsumer; import android.os.BatteryConsumer; import android.os.BatteryUsageStats; import android.os.UidBatteryConsumer; @@ -69,10 +70,17 @@ public class BatteryUsageStatsPulledTest { assertEquals(bus.getDischargeDurationMs(), proto.dischargeDurationMillis); assertEquals(3, proto.deviceBatteryConsumer.powerComponents.length); // Only 3 are non-empty + + final AggregateBatteryConsumer abc = bus.getAggregateBatteryConsumer( + AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); assertSameBatteryConsumer("For deviceBatteryConsumer", bus.getAggregateBatteryConsumer(AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE), proto.deviceBatteryConsumer); + for (int i = 0; i < BatteryConsumer.POWER_COMPONENT_COUNT; i++) { + assertPowerComponentModel(i, abc.getPowerModel(i), proto); + } + // Now for the UidBatteryConsumers. final List uidConsumers = bus.getUidBatteryConsumers(); uidConsumers.sort((a, b) -> a.getUid() - b.getUid()); @@ -196,6 +204,34 @@ public class BatteryUsageStatsPulledTest { } } + /** + * Validates the PowerComponentModel object that matches powerComponent. + */ + private void assertPowerComponentModel(int powerComponent, + @BatteryConsumer.PowerModel int powerModel, BatteryUsageStatsAtomsProto proto) { + boolean found = false; + for (BatteryUsageStatsAtomsProto.PowerComponentModel powerComponentModel : + proto.componentModels) { + if (powerComponentModel.component == powerComponent) { + if (found) { + fail("Power component " + BatteryConsumer.powerComponentIdToString( + powerComponent) + " found multiple times in the proto"); + } + found = true; + final int expectedPowerModel = BatteryConsumer.powerModelToProtoEnum(powerModel); + assertEquals(expectedPowerModel, powerComponentModel.powerModel); + } + } + if (!found) { + final int model = BatteryConsumer.powerModelToProtoEnum(powerModel); + assertEquals( + "Power component " + BatteryConsumer.powerComponentIdToString(powerComponent) + + " was not found in the proto but has a defined power model.", + BatteryUsageStatsAtomsProto.PowerComponentModel.UNDEFINED, + model); + } + } + /** Converts charge from milliamp hours (mAh) to decicoulombs (dC). */ private long convertMahToDc(double powerMah) { return (long) (powerMah * 36 + 0.5); @@ -259,11 +295,14 @@ public class BatteryUsageStatsPulledTest { builder.getAggregateBatteryConsumerBuilder(AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setConsumedPower(30000) .setConsumedPower( - BatteryConsumer.POWER_COMPONENT_CPU, 20100) + BatteryConsumer.POWER_COMPONENT_CPU, 20100, + BatteryConsumer.POWER_MODEL_POWER_PROFILE) .setConsumedPower( - BatteryConsumer.POWER_COMPONENT_AUDIO, 0) // Empty + BatteryConsumer.POWER_COMPONENT_AUDIO, 0, + BatteryConsumer.POWER_MODEL_POWER_PROFILE) // Empty .setConsumedPower( - BatteryConsumer.POWER_COMPONENT_CAMERA, 20150) + BatteryConsumer.POWER_COMPONENT_CAMERA, 20150, + BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) .setConsumedPowerForCustomComponent( BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 20200) .setUsageDurationMillis( @@ -275,7 +314,8 @@ public class BatteryUsageStatsPulledTest { builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS) .setConsumedPower( - BatteryConsumer.POWER_COMPONENT_CPU, 10100) + BatteryConsumer.POWER_COMPONENT_CPU, 10100, + BatteryConsumer.POWER_MODEL_POWER_PROFILE) .setConsumedPowerForCustomComponent( BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10200); @@ -285,7 +325,7 @@ public class BatteryUsageStatsPulledTest { @Test public void testLargeAtomTruncated() { final BatteryUsageStats.Builder builder = - new BatteryUsageStats.Builder(new String[0]); + new BatteryUsageStats.Builder(new String[0], true, false); // If not truncated, this BatteryUsageStats object would generate a proto buffer // significantly larger than 50 Kb for (int i = 0; i < 3000; i++) { diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index a23870567cdbb..d304de5d9f3ec 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -757,6 +757,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub new BatteryUsageStatsQuery.Builder() .includeProcessStateData() .includeVirtualUids() + .includePowerModels() .build(); bus = getBatteryUsageStats(List.of(querySinceReset)).get(0); break; @@ -766,6 +767,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub .includeProcessStateData() .includeVirtualUids() .powerProfileModeledOnly() + .includePowerModels() .build(); bus = getBatteryUsageStats(List.of(queryPowerProfile)).get(0); break;