Loading core/java/android/os/AggregateBatteryConsumer.java +14 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. */ Loading core/java/android/os/BatteryConsumer.java +15 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading core/java/android/os/BatteryUsageStats.java +5 −2 Original line number Diff line number Diff line Loading @@ -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]; } Loading Loading @@ -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()); Loading @@ -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); } Loading core/proto/android/os/batteryusagestats.proto +17 −0 Original line number Diff line number Diff line Loading @@ -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; } core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java +45 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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<android.os.UidBatteryConsumer> uidConsumers = bus.getUidBatteryConsumers(); uidConsumers.sort((a, b) -> a.getUid() - b.getUid()); Loading Loading @@ -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); Loading Loading @@ -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( Loading @@ -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); Loading @@ -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++) { Loading Loading
core/java/android/os/AggregateBatteryConsumer.java +14 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. */ Loading
core/java/android/os/BatteryConsumer.java +15 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading
core/java/android/os/BatteryUsageStats.java +5 −2 Original line number Diff line number Diff line Loading @@ -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]; } Loading Loading @@ -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()); Loading @@ -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); } Loading
core/proto/android/os/batteryusagestats.proto +17 −0 Original line number Diff line number Diff line Loading @@ -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; }
core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java +45 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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<android.os.UidBatteryConsumer> uidConsumers = bus.getUidBatteryConsumers(); uidConsumers.sort((a, b) -> a.getUid() - b.getUid()); Loading Loading @@ -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); Loading Loading @@ -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( Loading @@ -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); Loading @@ -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++) { Loading