Loading core/java/android/os/BatteryConsumer.java +1 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ public abstract class BatteryConsumer { POWER_COMPONENT_CPU, POWER_COMPONENT_MOBILE_RADIO, POWER_COMPONENT_WIFI, POWER_COMPONENT_BLUETOOTH, }; static final int COLUMN_INDEX_BATTERY_CONSUMER_TYPE = 0; Loading core/java/android/os/BatteryStats.java +10 −0 Original line number Diff line number Diff line Loading @@ -1036,6 +1036,16 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getBluetoothMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) of the uid's bluetooth usage * when in the specified process state. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ public abstract long getBluetoothMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState); /** * Returns the battery consumption (in microcoulombs) of the uid's cpu usage, derived from * on device power measurement data. Loading core/java/com/android/internal/os/BatteryStatsImpl.java +22 −1 Original line number Diff line number Diff line Loading @@ -265,6 +265,7 @@ public class BatteryStatsImpl extends BatteryStats { MeasuredEnergyStats.POWER_BUCKET_CPU, MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, MeasuredEnergyStats.POWER_BUCKET_WIFI, MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, }; // TimeInState counters need NUM_PROCESS_STATE states in order to accommodate Loading Loading @@ -8371,6 +8372,11 @@ public class BatteryStatsImpl extends BatteryStats { if (wifiControllerActivity != null) { wifiControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs); } final ControllerActivityCounterImpl bluetoothControllerActivity = getBluetoothControllerActivity(); if (bluetoothControllerActivity != null) { bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs); } final MeasuredEnergyStats energyStats = getOrCreateMeasuredEnergyStatsIfSupportedLocked(); if (energyStats != null) { Loading Loading @@ -8718,7 +8724,7 @@ public class BatteryStatsImpl extends BatteryStats { } @Override public ControllerActivityCounter getBluetoothControllerActivity() { public ControllerActivityCounterImpl getBluetoothControllerActivity() { return mBluetoothControllerActivity; } Loading Loading @@ -8837,6 +8843,14 @@ public class BatteryStatsImpl extends BatteryStats { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH); } @GuardedBy("mBsi") @Override public long getBluetoothMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState) { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, processState); } @GuardedBy("mBsi") @Override public long getCpuMeasuredBatteryConsumptionUC() { Loading Loading @@ -11424,6 +11438,13 @@ public class BatteryStatsImpl extends BatteryStats { wifiControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs); } final ControllerActivityCounterImpl bluetoothControllerActivity = getBluetoothControllerActivity(); if (bluetoothControllerActivity != null) { bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs); } final MeasuredEnergyStats energyStats = getOrCreateMeasuredEnergyStatsIfSupportedLocked(); if (energyStats != null) { Loading core/java/com/android/internal/os/BluetoothPowerCalculator.java +152 −70 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.internal.os; import android.annotation.Nullable; import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryStats.ControllerActivityCounter; Loading @@ -26,19 +27,33 @@ import android.os.UserHandle; import android.util.Log; import android.util.SparseArray; import java.util.Arrays; import java.util.List; public class BluetoothPowerCalculator extends PowerCalculator { private static final String TAG = "BluetoothPowerCalc"; private static final boolean DEBUG = BatteryStatsHelper.DEBUG; private static final BatteryConsumer.Key[] UNINITIALIZED_KEYS = new BatteryConsumer.Key[0]; private final double mIdleMa; private final double mRxMa; private final double mTxMa; private final boolean mHasBluetoothPowerController; private static class PowerAndDuration { // Return value of BT duration per app public long durationMs; // Return value of BT power per app public double powerMah; public BatteryConsumer.Key[] keys; public double[] powerPerKeyMah; // Aggregated BT duration across all apps public long totalDurationMs; // Aggregated BT power across all apps public double totalPowerMah; } public BluetoothPowerCalculator(PowerProfile profile) { Loading @@ -55,59 +70,88 @@ public class BluetoothPowerCalculator extends PowerCalculator { return; } final PowerAndDuration total = new PowerAndDuration(); BatteryConsumer.Key[] keys = UNINITIALIZED_KEYS; final PowerAndDuration powerAndDuration = new PowerAndDuration(); final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, total, query); if (keys == UNINITIALIZED_KEYS) { if (query.isProcessStateDataNeeded()) { keys = app.getKeys(BatteryConsumer.POWER_COMPONENT_BLUETOOTH); powerAndDuration.keys = keys; powerAndDuration.powerPerKeyMah = new double[keys.length]; } else { keys = null; } } calculateApp(app, powerAndDuration, query); } final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(measuredChargeUC, query); final ControllerActivityCounter activityCounter = batteryStats.getBluetoothControllerActivity(); final long systemDurationMs = calculateDuration(activityCounter); final double systemPowerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel()); calculatePowerAndDuration(null, powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel(), powerAndDuration); // Subtract what the apps used, but clamp to 0. final long systemComponentDurationMs = Math.max(0, systemDurationMs - total.durationMs); final long systemComponentDurationMs = Math.max(0, powerAndDuration.durationMs - powerAndDuration.totalDurationMs); if (DEBUG) { Log.d(TAG, "Bluetooth active: time=" + (systemComponentDurationMs) + " power=" + formatCharge(systemPowerMah)); + " power=" + formatCharge(powerAndDuration.powerMah)); } builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, systemDurationMs) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, Math.max(systemPowerMah, total.powerMah), powerModel); Math.max(powerAndDuration.powerMah, powerAndDuration.totalPowerMah), powerModel); builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, total.durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, total.powerMah, .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.totalDurationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.totalPowerMah, powerModel); } private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total, private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration powerAndDuration, BatteryUsageStatsQuery query) { final long measuredChargeUC = app.getBatteryStatsUid().getBluetoothMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(measuredChargeUC, query); final ControllerActivityCounter activityCounter = app.getBatteryStatsUid().getBluetoothControllerActivity(); final long durationMs = calculateDuration(activityCounter); final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel()); calculatePowerAndDuration(app.getBatteryStatsUid(), powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel(), powerAndDuration); app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah, powerModel); app.setUsageDurationMillis( BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.durationMs) .setConsumedPower( BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.powerMah, powerModel); powerAndDuration.totalDurationMs += powerAndDuration.durationMs; powerAndDuration.totalPowerMah += powerAndDuration.powerMah; if (query.isProcessStateDataNeeded() && powerAndDuration.keys != null) { for (int j = 0; j < powerAndDuration.keys.length; j++) { BatteryConsumer.Key key = powerAndDuration.keys[j]; final int processState = key.processState; if (processState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED) { // Already populated with the powerAndDuration across all process states continue; } total.durationMs += durationMs; total.powerMah += powerMah; app.setConsumedPower(key, powerAndDuration.powerPerKeyMah[j], powerModel); } } } @Override Loading @@ -117,12 +161,12 @@ public class BluetoothPowerCalculator extends PowerCalculator { return; } PowerAndDuration total = new PowerAndDuration(); PowerAndDuration powerAndDuration = new PowerAndDuration(); for (int i = sippers.size() - 1; i >= 0; i--) { final BatterySipper app = sippers.get(i); if (app.drainType == BatterySipper.DrainType.APP) { calculateApp(app, app.uidObj, statsType, total); calculateApp(app, app.uidObj, statsType, powerAndDuration); } } Loading @@ -131,13 +175,14 @@ public class BluetoothPowerCalculator extends PowerCalculator { final int powerModel = getPowerModel(measuredChargeUC); final ControllerActivityCounter activityCounter = batteryStats.getBluetoothControllerActivity(); final long systemDurationMs = calculateDuration(activityCounter); final double systemPowerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, false); calculatePowerAndDuration(null, powerModel, measuredChargeUC, activityCounter, false, powerAndDuration); // Subtract what the apps used, but clamp to 0. final double powerMah = Math.max(0, systemPowerMah - total.powerMah); final long durationMs = Math.max(0, systemDurationMs - total.durationMs); final double powerMah = Math.max(0, powerAndDuration.powerMah - powerAndDuration.totalPowerMah); final long durationMs = Math.max(0, powerAndDuration.durationMs - powerAndDuration.totalDurationMs); if (DEBUG && powerMah != 0) { Log.d(TAG, "Bluetooth active: time=" + (durationMs) + " power=" + formatCharge(powerMah)); Loading @@ -160,65 +205,102 @@ public class BluetoothPowerCalculator extends PowerCalculator { } private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType, PowerAndDuration total) { PowerAndDuration powerAndDuration) { final long measuredChargeUC = u.getBluetoothMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(measuredChargeUC); final ControllerActivityCounter activityCounter = u.getBluetoothControllerActivity(); final long durationMs = calculateDuration(activityCounter); final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, false); calculatePowerAndDuration(u, powerModel, measuredChargeUC, activityCounter, false, powerAndDuration); app.bluetoothRunningTimeMs = durationMs; app.bluetoothPowerMah = powerMah; app.bluetoothRunningTimeMs = powerAndDuration.durationMs; app.bluetoothPowerMah = powerAndDuration.powerMah; app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType); app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType); total.durationMs += durationMs; total.powerMah += powerMah; powerAndDuration.totalDurationMs += powerAndDuration.durationMs; powerAndDuration.totalPowerMah += powerAndDuration.powerMah; } private long calculateDuration(ControllerActivityCounter counter) { /** Returns bluetooth power usage based on the best data available. */ private void calculatePowerAndDuration(@Nullable BatteryStats.Uid uid, @BatteryConsumer.PowerModel int powerModel, long measuredChargeUC, ControllerActivityCounter counter, boolean ignoreReportedPower, PowerAndDuration powerAndDuration) { if (counter == null) { return 0; powerAndDuration.durationMs = 0; powerAndDuration.powerMah = 0; if (powerAndDuration.powerPerKeyMah != null) { Arrays.fill(powerAndDuration.powerPerKeyMah, 0); } return counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) + counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) + counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED); return; } /** Returns bluetooth power usage based on the best data available. */ private double calculatePowerMah(@BatteryConsumer.PowerModel int powerModel, long measuredChargeUC, ControllerActivityCounter counter, boolean ignoreReportedPower) { final BatteryStats.LongCounter idleTimeCounter = counter.getIdleTimeCounter(); final BatteryStats.LongCounter rxTimeCounter = counter.getRxTimeCounter(); final BatteryStats.LongCounter txTimeCounter = counter.getTxTimeCounters()[0]; final long idleTimeMs = idleTimeCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long rxTimeMs = rxTimeCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long txTimeMs = txTimeCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED); powerAndDuration.durationMs = idleTimeMs + rxTimeMs + txTimeMs; if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) { return uCtoMah(measuredChargeUC); powerAndDuration.powerMah = uCtoMah(measuredChargeUC); if (uid != null && powerAndDuration.keys != null) { for (int i = 0; i < powerAndDuration.keys.length; i++) { BatteryConsumer.Key key = powerAndDuration.keys[i]; final int processState = key.processState; if (processState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED) { // Already populated with the powerAndDuration across all process states continue; } if (counter == null) { return 0; powerAndDuration.powerPerKeyMah[i] = uCtoMah(uid.getBluetoothMeasuredBatteryConsumptionUC(processState)); } } } else { if (!ignoreReportedPower) { final double powerMah = counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) / (double) (1000 * 60 * 60); if (powerMah != 0) { return powerMah; powerAndDuration.powerMah = powerMah; if (powerAndDuration.powerPerKeyMah != null) { // Leave this use case unsupported: used energy is reported // via BluetoothActivityEnergyInfo rather than PowerStats HAL. Arrays.fill(powerAndDuration.powerPerKeyMah, 0); } return; } } if (!mHasBluetoothPowerController) { return 0; if (mHasBluetoothPowerController) { powerAndDuration.powerMah = calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs); if (powerAndDuration.keys != null) { for (int i = 0; i < powerAndDuration.keys.length; i++) { BatteryConsumer.Key key = powerAndDuration.keys[i]; final int processState = key.processState; if (processState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED) { // Already populated with the powerAndDuration across all process states continue; } final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED); return calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs); powerAndDuration.powerPerKeyMah[i] = calculatePowerMah( rxTimeCounter.getCountForProcessState(processState), txTimeCounter.getCountForProcessState(processState), idleTimeCounter.getCountForProcessState(processState)); } } } else { powerAndDuration.powerMah = 0; if (powerAndDuration.powerPerKeyMah != null) { Arrays.fill(powerAndDuration.powerPerKeyMah, 0); } } } } /** Returns estimated bluetooth power usage based on usage times. */ Loading core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ public class BatteryUsageStatsTest { final Parcel parcel = Parcel.obtain(); parcel.writeParcelable(outBatteryUsageStats, 0); assertThat(parcel.dataSize()).isLessThan(6000); assertThat(parcel.dataSize()).isLessThan(7000); parcel.setDataPosition(0); Loading Loading
core/java/android/os/BatteryConsumer.java +1 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ public abstract class BatteryConsumer { POWER_COMPONENT_CPU, POWER_COMPONENT_MOBILE_RADIO, POWER_COMPONENT_WIFI, POWER_COMPONENT_BLUETOOTH, }; static final int COLUMN_INDEX_BATTERY_CONSUMER_TYPE = 0; Loading
core/java/android/os/BatteryStats.java +10 −0 Original line number Diff line number Diff line Loading @@ -1036,6 +1036,16 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getBluetoothMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) of the uid's bluetooth usage * when in the specified process state. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ public abstract long getBluetoothMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState); /** * Returns the battery consumption (in microcoulombs) of the uid's cpu usage, derived from * on device power measurement data. Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +22 −1 Original line number Diff line number Diff line Loading @@ -265,6 +265,7 @@ public class BatteryStatsImpl extends BatteryStats { MeasuredEnergyStats.POWER_BUCKET_CPU, MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, MeasuredEnergyStats.POWER_BUCKET_WIFI, MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, }; // TimeInState counters need NUM_PROCESS_STATE states in order to accommodate Loading Loading @@ -8371,6 +8372,11 @@ public class BatteryStatsImpl extends BatteryStats { if (wifiControllerActivity != null) { wifiControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs); } final ControllerActivityCounterImpl bluetoothControllerActivity = getBluetoothControllerActivity(); if (bluetoothControllerActivity != null) { bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedTimeMs); } final MeasuredEnergyStats energyStats = getOrCreateMeasuredEnergyStatsIfSupportedLocked(); if (energyStats != null) { Loading Loading @@ -8718,7 +8724,7 @@ public class BatteryStatsImpl extends BatteryStats { } @Override public ControllerActivityCounter getBluetoothControllerActivity() { public ControllerActivityCounterImpl getBluetoothControllerActivity() { return mBluetoothControllerActivity; } Loading Loading @@ -8837,6 +8843,14 @@ public class BatteryStatsImpl extends BatteryStats { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH); } @GuardedBy("mBsi") @Override public long getBluetoothMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState) { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, processState); } @GuardedBy("mBsi") @Override public long getCpuMeasuredBatteryConsumptionUC() { Loading Loading @@ -11424,6 +11438,13 @@ public class BatteryStatsImpl extends BatteryStats { wifiControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs); } final ControllerActivityCounterImpl bluetoothControllerActivity = getBluetoothControllerActivity(); if (bluetoothControllerActivity != null) { bluetoothControllerActivity.setState(batteryConsumerProcessState, elapsedRealtimeMs); } final MeasuredEnergyStats energyStats = getOrCreateMeasuredEnergyStatsIfSupportedLocked(); if (energyStats != null) { Loading
core/java/com/android/internal/os/BluetoothPowerCalculator.java +152 −70 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.internal.os; import android.annotation.Nullable; import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryStats.ControllerActivityCounter; Loading @@ -26,19 +27,33 @@ import android.os.UserHandle; import android.util.Log; import android.util.SparseArray; import java.util.Arrays; import java.util.List; public class BluetoothPowerCalculator extends PowerCalculator { private static final String TAG = "BluetoothPowerCalc"; private static final boolean DEBUG = BatteryStatsHelper.DEBUG; private static final BatteryConsumer.Key[] UNINITIALIZED_KEYS = new BatteryConsumer.Key[0]; private final double mIdleMa; private final double mRxMa; private final double mTxMa; private final boolean mHasBluetoothPowerController; private static class PowerAndDuration { // Return value of BT duration per app public long durationMs; // Return value of BT power per app public double powerMah; public BatteryConsumer.Key[] keys; public double[] powerPerKeyMah; // Aggregated BT duration across all apps public long totalDurationMs; // Aggregated BT power across all apps public double totalPowerMah; } public BluetoothPowerCalculator(PowerProfile profile) { Loading @@ -55,59 +70,88 @@ public class BluetoothPowerCalculator extends PowerCalculator { return; } final PowerAndDuration total = new PowerAndDuration(); BatteryConsumer.Key[] keys = UNINITIALIZED_KEYS; final PowerAndDuration powerAndDuration = new PowerAndDuration(); final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, total, query); if (keys == UNINITIALIZED_KEYS) { if (query.isProcessStateDataNeeded()) { keys = app.getKeys(BatteryConsumer.POWER_COMPONENT_BLUETOOTH); powerAndDuration.keys = keys; powerAndDuration.powerPerKeyMah = new double[keys.length]; } else { keys = null; } } calculateApp(app, powerAndDuration, query); } final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(measuredChargeUC, query); final ControllerActivityCounter activityCounter = batteryStats.getBluetoothControllerActivity(); final long systemDurationMs = calculateDuration(activityCounter); final double systemPowerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel()); calculatePowerAndDuration(null, powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel(), powerAndDuration); // Subtract what the apps used, but clamp to 0. final long systemComponentDurationMs = Math.max(0, systemDurationMs - total.durationMs); final long systemComponentDurationMs = Math.max(0, powerAndDuration.durationMs - powerAndDuration.totalDurationMs); if (DEBUG) { Log.d(TAG, "Bluetooth active: time=" + (systemComponentDurationMs) + " power=" + formatCharge(systemPowerMah)); + " power=" + formatCharge(powerAndDuration.powerMah)); } builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, systemDurationMs) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, Math.max(systemPowerMah, total.powerMah), powerModel); Math.max(powerAndDuration.powerMah, powerAndDuration.totalPowerMah), powerModel); builder.getAggregateBatteryConsumerBuilder( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, total.durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, total.powerMah, .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.totalDurationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.totalPowerMah, powerModel); } private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total, private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration powerAndDuration, BatteryUsageStatsQuery query) { final long measuredChargeUC = app.getBatteryStatsUid().getBluetoothMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(measuredChargeUC, query); final ControllerActivityCounter activityCounter = app.getBatteryStatsUid().getBluetoothControllerActivity(); final long durationMs = calculateDuration(activityCounter); final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel()); calculatePowerAndDuration(app.getBatteryStatsUid(), powerModel, measuredChargeUC, activityCounter, query.shouldForceUsePowerProfileModel(), powerAndDuration); app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah, powerModel); app.setUsageDurationMillis( BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.durationMs) .setConsumedPower( BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.powerMah, powerModel); powerAndDuration.totalDurationMs += powerAndDuration.durationMs; powerAndDuration.totalPowerMah += powerAndDuration.powerMah; if (query.isProcessStateDataNeeded() && powerAndDuration.keys != null) { for (int j = 0; j < powerAndDuration.keys.length; j++) { BatteryConsumer.Key key = powerAndDuration.keys[j]; final int processState = key.processState; if (processState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED) { // Already populated with the powerAndDuration across all process states continue; } total.durationMs += durationMs; total.powerMah += powerMah; app.setConsumedPower(key, powerAndDuration.powerPerKeyMah[j], powerModel); } } } @Override Loading @@ -117,12 +161,12 @@ public class BluetoothPowerCalculator extends PowerCalculator { return; } PowerAndDuration total = new PowerAndDuration(); PowerAndDuration powerAndDuration = new PowerAndDuration(); for (int i = sippers.size() - 1; i >= 0; i--) { final BatterySipper app = sippers.get(i); if (app.drainType == BatterySipper.DrainType.APP) { calculateApp(app, app.uidObj, statsType, total); calculateApp(app, app.uidObj, statsType, powerAndDuration); } } Loading @@ -131,13 +175,14 @@ public class BluetoothPowerCalculator extends PowerCalculator { final int powerModel = getPowerModel(measuredChargeUC); final ControllerActivityCounter activityCounter = batteryStats.getBluetoothControllerActivity(); final long systemDurationMs = calculateDuration(activityCounter); final double systemPowerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, false); calculatePowerAndDuration(null, powerModel, measuredChargeUC, activityCounter, false, powerAndDuration); // Subtract what the apps used, but clamp to 0. final double powerMah = Math.max(0, systemPowerMah - total.powerMah); final long durationMs = Math.max(0, systemDurationMs - total.durationMs); final double powerMah = Math.max(0, powerAndDuration.powerMah - powerAndDuration.totalPowerMah); final long durationMs = Math.max(0, powerAndDuration.durationMs - powerAndDuration.totalDurationMs); if (DEBUG && powerMah != 0) { Log.d(TAG, "Bluetooth active: time=" + (durationMs) + " power=" + formatCharge(powerMah)); Loading @@ -160,65 +205,102 @@ public class BluetoothPowerCalculator extends PowerCalculator { } private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType, PowerAndDuration total) { PowerAndDuration powerAndDuration) { final long measuredChargeUC = u.getBluetoothMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(measuredChargeUC); final ControllerActivityCounter activityCounter = u.getBluetoothControllerActivity(); final long durationMs = calculateDuration(activityCounter); final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter, false); calculatePowerAndDuration(u, powerModel, measuredChargeUC, activityCounter, false, powerAndDuration); app.bluetoothRunningTimeMs = durationMs; app.bluetoothPowerMah = powerMah; app.bluetoothRunningTimeMs = powerAndDuration.durationMs; app.bluetoothPowerMah = powerAndDuration.powerMah; app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType); app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType); total.durationMs += durationMs; total.powerMah += powerMah; powerAndDuration.totalDurationMs += powerAndDuration.durationMs; powerAndDuration.totalPowerMah += powerAndDuration.powerMah; } private long calculateDuration(ControllerActivityCounter counter) { /** Returns bluetooth power usage based on the best data available. */ private void calculatePowerAndDuration(@Nullable BatteryStats.Uid uid, @BatteryConsumer.PowerModel int powerModel, long measuredChargeUC, ControllerActivityCounter counter, boolean ignoreReportedPower, PowerAndDuration powerAndDuration) { if (counter == null) { return 0; powerAndDuration.durationMs = 0; powerAndDuration.powerMah = 0; if (powerAndDuration.powerPerKeyMah != null) { Arrays.fill(powerAndDuration.powerPerKeyMah, 0); } return counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) + counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) + counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED); return; } /** Returns bluetooth power usage based on the best data available. */ private double calculatePowerMah(@BatteryConsumer.PowerModel int powerModel, long measuredChargeUC, ControllerActivityCounter counter, boolean ignoreReportedPower) { final BatteryStats.LongCounter idleTimeCounter = counter.getIdleTimeCounter(); final BatteryStats.LongCounter rxTimeCounter = counter.getRxTimeCounter(); final BatteryStats.LongCounter txTimeCounter = counter.getTxTimeCounters()[0]; final long idleTimeMs = idleTimeCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long rxTimeMs = rxTimeCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long txTimeMs = txTimeCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED); powerAndDuration.durationMs = idleTimeMs + rxTimeMs + txTimeMs; if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) { return uCtoMah(measuredChargeUC); powerAndDuration.powerMah = uCtoMah(measuredChargeUC); if (uid != null && powerAndDuration.keys != null) { for (int i = 0; i < powerAndDuration.keys.length; i++) { BatteryConsumer.Key key = powerAndDuration.keys[i]; final int processState = key.processState; if (processState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED) { // Already populated with the powerAndDuration across all process states continue; } if (counter == null) { return 0; powerAndDuration.powerPerKeyMah[i] = uCtoMah(uid.getBluetoothMeasuredBatteryConsumptionUC(processState)); } } } else { if (!ignoreReportedPower) { final double powerMah = counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED) / (double) (1000 * 60 * 60); if (powerMah != 0) { return powerMah; powerAndDuration.powerMah = powerMah; if (powerAndDuration.powerPerKeyMah != null) { // Leave this use case unsupported: used energy is reported // via BluetoothActivityEnergyInfo rather than PowerStats HAL. Arrays.fill(powerAndDuration.powerPerKeyMah, 0); } return; } } if (!mHasBluetoothPowerController) { return 0; if (mHasBluetoothPowerController) { powerAndDuration.powerMah = calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs); if (powerAndDuration.keys != null) { for (int i = 0; i < powerAndDuration.keys.length; i++) { BatteryConsumer.Key key = powerAndDuration.keys[i]; final int processState = key.processState; if (processState == BatteryConsumer.PROCESS_STATE_UNSPECIFIED) { // Already populated with the powerAndDuration across all process states continue; } final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED); final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED); return calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs); powerAndDuration.powerPerKeyMah[i] = calculatePowerMah( rxTimeCounter.getCountForProcessState(processState), txTimeCounter.getCountForProcessState(processState), idleTimeCounter.getCountForProcessState(processState)); } } } else { powerAndDuration.powerMah = 0; if (powerAndDuration.powerPerKeyMah != null) { Arrays.fill(powerAndDuration.powerPerKeyMah, 0); } } } } /** Returns estimated bluetooth power usage based on usage times. */ Loading
core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ public class BatteryUsageStatsTest { final Parcel parcel = Parcel.obtain(); parcel.writeParcelable(outBatteryUsageStats, 0); assertThat(parcel.dataSize()).isLessThan(6000); assertThat(parcel.dataSize()).isLessThan(7000); parcel.setDataPosition(0); Loading