Merge "Allow requesting BatteryUsageStats for specific power components"

This commit is contained in:
Dmitri Plotnikov
2022-01-27 00:11:17 +00:00
committed by Android (Google) Code Review
26 changed files with 234 additions and 20 deletions

View File

@@ -75,8 +75,9 @@ public final class BatteryUsageStatsQuery implements Parcelable {
@NonNull
private final int[] mUserIds;
private final long mMaxStatsAgeMs;
private long mFromTimestamp;
private long mToTimestamp;
private final long mFromTimestamp;
private final long mToTimestamp;
private final @BatteryConsumer.PowerComponent int[] mPowerComponents;
private BatteryUsageStatsQuery(@NonNull Builder builder) {
mFlags = builder.mFlags;
@@ -85,6 +86,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mMaxStatsAgeMs = builder.mMaxStatsAgeMs;
mFromTimestamp = builder.mFromTimestamp;
mToTimestamp = builder.mToTimestamp;
mPowerComponents = builder.mPowerComponents;
}
@BatteryUsageStatsFlags
@@ -115,6 +117,14 @@ public final class BatteryUsageStatsQuery implements Parcelable {
return (mFlags & FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0;
}
/**
* Returns the power components that should be estimated or null if all power components
* are being requested.
*/
public int[] getPowerComponents() {
return mPowerComponents;
}
/**
* Returns the client's tolerance for stale battery stats. The data is allowed to be up to
* this many milliseconds out-of-date.
@@ -147,6 +157,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mMaxStatsAgeMs = in.readLong();
mFromTimestamp = in.readLong();
mToTimestamp = in.readLong();
mPowerComponents = in.createIntArray();
}
@Override
@@ -157,6 +168,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
dest.writeLong(mMaxStatsAgeMs);
dest.writeLong(mFromTimestamp);
dest.writeLong(mToTimestamp);
dest.writeIntArray(mPowerComponents);
}
@Override
@@ -187,6 +199,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
private long mMaxStatsAgeMs = DEFAULT_MAX_STATS_AGE_MS;
private long mFromTimestamp;
private long mToTimestamp;
private @BatteryConsumer.PowerComponent int[] mPowerComponents;
/**
* Builds a read-only BatteryUsageStatsQuery object.
@@ -247,6 +260,16 @@ public final class BatteryUsageStatsQuery implements Parcelable {
return this;
}
/**
* Requests to return only statistics for the specified power components. The default
* is all power components.
*/
public Builder includePowerComponents(
@BatteryConsumer.PowerComponent int[] powerComponents) {
mPowerComponents = powerComponents;
return this;
}
/**
* Requests to aggregate stored snapshots between the two supplied timestamps
* @param fromTimestamp Exclusive starting timestamp, as per System.currentTimeMillis()

View File

@@ -33,6 +33,11 @@ import java.util.List;
public class AmbientDisplayPowerCalculator extends PowerCalculator {
private final UsageBasedPowerEstimator[] mPowerEstimators;
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY;
}
public AmbientDisplayPowerCalculator(PowerProfile powerProfile) {
final int numDisplays = powerProfile.getNumDisplays();
mPowerEstimators = new UsageBasedPowerEstimator[numDisplays];

View File

@@ -43,6 +43,11 @@ public class AudioPowerCalculator extends PowerCalculator {
powerProfile.getAveragePower(PowerProfile.POWER_AUDIO));
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_AUDIO;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -16,6 +16,7 @@
package com.android.internal.os;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
@@ -29,6 +30,12 @@ import java.util.List;
*/
public class BatteryChargeCalculator extends PowerCalculator {
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
// Always apply this power calculator, no matter what power components were requested
return true;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -181,9 +181,22 @@ public class BatteryUsageStatsProvider {
getProcessForegroundTimeMs(uid, realtimeUs));
}
final int[] powerComponents = query.getPowerComponents();
final List<PowerCalculator> powerCalculators = getPowerCalculators();
for (int i = 0, count = powerCalculators.size(); i < count; i++) {
PowerCalculator powerCalculator = powerCalculators.get(i);
if (powerComponents != null) {
boolean include = false;
for (int j = 0; j < powerComponents.length; j++) {
if (powerCalculator.isPowerComponentSupported(powerComponents[j])) {
include = true;
break;
}
}
if (!include) {
continue;
}
}
powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs,
query);
}

View File

@@ -63,6 +63,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
mHasBluetoothPowerController = mIdleMa != 0 && mRxMa != 0 && mTxMa != 0;
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_BLUETOOTH;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -36,6 +36,11 @@ public class CameraPowerCalculator extends PowerCalculator {
profile.getAveragePower(PowerProfile.POWER_CAMERA));
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_CAMERA;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -92,6 +92,11 @@ public class CpuPowerCalculator extends PowerCalculator {
}
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_CPU;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -36,6 +36,11 @@ public class CustomMeasuredPowerCalculator extends PowerCalculator {
public CustomMeasuredPowerCalculator(PowerProfile powerProfile) {
}
@Override
public boolean isPowerComponentSupported(int powerComponent) {
return false;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -34,6 +34,11 @@ public class FlashlightPowerCalculator extends PowerCalculator {
profile.getAveragePower(PowerProfile.POWER_FLASHLIGHT));
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_FLASHLIGHT;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -43,6 +43,11 @@ public class GnssPowerCalculator extends PowerCalculator {
}
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_GNSS;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -46,6 +46,11 @@ public class IdlePowerCalculator extends PowerCalculator {
/ (60 * 60 * 1_000_000.0);
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_IDLE;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -15,6 +15,7 @@
*/
package com.android.internal.os;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
/**
@@ -32,6 +33,12 @@ public class MediaPowerCalculator extends PowerCalculator {
mVideoAveragePowerMa = profile.getAveragePower(PowerProfile.POWER_VIDEO);
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_VIDEO
|| powerComponent == BatteryConsumer.POWER_COMPONENT_AUDIO;
}
@Override
protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
long rawUptimeUs, int statsType) {

View File

@@ -23,6 +23,11 @@ public class MemoryPowerCalculator extends PowerCalculator {
}
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_MEMORY;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -85,6 +85,11 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_SCANNING, 0));
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -36,6 +36,11 @@ public class PhonePowerCalculator extends PowerCalculator {
powerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE));
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_PHONE;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -35,6 +35,14 @@ public abstract class PowerCalculator {
protected static final double MILLIAMPHOUR_PER_MICROCOULOMB = 1.0 / 1000.0 / 60.0 / 60.0;
/**
* Returns true if this power calculator computes power/duration for the specified
* power component.
*/
public abstract boolean isPowerComponentSupported(
@BatteryConsumer.PowerComponent int powerComponent);
/**
* Attributes the total amount of power used by this subsystem to various consumers such
* as apps.

View File

@@ -65,6 +65,11 @@ public class ScreenPowerCalculator extends PowerCalculator {
}
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_SCREEN;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -38,6 +38,11 @@ public class SensorPowerCalculator extends PowerCalculator {
}
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_SENSORS;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -61,6 +61,11 @@ public class SystemServicePowerCalculator extends PowerCalculator {
}
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -16,6 +16,7 @@
package com.android.internal.os;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
@@ -33,6 +34,11 @@ import java.util.List;
*/
public class UserPowerCalculator extends PowerCalculator {
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return true;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -40,6 +40,11 @@ public class VideoPowerCalculator extends PowerCalculator {
powerProfile.getAveragePower(PowerProfile.POWER_VIDEO));
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_VIDEO;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -43,6 +43,11 @@ public class WakelockPowerCalculator extends PowerCalculator {
profile.getAveragePower(PowerProfile.POWER_CPU_IDLE));
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_WAKELOCK;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -81,6 +81,11 @@ public class WifiPowerCalculator extends PowerCalculator {
&& mRxPowerEstimator.isSupported();
}
@Override
public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_WIFI;
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {

View File

@@ -50,19 +50,75 @@ import java.util.List;
@SmallTest
@RunWith(AndroidJUnit4.class)
@SuppressWarnings("GuardedBy")
public class BatteryUsageStatsProviderTest {
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
private static final long MINUTE_IN_MS = 60 * 1000;
private static final double PRECISION = 0.00001;
private final File mHistoryDir =
TestIoUtils.createTemporaryDirectory(getClass().getSimpleName());
@Rule
public final BatteryUsageStatsRule mStatsRule =
new BatteryUsageStatsRule(12345, mHistoryDir)
.setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0);
.setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0)
.setAveragePower(PowerProfile.POWER_AUDIO, 720.0);
@Test
public void test_getBatteryUsageStats() {
BatteryStatsImpl batteryStats = prepareBatteryStats();
Context context = InstrumentationRegistry.getContext();
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
final BatteryUsageStats batteryUsageStats =
provider.getBatteryUsageStats(BatteryUsageStatsQuery.DEFAULT);
final List<UidBatteryConsumer> uidBatteryConsumers =
batteryUsageStats.getUidBatteryConsumers();
final UidBatteryConsumer uidBatteryConsumer = uidBatteryConsumers.get(0);
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
.isEqualTo(60 * MINUTE_IN_MS);
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
.isEqualTo(10 * MINUTE_IN_MS);
assertThat(uidBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_AUDIO))
.isWithin(PRECISION).of(2.0);
assertThat(
uidBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isWithin(PRECISION).of(0.4);
assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(12345);
assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(54321);
}
@Test
public void test_selectPowerComponents() {
BatteryStatsImpl batteryStats = prepareBatteryStats();
Context context = InstrumentationRegistry.getContext();
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
final BatteryUsageStats batteryUsageStats =
provider.getBatteryUsageStats(
new BatteryUsageStatsQuery.Builder()
.includePowerComponents(
new int[]{BatteryConsumer.POWER_COMPONENT_AUDIO})
.build()
);
final List<UidBatteryConsumer> uidBatteryConsumers =
batteryUsageStats.getUidBatteryConsumers();
final UidBatteryConsumer uidBatteryConsumer = uidBatteryConsumers.get(0);
assertThat(uidBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_AUDIO))
.isWithin(PRECISION).of(2.0);
// FLASHLIGHT power estimation not requested, so the returned value is 0
assertThat(
uidBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isEqualTo(0);
}
private BatteryStatsImpl prepareBatteryStats() {
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
batteryStats.noteActivityResumedLocked(APP_UID,
@@ -82,24 +138,14 @@ public class BatteryUsageStatsProviderTest {
batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
batteryStats.noteFlashlightOnLocked(APP_UID, 1000, 1000);
batteryStats.noteFlashlightOffLocked(APP_UID, 5000, 5000);
batteryStats.noteAudioOnLocked(APP_UID, 10000, 10000);
batteryStats.noteAudioOffLocked(APP_UID, 20000, 20000);
mStatsRule.setCurrentTime(54321);
Context context = InstrumentationRegistry.getContext();
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
final BatteryUsageStats batteryUsageStats =
provider.getBatteryUsageStats(BatteryUsageStatsQuery.DEFAULT);
final List<UidBatteryConsumer> uidBatteryConsumers =
batteryUsageStats.getUidBatteryConsumers();
final UidBatteryConsumer uidBatteryConsumer = uidBatteryConsumers.get(0);
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
.isEqualTo(60 * MINUTE_IN_MS);
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
.isEqualTo(10 * MINUTE_IN_MS);
assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(12345);
assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(54321);
return batteryStats;
}
@Test

View File

@@ -126,6 +126,13 @@ public class UserPowerCalculatorTest {
}
private static class FakeAudioPowerCalculator extends PowerCalculator {
@Override
public boolean isPowerComponentSupported(
@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_AUDIO;
}
@Override
protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
@@ -135,6 +142,13 @@ public class UserPowerCalculatorTest {
}
private static class FakeVideoPowerCalculator extends PowerCalculator {
@Override
public boolean isPowerComponentSupported(
@BatteryConsumer.PowerComponent int powerComponent) {
return powerComponent == BatteryConsumer.POWER_COMPONENT_VIDEO;
}
@Override
protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {