Merge "Attribution of Bluetooth power per process state"

This commit is contained in:
Dmitri Plotnikov
2022-01-21 00:01:02 +00:00
committed by Android (Google) Code Review
6 changed files with 322 additions and 80 deletions

View File

@@ -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;

View File

@@ -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.

View File

@@ -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
@@ -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) {
@@ -8718,7 +8724,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
@Override
public ControllerActivityCounter getBluetoothControllerActivity() {
public ControllerActivityCounterImpl getBluetoothControllerActivity() {
return mBluetoothControllerActivity;
}
@@ -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() {
@@ -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) {

View File

@@ -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;
@@ -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) {
@@ -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)
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
.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,
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
.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);
total.durationMs += durationMs;
total.powerMah += powerMah;
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;
}
app.setConsumedPower(key, powerAndDuration.powerPerKeyMah[j], powerModel);
}
}
}
@Override
@@ -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);
}
}
@@ -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));
@@ -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;
}
private long calculateDuration(ControllerActivityCounter counter) {
if (counter == null) {
return 0;
}
return counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED)
+ counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED)
+ counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
powerAndDuration.totalDurationMs += powerAndDuration.durationMs;
powerAndDuration.totalPowerMah += powerAndDuration.powerMah;
}
/** Returns bluetooth power usage based on the best data available. */
private double calculatePowerMah(@BatteryConsumer.PowerModel int powerModel,
long measuredChargeUC, ControllerActivityCounter counter, boolean ignoreReportedPower) {
if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
return uCtoMah(measuredChargeUC);
}
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;
}
if (!ignoreReportedPower) {
final double powerMah =
counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED)
/ (double) (1000 * 60 * 60);
if (powerMah != 0) {
return powerMah;
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) {
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;
}
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) {
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) {
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;
}
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);
}
}
}
if (!mHasBluetoothPowerController) {
return 0;
}
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);
}
/** Returns estimated bluetooth power usage based on usage times. */

View File

@@ -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);

View File

@@ -25,18 +25,20 @@ import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
@SmallTest
@SuppressWarnings("GuardedBy")
public class BluetoothPowerCalculatorTest {
private static final double PRECISION = 0.00001;
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
@@ -61,6 +63,69 @@ public class BluetoothPowerCalculatorTest {
BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
@Test
public void testTimerBasedModel_byProcessState() {
mStatsRule.setTime(1000, 1000);
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
BatteryStatsImpl.Uid uid = batteryStats.getUidStatsLocked(APP_UID);
uid.setProcessStateForTest(
BatteryStats.Uid.PROCESS_STATE_FOREGROUND, 1000);
BluetoothActivityEnergyInfo info1 = new BluetoothActivityEnergyInfo(2000,
BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 1000, 2000, 3000, 4000);
info1.setUidTraffic(ImmutableList.of(
new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000),
new UidTraffic(APP_UID, 3000, 4000)));
batteryStats.updateBluetoothStateLocked(info1,
0/*1_000_000*/, 2000, 2000);
uid.setProcessStateForTest(
BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 3000);
BluetoothActivityEnergyInfo info2 = new BluetoothActivityEnergyInfo(4000,
BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 5000, 6000, 7000, 8000);
info2.setUidTraffic(ImmutableList.of(
new UidTraffic(Process.BLUETOOTH_UID, 5000, 6000),
new UidTraffic(APP_UID, 7000, 8000)));
batteryStats.updateBluetoothStateLocked(info2,
0 /*5_000_000 */, 4000, 4000);
BluetoothPowerCalculator calculator =
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(new BatteryUsageStatsQuery.Builder()
.powerProfileModeledOnly()
.includePowerModels()
.includeProcessStateData()
.build(), calculator);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH))
.isEqualTo(6166);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH))
.isWithin(PRECISION).of(0.1226666);
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_BLUETOOTH))
.isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
final BatteryConsumer.Key foreground = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_FOREGROUND);
final BatteryConsumer.Key background = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_BACKGROUND);
final BatteryConsumer.Key fgs = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.081);
assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.0416666);
assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
}
@Test
public void testReportedEnergyBasedModel() {
setupBluetoothEnergyInfo(4000000, BatteryStats.POWER_DATA_UNAVAILABLE);
@@ -89,6 +154,70 @@ public class BluetoothPowerCalculatorTest {
BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
@Test
public void testMeasuredEnergyBasedModel_byProcessState() {
mStatsRule.initMeasuredEnergyStatsLocked();
mStatsRule.setTime(1000, 1000);
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
BatteryStatsImpl.Uid uid = batteryStats.getUidStatsLocked(APP_UID);
uid.setProcessStateForTest(
BatteryStats.Uid.PROCESS_STATE_FOREGROUND, 1000);
BluetoothActivityEnergyInfo info1 = new BluetoothActivityEnergyInfo(2000,
BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 1000, 2000, 3000, 4000);
info1.setUidTraffic(ImmutableList.of(
new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000),
new UidTraffic(APP_UID, 3000, 4000)));
batteryStats.updateBluetoothStateLocked(info1,
1_000_000, 2000, 2000);
uid.setProcessStateForTest(
BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 3000);
BluetoothActivityEnergyInfo info2 = new BluetoothActivityEnergyInfo(4000,
BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 5000, 6000, 7000, 8000);
info2.setUidTraffic(ImmutableList.of(
new UidTraffic(Process.BLUETOOTH_UID, 5000, 6000),
new UidTraffic(APP_UID, 7000, 8000)));
batteryStats.updateBluetoothStateLocked(info2,
5_000_000, 4000, 4000);
BluetoothPowerCalculator calculator =
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(new BatteryUsageStatsQuery.Builder()
.includePowerModels()
.includeProcessStateData()
.build(), calculator);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_BLUETOOTH))
.isEqualTo(6166);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH))
.isWithin(PRECISION).of(0.8220561);
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_BLUETOOTH))
.isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
final BatteryConsumer.Key foreground = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_FOREGROUND);
final BatteryConsumer.Key background = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_BACKGROUND);
final BatteryConsumer.Key fgs = uidConsumer.getKey(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.4965352);
assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.3255208);
assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
}
@Test
public void testIgnoreMeasuredEnergyBasedModel() {
mStatsRule.initMeasuredEnergyStatsLocked();
@@ -107,10 +236,9 @@ public class BluetoothPowerCalculatorTest {
final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(1000,
BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 7000, 5000, 0,
reportedEnergyUc);
info.setUidTraffic(new ArrayList<UidTraffic>(){{
add(new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000));
add(new UidTraffic(APP_UID, 3000, 4000));
}});
info.setUidTraffic(ImmutableList.of(
new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000),
new UidTraffic(APP_UID, 3000, 4000)));
mStatsRule.getBatteryStats().updateBluetoothStateLocked(info,
consumedEnergyUc, 1000, 1000);
}