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;
}
/**
* 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.
*/

View File

@@ -29,6 +29,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -234,8 +235,9 @@ public class BatteryUsageStatsProvider {
final boolean includePowerModels = (query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
final String[] customEnergyConsumerNames = mStats.getCustomEnergyConsumerNames();
final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
mStats.getCustomEnergyConsumerNames(), includePowerModels);
customEnergyConsumerNames, includePowerModels);
if (mBatteryUsageStatsStore == null) {
Log.e(TAG, "BatteryUsageStatsStore is unavailable");
return builder.build();
@@ -247,7 +249,14 @@ public class BatteryUsageStatsProvider {
final BatteryUsageStats snapshot =
mBatteryUsageStatsStore.loadBatteryUsageStats(timestamp);
if (snapshot != null) {
builder.add(snapshot);
if (Arrays.equals(snapshot.getCustomPowerComponentNames(),
customEnergyConsumerNames)) {
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() {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
bi.initMeasuredEnergyStats();
bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
clocks.realtime = 0;
int screen = Display.STATE_OFF;
@@ -677,7 +677,7 @@ public class BatteryStatsNoteTest extends TestCase {
public void testUpdateCustomMeasuredEnergyStatsLocked_neverCalled() {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
bi.initMeasuredEnergyStats();
bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
bi.setOnBatteryInternal(true);
final int uid1 = 11500;
@@ -691,7 +691,7 @@ public class BatteryStatsNoteTest extends TestCase {
public void testUpdateCustomMeasuredEnergyStatsLocked() {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
bi.initMeasuredEnergyStats();
bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
final int bucketA = 0; // Custom bucket 0
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 org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.Context;
import android.os.BatteryConsumer;
@@ -263,6 +266,39 @@ public class BatteryUsageStatsProviderTest {
.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 {
TestHandler() {
super(Looper.getMainLooper());

View File

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