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

Commit da600e0c authored by Adam Bookatz's avatar Adam Bookatz
Browse files

BatteryStats.getCustomMeasuredEnergiesMicroJoules

BatteryStats now has access to the custom measured energies,
in the form of an array of energies, indexed by the custom
energy bucket number (i.e. by the ordinal of each energy
consumer of type OTHER).

Also cleans up unused methods (now that we've solidified this
method as being the one required).

Bug: 179107328
Bug: 174818228

Test: atest FrameworksCoreTests:com.android.internal.os.BatteryStatsNoteTest
Test: atest FrameworksCoreTests:com.android.internal.power.MeasuredEnergyStatsTest
Change-Id: I96d646bd844dfa64d48dbb1158358b7561bae971
parent 822ed39c
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -994,6 +994,19 @@ public abstract class BatteryStats implements Parcelable {
         */
        public abstract long getScreenOnEnergy();

        /**
         * Returns the energies used by this uid for each
         * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
         * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
         *
         * @return energies (in microjoules) used since boot for each (custom) energy consumer of
         *         type OTHER, indexed by their ordinal. Returns null if no energy reporting is
         *         supported.
         *
         * {@hide}
         */
        public abstract @Nullable long[] getCustomMeasuredEnergiesMicroJoules();

        public static abstract class Sensor {

            @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -2511,6 +2524,19 @@ public abstract class BatteryStats implements Parcelable {
     */
    public abstract long getScreenDozeEnergy();

    /**
     * Returns the energies used for each
     * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
     * type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
     *
     * @return energies (in microjoules) used since boot for each (custom) energy consumer of
     *         type OTHER, indexed by their ordinal. Returns null if no energy reporting is
     *         supported.
     *
     * {@hide}
     */
    public abstract @Nullable long[] getCustomMeasuredEnergiesMicroJoules();

    public static final BitDescription[] HISTORY_STATE_DESCRIPTIONS = new BitDescription[] {
        new BitDescription(HistoryItem.STATE_CPU_RUNNING_FLAG, "running", "r"),
        new BitDescription(HistoryItem.STATE_WAKE_LOCK_FLAG, "wake_lock", "w"),
+30 −28
Original line number Diff line number Diff line
@@ -7156,34 +7156,34 @@ public class BatteryStatsImpl extends BatteryStats {
    @Override
    public long getScreenOnEnergy() {
        if (mGlobalMeasuredEnergyStats == null) {
            return ENERGY_DATA_UNAVAILABLE;
        }
        return mGlobalMeasuredEnergyStats
                .getAccumulatedStandardBucketEnergy(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON);
        return getMeasuredEnergyMicroJoules(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON);
    }
    @Override
    public long getScreenDozeEnergy() {
        if (mGlobalMeasuredEnergyStats == null) {
            return ENERGY_DATA_UNAVAILABLE;
        }
        return mGlobalMeasuredEnergyStats
                .getAccumulatedStandardBucketEnergy(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE);
        return getMeasuredEnergyMicroJoules(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE);
    }
    /**
     * Returns the energy in microjoules that the given custom energy bucket consumed.
     * Returns the energy in microjoules that the given standard energy bucket consumed.
     * Will return {@link #ENERGY_DATA_UNAVAILABLE} if data is unavailable
     *
     * @param customEnergyBucket custom energy bucket of interest
     * @return energy (in microjoules) used by this uid for this energy bucket
     * @param bucket standard energy bucket of interest
     * @return energy (in microjoules) used for this energy bucket
     */
    public long getCustomMeasuredEnergyMicroJoules(int customEnergyBucket) {
    private long getMeasuredEnergyMicroJoules(@StandardEnergyBucket int bucket) {
        if (mGlobalMeasuredEnergyStats == null) {
            return ENERGY_DATA_UNAVAILABLE;
        }
        return mGlobalMeasuredEnergyStats.getAccumulatedCustomBucketEnergy(customEnergyBucket);
        return mGlobalMeasuredEnergyStats.getAccumulatedStandardBucketEnergy(bucket);
    }
    @Override
    public @Nullable long[] getCustomMeasuredEnergiesMicroJoules() {
        if (mGlobalMeasuredEnergyStats == null) {
            return null;
        }
        return mGlobalMeasuredEnergyStats.getAccumulatedCustomBucketEnergies();
    }
    @Override public long getStartClockTime() {
@@ -7977,20 +7977,16 @@ public class BatteryStatsImpl extends BatteryStats {
            return mUidMeasuredEnergyStats.getAccumulatedStandardBucketEnergy(bucket);
        }
        /**
         * Returns the energy used by this uid for a custom energy bucket of interest.
         * @param customEnergyBucket custom energy bucket of interest
         * @return energy (in microjoules) used by this uid for this energy bucket
         */
        public long getCustomMeasuredEnergyMicroJoules(int customEnergyBucket) {
            if (mBsi.mGlobalMeasuredEnergyStats == null
                    || !mBsi.mGlobalMeasuredEnergyStats.isValidCustomBucket(customEnergyBucket)) {
                return ENERGY_DATA_UNAVAILABLE;
        @Override
        public long[] getCustomMeasuredEnergiesMicroJoules() {
            if (mBsi.mGlobalMeasuredEnergyStats == null) {
                return null;
            }
            if (mUidMeasuredEnergyStats == null) {
                return 0L; // It is supported, but was never filled, so it must be 0
                // Custom buckets may exist. But all values for this uid are 0 so we report all 0s.
                return new long[mBsi.mGlobalMeasuredEnergyStats.getNumberCustomEnergyBuckets()];
            }
            return mUidMeasuredEnergyStats.getAccumulatedCustomBucketEnergy(customEnergyBucket);
            return mUidMeasuredEnergyStats.getAccumulatedCustomBucketEnergies();
        }
        /**
@@ -14522,7 +14518,12 @@ public class BatteryStatsImpl extends BatteryStats {
     */
    @GuardedBy("this")
    public void dumpMeasuredEnergyStatsLocked(PrintWriter pw) {
        if (mGlobalMeasuredEnergyStats == null) return;
        pw.printf("On battery measured energy stats (microjoules) \n");
        if (mGlobalMeasuredEnergyStats == null) {
            pw.printf("    Not supported on this device.\n");
            return;
        }
        dumpMeasuredEnergyStatsLocked(pw, "non-uid usage", mGlobalMeasuredEnergyStats);
        int size = mUidStats.size();
@@ -14540,7 +14541,8 @@ public class BatteryStatsImpl extends BatteryStats {
            MeasuredEnergyStats stats) {
        if (stats == null) return;
        final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, "    ");
        iPw.printf("On battery measured energy stats for %s:\n", name);
        iPw.increaseIndent();
        iPw.printf("%s:\n", name);
        iPw.increaseIndent();
        stats.dump(iPw);
        iPw.decreaseIndent();
+18 −1
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ public class MeasuredEnergyStats {
     * Return accumulated energy (in microjoules) for the a custom energy bucket since last reset.
     * Returns {@link android.os.BatteryStats#ENERGY_DATA_UNAVAILABLE} if this data is unavailable.
     */
    @VisibleForTesting
    public long getAccumulatedCustomBucketEnergy(int customBucket) {
        if (!isValidCustomBucket(customBucket)) {
            return ENERGY_DATA_UNAVAILABLE;
@@ -245,6 +246,17 @@ public class MeasuredEnergyStats {
        return mAccumulatedEnergiesMicroJoules[customBucketToIndex(customBucket)];
    }

    /**
     * Return accumulated energies (in microjoules) for all custom energy buckets since last reset.
     */
    public @NonNull long[] getAccumulatedCustomBucketEnergies() {
        final long[] energies = new long[getNumberCustomEnergyBuckets()];
        for (int bucket = 0; bucket < energies.length; bucket++) {
            energies[bucket] = mAccumulatedEnergiesMicroJoules[customBucketToIndex(bucket)];
        }
        return energies;
    }

    /**
     * Map {@link android.view.Display} STATE_ to corresponding {@link StandardEnergyBucket}.
     */
@@ -404,7 +416,6 @@ public class MeasuredEnergyStats {

    /** Dump debug data. */
    public void dump(PrintWriter pw) {
        pw.println("Accumulated energy since last reset (microjoules):");
        pw.print("   ");
        for (int index = 0; index < mAccumulatedEnergiesMicroJoules.length; index++) {
            pw.print(getBucketName(index));
@@ -431,6 +442,11 @@ public class MeasuredEnergyStats {
        return "CUSTOM_" + indexToCustomBucket(index);
    }

    /** Get the number of custom energy buckets on this device. */
    public int getNumberCustomEnergyBuckets() {
        return mAccumulatedEnergiesMicroJoules.length - NUMBER_STANDARD_ENERGY_BUCKETS;
    }

    private static int customBucketToIndex(int customBucket) {
        return customBucket + NUMBER_STANDARD_ENERGY_BUCKETS;
    }
@@ -450,6 +466,7 @@ public class MeasuredEnergyStats {
    }

    /** Returns whether the given custom bucket is valid (exists) on this device. */
    @VisibleForTesting
    public boolean isValidCustomBucket(int customBucket) {
        return customBucket >= 0
                && customBucketToIndex(customBucket) < mAccumulatedEnergiesMicroJoules.length;
+14 −10
Original line number Diff line number Diff line
@@ -707,22 +707,26 @@ public class BatteryStatsNoteTest extends TestCase {
            int uid2, long blame2A, long blame2B,
            MockBatteryStatsImpl bi) {

        final long[] actualTotal = bi.getCustomMeasuredEnergiesMicroJoules();
        final long[] actualUid1 = bi.getUidStatsLocked(uid1).getCustomMeasuredEnergiesMicroJoules();
        final long[] actualUid2 = bi.getUidStatsLocked(uid2).getCustomMeasuredEnergiesMicroJoules();

        assertNotNull(actualTotal);
        assertNotNull(actualUid1);
        assertNotNull(actualUid2);

        assertEquals("Wrong total blame in bucket 0 for Case " + caseName, totalBlameA,
                bi.getCustomMeasuredEnergyMicroJoules(0));
                actualTotal[0]);

        assertEquals("Wrong total blame in bucket 1 for Case " + caseName, totalBlameB,
                bi.getCustomMeasuredEnergyMicroJoules(1));
                actualTotal[1]);

        assertEquals("Wrong uid1 blame in bucket 0 for Case " + caseName, blame1A,
                bi.getUidStatsLocked(uid1).getCustomMeasuredEnergyMicroJoules(0));
        assertEquals("Wrong uid1 blame in bucket 0 for Case " + caseName, blame1A, actualUid1[0]);

        assertEquals("Wrong uid1 blame in bucket 1 for Case " + caseName, blame1B,
                bi.getUidStatsLocked(uid1).getCustomMeasuredEnergyMicroJoules(1));
        assertEquals("Wrong uid1 blame in bucket 1 for Case " + caseName, blame1B, actualUid1[1]);

        assertEquals("Wrong uid2 blame in bucket 0 for Case " + caseName, blame2A,
                bi.getUidStatsLocked(uid2).getCustomMeasuredEnergyMicroJoules(0));
        assertEquals("Wrong uid2 blame in bucket 0 for Case " + caseName, blame2A, actualUid2[0]);

        assertEquals("Wrong uid2 blame in bucket 1 for Case " + caseName, blame2B,
                bi.getUidStatsLocked(uid2).getCustomMeasuredEnergyMicroJoules(1));
        assertEquals("Wrong uid2 blame in bucket 1 for Case " + caseName, blame2B, actualUid2[1]);
    }
}
+35 −0
Original line number Diff line number Diff line
@@ -404,6 +404,41 @@ public class MeasuredEnergyStatsTest {
        assertFalse(boringStats.isValidCustomBucket(1));
    }

    @Test
    public void testGetAccumulatedCustomBucketEnergies() {
        final MeasuredEnergyStats stats
                = new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 3);

        stats.updateCustomBucket(0, 50, true);
        stats.updateCustomBucket(1, 60, true);
        stats.updateCustomBucket(2, 13, true);
        stats.updateCustomBucket(1, 70, true);

        final long[] output = stats.getAccumulatedCustomBucketEnergies();
        assertEquals(3, output.length);

        assertEquals(50, output[0]);
        assertEquals(60 + 70, output[1]);
        assertEquals(13, output[2]);
    }

    @Test
    public void testGetAccumulatedCustomBucketEnergies_empty() {
        final MeasuredEnergyStats stats
                = new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 0);

        final long[] output = stats.getAccumulatedCustomBucketEnergies();
        assertEquals(0, output.length);
    }

    @Test
    public void testGetNumberCustomEnergyBuckets() {
        assertEquals(0, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 0)
                .getNumberCustomEnergyBuckets());
        assertEquals(3, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], 3)
                .getNumberCustomEnergyBuckets());
    }

    @Test
    public void testReset() {
        final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];