Merge "Attribution of Bluetooth power per process state"
This commit is contained in:
committed by
Android (Google) Code Review
commit
802df78a0b
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user