Merge "MeasuredEnergyStats supports custom energy buckets" into sc-dev
This commit is contained in:
@@ -21,8 +21,6 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||
import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
|
||||
import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
|
||||
|
||||
import static com.android.internal.power.MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -107,7 +105,7 @@ import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeRea
|
||||
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
|
||||
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
|
||||
import com.android.internal.power.MeasuredEnergyStats;
|
||||
import com.android.internal.power.MeasuredEnergyStats.EnergyBucket;
|
||||
import com.android.internal.power.MeasuredEnergyStats.StandardEnergyBucket;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FastPrintWriter;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
@@ -173,7 +171,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
|
||||
|
||||
// Current on-disk Parcel version
|
||||
static final int VERSION = 192 + (USE_OLD_HISTORY ? 1000 : 0);
|
||||
static final int VERSION = 193 + (USE_OLD_HISTORY ? 1000 : 0);
|
||||
|
||||
// The maximum number of names wakelocks we will keep track of
|
||||
// per uid; once the limit is reached, we batch the remaining wakelocks
|
||||
@@ -7161,8 +7159,8 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
if (mGlobalMeasuredEnergyStats == null) {
|
||||
return ENERGY_DATA_UNAVAILABLE;
|
||||
}
|
||||
return mGlobalMeasuredEnergyStats.getAccumulatedBucketEnergy(
|
||||
MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON);
|
||||
return mGlobalMeasuredEnergyStats
|
||||
.getAccumulatedStandardBucketEnergy(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -7170,8 +7168,8 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
if (mGlobalMeasuredEnergyStats == null) {
|
||||
return ENERGY_DATA_UNAVAILABLE;
|
||||
}
|
||||
return mGlobalMeasuredEnergyStats.getAccumulatedBucketEnergy(
|
||||
MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE);
|
||||
return mGlobalMeasuredEnergyStats
|
||||
.getAccumulatedStandardBucketEnergy(MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE);
|
||||
}
|
||||
|
||||
@Override public long getStartClockTime() {
|
||||
@@ -7935,27 +7933,27 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
return mUidMeasuredEnergyStats;
|
||||
}
|
||||
|
||||
/** Adds the given energy to the given energy bucket for this uid. */
|
||||
private void addEnergyToEnergyBucketLocked(long energyDeltaUJ,
|
||||
@MeasuredEnergyStats.EnergyBucket int energyBucket, boolean accumulate) {
|
||||
/** Adds the given energy to the given standard energy bucket for this uid. */
|
||||
private void addEnergyToStandardBucketLocked(long energyDeltaUJ,
|
||||
@StandardEnergyBucket int energyBucket, boolean accumulate) {
|
||||
getOrCreateMeasuredEnergyStatsLocked()
|
||||
.updateBucket(energyBucket, energyDeltaUJ, accumulate);
|
||||
.updateStandardBucket(energyBucket, energyDeltaUJ, accumulate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the energy used by this uid for an energy bucket of interest.
|
||||
* @param bucket energy bucket of interest
|
||||
* Returns the energy used by this uid for a standard energy bucket of interest.
|
||||
* @param bucket standard energy bucket of interest
|
||||
* @return energy (in microjoules) used by this uid for this energy bucket
|
||||
*/
|
||||
public long getMeasuredEnergyMicroJoules(@MeasuredEnergyStats.EnergyBucket int bucket) {
|
||||
public long getMeasuredEnergyMicroJoules(@StandardEnergyBucket int bucket) {
|
||||
if (mBsi.mGlobalMeasuredEnergyStats == null
|
||||
|| !mBsi.mGlobalMeasuredEnergyStats.isEnergyBucketSupported(bucket)) {
|
||||
|| !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) {
|
||||
return ENERGY_DATA_UNAVAILABLE;
|
||||
}
|
||||
if (mUidMeasuredEnergyStats == null) {
|
||||
return 0L; // It is supported, but was never filled, so it must be 0
|
||||
}
|
||||
return mUidMeasuredEnergyStats.getAccumulatedBucketEnergy(bucket);
|
||||
return mUidMeasuredEnergyStats.getAccumulatedStandardBucketEnergy(bucket);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -12396,7 +12394,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
return;
|
||||
}
|
||||
|
||||
final @EnergyBucket int energyBucket =
|
||||
final @StandardEnergyBucket int energyBucket =
|
||||
MeasuredEnergyStats.getDisplayEnergyBucket(mScreenStateAtLastEnergyMeasurement);
|
||||
mScreenStateAtLastEnergyMeasurement = screenState;
|
||||
|
||||
@@ -12415,7 +12413,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
return;
|
||||
}
|
||||
|
||||
mGlobalMeasuredEnergyStats.updateBucket(energyBucket, energyUJ, true);
|
||||
mGlobalMeasuredEnergyStats.updateStandardBucket(energyBucket, energyUJ, true);
|
||||
|
||||
// Now we blame individual apps, but only if the display was ON.
|
||||
if (energyBucket != MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON) {
|
||||
@@ -12453,7 +12451,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
final long appDisplayEnergyMJ =
|
||||
(totalDisplayEnergyMJ * fgTimeMs + (totalFgTimeMs / 2))
|
||||
/ totalFgTimeMs;
|
||||
uid.addEnergyToEnergyBucketLocked(appDisplayEnergyMJ * 1000, energyBucket, true);
|
||||
uid.addEnergyToStandardBucketLocked(appDisplayEnergyMJ * 1000, energyBucket, true);
|
||||
|
||||
// To mitigate round-off errors, remove this app from numerator & denominator totals
|
||||
totalDisplayEnergyMJ -= appDisplayEnergyMJ;
|
||||
@@ -14138,33 +14136,34 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
/**
|
||||
* Initialize the measured energy stats data structures.
|
||||
*
|
||||
* @param supportedEnergyBuckets boolean array indicating which buckets are currently supported
|
||||
* @param supportedStandardBuckets boolean array indicating which {@link StandardEnergyBucket}s
|
||||
* are currently supported.
|
||||
* If null, none are supported (regardless of numCustomBuckets).
|
||||
* @param numCustomBuckets number of custom (OTHER) EnergyConsumers on this device
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
public void initMeasuredEnergyStatsLocked(boolean[] supportedEnergyBuckets) {
|
||||
public void initMeasuredEnergyStatsLocked(@Nullable boolean[] supportedStandardBuckets,
|
||||
int numCustomBuckets) {
|
||||
boolean supportedBucketMismatch = false;
|
||||
mScreenStateAtLastEnergyMeasurement = mScreenState;
|
||||
|
||||
if (supportedEnergyBuckets == null) {
|
||||
if (supportedStandardBuckets == null) {
|
||||
if (mGlobalMeasuredEnergyStats != null) {
|
||||
// Measured energy buckets no longer supported, wipe out the existing data.
|
||||
supportedBucketMismatch = true;
|
||||
}
|
||||
} else if (mGlobalMeasuredEnergyStats == null) {
|
||||
mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
mGlobalMeasuredEnergyStats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
return;
|
||||
} else {
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
if (mGlobalMeasuredEnergyStats.isEnergyBucketSupported(i)
|
||||
!= supportedEnergyBuckets[i]) {
|
||||
mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
supportedBucketMismatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo(
|
||||
supportedStandardBuckets, numCustomBuckets);
|
||||
}
|
||||
|
||||
if (supportedBucketMismatch) {
|
||||
mGlobalMeasuredEnergyStats = supportedStandardBuckets == null ?
|
||||
null : new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
// Supported energy buckets changed since last boot.
|
||||
// Existing data is no longer reliable.
|
||||
resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime());
|
||||
|
||||
@@ -20,8 +20,10 @@ package com.android.internal.power;
|
||||
import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.util.DebugUtils;
|
||||
import android.util.Slog;
|
||||
import android.view.Display;
|
||||
|
||||
@@ -33,7 +35,9 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Tracks the measured energy usage of various subsystems according to their {@link EnergyBucket}.
|
||||
* Tracks the measured energy usage of various subsystems according to their
|
||||
* {@link StandardEnergyBucket} or custom energy bucket (which is tied to
|
||||
* {@link android.hardware.power.stats.EnergyConsumer.ordinal}).
|
||||
*
|
||||
* This class doesn't use a TimeBase, and instead requires manually decisions about when to
|
||||
* accumulate since it is trivial. However, in the future, a TimeBase could be used instead.
|
||||
@@ -42,15 +46,13 @@ import java.lang.annotation.RetentionPolicy;
|
||||
public class MeasuredEnergyStats {
|
||||
private static final String TAG = "MeasuredEnergyStats";
|
||||
|
||||
// Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if energy
|
||||
// bucket integers are modified.
|
||||
// Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} MUST be updated if standard
|
||||
// energy bucket integers are modified/added/removed.
|
||||
public static final int ENERGY_BUCKET_UNKNOWN = -1;
|
||||
public static final int ENERGY_BUCKET_SCREEN_ON = 0;
|
||||
public static final int ENERGY_BUCKET_SCREEN_DOZE = 1;
|
||||
public static final int ENERGY_BUCKET_SCREEN_OTHER = 2;
|
||||
public static final int NUMBER_ENERGY_BUCKETS = 3;
|
||||
private static final String[] ENERGY_BUCKET_NAMES =
|
||||
{"screen-on", "screen-doze", "screen-other"};
|
||||
public static final int NUMBER_STANDARD_ENERGY_BUCKETS = 3; // Buckets above this are custom.
|
||||
|
||||
@IntDef(prefix = {"ENERGY_BUCKET_"}, value = {
|
||||
ENERGY_BUCKET_UNKNOWN,
|
||||
@@ -59,28 +61,37 @@ public class MeasuredEnergyStats {
|
||||
ENERGY_BUCKET_SCREEN_OTHER,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface EnergyBucket {
|
||||
public @interface StandardEnergyBucket {
|
||||
}
|
||||
|
||||
/**
|
||||
* Total energy (in microjoules) that an {@link EnergyBucket} has accumulated since the last
|
||||
* reset. Values MUST be non-zero or ENERGY_DATA_UNAVAILABLE. Accumulation only occurs
|
||||
* Total energy (in microjoules) that an energy bucket (including both
|
||||
* {@link StandardEnergyBucket} and custom buckets) has accumulated since the last reset.
|
||||
* Values MUST be non-zero or ENERGY_DATA_UNAVAILABLE. Accumulation only occurs
|
||||
* while the necessary conditions are satisfied (e.g. on battery).
|
||||
*
|
||||
* Energy for both {@link StandardEnergyBucket}s and custom energy buckets are stored in this
|
||||
* array, and may internally both referred to as 'buckets'. This is an implementation detail;
|
||||
* externally, we differentiate between these two data sources.
|
||||
*
|
||||
* Warning: Long array is used for access speed. If the number of supported subsystems
|
||||
* becomes large, consider using an alternate data structure such as a SparseLongArray.
|
||||
*/
|
||||
private final long[] mAccumulatedEnergiesMicroJoules = new long[NUMBER_ENERGY_BUCKETS];
|
||||
private final long[] mAccumulatedEnergiesMicroJoules;
|
||||
|
||||
/**
|
||||
* Creates a MeasuredEnergyStats set to support the provided energy buckets.
|
||||
* supportedEnergyBuckets should generally be of size {@link #NUMBER_ENERGY_BUCKETS}.
|
||||
* supportedStandardBuckets must be of size {@link #NUMBER_STANDARD_ENERGY_BUCKETS}.
|
||||
* numCustomBuckets >= 0 is the number of (non-standard) custom energy buckets on the device.
|
||||
*/
|
||||
public MeasuredEnergyStats(boolean[] supportedEnergyBuckets) {
|
||||
public MeasuredEnergyStats(boolean[] supportedStandardBuckets, int numCustomBuckets) {
|
||||
final int numTotalBuckets = NUMBER_STANDARD_ENERGY_BUCKETS + numCustomBuckets;
|
||||
mAccumulatedEnergiesMicroJoules = new long[numTotalBuckets];
|
||||
// Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE.
|
||||
for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
|
||||
if (!supportedEnergyBuckets[bucket]) {
|
||||
mAccumulatedEnergiesMicroJoules[bucket] = ENERGY_DATA_UNAVAILABLE;
|
||||
// All custom buckets are, by definition, supported, so their values stay at 0.
|
||||
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_ENERGY_BUCKETS; stdBucket++) {
|
||||
if (!supportedStandardBuckets[stdBucket]) {
|
||||
mAccumulatedEnergiesMicroJoules[stdBucket] = ENERGY_DATA_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,10 +101,13 @@ public class MeasuredEnergyStats {
|
||||
* supported. This certainly does NOT produce an exact clone of the template.
|
||||
*/
|
||||
private MeasuredEnergyStats(MeasuredEnergyStats template) {
|
||||
final int numIndices = template.getNumberOfIndices();
|
||||
mAccumulatedEnergiesMicroJoules = new long[numIndices];
|
||||
// Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE.
|
||||
for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
|
||||
if (!template.isEnergyBucketSupported(bucket)) {
|
||||
mAccumulatedEnergiesMicroJoules[bucket] = ENERGY_DATA_UNAVAILABLE;
|
||||
// All custom buckets are, by definition, supported, so their values stay at 0.
|
||||
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_ENERGY_BUCKETS; stdBucket++) {
|
||||
if (!template.isIndexSupported(stdBucket)) {
|
||||
mAccumulatedEnergiesMicroJoules[stdBucket] = ENERGY_DATA_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,18 +122,22 @@ public class MeasuredEnergyStats {
|
||||
|
||||
/**
|
||||
* Constructor for creating a temp MeasuredEnergyStats.
|
||||
* See {@link #readSummaryFromParcel(MeasuredEnergyStats, Parcel)}.
|
||||
* See {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}.
|
||||
*/
|
||||
private MeasuredEnergyStats() {
|
||||
private MeasuredEnergyStats(int numIndices) {
|
||||
mAccumulatedEnergiesMicroJoules = new long[numIndices];
|
||||
}
|
||||
|
||||
/** Construct from parcel. */
|
||||
public MeasuredEnergyStats(Parcel in) {
|
||||
final int size = in.readInt();
|
||||
mAccumulatedEnergiesMicroJoules = new long[size];
|
||||
in.readLongArray(mAccumulatedEnergiesMicroJoules);
|
||||
}
|
||||
|
||||
/** Write to parcel */
|
||||
public void writeToParcel(Parcel out) {
|
||||
out.writeInt(mAccumulatedEnergiesMicroJoules.length);
|
||||
out.writeLongArray(mAccumulatedEnergiesMicroJoules);
|
||||
}
|
||||
|
||||
@@ -129,16 +147,18 @@ public class MeasuredEnergyStats {
|
||||
* summary parcel was written. Availability has already been correctly set in the constructor.
|
||||
* Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary
|
||||
* parceling changes.
|
||||
*
|
||||
* Corresponding write performed by {@link #writeSummaryToParcel(Parcel, boolean)}.
|
||||
*/
|
||||
private void readSummaryFromParcel(Parcel in, boolean overwriteAvailability) {
|
||||
final int size = in.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int bucket = in.readInt();
|
||||
final int numWrittenEntries = in.readInt();
|
||||
for (int entry = 0; entry < numWrittenEntries; entry++) {
|
||||
final int index = in.readInt();
|
||||
final long energyUJ = in.readLong();
|
||||
if (overwriteAvailability) {
|
||||
mAccumulatedEnergiesMicroJoules[bucket] = energyUJ;
|
||||
mAccumulatedEnergiesMicroJoules[index] = energyUJ;
|
||||
} else {
|
||||
setValueIfSupported(bucket, energyUJ);
|
||||
setValueIfSupported(index, energyUJ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,52 +166,90 @@ public class MeasuredEnergyStats {
|
||||
/**
|
||||
* Write to summary parcel.
|
||||
* Note: Measured subsystem availability may be different when the summary parcel is read.
|
||||
*
|
||||
* Corresponding read performed by {@link #readSummaryFromParcel(Parcel, boolean)}.
|
||||
*/
|
||||
private void writeSummaryToParcel(Parcel out, boolean skipZero) {
|
||||
final int sizePos = out.dataPosition();
|
||||
final int posOfNumWrittenEntries = out.dataPosition();
|
||||
out.writeInt(0);
|
||||
int size = 0;
|
||||
// Write only the supported buckets with non-zero energy.
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
final long energy = mAccumulatedEnergiesMicroJoules[i];
|
||||
int numWrittenEntries = 0;
|
||||
// Write only the supported buckets (with non-zero energy, if applicable).
|
||||
for (int index = 0; index < mAccumulatedEnergiesMicroJoules.length; index++) {
|
||||
final long energy = mAccumulatedEnergiesMicroJoules[index];
|
||||
if (energy < 0) continue;
|
||||
if (energy == 0 && skipZero) continue;
|
||||
|
||||
out.writeInt(i);
|
||||
out.writeLong(mAccumulatedEnergiesMicroJoules[i]);
|
||||
size++;
|
||||
out.writeInt(index);
|
||||
out.writeLong(mAccumulatedEnergiesMicroJoules[index]);
|
||||
numWrittenEntries++;
|
||||
}
|
||||
final int currPos = out.dataPosition();
|
||||
out.setDataPosition(sizePos);
|
||||
out.writeInt(size);
|
||||
out.setDataPosition(posOfNumWrittenEntries);
|
||||
out.writeInt(numWrittenEntries);
|
||||
out.setDataPosition(currPos);
|
||||
}
|
||||
|
||||
/** Updates the given bucket with the given energy iff accumulate is true. */
|
||||
public void updateBucket(@EnergyBucket int bucket, long energyDeltaUJ, boolean accumulate) {
|
||||
/** Get number of possible buckets, including both standard and custom ones. */
|
||||
private int getNumberOfIndices() {
|
||||
return mAccumulatedEnergiesMicroJoules.length;
|
||||
}
|
||||
|
||||
// TODO: Get rid of the 'accumulate' boolean. It's always true.
|
||||
/** Updates the given standard energy bucket with the given energy if accumulate is true. */
|
||||
public void updateStandardBucket(@StandardEnergyBucket int bucket, long energyDeltaUJ,
|
||||
boolean accumulate) {
|
||||
checkValidStandardBucket(bucket);
|
||||
updateEntry(bucket, energyDeltaUJ, accumulate);
|
||||
}
|
||||
|
||||
/** Updates the given custom energy bucket with the given energy if accumulate is true. */
|
||||
public void updateCustomBucket(int customBucket, long energyDeltaUJ, boolean accumulate) {
|
||||
if (!isValidCustomBucket(customBucket)) {
|
||||
Slog.e(TAG, "Attempted to update invalid custom bucket " + customBucket);
|
||||
return;
|
||||
}
|
||||
final int index = customBucketToIndex(customBucket);
|
||||
updateEntry(index, energyDeltaUJ, accumulate);
|
||||
}
|
||||
|
||||
/** Updates the given index with the given energy if accumulate is true. */
|
||||
private void updateEntry(int index, long energyDeltaUJ, boolean accumulate) {
|
||||
if (accumulate) {
|
||||
if (mAccumulatedEnergiesMicroJoules[bucket] >= 0L) {
|
||||
mAccumulatedEnergiesMicroJoules[bucket] += energyDeltaUJ;
|
||||
if (mAccumulatedEnergiesMicroJoules[index] >= 0L) {
|
||||
mAccumulatedEnergiesMicroJoules[index] += energyDeltaUJ;
|
||||
} else {
|
||||
Slog.wtf(TAG, "Attempting to add " + energyDeltaUJ + " to unavailable bucket "
|
||||
+ ENERGY_BUCKET_NAMES[bucket] + " whose value was "
|
||||
+ mAccumulatedEnergiesMicroJoules[bucket]);
|
||||
+ getBucketName(index) + " whose value was "
|
||||
+ mAccumulatedEnergiesMicroJoules[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return accumulated energy (in microjoules) for the given energy bucket since last reset.
|
||||
* Returns {@link BatteryStats#ENERGY_DATA_UNAVAILABLE} if this energy data is unavailable.
|
||||
* Return accumulated energy (in microjoules) for a standard energy bucket since last reset.
|
||||
* Returns {@link android.os.BatteryStats#ENERGY_DATA_UNAVAILABLE} if this data is unavailable.
|
||||
* @throws IllegalArgumentException if no such {@link StandardEnergyBucket}.
|
||||
*/
|
||||
public long getAccumulatedBucketEnergy(@EnergyBucket int bucket) {
|
||||
public long getAccumulatedStandardBucketEnergy(@StandardEnergyBucket int bucket) {
|
||||
checkValidStandardBucket(bucket);
|
||||
return mAccumulatedEnergiesMicroJoules[bucket];
|
||||
}
|
||||
|
||||
/**
|
||||
* Map {@link MeasuredEnergySubsystem} and device state to a Display {@link EnergyBucket}.
|
||||
* Return accumulated energy (in microjoules) for the a custom energy bucket since last reset.
|
||||
* Returns {@link android.os.BatteryStats#ENERGY_DATA_UNAVAILABLE} if this data is unavailable.
|
||||
*/
|
||||
public static @EnergyBucket int getDisplayEnergyBucket(int screenState) {
|
||||
public long getAccumulatedCustomBucketEnergy(int customBucket) {
|
||||
if (!isValidCustomBucket(customBucket)) {
|
||||
return ENERGY_DATA_UNAVAILABLE;
|
||||
}
|
||||
return mAccumulatedEnergiesMicroJoules[customBucketToIndex(customBucket)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Map {@link MeasuredEnergySubsystem} and device state to Display {@link StandardEnergyBucket}.
|
||||
*/
|
||||
public static @StandardEnergyBucket int getDisplayEnergyBucket(int screenState) {
|
||||
if (Display.isOnState(screenState)) {
|
||||
return ENERGY_BUCKET_SCREEN_ON;
|
||||
}
|
||||
@@ -204,15 +262,20 @@ public class MeasuredEnergyStats {
|
||||
/**
|
||||
* Create a MeasuredEnergyStats object from a summary parcel.
|
||||
*
|
||||
* Corresponding write performed by
|
||||
* {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean)}.
|
||||
*
|
||||
* @return a new MeasuredEnergyStats object as described.
|
||||
* Returns null if the parcel indicates there is no data to populate.
|
||||
*/
|
||||
public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in) {
|
||||
final int arraySize = in.readInt();
|
||||
// Check if any MeasuredEnergyStats exists on the parcel
|
||||
if (in.readInt() == 0) return null;
|
||||
if (arraySize == 0) return null;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(new boolean[NUMBER_ENERGY_BUCKETS]);
|
||||
final int numCustomBuckets = arraySize - NUMBER_STANDARD_ENERGY_BUCKETS;
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(
|
||||
new boolean[NUMBER_STANDARD_ENERGY_BUCKETS], numCustomBuckets);
|
||||
stats.readSummaryFromParcel(in, true);
|
||||
return stats;
|
||||
}
|
||||
@@ -221,6 +284,12 @@ public class MeasuredEnergyStats {
|
||||
* Create a MeasuredEnergyStats using the template to determine which buckets are supported,
|
||||
* and populate this new object from the given parcel.
|
||||
*
|
||||
* The parcel must be consistent with the template in terms of the number of
|
||||
* possible (not necessarily supported) standard and custom buckets.
|
||||
*
|
||||
* Corresponding write performed by
|
||||
* {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean)}.
|
||||
*
|
||||
* @return a new MeasuredEnergyStats object as described.
|
||||
* Returns null if the stats contain no non-0 information (such as if template is null
|
||||
* or if the parcel indicates there is no data to populate).
|
||||
@@ -229,12 +298,22 @@ public class MeasuredEnergyStats {
|
||||
*/
|
||||
public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in,
|
||||
@Nullable MeasuredEnergyStats template) {
|
||||
final int arraySize = in.readInt();
|
||||
// Check if any MeasuredEnergyStats exists on the parcel
|
||||
if (in.readInt() == 0) return null;
|
||||
if (arraySize == 0) return null;
|
||||
|
||||
if (template == null) {
|
||||
// Nothing supported now. Create placeholder object just to consume the parcel data.
|
||||
final MeasuredEnergyStats mes = new MeasuredEnergyStats();
|
||||
// Nothing supported anymore. Create placeholder object just to consume the parcel data.
|
||||
final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize);
|
||||
mes.readSummaryFromParcel(in, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (arraySize != template.getNumberOfIndices()) {
|
||||
Slog.wtf(TAG, "Size of MeasuredEnergyStats parcel (" + arraySize
|
||||
+ ") does not match template (" + template.getNumberOfIndices() + ").");
|
||||
// Something is horribly wrong. Just consume the parcel and return null.
|
||||
final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize);
|
||||
mes.readSummaryFromParcel(in, false);
|
||||
return null;
|
||||
}
|
||||
@@ -251,14 +330,17 @@ public class MeasuredEnergyStats {
|
||||
|
||||
/** Returns true iff any of the buckets are supported and non-zero. */
|
||||
private boolean containsInterestingData() {
|
||||
for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
|
||||
if (mAccumulatedEnergiesMicroJoules[bucket] > 0) return true;
|
||||
for (int index = 0; index < mAccumulatedEnergiesMicroJoules.length; index++) {
|
||||
if (mAccumulatedEnergiesMicroJoules[index] > 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a MeasuredEnergyStats to a parcel. If the stats is null, just write a 0.
|
||||
*
|
||||
* Corresponding read performed by {@link #createAndReadSummaryFromParcel(Parcel)}
|
||||
* and {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}.
|
||||
*/
|
||||
public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats,
|
||||
Parcel dest, boolean skipZero) {
|
||||
@@ -266,14 +348,15 @@ public class MeasuredEnergyStats {
|
||||
dest.writeInt(0);
|
||||
return;
|
||||
}
|
||||
dest.writeInt(1);
|
||||
dest.writeInt(stats.getNumberOfIndices());
|
||||
stats.writeSummaryToParcel(dest, skipZero);
|
||||
}
|
||||
|
||||
/** Reset accumulated energy. */
|
||||
private void reset() {
|
||||
for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
|
||||
setValueIfSupported(bucket, 0L);
|
||||
final int numIndices = getNumberOfIndices();
|
||||
for (int index = 0; index < numIndices; index++) {
|
||||
setValueIfSupported(index, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,33 +365,93 @@ public class MeasuredEnergyStats {
|
||||
if (stats != null) stats.reset();
|
||||
}
|
||||
|
||||
/** If the bucket is AVAILABLE, overwrite its value; otherwise leave it as UNAVAILABLE. */
|
||||
private void setValueIfSupported(@EnergyBucket int bucket, long value) {
|
||||
if (mAccumulatedEnergiesMicroJoules[bucket] != ENERGY_DATA_UNAVAILABLE) {
|
||||
mAccumulatedEnergiesMicroJoules[bucket] = value;
|
||||
/** If the index is AVAILABLE, overwrite its value; otherwise leave it as UNAVAILABLE. */
|
||||
private void setValueIfSupported(int index, long value) {
|
||||
if (mAccumulatedEnergiesMicroJoules[index] != ENERGY_DATA_UNAVAILABLE) {
|
||||
mAccumulatedEnergiesMicroJoules[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if measuring the energy of the given bucket is supported by this device. */
|
||||
public boolean isEnergyBucketSupported(@EnergyBucket int bucket) {
|
||||
return mAccumulatedEnergiesMicroJoules[bucket] != ENERGY_DATA_UNAVAILABLE;
|
||||
/**
|
||||
* Check if measuring the energy of the given bucket is supported by this device.
|
||||
* @throws IllegalArgumentException if not a valid {@link StandardEnergyBucket}.
|
||||
*/
|
||||
public boolean isStandardBucketSupported(@StandardEnergyBucket int bucket) {
|
||||
checkValidStandardBucket(bucket);
|
||||
return isIndexSupported(bucket);
|
||||
}
|
||||
|
||||
private boolean isIndexSupported(int index) {
|
||||
return mAccumulatedEnergiesMicroJoules[index] != ENERGY_DATA_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/** Check if the supported energy buckets are precisely those given. */
|
||||
public boolean isSupportEqualTo(
|
||||
@NonNull boolean[] queriedStandardBuckets, int numCustomBuckets) {
|
||||
|
||||
final int numBuckets = getNumberOfIndices();
|
||||
// TODO(b/178504428): Detect whether custom buckets have changed qualitatively, not just
|
||||
// quantitatively, and treat as mismatch if so.
|
||||
if (numBuckets != NUMBER_STANDARD_ENERGY_BUCKETS + numCustomBuckets) {
|
||||
return false;
|
||||
}
|
||||
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_ENERGY_BUCKETS; stdBucket++) {
|
||||
if (isStandardBucketSupported(stdBucket) != queriedStandardBuckets[stdBucket]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Dump debug data. */
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.println("Accumulated energy since last reset (microjoules):");
|
||||
pw.print(" ");
|
||||
for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
|
||||
pw.print(ENERGY_BUCKET_NAMES[bucket]);
|
||||
for (int index = 0; index < mAccumulatedEnergiesMicroJoules.length; index++) {
|
||||
pw.print(getBucketName(index));
|
||||
pw.print(" : ");
|
||||
pw.print(mAccumulatedEnergiesMicroJoules[bucket]);
|
||||
if (!isEnergyBucketSupported(bucket)) {
|
||||
pw.print(mAccumulatedEnergiesMicroJoules[index]);
|
||||
if (!isIndexSupported(index)) {
|
||||
pw.print(" (unsupported)");
|
||||
}
|
||||
if (bucket != NUMBER_ENERGY_BUCKETS - 1) {
|
||||
if (index != mAccumulatedEnergiesMicroJoules.length - 1) {
|
||||
pw.print(", ");
|
||||
}
|
||||
}
|
||||
pw.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the index is a standard bucket, returns its name; otherwise returns its prefixed custom
|
||||
* bucket number.
|
||||
*/
|
||||
private static String getBucketName(int index) {
|
||||
if (isValidStandardBucket(index)) {
|
||||
return DebugUtils.valueToString(MeasuredEnergyStats.class, "ENERGY_BUCKET_", index);
|
||||
}
|
||||
return "CUSTOM_" + indexToCustomBucket(index);
|
||||
}
|
||||
|
||||
private static int customBucketToIndex(int customBucket) {
|
||||
return customBucket + NUMBER_STANDARD_ENERGY_BUCKETS;
|
||||
}
|
||||
|
||||
private static int indexToCustomBucket(int index) {
|
||||
return index - NUMBER_STANDARD_ENERGY_BUCKETS;
|
||||
}
|
||||
|
||||
private static void checkValidStandardBucket(@StandardEnergyBucket int bucket) {
|
||||
if (!isValidStandardBucket(bucket)) {
|
||||
throw new IllegalArgumentException("Illegal StandardEnergyBucket " + bucket);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isValidStandardBucket(@StandardEnergyBucket int bucket) {
|
||||
return bucket >= 0 && bucket < NUMBER_STANDARD_ENERGY_BUCKETS;
|
||||
}
|
||||
|
||||
private boolean isValidCustomBucket(int customBucket) {
|
||||
return customBucket >= 0
|
||||
&& customBucketToIndex(customBucket) < mAccumulatedEnergiesMicroJoules.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,9 +47,10 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
|
||||
|
||||
setExternalStatsSyncLocked(new DummyExternalStatsSync());
|
||||
|
||||
final boolean[] supportedBuckets = new boolean[MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS];
|
||||
Arrays.fill(supportedBuckets, true);
|
||||
mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedBuckets);
|
||||
final boolean[] supportedStandardBuckets
|
||||
= new boolean[MeasuredEnergyStats.NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
Arrays.fill(supportedStandardBuckets, true);
|
||||
mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedStandardBuckets, 2);
|
||||
|
||||
// A no-op handler.
|
||||
mHandler = new Handler(Looper.getMainLooper()) {
|
||||
|
||||
@@ -21,10 +21,11 @@ import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_OTHER;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.NUMBER_STANDARD_ENERGY_BUCKETS;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.os.Parcel;
|
||||
@@ -47,60 +48,77 @@ public class MeasuredEnergyStatsTest {
|
||||
|
||||
@Test
|
||||
public void testConstruction() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
if (supportedEnergyBuckets[i]) {
|
||||
assertTrue(stats.isEnergyBucketSupported(i));
|
||||
assertEquals(0L, stats.getAccumulatedBucketEnergy(i));
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
if (supportedStandardBuckets[i]) {
|
||||
assertTrue(stats.isStandardBucketSupported(i));
|
||||
assertEquals(0L, stats.getAccumulatedStandardBucketEnergy(i));
|
||||
} else {
|
||||
assertFalse(stats.isEnergyBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedBucketEnergy(i));
|
||||
assertFalse(stats.isStandardBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numCustomBuckets; i++) {
|
||||
assertEquals(0L, stats.getAccumulatedCustomBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromTemplate() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
stats.updateCustomBucket(0, 50, true);
|
||||
stats.updateCustomBucket(1, 60, true);
|
||||
|
||||
final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats);
|
||||
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
if (supportedEnergyBuckets[i]) {
|
||||
assertTrue(newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(0, newStats.getAccumulatedBucketEnergy(i));
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
if (supportedStandardBuckets[i]) {
|
||||
assertTrue(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(0L, newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
} else {
|
||||
assertFalse(newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
|
||||
assertFalse(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numCustomBuckets; i++) {
|
||||
assertEquals(0L, newStats.getAccumulatedCustomBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadWriteParcel() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
stats.updateCustomBucket(0, 50, true);
|
||||
stats.updateCustomBucket(1, 60, true);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
stats.writeToParcel(parcel);
|
||||
@@ -108,94 +126,127 @@ public class MeasuredEnergyStatsTest {
|
||||
parcel.setDataPosition(0);
|
||||
MeasuredEnergyStats newStats = new MeasuredEnergyStats(parcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
assertEquals(stats.getAccumulatedBucketEnergy(i),
|
||||
newStats.getAccumulatedBucketEnergy(i));
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
assertEquals(stats.getAccumulatedStandardBucketEnergy(i),
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
for (int i = 0; i < numCustomBuckets; i++) {
|
||||
assertEquals(stats.getAccumulatedCustomBucketEnergy(i),
|
||||
newStats.getAccumulatedCustomBucketEnergy(i));
|
||||
}
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedCustomBucketEnergy(numCustomBuckets + 1));
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
stats.updateCustomBucket(0, 50, true);
|
||||
stats.updateCustomBucket(1, 60, true);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
|
||||
parcel.setDataPosition(0);
|
||||
MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
assertEquals(stats.isEnergyBucketSupported(i),
|
||||
newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedBucketEnergy(i),
|
||||
newStats.getAccumulatedBucketEnergy(i));
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
assertEquals(stats.isStandardBucketSupported(i),
|
||||
newStats.isStandardBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedStandardBucketEnergy(i),
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
for (int i = 0; i < numCustomBuckets; i++) {
|
||||
assertEquals(stats.getAccumulatedCustomBucketEnergy(i),
|
||||
newStats.getAccumulatedCustomBucketEnergy(i));
|
||||
}
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedCustomBucketEnergy(numCustomBuckets + 1));
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel_existingTemplate() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats template = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
template.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
template.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
template.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
final MeasuredEnergyStats template
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
template.updateCustomBucket(0, 50, true);
|
||||
|
||||
final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 7, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 63, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 7, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 63, true);
|
||||
stats.updateCustomBucket(0, 315, true);
|
||||
stats.updateCustomBucket(1, 316, true);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
|
||||
|
||||
final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched from false to true
|
||||
newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true to false
|
||||
final MeasuredEnergyStats newTemplate = new MeasuredEnergyStats(newSupportedEnergyBuckets);
|
||||
final boolean[] newsupportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
newsupportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
newsupportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched false > true
|
||||
newsupportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true > false
|
||||
final MeasuredEnergyStats newTemplate
|
||||
= new MeasuredEnergyStats(newsupportedStandardBuckets, numCustomBuckets);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
final MeasuredEnergyStats newStats =
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
|
||||
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
if (!newSupportedEnergyBuckets[i]) {
|
||||
assertFalse(newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
|
||||
} else if (!supportedEnergyBuckets[i]) {
|
||||
assertTrue(newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(0L, newStats.getAccumulatedBucketEnergy(i));
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
if (!newsupportedStandardBuckets[i]) {
|
||||
assertFalse(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
} else if (!supportedStandardBuckets[i]) {
|
||||
assertTrue(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(0L, newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
} else {
|
||||
assertTrue(newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedBucketEnergy(i),
|
||||
newStats.getAccumulatedBucketEnergy(i));
|
||||
assertTrue(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedStandardBucketEnergy(i),
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numCustomBuckets; i++) {
|
||||
assertEquals(stats.getAccumulatedCustomBucketEnergy(i),
|
||||
newStats.getAccumulatedCustomBucketEnergy(i));
|
||||
}
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedCustomBucketEnergy(numCustomBuckets + 1));
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel_skipZero() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
Arrays.fill(supportedEnergyBuckets, true);
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
Arrays.fill(supportedStandardBuckets, true);
|
||||
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
// Accumulate energy in one bucket, the rest should be zero
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
// Accumulate energy in one bucket and one custom bucket, the rest should be zero
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
|
||||
stats.updateCustomBucket(1, 60, true);
|
||||
|
||||
// Let's try parcelling with including zeros
|
||||
final Parcel includeZerosParcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, includeZerosParcel, false);
|
||||
includeZerosParcel.setDataPosition(0);
|
||||
@@ -203,90 +254,180 @@ public class MeasuredEnergyStatsTest {
|
||||
MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
|
||||
includeZerosParcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
if (i == ENERGY_BUCKET_SCREEN_ON) {
|
||||
assertEquals(stats.isEnergyBucketSupported(i),
|
||||
newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedBucketEnergy(i),
|
||||
newStats.getAccumulatedBucketEnergy(i));
|
||||
assertEquals(stats.isStandardBucketSupported(i),
|
||||
newStats.isStandardBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedStandardBucketEnergy(i),
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
} else {
|
||||
assertTrue(newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(0L, newStats.getAccumulatedBucketEnergy(i));
|
||||
assertTrue(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(0L, newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
assertEquals(0L, newStats.getAccumulatedCustomBucketEnergy(0));
|
||||
assertEquals(stats.getAccumulatedCustomBucketEnergy(1),
|
||||
newStats.getAccumulatedCustomBucketEnergy(1));
|
||||
includeZerosParcel.recycle();
|
||||
|
||||
// Now let's try parcelling with skipping zeros
|
||||
final Parcel skipZerosParcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, skipZerosParcel, true);
|
||||
skipZerosParcel.setDataPosition(0);
|
||||
|
||||
newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(skipZerosParcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
if (i == ENERGY_BUCKET_SCREEN_ON) {
|
||||
assertEquals(stats.isEnergyBucketSupported(i),
|
||||
newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedBucketEnergy(i),
|
||||
newStats.getAccumulatedBucketEnergy(i));
|
||||
assertEquals(stats.isStandardBucketSupported(i),
|
||||
newStats.isStandardBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedStandardBucketEnergy(i),
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
} else {
|
||||
assertFalse(newStats.isEnergyBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
|
||||
assertFalse(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
assertEquals(0L, newStats.getAccumulatedCustomBucketEnergy(0));
|
||||
assertEquals(stats.getAccumulatedCustomBucketEnergy(1),
|
||||
newStats.getAccumulatedCustomBucketEnergy(1));
|
||||
skipZerosParcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel_nullTemplate() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
stats.updateCustomBucket(0, 50, true);
|
||||
stats.updateCustomBucket(1, 60, true);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
MeasuredEnergyStats newStats
|
||||
= MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, null);
|
||||
assertNull(newStats);
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel_boring() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats template
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
template.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
template.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
template.updateCustomBucket(0, 50, true);
|
||||
|
||||
final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 0L, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 7L, true);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false);
|
||||
|
||||
final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
newSupportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
newSupportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched false > true
|
||||
newSupportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true > false
|
||||
final MeasuredEnergyStats newTemplate
|
||||
= new MeasuredEnergyStats(newSupportedStandardBuckets, numCustomBuckets);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
final MeasuredEnergyStats newStats =
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
|
||||
// The only non-0 entry in stats is no longer supported, so now there's no interesting data.
|
||||
assertNull(newStats);
|
||||
assertEquals("Parcel was not properly consumed", 0, parcel.dataAvail());
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateBucket() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_DOZE, 30, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_DOZE, 30, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
|
||||
assertEquals(15, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
|
||||
stats.updateCustomBucket(0, 50, true);
|
||||
stats.updateCustomBucket(1, 60, true);
|
||||
stats.updateCustomBucket(0, 3, true);
|
||||
|
||||
assertEquals(15, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE,
|
||||
stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_DOZE));
|
||||
assertEquals(40, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_OTHER));
|
||||
stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_DOZE));
|
||||
assertEquals(40, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_OTHER));
|
||||
assertEquals(50 + 3, stats.getAccumulatedCustomBucketEnergy(0));
|
||||
assertEquals(60, stats.getAccumulatedCustomBucketEnergy(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReset() {
|
||||
final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int numCustomBuckets = 2;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
final MeasuredEnergyStats stats
|
||||
= new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
|
||||
stats.updateCustomBucket(0, 50, true);
|
||||
stats.updateCustomBucket(1, 60, true);
|
||||
|
||||
MeasuredEnergyStats.resetIfNotNull(stats);
|
||||
// All energy should be reset to 0
|
||||
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
|
||||
if (supportedEnergyBuckets[i]) {
|
||||
assertTrue(stats.isEnergyBucketSupported(i));
|
||||
assertEquals(0, stats.getAccumulatedBucketEnergy(i));
|
||||
for (int i = 0; i < NUMBER_STANDARD_ENERGY_BUCKETS; i++) {
|
||||
if (supportedStandardBuckets[i]) {
|
||||
assertTrue(stats.isStandardBucketSupported(i));
|
||||
assertEquals(0, stats.getAccumulatedStandardBucketEnergy(i));
|
||||
} else {
|
||||
assertFalse(stats.isEnergyBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedBucketEnergy(i));
|
||||
assertFalse(stats.isStandardBucketSupported(i));
|
||||
assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketEnergy(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numCustomBuckets; i++) {
|
||||
assertEquals(0, stats.getAccumulatedCustomBucketEnergy(i));
|
||||
}
|
||||
|
||||
// Values should increase as usual.
|
||||
stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 70, true);
|
||||
assertEquals(70L, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
|
||||
stats.updateStandardBucket(ENERGY_BUCKET_SCREEN_ON, 70, true);
|
||||
assertEquals(70L, stats.getAccumulatedStandardBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
|
||||
|
||||
stats.updateCustomBucket(1, 12, true);
|
||||
assertEquals(12L, stats.getAccumulatedCustomBucketEnergy(1));
|
||||
}
|
||||
|
||||
/** Test that states are mapped to the expected energy buckets. Beware of mapping changes. */
|
||||
@Test
|
||||
public void testEnergyBucketMapping() {
|
||||
public void testStandardBucketMapping() {
|
||||
int exp;
|
||||
|
||||
exp = ENERGY_BUCKET_SCREEN_ON;
|
||||
|
||||
@@ -207,12 +207,13 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
if (mPowerStatsInternal != null) {
|
||||
populateEnergyConsumerSubsystemMapsLocked();
|
||||
final MeasuredEnergyArray initialMeasuredEnergies = getEnergyConsumptionData();
|
||||
final boolean[] supportedBuckets = getSupportedEnergyBuckets(
|
||||
initialMeasuredEnergies);
|
||||
mMeasuredEnergySnapshot = initialMeasuredEnergies == null
|
||||
? null : new MeasuredEnergySnapshot(initialMeasuredEnergies);
|
||||
final boolean[] supportedStdBuckets
|
||||
= getSupportedEnergyBuckets(initialMeasuredEnergies);
|
||||
final int numCustomBuckets = 0; // TODO: Get this from initialMeasuredEnergies
|
||||
synchronized (mStats) {
|
||||
mStats.initMeasuredEnergyStatsLocked(supportedBuckets);
|
||||
mStats.initMeasuredEnergyStatsLocked(supportedStdBuckets, numCustomBuckets);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -740,15 +741,16 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
|
||||
/**
|
||||
* Map the {@link MeasuredEnergyArray.MeasuredEnergySubsystem}s in the given energyArray to
|
||||
* their corresponding {@link MeasuredEnergyStats.EnergyBucket}s.
|
||||
* their corresponding {@link MeasuredEnergyStats.StandardEnergyBucket}s.
|
||||
* Does not include custom energy buckets (which are always, by definition, supported).
|
||||
*
|
||||
* @return array with true for index i if energy bucket i is supported.
|
||||
* @return array with true for index i if standard energy bucket i is supported.
|
||||
*/
|
||||
private static @Nullable boolean[] getSupportedEnergyBuckets(MeasuredEnergyArray energyArray) {
|
||||
if (energyArray == null) {
|
||||
return null;
|
||||
}
|
||||
final boolean[] buckets = new boolean[MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS];
|
||||
final boolean[] buckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_ENERGY_BUCKETS];
|
||||
final int size = energyArray.size();
|
||||
for (int energyIdx = 0; energyIdx < size; energyIdx++) {
|
||||
switch (energyArray.getSubsystem(energyIdx)) {
|
||||
|
||||
Reference in New Issue
Block a user