diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java index 6e99bbbf2331e..c322258eda85a 100644 --- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java +++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java @@ -51,7 +51,7 @@ public class BluetoothPowerCalculator extends PowerCalculator { @Override public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { - if (!mHasBluetoothPowerController || !batteryStats.hasBluetoothActivityReporting()) { + if (!batteryStats.hasBluetoothActivityReporting()) { return; } @@ -69,8 +69,8 @@ public class BluetoothPowerCalculator extends PowerCalculator { final ControllerActivityCounter activityCounter = batteryStats.getBluetoothControllerActivity(); final long systemDurationMs = calculateDuration(activityCounter); - final double systemPowerMah = - calculatePowerMah(powerModel, measuredChargeUC, activityCounter); + final double systemPowerMah = calculatePowerMah(powerModel, measuredChargeUC, + activityCounter, query.shouldForceUsePowerProfileModel()); // Subtract what the apps used, but clamp to 0. final long systemComponentDurationMs = Math.max(0, systemDurationMs - total.durationMs); @@ -100,7 +100,8 @@ public class BluetoothPowerCalculator extends PowerCalculator { final ControllerActivityCounter activityCounter = app.getBatteryStatsUid().getBluetoothControllerActivity(); final long durationMs = calculateDuration(activityCounter); - final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter); + final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, + query.shouldForceUsePowerProfileModel()); app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah, powerModel); @@ -132,7 +133,7 @@ public class BluetoothPowerCalculator extends PowerCalculator { batteryStats.getBluetoothControllerActivity(); final long systemDurationMs = calculateDuration(activityCounter); final double systemPowerMah = - calculatePowerMah(powerModel, measuredChargeUC, activityCounter); + calculatePowerMah(powerModel, measuredChargeUC, activityCounter, false); // Subtract what the apps used, but clamp to 0. final double powerMah = Math.max(0, systemPowerMah - total.powerMah); @@ -165,7 +166,8 @@ public class BluetoothPowerCalculator extends PowerCalculator { final int powerModel = getPowerModel(measuredChargeUC); final ControllerActivityCounter activityCounter = u.getBluetoothControllerActivity(); final long durationMs = calculateDuration(activityCounter); - final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter); + final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, + false); app.bluetoothRunningTimeMs = durationMs; app.bluetoothPowerMah = powerMah; @@ -188,7 +190,7 @@ public class BluetoothPowerCalculator extends PowerCalculator { /** Returns bluetooth power usage based on the best data available. */ private double calculatePowerMah(@BatteryConsumer.PowerModel int powerModel, - long measuredChargeUC, ControllerActivityCounter counter) { + long measuredChargeUC, ControllerActivityCounter counter, boolean ignoreReportedPower) { if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) { return uCtoMah(measuredChargeUC); } @@ -197,12 +199,17 @@ public class BluetoothPowerCalculator extends PowerCalculator { return 0; } - final double powerMah = - counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) - / (double) (1000 * 60 * 60); + if (!ignoreReportedPower) { + final double powerMah = + counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) + / (double) (1000 * 60 * 60); + if (powerMah != 0) { + return powerMah; + } + } - if (powerMah != 0) { - return powerMah; + if (!mHasBluetoothPowerController) { + return 0; } final long idleTimeMs = diff --git a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java index 4a5528d2ca36a..79f7a5c9df187 100644 --- a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java @@ -40,6 +40,7 @@ public class AmbientDisplayPowerCalculatorTest { @Test public void testMeasuredEnergyBasedModel() { + mStatsRule.initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); stats.updateDisplayMeasuredEnergyStatsLocked(300_000_000, Display.STATE_ON, 0); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index f168b3c160cb4..464412f177226 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -506,6 +506,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(); clocks.realtime = 0; int screen = Display.STATE_OFF; @@ -590,6 +591,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.setOnBatteryInternal(true); final int uid1 = 11500; @@ -603,6 +605,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(); final int bucketA = 0; // Custom bucket 0 final int bucketB = 1; // Custom bucket 1 diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java index 1a6408ff7eb3f..8c9591ca8247e 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java @@ -51,12 +51,7 @@ public class BatteryUsageStatsRule implements TestRule { private final PowerProfile mPowerProfile; private final MockClocks mMockClocks = new MockClocks(); - private final MockBatteryStatsImpl mBatteryStats = new MockBatteryStatsImpl(mMockClocks) { - @Override - public boolean hasBluetoothActivityReporting() { - return true; - } - }; + private final MockBatteryStatsImpl mBatteryStats; private BatteryUsageStats mBatteryUsageStats; private boolean mScreenOn; @@ -64,6 +59,7 @@ public class BatteryUsageStatsRule implements TestRule { public BatteryUsageStatsRule() { Context context = InstrumentationRegistry.getContext(); mPowerProfile = spy(new PowerProfile(context, true /* forTest */)); + mBatteryStats = new MockBatteryStatsImpl(mMockClocks); mBatteryStats.setPowerProfile(mPowerProfile); } @@ -110,10 +106,17 @@ public class BatteryUsageStatsRule implements TestRule { /** Call only after setting the power profile information. */ public BatteryUsageStatsRule initMeasuredEnergyStatsLocked() { + return initMeasuredEnergyStatsLocked(new String[0]); + } + + /** Call only after setting the power profile information. */ + public BatteryUsageStatsRule initMeasuredEnergyStatsLocked( + String[] customPowerComponentNames) { final boolean[] supportedStandardBuckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; Arrays.fill(supportedStandardBuckets, true); - mBatteryStats.initMeasuredEnergyStatsLocked(supportedStandardBuckets, new String[0]); + mBatteryStats.initMeasuredEnergyStatsLocked(supportedStandardBuckets, + customPowerComponentNames); mBatteryStats.informThatAllExternalStatsAreFlushed(); return this; } diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java index 2de621c8fa6f5..5c8479406c03a 100644 --- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.UidTraffic; import android.os.BatteryConsumer; +import android.os.BatteryStats; import android.os.BatteryUsageStatsQuery; import android.os.Process; @@ -43,111 +44,89 @@ public class BluetoothPowerCalculatorTest { .setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE, 10.0) .setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX, 50.0) .setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX, 100.0) - .initMeasuredEnergyStatsLocked(); + .setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE, 3700); @Test public void testTimerBasedModel() { - setDurationsAndPower(mStatsRule.getUidStats(Process.BLUETOOTH_UID) - .getOrCreateBluetoothControllerActivityLocked(), - 1000, 2000, 3000, 0); - - setDurationsAndPower(mStatsRule.getUidStats(APP_UID) - .getOrCreateBluetoothControllerActivityLocked(), - 4000, 5000, 6000, 0); - - setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl) - mStatsRule.getBatteryStats().getBluetoothControllerActivity(), - 6000, 8000, 10000, 0); + setupBluetoothEnergyInfo(0, BatteryStats.POWER_DATA_UNAVAILABLE); BluetoothPowerCalculator calculator = new BluetoothPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); - assertBluetoothPowerAndDuration( - mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID), - 0.11388, 6000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertBluetoothPowerAndDuration( - mStatsRule.getUidBatteryConsumer(APP_UID), - 0.24722, 15000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertBluetoothPowerAndDuration( - mStatsRule.getDeviceBatteryConsumer(), - 0.40555, 24000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertBluetoothPowerAndDuration( - mStatsRule.getAppsBatteryConsumer(), - 0.36111, 21000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); + assertCalculatedPower(0.08216, 0.18169, 0.26388, 0.26386, + BatteryConsumer.POWER_MODEL_POWER_PROFILE); } @Test - public void testReportedPowerBasedModel() { - setDurationsAndPower(mStatsRule.getUidStats(Process.BLUETOOTH_UID) - .getOrCreateBluetoothControllerActivityLocked(), - 1000, 2000, 3000, 360000); - - setDurationsAndPower(mStatsRule.getUidStats(APP_UID) - .getOrCreateBluetoothControllerActivityLocked(), - 4000, 5000, 6000, 720000); - - setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl) - mStatsRule.getBatteryStats().getBluetoothControllerActivity(), - 6000, 8000, 10000, 1260000); + public void testReportedEnergyBasedModel() { + setupBluetoothEnergyInfo(4000000, BatteryStats.POWER_DATA_UNAVAILABLE); BluetoothPowerCalculator calculator = new BluetoothPowerCalculator(mStatsRule.getPowerProfile()); - mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); - - assertBluetoothPowerAndDuration( - mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID), - 0.1, 6000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertBluetoothPowerAndDuration( - mStatsRule.getUidBatteryConsumer(APP_UID), - 0.2, 15000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertBluetoothPowerAndDuration( - mStatsRule.getDeviceBatteryConsumer(), - 0.35, 24000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); - assertBluetoothPowerAndDuration( - mStatsRule.getAppsBatteryConsumer(), - 0.3, 21000, BatteryConsumer.POWER_MODEL_POWER_PROFILE); - } - - @Test - public void testMeasuredEnergyBasedModel() { - final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(1000, - BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 7000, 5000, 0, 100000); - info.setUidTraffic(new UidTraffic[]{ - new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000), - new UidTraffic(APP_UID, 3000, 4000) - }); - mStatsRule.getBatteryStats().updateBluetoothStateLocked(info, 1200000, 1000, 1000); - - final BluetoothPowerCalculator calculator = - new BluetoothPowerCalculator(mStatsRule.getPowerProfile()); - mStatsRule.apply(new BatteryUsageStatsQuery.Builder().includePowerModels().build(), calculator); - assertBluetoothPowerAndDuration( - mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID), - 0.10378, 3583, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertBluetoothPowerAndDuration( - mStatsRule.getUidBatteryConsumer(APP_UID), - 0.22950, 8416, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertBluetoothPowerAndDuration( - mStatsRule.getDeviceBatteryConsumer(), - 0.33333, 12000, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); - assertBluetoothPowerAndDuration( - mStatsRule.getAppsBatteryConsumer(), - 0.33329, 11999, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); + assertCalculatedPower(0.08216, 0.18169, 0.30030, 0.26386, + BatteryConsumer.POWER_MODEL_POWER_PROFILE); } - private void setDurationsAndPower( - BatteryStatsImpl.ControllerActivityCounterImpl controllerActivity, int idleDurationMs, - int rxDurationMs, int txDurationMs, long powerMaMs) { - controllerActivity.getIdleTimeCounter().addCountLocked(idleDurationMs); - controllerActivity.getRxTimeCounter().addCountLocked(rxDurationMs); - controllerActivity.getTxTimeCounters()[0].addCountLocked(txDurationMs); - controllerActivity.getPowerCounter().addCountLocked(powerMaMs); + @Test + public void testMeasuredEnergyBasedModel() { + mStatsRule.initMeasuredEnergyStatsLocked(); + setupBluetoothEnergyInfo(0, 1200000); + + final BluetoothPowerCalculator calculator = + new BluetoothPowerCalculator(mStatsRule.getPowerProfile()); + + mStatsRule.apply(calculator); + + assertCalculatedPower(0.10378, 0.22950, 0.33333, 0.33329, + BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); + } + + @Test + public void testIgnoreMeasuredEnergyBasedModel() { + mStatsRule.initMeasuredEnergyStatsLocked(); + setupBluetoothEnergyInfo(4000000, 1200000); + + BluetoothPowerCalculator calculator = + new BluetoothPowerCalculator(mStatsRule.getPowerProfile()); + + mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); + + assertCalculatedPower(0.08216, 0.18169, 0.26388, 0.26386, + BatteryConsumer.POWER_MODEL_POWER_PROFILE); + } + + private void setupBluetoothEnergyInfo(long reportedEnergyUc, long consumedEnergyUc) { + final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(1000, + BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 7000, 5000, 0, + reportedEnergyUc); + info.setUidTraffic(new UidTraffic[]{ + new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000), + new UidTraffic(APP_UID, 3000, 4000) + }); + mStatsRule.getBatteryStats().updateBluetoothStateLocked(info, + consumedEnergyUc, 1000, 1000); + } + + private void assertCalculatedPower(double bluetoothUidPowerMah, double appPowerMah, + double devicePowerMah, double allAppsPowerMah, int powerModelPowerProfile) { + assertBluetoothPowerAndDuration( + mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID), + bluetoothUidPowerMah, 3583, powerModelPowerProfile); + assertBluetoothPowerAndDuration( + mStatsRule.getUidBatteryConsumer(APP_UID), + appPowerMah, 8416, powerModelPowerProfile); + assertBluetoothPowerAndDuration( + mStatsRule.getDeviceBatteryConsumer(), + devicePowerMah, 12000, powerModelPowerProfile); + assertBluetoothPowerAndDuration( + mStatsRule.getAppsBatteryConsumer(), + allAppsPowerMah, 11999, powerModelPowerProfile); } private void assertBluetoothPowerAndDuration(@Nullable BatteryConsumer batteryConsumer, @@ -162,7 +141,6 @@ public class BluetoothPowerCalculatorTest { long usageDurationMillis = batteryConsumer.getUsageDurationMillis( BatteryConsumer.POWER_COMPONENT_BLUETOOTH); - assertThat(usageDurationMillis).isEqualTo(durationMs); } } diff --git a/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java index f8c2bc6c3d80a..5334f07d28f5c 100644 --- a/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/CustomMeasuredPowerCalculatorTest.java @@ -38,7 +38,8 @@ public class CustomMeasuredPowerCalculatorTest { private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42; @Rule - public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(); + public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() + .initMeasuredEnergyStatsLocked(new String[]{"CUSTOM_COMPONENT1", "CUSTOM_COMPONENT2"}); @Test public void testMeasuredEnergyCopiedIntoBatteryConsumers() { diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java index 7a7d9f541328c..80def71ce8124 100644 --- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java @@ -48,13 +48,6 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { setExternalStatsSyncLocked(new DummyExternalStatsSync()); informThatAllExternalStatsAreFlushed(); - final boolean[] supportedStandardBuckets = - new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; - Arrays.fill(supportedStandardBuckets, true); - final String[] customBucketNames = {"FOO", "BAR"}; - mGlobalMeasuredEnergyStats = - new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); - // A no-op handler. mHandler = new Handler(Looper.getMainLooper()) { }; @@ -64,6 +57,15 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { this(new MockClocks()); } + public void initMeasuredEnergyStats() { + final boolean[] supportedStandardBuckets = + new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; + Arrays.fill(supportedStandardBuckets, true); + final String[] customBucketNames = {"FOO", "BAR"}; + mGlobalMeasuredEnergyStats = + new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames); + } + public TimeBase getOnBatteryTimeBase() { return mOnBatteryTimeBase; } diff --git a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java index 4c29c204618af..c695fc9eb87d8 100644 --- a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java @@ -47,6 +47,7 @@ public class ScreenPowerCalculatorTest { @Test public void testMeasuredEnergyBasedModel() { + mStatsRule.initMeasuredEnergyStatsLocked(); BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats(); batteryStats.noteScreenStateLocked(Display.STATE_ON, 0, 0, 0);