Merge "Check custom component names before aggregating BatteryUsageStats snapshots" into sc-qpr1-dev

This commit is contained in:
TreeHugger Robot
2021-09-20 20:48:13 +00:00
committed by Android (Google) Code Review
5 changed files with 61 additions and 7 deletions

View File

@@ -270,6 +270,16 @@ public final class BatteryUsageStats implements Parcelable {
return mUserBatteryConsumers; return mUserBatteryConsumers;
} }
/**
* Returns the names of custom power components in order, so the first name in the array
* corresponds to the custom componentId
* {@link BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID}.
*/
@NonNull
public String[] getCustomPowerComponentNames() {
return mCustomPowerComponentNames;
}
/** /**
* Returns an iterator for {@link android.os.BatteryStats.HistoryItem}'s. * Returns an iterator for {@link android.os.BatteryStats.HistoryItem}'s.
*/ */

View File

@@ -29,6 +29,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -234,8 +235,9 @@ public class BatteryUsageStatsProvider {
final boolean includePowerModels = (query.getFlags() final boolean includePowerModels = (query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0; & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
final String[] customEnergyConsumerNames = mStats.getCustomEnergyConsumerNames();
final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder( final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
mStats.getCustomEnergyConsumerNames(), includePowerModels); customEnergyConsumerNames, includePowerModels);
if (mBatteryUsageStatsStore == null) { if (mBatteryUsageStatsStore == null) {
Log.e(TAG, "BatteryUsageStatsStore is unavailable"); Log.e(TAG, "BatteryUsageStatsStore is unavailable");
return builder.build(); return builder.build();
@@ -247,7 +249,14 @@ public class BatteryUsageStatsProvider {
final BatteryUsageStats snapshot = final BatteryUsageStats snapshot =
mBatteryUsageStatsStore.loadBatteryUsageStats(timestamp); mBatteryUsageStatsStore.loadBatteryUsageStats(timestamp);
if (snapshot != null) { if (snapshot != null) {
if (Arrays.equals(snapshot.getCustomPowerComponentNames(),
customEnergyConsumerNames)) {
builder.add(snapshot); builder.add(snapshot);
} else {
Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which has different "
+ "custom power components: "
+ Arrays.toString(snapshot.getCustomPowerComponentNames()));
}
} }
} }
} }

View File

@@ -592,7 +592,7 @@ public class BatteryStatsNoteTest extends TestCase {
public void testUpdateDisplayMeasuredEnergyStatsLocked() { public void testUpdateDisplayMeasuredEnergyStatsLocked() {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
bi.initMeasuredEnergyStats(); bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
clocks.realtime = 0; clocks.realtime = 0;
int screen = Display.STATE_OFF; int screen = Display.STATE_OFF;
@@ -677,7 +677,7 @@ public class BatteryStatsNoteTest extends TestCase {
public void testUpdateCustomMeasuredEnergyStatsLocked_neverCalled() { public void testUpdateCustomMeasuredEnergyStatsLocked_neverCalled() {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
bi.initMeasuredEnergyStats(); bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
bi.setOnBatteryInternal(true); bi.setOnBatteryInternal(true);
final int uid1 = 11500; final int uid1 = 11500;
@@ -691,7 +691,7 @@ public class BatteryStatsNoteTest extends TestCase {
public void testUpdateCustomMeasuredEnergyStatsLocked() { public void testUpdateCustomMeasuredEnergyStatsLocked() {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
bi.initMeasuredEnergyStats(); bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
final int bucketA = 0; // Custom bucket 0 final int bucketA = 0; // Custom bucket 0
final int bucketB = 1; // Custom bucket 1 final int bucketB = 1; // Custom bucket 1

View File

@@ -18,6 +18,9 @@ package com.android.internal.os;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.os.BatteryConsumer; import android.os.BatteryConsumer;
@@ -263,6 +266,39 @@ public class BatteryUsageStatsProviderTest {
.of(180.0); .of(180.0);
} }
@Test
public void testAggregateBatteryStats_incompatibleSnapshot() {
Context context = InstrumentationRegistry.getContext();
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
batteryStats.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
BatteryUsageStatsStore batteryUsageStatsStore = mock(BatteryUsageStatsStore.class);
when(batteryUsageStatsStore.listBatteryUsageStatsTimestamps())
.thenReturn(new long[]{1000, 2000});
when(batteryUsageStatsStore.loadBatteryUsageStats(1000)).thenReturn(
new BatteryUsageStats.Builder(batteryStats.getCustomEnergyConsumerNames())
.setStatsDuration(1234).build());
// Add a snapshot, with a different set of custom power components. It should
// be skipped by the aggregation.
when(batteryUsageStatsStore.loadBatteryUsageStats(2000)).thenReturn(
new BatteryUsageStats.Builder(new String[]{"different"})
.setStatsDuration(4321).build());
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context,
batteryStats, batteryUsageStatsStore);
BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
.aggregateSnapshots(0, 3000)
.build();
final BatteryUsageStats stats = provider.getBatteryUsageStats(query);
assertThat(stats.getCustomPowerComponentNames())
.isEqualTo(batteryStats.getCustomEnergyConsumerNames());
assertThat(stats.getStatsDuration()).isEqualTo(1234);
}
private static class TestHandler extends Handler { private static class TestHandler extends Handler {
TestHandler() { TestHandler() {
super(Looper.getMainLooper()); super(Looper.getMainLooper());

View File

@@ -57,11 +57,10 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
this(new MockClocks()); this(new MockClocks());
} }
public void initMeasuredEnergyStats() { public void initMeasuredEnergyStats(String[] customBucketNames) {
final boolean[] supportedStandardBuckets = final boolean[] supportedStandardBuckets =
new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
Arrays.fill(supportedStandardBuckets, true); Arrays.fill(supportedStandardBuckets, true);
final String[] customBucketNames = {"FOO", "BAR"};
mGlobalMeasuredEnergyStats = mGlobalMeasuredEnergyStats =
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
} }