Wipe BatteryStats on Custom Power Bucket change

If the supported OTHER EnergyConsumers change after a reboot, the
MeasuredEnergyStats from the reboot can no longer be considered valid.

Bug: 178504428
Test: atest FrameworksCoreTests:com.android.internal.power.MeasuredEnergyStatsTest
Change-Id: I2561c459c0b2a881661bd2913f9413a2cbd96abb
This commit is contained in:
Michael Wachenschwanz
2021-04-28 21:17:34 -07:00
parent 720add59c7
commit fa2a4f44bd
2 changed files with 97 additions and 7 deletions

View File

@@ -33,6 +33,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
/**
* Tracks the measured charge consumption of various subsystems according to their
@@ -96,8 +97,10 @@ public class MeasuredEnergyStats {
* supportedStandardBuckets must be of size {@link #NUMBER_STANDARD_POWER_BUCKETS}.
* numCustomBuckets >= 0 is the number of (non-standard) custom power buckets on the device.
*/
public MeasuredEnergyStats(boolean[] supportedStandardBuckets, String[] customBucketNames) {
final int numTotalBuckets = NUMBER_STANDARD_POWER_BUCKETS + customBucketNames.length;
public MeasuredEnergyStats(@NonNull boolean[] supportedStandardBuckets,
@Nullable String[] customBucketNames) {
mCustomBucketNames = customBucketNames == null ? new String[0] : customBucketNames;
final int numTotalBuckets = NUMBER_STANDARD_POWER_BUCKETS + mCustomBucketNames.length;
mAccumulatedChargeMicroCoulomb = new long[numTotalBuckets];
// Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE.
// All custom buckets are, by definition, supported, so their values stay at 0.
@@ -106,7 +109,6 @@ public class MeasuredEnergyStats {
mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE;
}
}
mCustomBucketNames = customBucketNames;
}
/**
@@ -431,14 +433,22 @@ public class MeasuredEnergyStats {
/** Check if the supported power buckets are precisely those given. */
public boolean isSupportEqualTo(
@NonNull boolean[] queriedStandardBuckets, String[] customBucketNames) {
@NonNull boolean[] queriedStandardBuckets, @Nullable String[] customBucketNames) {
if (customBucketNames == null) {
//In practice customBucketNames should never be null, but sanitize it just to be sure.
customBucketNames = new String[0];
}
final int numBuckets = getNumberOfIndices();
// TODO(b/178504428): Detect whether custom buckets have changed qualitatively, not just
// quantitatively, and treat as mismatch if so.
if (numBuckets != NUMBER_STANDARD_POWER_BUCKETS + customBucketNames.length) {
final int numCustomBuckets = customBucketNames == null ? 0 : customBucketNames.length;
if (numBuckets != NUMBER_STANDARD_POWER_BUCKETS + numCustomBuckets) {
return false;
}
if (!Arrays.equals(mCustomBucketNames, customBucketNames)) {
return false;
}
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) {
if (isStandardBucketSupported(stdBucket) != queriedStandardBuckets[stdBucket]) {
return false;

View File

@@ -499,4 +499,84 @@ public class MeasuredEnergyStatsTest {
assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_DOZE));
assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_DOZE_SUSPEND));
}
/** Test MeasuredEnergyStats#isSupportEqualTo */
@Test
public void testIsSupportEqualTo() {
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
Arrays.fill(supportedStandardBuckets, true);
final String[] customBucketNames = {"A", "B"};
final MeasuredEnergyStats stats =
new MeasuredEnergyStats(supportedStandardBuckets.clone(),
customBucketNames.clone());
assertTrue(
"All standard and custom bucket supports match",
stats.isSupportEqualTo(supportedStandardBuckets, customBucketNames));
boolean[] differentSupportedStandardBuckets = supportedStandardBuckets.clone();
differentSupportedStandardBuckets[0] = !differentSupportedStandardBuckets[0];
assertFalse(
"Standard bucket support mismatch",
stats.isSupportEqualTo(differentSupportedStandardBuckets, customBucketNames));
assertFalse(
"Custom bucket support mismatch",
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"C", "B"}));
assertFalse(
"Fewer custom buckets supported",
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A"}));
assertFalse(
"More custom bucket supported",
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B", "C"}));
assertFalse(
"Custom bucket support order changed",
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"B", "A"}));
}
/** Test MeasuredEnergyStats#isSupportEqualTo when holding a null array of custom buckets */
@Test
public void testIsSupportEqualTo_nullCustomBuckets() {
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
final MeasuredEnergyStats stats =
new MeasuredEnergyStats(supportedStandardBuckets.clone(), null);
assertTrue(
"Null custom bucket name lists should match",
stats.isSupportEqualTo(supportedStandardBuckets, null));
assertTrue(
"Null and empty custom buckets should match",
stats.isSupportEqualTo(supportedStandardBuckets, new String[0]));
assertFalse(
"Null custom buckets should not match populated list",
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"}));
}
/** Test MeasuredEnergyStats#isSupportEqualTo when holding an empty array of custom buckets */
@Test
public void testIsSupportEqualTo_emptyCustomBuckets() {
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
final MeasuredEnergyStats stats =
new MeasuredEnergyStats(supportedStandardBuckets.clone(), new String[0]);
assertTrue(
"Empty custom buckets should match",
stats.isSupportEqualTo(supportedStandardBuckets, new String[0]));
assertTrue(
"Empty and null custom buckets should match",
stats.isSupportEqualTo(supportedStandardBuckets, null));
assertFalse(
"Empty custom buckets should not match populated list",
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"}));
}
}