Merge "Add discharge power estimates to BatteryUsageStats" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-02-20 20:34:33 +00:00
committed by Android (Google) Code Review
12 changed files with 339 additions and 159 deletions

View File

@@ -130,7 +130,7 @@ public abstract class BatteryConsumer {
* Total power consumed by this consumer, in mAh.
*/
public double getConsumedPower() {
return mPowerComponents.getTotalPowerConsumed();
return mPowerComponents.getTotalConsumedPower();
}
/**

View File

@@ -1671,7 +1671,7 @@ public abstract class BatteryStats implements Parcelable {
public char batteryVoltage;
// The charge of the battery in micro-Ampere-hours.
public int batteryChargeUAh;
public int batteryChargeUah;
public double modemRailChargeMah;
public double wifiRailChargeMah;
@@ -1884,7 +1884,7 @@ public abstract class BatteryStats implements Parcelable {
bat = (((int)batteryTemperature)&0xffff)
| ((((int)batteryVoltage)<<16)&0xffff0000);
dest.writeInt(bat);
dest.writeInt(batteryChargeUAh);
dest.writeInt(batteryChargeUah);
dest.writeDouble(modemRailChargeMah);
dest.writeDouble(wifiRailChargeMah);
dest.writeInt(states);
@@ -1916,7 +1916,7 @@ public abstract class BatteryStats implements Parcelable {
int bat2 = src.readInt();
batteryTemperature = (short)(bat2&0xffff);
batteryVoltage = (char)((bat2>>16)&0xffff);
batteryChargeUAh = src.readInt();
batteryChargeUah = src.readInt();
modemRailChargeMah = src.readDouble();
wifiRailChargeMah = src.readDouble();
states = src.readInt();
@@ -1959,7 +1959,7 @@ public abstract class BatteryStats implements Parcelable {
batteryPlugType = 0;
batteryTemperature = 0;
batteryVoltage = 0;
batteryChargeUAh = 0;
batteryChargeUah = 0;
modemRailChargeMah = 0;
wifiRailChargeMah = 0;
states = 0;
@@ -1991,7 +1991,7 @@ public abstract class BatteryStats implements Parcelable {
batteryPlugType = o.batteryPlugType;
batteryTemperature = o.batteryTemperature;
batteryVoltage = o.batteryVoltage;
batteryChargeUAh = o.batteryChargeUAh;
batteryChargeUah = o.batteryChargeUah;
modemRailChargeMah = o.modemRailChargeMah;
wifiRailChargeMah = o.wifiRailChargeMah;
states = o.states;
@@ -2025,7 +2025,7 @@ public abstract class BatteryStats implements Parcelable {
&& batteryPlugType == o.batteryPlugType
&& batteryTemperature == o.batteryTemperature
&& batteryVoltage == o.batteryVoltage
&& batteryChargeUAh == o.batteryChargeUAh
&& batteryChargeUah == o.batteryChargeUah
&& modemRailChargeMah == o.modemRailChargeMah
&& wifiRailChargeMah == o.wifiRailChargeMah
&& states == o.states
@@ -2858,6 +2858,11 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract boolean getIsOnBattery();
/**
* Returns the timestamp of when battery stats collection started, in microseconds.
*/
public abstract long getStatsStartRealtime();
/**
* Returns a SparseArray containing the statistics for each uid.
*/
@@ -6520,7 +6525,7 @@ public abstract class BatteryStats implements Parcelable {
item.append(checkin ? ",Bv=" : " volt=");
item.append(oldVolt);
}
final int chargeMAh = rec.batteryChargeUAh / 1000;
final int chargeMAh = rec.batteryChargeUah / 1000;
if (oldChargeMAh != chargeMAh) {
oldChargeMAh = chargeMAh;
item.append(checkin ? ",Bcc=" : " charge=");

View File

@@ -17,7 +17,7 @@
package android.os;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.util.Range;
import android.util.SparseArray;
import java.util.ArrayList;
@@ -31,35 +31,59 @@ import java.util.List;
public final class BatteryUsageStats implements Parcelable {
private final double mConsumedPower;
private final int mDischargePercentage;
private final long mStatsStartRealtimeMs;
private final double mDischargedPowerLowerBound;
private final double mDischargedPowerUpperBound;
private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers;
private final ArrayList<SystemBatteryConsumer> mSystemBatteryConsumers;
private final ArrayList<UserBatteryConsumer> mUserBatteryConsumers;
private BatteryUsageStats(@NonNull Builder builder) {
mConsumedPower = builder.mConsumedPower;
mStatsStartRealtimeMs = builder.mStatsStartRealtimeMs;
mDischargePercentage = builder.mDischargePercentage;
mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
double totalPower = 0;
final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount);
for (int i = 0; i < uidBatteryConsumerCount; i++) {
UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
final UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
builder.mUidBatteryConsumerBuilders.valueAt(i);
if (!uidBatteryConsumerBuilder.isExcludedFromBatteryUsageStats()) {
mUidBatteryConsumers.add(uidBatteryConsumerBuilder.build());
final UidBatteryConsumer consumer = uidBatteryConsumerBuilder.build();
totalPower += consumer.getConsumedPower();
mUidBatteryConsumers.add(consumer);
}
}
int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size();
final int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size();
mSystemBatteryConsumers = new ArrayList<>(systemBatteryConsumerCount);
for (int i = 0; i < systemBatteryConsumerCount; i++) {
mSystemBatteryConsumers.add(builder.mSystemBatteryConsumerBuilders.valueAt(i).build());
final SystemBatteryConsumer consumer =
builder.mSystemBatteryConsumerBuilders.valueAt(i).build();
totalPower += consumer.getConsumedPower();
mSystemBatteryConsumers.add(consumer);
}
int userBatteryConsumerCount = builder.mUserBatteryConsumerBuilders.size();
final int userBatteryConsumerCount = builder.mUserBatteryConsumerBuilders.size();
mUserBatteryConsumers = new ArrayList<>(userBatteryConsumerCount);
for (int i = 0; i < userBatteryConsumerCount; i++) {
mUserBatteryConsumers.add(builder.mUserBatteryConsumerBuilders.valueAt(i).build());
final UserBatteryConsumer consumer =
builder.mUserBatteryConsumerBuilders.valueAt(i).build();
totalPower += consumer.getConsumedPower();
mUserBatteryConsumers.add(consumer);
}
mConsumedPower = totalPower;
}
/**
* Timestamp of the latest battery stats reset, in milliseconds.
*/
public long getStatsStartRealtime() {
return mStatsStartRealtimeMs;
}
/**
@@ -70,6 +94,14 @@ public final class BatteryUsageStats implements Parcelable {
return mDischargePercentage;
}
/**
* Returns the discharged power since BatteryStats were last reset, in mAh as an estimated
* range.
*/
public Range<Double> getDischargedPowerRange() {
return Range.create(mDischargedPowerLowerBound, mDischargedPowerUpperBound);
}
/**
* Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully
* charged), in mAh
@@ -99,23 +131,29 @@ public final class BatteryUsageStats implements Parcelable {
}
private BatteryUsageStats(@NonNull Parcel source) {
mStatsStartRealtimeMs = source.readLong();
mConsumedPower = source.readDouble();
mDischargePercentage = source.readInt();
mDischargedPowerLowerBound = source.readDouble();
mDischargedPowerUpperBound = source.readDouble();
mUidBatteryConsumers = new ArrayList<>();
source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader());
mSystemBatteryConsumers = new ArrayList<>();
source.readParcelableList(mSystemBatteryConsumers, getClass().getClassLoader());
mUserBatteryConsumers = new ArrayList<>();
source.readParcelableList(mUserBatteryConsumers, getClass().getClassLoader());
mConsumedPower = source.readDouble();
mDischargePercentage = source.readInt();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mStatsStartRealtimeMs);
dest.writeDouble(mConsumedPower);
dest.writeInt(mDischargePercentage);
dest.writeDouble(mDischargedPowerLowerBound);
dest.writeDouble(mDischargedPowerUpperBound);
dest.writeParcelableList(mUidBatteryConsumers, flags);
dest.writeParcelableList(mSystemBatteryConsumers, flags);
dest.writeParcelableList(mUserBatteryConsumers, flags);
dest.writeDouble(mConsumedPower);
dest.writeInt(mDischargePercentage);
}
@NonNull
@@ -135,8 +173,10 @@ public final class BatteryUsageStats implements Parcelable {
public static final class Builder {
private final int mCustomPowerComponentCount;
private final int mCustomTimeComponentCount;
private double mConsumedPower;
private long mStatsStartRealtimeMs;
private int mDischargePercentage;
private double mDischargedPowerLowerBoundMah;
private double mDischargedPowerUpperBoundMah;
private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
new SparseArray<>();
private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders =
@@ -157,11 +197,18 @@ public final class BatteryUsageStats implements Parcelable {
return new BatteryUsageStats(this);
}
/**
* Sets the timestamp of the latest battery stats reset, in milliseconds.
*/
public Builder setStatsStartRealtime(long statsStartRealtimeMs) {
mStatsStartRealtimeMs = statsStartRealtimeMs;
return this;
}
/**
* Sets the battery discharge amount since BatteryStats reset as percentage of the full
* charge.
*/
@SuppressLint("PercentageInt") // See b/174188159
@NonNull
public Builder setDischargePercentage(int dischargePercentage) {
mDischargePercentage = dischargePercentage;
@@ -169,11 +216,13 @@ public final class BatteryUsageStats implements Parcelable {
}
/**
* Sets the battery discharge amount since BatteryStats reset, in mAh.
* Sets the estimated battery discharge range.
*/
@NonNull
public Builder setConsumedPower(double consumedPower) {
mConsumedPower = consumedPower;
public Builder setDischargedPowerRange(double dischargedPowerLowerBoundMah,
double dischargedPowerUpperBoundMah) {
mDischargedPowerLowerBoundMah = dischargedPowerLowerBoundMah;
mDischargedPowerUpperBoundMah = dischargedPowerUpperBoundMah;
return this;
}

View File

@@ -29,38 +29,38 @@ class PowerComponents {
public static final int CUSTOM_TIME_COMPONENT_OFFSET = BatteryConsumer.TIME_COMPONENT_COUNT
- BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID;
private final double mTotalPowerConsumed;
private final double[] mPowerComponents;
private final long[] mTimeComponents;
private final double mTotalConsumedPowerMah;
private final double[] mPowerComponentsMah;
private final long[] mTimeComponentsMs;
private final int mCustomPowerComponentCount;
PowerComponents(@NonNull Builder builder) {
mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
mPowerComponents = builder.mPowerComponents;
mTimeComponents = builder.mTimeComponents;
mTotalPowerConsumed = builder.getTotalPower();
mPowerComponentsMah = builder.mPowerComponentsMah;
mTimeComponentsMs = builder.mTimeComponentsMs;
mTotalConsumedPowerMah = builder.getTotalPower();
}
PowerComponents(@NonNull Parcel source) {
mTotalPowerConsumed = source.readDouble();
mTotalConsumedPowerMah = source.readDouble();
mCustomPowerComponentCount = source.readInt();
mPowerComponents = source.createDoubleArray();
mTimeComponents = source.createLongArray();
mPowerComponentsMah = source.createDoubleArray();
mTimeComponentsMs = source.createLongArray();
}
/** Writes contents to Parcel */
void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeDouble(mTotalPowerConsumed);
dest.writeDouble(mTotalConsumedPowerMah);
dest.writeInt(mCustomPowerComponentCount);
dest.writeDoubleArray(mPowerComponents);
dest.writeLongArray(mTimeComponents);
dest.writeDoubleArray(mPowerComponentsMah);
dest.writeLongArray(mTimeComponentsMs);
}
/**
* Total power consumed by this consumer, in mAh.
*/
public double getTotalPowerConsumed() {
return mTotalPowerConsumed;
public double getTotalConsumedPower() {
return mTotalConsumedPowerMah;
}
/**
@@ -76,7 +76,7 @@ class PowerComponents {
"Unsupported power component ID: " + componentId);
}
try {
return mPowerComponents[componentId];
return mPowerComponentsMah[componentId];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
}
@@ -92,7 +92,7 @@ class PowerComponents {
if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
&& componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
try {
return mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
return mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
@@ -116,7 +116,7 @@ class PowerComponents {
"Unsupported time component ID: " + componentId);
}
try {
return mTimeComponents[componentId];
return mTimeComponentsMs[componentId];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
}
@@ -134,7 +134,7 @@ class PowerComponents {
"Unsupported custom time component ID: " + componentId);
}
try {
return mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId];
return mTimeComponentsMs[CUSTOM_TIME_COMPONENT_OFFSET + componentId];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"Unsupported custom time component ID: " + componentId);
@@ -145,16 +145,16 @@ class PowerComponents {
* Builder for PowerComponents.
*/
static final class Builder {
private final double[] mPowerComponents;
private final double[] mPowerComponentsMah;
private final int mCustomPowerComponentCount;
private final long[] mTimeComponents;
private final long[] mTimeComponentsMs;
Builder(int customPowerComponentCount, int customTimeComponentCount) {
mCustomPowerComponentCount = customPowerComponentCount;
int powerComponentCount =
BatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount;
mPowerComponents = new double[powerComponentCount];
mTimeComponents =
mPowerComponentsMah = new double[powerComponentCount];
mTimeComponentsMs =
new long[BatteryConsumer.TIME_COMPONENT_COUNT + customTimeComponentCount];
}
@@ -173,7 +173,7 @@ class PowerComponents {
"Unsupported power component ID: " + componentId);
}
try {
mPowerComponents[componentId] = componentPower;
mPowerComponentsMah[componentId] = componentPower;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
@@ -192,7 +192,8 @@ class PowerComponents {
if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
&& componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
try {
mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId] = componentPower;
mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId] =
componentPower;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
@@ -219,7 +220,7 @@ class PowerComponents {
"Unsupported time component ID: " + componentId);
}
try {
mTimeComponents[componentId] = componentUsageDurationMillis;
mTimeComponentsMs[componentId] = componentUsageDurationMillis;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"Unsupported time component ID: " + componentId);
@@ -241,7 +242,7 @@ class PowerComponents {
"Unsupported custom time component ID: " + componentId);
}
try {
mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId] =
mTimeComponentsMs[CUSTOM_TIME_COMPONENT_OFFSET + componentId] =
componentUsageDurationMillis;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
@@ -251,11 +252,11 @@ class PowerComponents {
}
public void addPowerAndDuration(Builder other) {
for (int i = 0; i < mPowerComponents.length; i++) {
mPowerComponents[i] += other.mPowerComponents[i];
for (int i = 0; i < mPowerComponentsMah.length; i++) {
mPowerComponentsMah[i] += other.mPowerComponentsMah[i];
}
for (int i = 0; i < mTimeComponents.length; i++) {
mTimeComponents[i] += other.mTimeComponents[i];
for (int i = 0; i < mTimeComponentsMs.length; i++) {
mTimeComponentsMs[i] += other.mTimeComponentsMs[i];
}
}
@@ -264,11 +265,11 @@ class PowerComponents {
* by the time the {@code build()} method is called.
*/
public double getTotalPower() {
double totalPower = 0;
for (int i = mPowerComponents.length - 1; i >= 0; i--) {
totalPower += mPowerComponents[i];
double totalPowerMah = 0;
for (int i = mPowerComponentsMah.length - 1; i >= 0; i--) {
totalPowerMah += mPowerComponentsMah[i];
}
return totalPower;
return totalPowerMah;
}
/**

View File

@@ -45,10 +45,10 @@ public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable
DRAIN_TYPE_FLASHLIGHT,
DRAIN_TYPE_IDLE,
DRAIN_TYPE_MEMORY,
DRAIN_TYPE_OVERCOUNTED,
// Reserved: OVERCOUNTED,
DRAIN_TYPE_PHONE,
DRAIN_TYPE_SCREEN,
DRAIN_TYPE_UNACCOUNTED,
// Reserved: UNACCOUNTED,
// Reserved: USER,
DRAIN_TYPE_WIFI,
})
@@ -63,10 +63,8 @@ public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable
public static final int DRAIN_TYPE_FLASHLIGHT = 5;
public static final int DRAIN_TYPE_IDLE = 6;
public static final int DRAIN_TYPE_MEMORY = 7;
public static final int DRAIN_TYPE_OVERCOUNTED = 8;
public static final int DRAIN_TYPE_PHONE = 9;
public static final int DRAIN_TYPE_SCREEN = 10;
public static final int DRAIN_TYPE_UNACCOUNTED = 11;
public static final int DRAIN_TYPE_WIFI = 13;
@DrainType

View File

@@ -767,7 +767,7 @@ public class BatteryStatsImpl extends BatteryStats {
// Last recorded battery energy capacity.
// This is used for computing foregrund power per application.
// See: PowerForUid below
private long mLastBatteryEnergyCapacityNWh = 0;
private long mLastBatteryEnergyCapacityNwh = 0;
private static final class PowerForUid {
public long energyNwh = 0;
@@ -1089,12 +1089,12 @@ public class BatteryStatsImpl extends BatteryStats {
private int mNumConnectivityChange;
private int mBatteryVolt = -1;
private int mBatteryCharge = -1;
private int mEstimatedBatteryCapacity = -1;
private int mBatteryVoltageMv = -1;
private int mBatteryChargeUah = -1;
private int mEstimatedBatteryCapacityMah = -1;
private int mMinLearnedBatteryCapacity = -1;
private int mMaxLearnedBatteryCapacity = -1;
private int mMinLearnedBatteryCapacityUah = -1;
private int mMaxLearnedBatteryCapacityUah = -1;
private long mBatteryTimeToFullSeconds = -1;
@@ -1175,17 +1175,17 @@ public class BatteryStatsImpl extends BatteryStats {
@Override
public int getEstimatedBatteryCapacity() {
return mEstimatedBatteryCapacity;
return mEstimatedBatteryCapacityMah;
}
@Override
public int getMinLearnedBatteryCapacity() {
return mMinLearnedBatteryCapacity;
return mMinLearnedBatteryCapacityUah;
}
@Override
public int getMaxLearnedBatteryCapacity() {
return mMaxLearnedBatteryCapacity;
return mMaxLearnedBatteryCapacityUah;
}
public BatteryStatsImpl() {
@@ -3416,7 +3416,7 @@ public class BatteryStatsImpl extends BatteryStats {
firstToken |= DELTA_EVENT_FLAG;
}
final boolean batteryChargeChanged = cur.batteryChargeUAh != last.batteryChargeUAh;
final boolean batteryChargeChanged = cur.batteryChargeUah != last.batteryChargeUah;
if (batteryChargeChanged) {
firstToken |= DELTA_BATTERY_CHARGE_FLAG;
}
@@ -3505,8 +3505,8 @@ public class BatteryStatsImpl extends BatteryStats {
mLastHistoryStepLevel = cur.batteryLevel;
if (batteryChargeChanged) {
if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh);
dest.writeInt(cur.batteryChargeUAh);
if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUah=" + cur.batteryChargeUah);
dest.writeInt(cur.batteryChargeUah);
}
dest.writeDouble(cur.modemRailChargeMah);
dest.writeDouble(cur.wifiRailChargeMah);
@@ -3756,7 +3756,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) {
cur.batteryChargeUAh = src.readInt();
cur.batteryChargeUah = src.readInt();
}
cur.modemRailChargeMah = src.readDouble();
cur.wifiRailChargeMah = src.readDouble();
@@ -7222,6 +7222,10 @@ public class BatteryStatsImpl extends BatteryStats {
return mOnBattery;
}
@Override public long getStatsStartRealtime() {
return mRealtimeStartUs;
}
@UnsupportedAppUsage
@Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
return mUidStats;
@@ -10745,11 +10749,6 @@ public class BatteryStatsImpl extends BatteryStats {
long realtimeUs = mClocks.elapsedRealtime() * 1000;
initTimes(uptimeUs, realtimeUs);
mStartPlatformVersion = mEndPlatformVersion = Build.ID;
mDischargeStartLevel = 0;
mDischargeUnplugLevel = 0;
mDischargePlugLevel = -1;
mDischargeCurrentLevel = 0;
mCurrentBatteryLevel = 0;
initDischarge(realtimeUs);
clearHistoryLocked();
updateDailyDeadlineLocked();
@@ -10835,6 +10834,11 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
mDischargeStartLevel = 0;
mDischargeUnplugLevel = 0;
mDischargePlugLevel = -1;
mDischargeCurrentLevel = 0;
mCurrentBatteryLevel = 0;
}
@UnsupportedAppUsage
@@ -10873,9 +10877,9 @@ public class BatteryStatsImpl extends BatteryStats {
firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
}
if (mEstimatedBatteryCapacity == -1) {
if (mEstimatedBatteryCapacityMah == -1) {
// Initialize the estimated battery capacity to a known preset one.
mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
}
}
@@ -11439,12 +11443,12 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (mPowerProfile != null) {
mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
mEstimatedBatteryCapacityMah = (int) mPowerProfile.getBatteryCapacity();
} else {
mEstimatedBatteryCapacity = -1;
mEstimatedBatteryCapacityMah = -1;
}
mMinLearnedBatteryCapacity = -1;
mMaxLearnedBatteryCapacity = -1;
mMinLearnedBatteryCapacityUah = -1;
mMaxLearnedBatteryCapacityUah = -1;
mInteractiveTimer.reset(false, elapsedRealtimeUs);
mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs);
mLastIdleTimeStartMs = elapsedRealtimeMillis;
@@ -11563,7 +11567,9 @@ public class BatteryStatsImpl extends BatteryStats {
initDischarge(elapsedRealtimeUs);
clearHistoryLocked();
mBatteryStatsHistory.resetAllFiles();
if (mBatteryStatsHistory != null) {
mBatteryStatsHistory.resetAllFiles();
}
// Flush external data, gathering snapshots, but don't process it since it is pre-reset data
mIgnoreNextExternalStats = true;
@@ -13212,7 +13218,7 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) {
final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
boolean doWrite = false;
Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
m.arg1 = onBattery ? 1 : 0;
@@ -13268,10 +13274,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
doWrite = true;
resetAllStatsLocked(mSecUptime, mSecRealtime);
if (chargeUAh > 0 && level > 0) {
mBatteryCharge = chargeUAh;
if (chargeUah > 0 && level > 0) {
mBatteryChargeUah = chargeUah;
// Only use the reported coulomb charge value if it is supported and reported.
mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0));
mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
}
mDischargeStartLevel = level;
reset = true;
@@ -13386,16 +13392,16 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void setBatteryStateLocked(final int status, final int health, final int plugType,
final int level, /* not final */ int temp, final int volt, final int chargeUAh,
final int chargeFullUAh, final long chargeTimeToFullSeconds) {
setBatteryStateLocked(status, health, plugType, level, temp, volt, chargeUAh,
chargeFullUAh, chargeTimeToFullSeconds,
final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
final int chargeFullUah, final long chargeTimeToFullSeconds) {
setBatteryStateLocked(status, health, plugType, level, temp, voltageMv, chargeUah,
chargeFullUah, chargeTimeToFullSeconds,
mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis());
}
public void setBatteryStateLocked(final int status, final int health, final int plugType,
final int level, /* not final */ int temp, final int volt, final int chargeUAh,
final int chargeFullUAh, final long chargeTimeToFullSeconds,
final int level, /* not final */ int temp, final int voltageMv, final int chargeUah,
final int chargeFullUah, final long chargeTimeToFullSeconds,
final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) {
// Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
temp = Math.max(0, temp);
@@ -13421,7 +13427,7 @@ public class BatteryStatsImpl extends BatteryStats {
mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
mHistoryCur.batteryStatus = (byte)status;
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.batteryChargeUAh = chargeUAh;
mHistoryCur.batteryChargeUah = chargeUah;
mMaxChargeStepLevel = mMinDischargeStepLevel =
mLastChargeStepLevel = mLastDischargeStepLevel = level;
mLastChargingStateLevel = level;
@@ -13444,10 +13450,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
if (ENABLE_FOREGROUND_STATS_COLLECTION) {
mBatteryVolt = volt;
mBatteryVoltageMv = voltageMv;
if (onBattery) {
final long energyNwh = (volt * (long) chargeUAh);
final long energyDelta = mLastBatteryEnergyCapacityNWh - energyNwh;
final long energyNwh = (voltageMv * (long) chargeUah);
final long energyDelta = mLastBatteryEnergyCapacityNwh - energyNwh;
for (int i = 0; i < mForegroundUids.size(); i++) {
final int uid = mForegroundUids.get(i);
if (uid == INVALID_UID) {
@@ -13458,7 +13464,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (pfu.baseTimeMs <= 0) {
pfu.baseTimeMs = currentTimeMs;
} else {
// Check if mLastBatteryEnergyCapacityNWh > energyNwh,
// Check if mLastBatteryEnergyCapacityNwh > energyNwh,
// to make sure we only count discharges
if (energyDelta > 0) {
pfu.energyNwh += energyDelta;
@@ -13476,7 +13482,7 @@ public class BatteryStatsImpl extends BatteryStats {
pfu.baseTimeMs = currentTimeMs;
}
}
mLastBatteryEnergyCapacityNWh = energyNwh;
mLastBatteryEnergyCapacityNwh = energyNwh;
} else if (onBattery != mOnBattery) {
// Transition to onBattery = false
mUidToPower.values().forEach(v -> v.baseTimeMs = 0);
@@ -13494,10 +13500,10 @@ public class BatteryStatsImpl extends BatteryStats {
mHistoryCur.batteryHealth = (byte)health;
mHistoryCur.batteryPlugType = (byte)plugType;
mHistoryCur.batteryTemperature = (short)temp;
mHistoryCur.batteryVoltage = (char)volt;
if (chargeUAh < mHistoryCur.batteryChargeUAh) {
mHistoryCur.batteryVoltage = (char) voltageMv;
if (chargeUah < mHistoryCur.batteryChargeUah) {
// Only record discharges
final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -13509,8 +13515,8 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
mHistoryCur.batteryChargeUAh = chargeUAh;
setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUAh);
mHistoryCur.batteryChargeUah = chargeUah;
setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUah);
} else {
boolean changed = false;
if (mHistoryCur.batteryLevel != level) {
@@ -13539,16 +13545,16 @@ public class BatteryStatsImpl extends BatteryStats {
mHistoryCur.batteryTemperature = (short)temp;
changed = true;
}
if (volt > (mHistoryCur.batteryVoltage+20)
|| volt < (mHistoryCur.batteryVoltage-20)) {
mHistoryCur.batteryVoltage = (char)volt;
if (voltageMv > (mHistoryCur.batteryVoltage + 20)
|| voltageMv < (mHistoryCur.batteryVoltage - 20)) {
mHistoryCur.batteryVoltage = (char) voltageMv;
changed = true;
}
if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
|| chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
if (chargeUAh < mHistoryCur.batteryChargeUAh) {
if (chargeUah >= (mHistoryCur.batteryChargeUah + 10)
|| chargeUah <= (mHistoryCur.batteryChargeUah - 10)) {
if (chargeUah < mHistoryCur.batteryChargeUah) {
// Only record discharges
final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
final long chargeDiff = mHistoryCur.batteryChargeUah - chargeUah;
mDischargeCounter.addCountLocked(chargeDiff);
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
if (Display.isDozeState(mScreenState)) {
@@ -13560,7 +13566,7 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeDeepDozeCounter.addCountLocked(chargeDiff);
}
}
mHistoryCur.batteryChargeUAh = chargeUAh;
mHistoryCur.batteryChargeUah = chargeUah;
changed = true;
}
long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
@@ -13632,12 +13638,12 @@ public class BatteryStatsImpl extends BatteryStats {
mRecordingHistory = DEBUG;
}
if (mMinLearnedBatteryCapacity == -1) {
mMinLearnedBatteryCapacity = chargeFullUAh;
if (mMinLearnedBatteryCapacityUah == -1) {
mMinLearnedBatteryCapacityUah = chargeFullUah;
} else {
mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
mMinLearnedBatteryCapacityUah = Math.min(mMinLearnedBatteryCapacityUah, chargeFullUah);
}
mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
mMaxLearnedBatteryCapacityUah = Math.max(mMaxLearnedBatteryCapacityUah, chargeFullUah);
mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
}
@@ -14912,9 +14918,9 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
mCurrentBatteryLevel = in.readInt();
mEstimatedBatteryCapacity = in.readInt();
mMinLearnedBatteryCapacity = in.readInt();
mMaxLearnedBatteryCapacity = in.readInt();
mEstimatedBatteryCapacityMah = in.readInt();
mMinLearnedBatteryCapacityUah = in.readInt();
mMaxLearnedBatteryCapacityUah = in.readInt();
mLowDischargeAmountSinceCharge = in.readInt();
mHighDischargeAmountSinceCharge = in.readInt();
mDischargeAmountScreenOnSinceCharge = in.readInt();
@@ -15416,9 +15422,9 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeInt(mDischargePlugLevel);
out.writeInt(mDischargeCurrentLevel);
out.writeInt(mCurrentBatteryLevel);
out.writeInt(mEstimatedBatteryCapacity);
out.writeInt(mMinLearnedBatteryCapacity);
out.writeInt(mMaxLearnedBatteryCapacity);
out.writeInt(mEstimatedBatteryCapacityMah);
out.writeInt(mMinLearnedBatteryCapacityUah);
out.writeInt(mMaxLearnedBatteryCapacityUah);
out.writeInt(getLowDischargeAmountSinceCharge());
out.writeInt(getHighDischargeAmountSinceCharge());
out.writeInt(getDischargeAmountScreenOnSinceCharge());
@@ -15917,9 +15923,9 @@ public class BatteryStatsImpl extends BatteryStats {
mRealtimeUs = in.readLong();
mRealtimeStartUs = in.readLong();
mOnBattery = in.readInt() != 0;
mEstimatedBatteryCapacity = in.readInt();
mMinLearnedBatteryCapacity = in.readInt();
mMaxLearnedBatteryCapacity = in.readInt();
mEstimatedBatteryCapacityMah = in.readInt();
mMinLearnedBatteryCapacityUah = in.readInt();
mMaxLearnedBatteryCapacityUah = in.readInt();
mOnBatteryInternal = false; // we are no longer really running.
mOnBatteryTimeBase.readFromParcel(in);
mOnBatteryScreenOffTimeBase.readFromParcel(in);
@@ -16156,9 +16162,9 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeLong(mRealtimeUs);
out.writeLong(mRealtimeStartUs);
out.writeInt(mOnBattery ? 1 : 0);
out.writeInt(mEstimatedBatteryCapacity);
out.writeInt(mMinLearnedBatteryCapacity);
out.writeInt(mMaxLearnedBatteryCapacity);
out.writeInt(mEstimatedBatteryCapacityMah);
out.writeInt(mMinLearnedBatteryCapacityUah);
out.writeInt(mMaxLearnedBatteryCapacityUah);
mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
@@ -16414,8 +16420,8 @@ public class BatteryStatsImpl extends BatteryStats {
public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
if (ENABLE_FOREGROUND_STATS_COLLECTION) {
long actualCharge = -1;
long actualEnergy = -1;
long actualChargeUah = -1;
long actualEnergyNwh = -1;
try {
IBatteryPropertiesRegistrar registrar =
IBatteryPropertiesRegistrar.Stub.asInterface(
@@ -16424,27 +16430,27 @@ public class BatteryStatsImpl extends BatteryStats {
BatteryProperty prop = new BatteryProperty();
if (registrar.getProperty(
BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, prop) == 0) {
actualCharge = prop.getLong();
actualChargeUah = prop.getLong();
}
prop = new BatteryProperty();
if (registrar.getProperty(
BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER, prop) == 0) {
actualEnergy = prop.getLong();
actualEnergyNwh = prop.getLong();
}
}
} catch (RemoteException e) {
// Ignore.
}
pw.printf("ActualCharge (uAh): %d\n", (int) actualCharge);
pw.printf("ActualEnergy (nWh): %d\n", actualEnergy);
pw.printf("mBatteryCharge (uAh): %d\n", mBatteryCharge);
pw.printf("mBatteryVolts (mV): %d\n", mBatteryVolt);
pw.printf("est energy (nWh): %d\n", mBatteryVolt * (long) mBatteryCharge);
pw.printf("mEstimatedBatteryCapacity (mAh): %d\n", mEstimatedBatteryCapacity);
pw.printf("mMinLearnedBatteryCapacity (uAh): %d\n", mMinLearnedBatteryCapacity);
pw.printf("mMaxLearnedBatteryCapacity (uAh): %d\n", mMaxLearnedBatteryCapacity);
pw.printf("ActualCharge (uAh): %d\n", (int) actualChargeUah);
pw.printf("ActualEnergy (nWh): %d\n", actualEnergyNwh);
pw.printf("mBatteryCharge (uAh): %d\n", mBatteryChargeUah);
pw.printf("mBatteryVolts (mV): %d\n", mBatteryVoltageMv);
pw.printf("est energy (nWh): %d\n", mBatteryVoltageMv * (long) mBatteryChargeUah);
pw.printf("mEstimatedBatteryCapacity (mAh): %d\n", mEstimatedBatteryCapacityMah);
pw.printf("mMinLearnedBatteryCapacity (uAh): %d\n", mMinLearnedBatteryCapacityUah);
pw.printf("mMaxLearnedBatteryCapacity (uAh): %d\n", mMaxLearnedBatteryCapacityUah);
pw.printf("est. capacity: %f\n",
(float) actualCharge / (mEstimatedBatteryCapacity * 1000));
(float) actualChargeUah / (mEstimatedBatteryCapacityMah * 1000));
pw.printf("mCurrentBatteryLevel: %d\n", mCurrentBatteryLevel);
pw.println("Total Power per app:");
mUidToPower.entrySet().forEach(e ->

View File

@@ -52,6 +52,7 @@ public class BatteryUsageStatsProvider {
mPowerCalculators = new ArrayList<>();
// Power calculators are applied in the order of registration
mPowerCalculators.add(new DischargedPowerCalculator(mPowerProfile));
mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile));
mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
@@ -106,21 +107,19 @@ public class BatteryUsageStatsProvider {
ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
for (int i = 0; i < queries.size(); i++) {
results.add(getBatteryUsageStats(queries.get(i), batteryStatsHelper));
results.add(getBatteryUsageStats(queries.get(i)));
}
return results;
}
private BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query,
BatteryStatsHelper batteryStatsHelper) {
private BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
// TODO(b/174186358): read extra power component number from configuration
final int customPowerComponentCount = 0;
final int customTimeComponentCount = 0;
final BatteryUsageStats.Builder batteryUsageStatsBuilder =
new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount)
.setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
.setConsumedPower(batteryStatsHelper.getTotalPower());
.setStatsStartRealtime(mStats.getStatsStartRealtime() / 1000);
SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
for (int i = uidStats.size() - 1; i >= 0; i--) {

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.os;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.UserHandle;
import android.util.SparseArray;
import java.util.List;
/**
* Estimates the battery discharge amounts.
*/
public class DischargedPowerCalculator extends PowerCalculator {
private final double mBatteryCapacity;
public DischargedPowerCalculator(PowerProfile powerProfile) {
mBatteryCapacity = powerProfile.getBatteryCapacity();
}
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
builder.setDischargePercentage(
batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED))
.setDischargedPowerRange(
batteryStats.getLowDischargeAmountSinceCharge() * mBatteryCapacity / 100,
batteryStats.getHighDischargeAmountSinceCharge() * mBatteryCapacity / 100);
}
@Override
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
// Not implemented. The computation is done by BatteryStatsHelper
}
}

View File

@@ -46,6 +46,7 @@ import org.junit.runners.Suite;
BstatsCpuTimesValidationTest.class,
CameraPowerCalculatorTest.class,
CpuPowerCalculatorTest.class,
DischargedPowerCalculatorTest.class,
FlashlightPowerCalculatorTest.class,
GnssPowerCalculatorTest.class,
IdlePowerCalculatorTest.class,

View File

@@ -136,16 +136,16 @@ public class BatteryUsageStatsRule implements TestRule {
return mBatteryStats.getUidStatsLocked(uid);
}
public void setTime(long realtimeUs, long uptimeUs) {
mMockClocks.realtime = realtimeUs;
mMockClocks.uptime = uptimeUs;
public void setTime(long realtimeMs, long uptimeMs) {
mMockClocks.realtime = realtimeMs;
mMockClocks.uptime = uptimeMs;
}
void apply(PowerCalculator... calculators) {
apply(BatteryUsageStatsQuery.DEFAULT, calculators);
BatteryUsageStats apply(PowerCalculator... calculators) {
return apply(BatteryUsageStatsQuery.DEFAULT, calculators);
}
void apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
BatteryUsageStats apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(0, 0);
SparseArray<? extends BatteryStats.Uid> uidStats = mBatteryStats.getUidStats();
for (int i = 0; i < uidStats.size(); i++) {
@@ -158,6 +158,7 @@ public class BatteryUsageStatsRule implements TestRule {
}
mBatteryUsageStats = builder.build();
return mBatteryUsageStats;
}
public UidBatteryConsumer getUidBatteryConsumer(int uid) {

View File

@@ -67,8 +67,8 @@ public class BatteryUsageStatsTest {
final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(2000);
final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(1, 1);
builder.setConsumedPower(100);
builder.setDischargePercentage(20);
builder.setDischargedPowerRange(1000, 2000);
final UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid);
@@ -100,6 +100,8 @@ public class BatteryUsageStatsTest {
public void validateBatteryUsageStats(BatteryUsageStats batteryUsageStats) {
assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(100);
assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(20);
assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo(1000);
assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo(2000);
final List<UidBatteryConsumer> uidBatteryConsumers =
batteryUsageStats.getUidBatteryConsumers();

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.os;
import static com.google.common.truth.Truth.assertThat;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DischargedPowerCalculatorTest {
private static final double PRECISION = 0.00001;
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
.setAveragePower(PowerProfile.POWER_BATTERY_CAPACITY, 4000.0);
@Test
public void testDischargeTotals() {
final BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
mStatsRule.setTime(1000, 1000);
batteryStats.resetAllStatsCmdLocked();
batteryStats.setNoAutoReset(true);
batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
/* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, 1_000_000,
1_000_000, 1_000_000);
batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
/* plugType */ 0, 80, 72, 3700, 2_400_000, 4_000_000, 0, 2_000_000,
2_000_000, 2_000_000);
DischargedPowerCalculator calculator =
new DischargedPowerCalculator(mStatsRule.getPowerProfile());
final BatteryUsageStats batteryUsageStats = mStatsRule.apply(calculator);
assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(10);
assertThat(batteryUsageStats.getDischargedPowerRange().getLower())
.isWithin(PRECISION).of(360.0);
assertThat(batteryUsageStats.getDischargedPowerRange().getUpper())
.isWithin(PRECISION).of(400.0);
}
}