Merge changes Ie40ff8ae,Iff6eb6de
* changes: Add @GuardedBy annotations Add support for per process state data to MeasuredEnergyStats
This commit is contained in:
committed by
Android (Google) Code Review
commit
0054447bec
@@ -174,7 +174,7 @@ public abstract class BatteryConsumer {
|
||||
public static final int PROCESS_STATE_BACKGROUND = 2;
|
||||
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
|
||||
|
||||
static final int PROCESS_STATE_COUNT = 4;
|
||||
public static final int PROCESS_STATE_COUNT = 4;
|
||||
|
||||
private static final String[] sProcessStateNames = new String[PROCESS_STATE_COUNT];
|
||||
|
||||
|
||||
@@ -653,6 +653,24 @@ public abstract class BatteryStats implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps BatteryStats.Uid process state to the BatteryConsumer process state.
|
||||
*/
|
||||
public static @BatteryConsumer.ProcessState int
|
||||
mapUidProcessStateToBatteryConsumerProcessState(int processState) {
|
||||
switch (processState) {
|
||||
case BatteryStats.Uid.PROCESS_STATE_TOP:
|
||||
return BatteryConsumer.PROCESS_STATE_FOREGROUND;
|
||||
case BatteryStats.Uid.PROCESS_STATE_BACKGROUND:
|
||||
case BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING:
|
||||
return BatteryConsumer.PROCESS_STATE_BACKGROUND;
|
||||
case BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE:
|
||||
return BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
|
||||
default:
|
||||
return BatteryConsumer.PROCESS_STATE_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if battery consumption is tracked on a per-process-state basis.
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,7 @@ import android.util.Slog;
|
||||
import android.view.Display;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.os.LongMultiStateCounter;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -75,6 +76,147 @@ public class MeasuredEnergyStats {
|
||||
public @interface StandardPowerBucket {
|
||||
}
|
||||
|
||||
private static final int INVALID_STATE = -1;
|
||||
|
||||
/**
|
||||
* Configuration of measured energy stats: which power rails (buckets) are supported on
|
||||
* this device, what custom power drains are supported etc.
|
||||
*/
|
||||
public static class Config {
|
||||
private final boolean[] mSupportedStandardBuckets;
|
||||
@NonNull
|
||||
private final String[] mCustomBucketNames;
|
||||
private final boolean[] mSupportedMultiStateBuckets;
|
||||
@NonNull
|
||||
private final String[] mStateNames;
|
||||
|
||||
public Config(@NonNull boolean[] supportedStandardBuckets,
|
||||
@Nullable String[] customBucketNames,
|
||||
@NonNull int[] supportedMultiStateBuckets,
|
||||
@Nullable String[] stateNames) {
|
||||
mSupportedStandardBuckets = supportedStandardBuckets;
|
||||
mCustomBucketNames = customBucketNames != null ? customBucketNames : new String[0];
|
||||
mSupportedMultiStateBuckets =
|
||||
new boolean[supportedStandardBuckets.length + mCustomBucketNames.length];
|
||||
for (int bucket : supportedMultiStateBuckets) {
|
||||
if (mSupportedStandardBuckets[bucket]) {
|
||||
mSupportedMultiStateBuckets[bucket] = true;
|
||||
}
|
||||
}
|
||||
mStateNames = stateNames != null ? stateNames : new String[] {""};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied Config is compatible with this one and therefore
|
||||
* data collected with one of them will work with the other.
|
||||
*/
|
||||
public boolean isCompatible(Config other) {
|
||||
return Arrays.equals(mSupportedStandardBuckets, other.mSupportedStandardBuckets)
|
||||
&& Arrays.equals(mCustomBucketNames, other.mCustomBucketNames)
|
||||
&& Arrays.equals(mSupportedMultiStateBuckets,
|
||||
other.mSupportedMultiStateBuckets)
|
||||
&& Arrays.equals(mStateNames, other.mStateNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the Config object into the supplied Parcel.
|
||||
*/
|
||||
public static void writeToParcel(@Nullable Config config, Parcel out) {
|
||||
if (config == null) {
|
||||
out.writeBoolean(false);
|
||||
return;
|
||||
}
|
||||
|
||||
out.writeBoolean(true);
|
||||
out.writeInt(config.mSupportedStandardBuckets.length);
|
||||
out.writeBooleanArray(config.mSupportedStandardBuckets);
|
||||
out.writeStringArray(config.mCustomBucketNames);
|
||||
int multiStateBucketCount = 0;
|
||||
for (boolean supported : config.mSupportedMultiStateBuckets) {
|
||||
if (supported) {
|
||||
multiStateBucketCount++;
|
||||
}
|
||||
}
|
||||
final int[] supportedMultiStateBuckets = new int[multiStateBucketCount];
|
||||
int index = 0;
|
||||
for (int bucket = 0; bucket < config.mSupportedMultiStateBuckets.length; bucket++) {
|
||||
if (config.mSupportedMultiStateBuckets[bucket]) {
|
||||
supportedMultiStateBuckets[index++] = bucket;
|
||||
}
|
||||
}
|
||||
out.writeInt(multiStateBucketCount);
|
||||
out.writeIntArray(supportedMultiStateBuckets);
|
||||
out.writeStringArray(config.mStateNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a Config object from the supplied Parcel.
|
||||
*/
|
||||
@Nullable
|
||||
public static Config createFromParcel(Parcel in) {
|
||||
if (!in.readBoolean()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int supportedStandardBucketCount = in.readInt();
|
||||
final boolean[] supportedStandardBuckets = new boolean[supportedStandardBucketCount];
|
||||
in.readBooleanArray(supportedStandardBuckets);
|
||||
final String[] customBucketNames = in.readStringArray();
|
||||
final int supportedMultiStateBucketCount = in.readInt();
|
||||
final int[] supportedMultiStateBuckets = new int[supportedMultiStateBucketCount];
|
||||
in.readIntArray(supportedMultiStateBuckets);
|
||||
final String[] stateNames = in.readStringArray();
|
||||
return new Config(supportedStandardBuckets, customBucketNames,
|
||||
supportedMultiStateBuckets, stateNames);
|
||||
}
|
||||
|
||||
/** Get number of possible buckets, including both standard and custom ones. */
|
||||
private int getNumberOfBuckets() {
|
||||
return mSupportedStandardBuckets.length + mCustomBucketNames.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified charge bucket is tracked.
|
||||
*/
|
||||
public boolean isSupportedBucket(int index) {
|
||||
return mSupportedStandardBuckets[index];
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String[] getCustomBucketNames() {
|
||||
return mCustomBucketNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified charge bucket is tracked on a per-state basis.
|
||||
*/
|
||||
public boolean isSupportedMultiStateBucket(int index) {
|
||||
return mSupportedMultiStateBuckets[index];
|
||||
}
|
||||
|
||||
public String[] getStateNames() {
|
||||
return mStateNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the index is a standard bucket, returns its name; otherwise returns its prefixed
|
||||
* custom bucket number.
|
||||
*/
|
||||
private String getBucketName(int index) {
|
||||
if (isValidStandardBucket(index)) {
|
||||
return DebugUtils.valueToString(MeasuredEnergyStats.class, "POWER_BUCKET_", index);
|
||||
}
|
||||
final int customBucket = indexToCustomBucket(index);
|
||||
StringBuilder name = new StringBuilder().append("CUSTOM_").append(customBucket);
|
||||
if (!TextUtils.isEmpty(mCustomBucketNames[customBucket])) {
|
||||
name.append('(').append(mCustomBucketNames[customBucket]).append(')');
|
||||
}
|
||||
return name.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private final Config mConfig;
|
||||
|
||||
/**
|
||||
* Total charge (in microcoulombs) that a power bucket (including both
|
||||
* {@link StandardPowerBucket} and custom buckets) has accumulated since the last reset.
|
||||
@@ -90,74 +232,76 @@ public class MeasuredEnergyStats {
|
||||
*/
|
||||
private final long[] mAccumulatedChargeMicroCoulomb;
|
||||
|
||||
private final String[] mCustomBucketNames;
|
||||
private LongMultiStateCounter[] mAccumulatedMultiStateChargeMicroCoulomb;
|
||||
private int mState = INVALID_STATE;
|
||||
private long mStateChangeTimestampMs;
|
||||
|
||||
/**
|
||||
* Creates a MeasuredEnergyStats set to support the provided power buckets.
|
||||
* supportedStandardBuckets must be of size {@link #NUMBER_STANDARD_POWER_BUCKETS}.
|
||||
* numCustomBuckets >= 0 is the number of (non-standard) custom power buckets on the device.
|
||||
*/
|
||||
public MeasuredEnergyStats(@NonNull boolean[] supportedStandardBuckets,
|
||||
@Nullable String[] customBucketNames) {
|
||||
mCustomBucketNames = customBucketNames == null ? new String[0] : customBucketNames;
|
||||
final int numTotalBuckets = NUMBER_STANDARD_POWER_BUCKETS + mCustomBucketNames.length;
|
||||
public MeasuredEnergyStats(MeasuredEnergyStats.Config config) {
|
||||
mConfig = config;
|
||||
final int numTotalBuckets = config.getNumberOfBuckets();
|
||||
mAccumulatedChargeMicroCoulomb = new long[numTotalBuckets];
|
||||
// Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE.
|
||||
// All custom buckets are, by definition, supported, so their values stay at 0.
|
||||
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) {
|
||||
if (!supportedStandardBuckets[stdBucket]) {
|
||||
if (!mConfig.mSupportedStandardBuckets[stdBucket]) {
|
||||
mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
|
||||
* supported. This certainly does NOT produce an exact clone of the template.
|
||||
* Reads a MeasuredEnergyStats from the supplied Parcel.
|
||||
*/
|
||||
private MeasuredEnergyStats(MeasuredEnergyStats template) {
|
||||
final int numIndices = template.getNumberOfIndices();
|
||||
mAccumulatedChargeMicroCoulomb = new long[numIndices];
|
||||
// Initialize to all zeros where supported, otherwise POWER_DATA_UNAVAILABLE.
|
||||
// All custom buckets are, by definition, supported, so their values stay at 0.
|
||||
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) {
|
||||
if (!template.isIndexSupported(stdBucket)) {
|
||||
mAccumulatedChargeMicroCoulomb[stdBucket] = POWER_DATA_UNAVAILABLE;
|
||||
}
|
||||
@Nullable
|
||||
public static MeasuredEnergyStats createFromParcel(Config config, Parcel in) {
|
||||
if (!in.readBoolean()) {
|
||||
return null;
|
||||
}
|
||||
mCustomBucketNames = template.getCustomBucketNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
|
||||
* supported.
|
||||
*/
|
||||
public static MeasuredEnergyStats createFromTemplate(MeasuredEnergyStats template) {
|
||||
return new MeasuredEnergyStats(template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for creating a temp MeasuredEnergyStats.
|
||||
* See {@link #createAndReadSummaryFromParcel(Parcel, MeasuredEnergyStats)}.
|
||||
*/
|
||||
private MeasuredEnergyStats(int numIndices) {
|
||||
mAccumulatedChargeMicroCoulomb = new long[numIndices];
|
||||
mCustomBucketNames = new String[numIndices - NUMBER_STANDARD_POWER_BUCKETS];
|
||||
return new MeasuredEnergyStats(config, in);
|
||||
}
|
||||
|
||||
/** Construct from parcel. */
|
||||
public MeasuredEnergyStats(Parcel in) {
|
||||
public MeasuredEnergyStats(MeasuredEnergyStats.Config config, Parcel in) {
|
||||
mConfig = config;
|
||||
|
||||
final int size = in.readInt();
|
||||
mAccumulatedChargeMicroCoulomb = new long[size];
|
||||
in.readLongArray(mAccumulatedChargeMicroCoulomb);
|
||||
mCustomBucketNames = in.readStringArray();
|
||||
if (in.readBoolean()) {
|
||||
mAccumulatedMultiStateChargeMicroCoulomb = new LongMultiStateCounter[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (in.readBoolean()) {
|
||||
mAccumulatedMultiStateChargeMicroCoulomb[i] =
|
||||
LongMultiStateCounter.CREATOR.createFromParcel(in);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mAccumulatedMultiStateChargeMicroCoulomb = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Write to parcel */
|
||||
public void writeToParcel(Parcel out) {
|
||||
out.writeInt(mAccumulatedChargeMicroCoulomb.length);
|
||||
out.writeLongArray(mAccumulatedChargeMicroCoulomb);
|
||||
out.writeStringArray(mCustomBucketNames);
|
||||
if (mAccumulatedMultiStateChargeMicroCoulomb != null) {
|
||||
out.writeBoolean(true);
|
||||
for (LongMultiStateCounter counter : mAccumulatedMultiStateChargeMicroCoulomb) {
|
||||
if (counter != null) {
|
||||
out.writeBoolean(true);
|
||||
counter.writeToParcel(out, 0);
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,17 +311,27 @@ public class MeasuredEnergyStats {
|
||||
* Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary
|
||||
* parceling changes.
|
||||
*
|
||||
* Corresponding write performed by {@link #writeSummaryToParcel(Parcel, boolean)}.
|
||||
* Corresponding write performed by {@link #writeSummaryToParcel(Parcel)}.
|
||||
*/
|
||||
private void readSummaryFromParcel(Parcel in, boolean overwriteAvailability) {
|
||||
private void readSummaryFromParcel(Parcel in) {
|
||||
final int numWrittenEntries = in.readInt();
|
||||
for (int entry = 0; entry < numWrittenEntries; entry++) {
|
||||
final int index = in.readInt();
|
||||
final long chargeUC = in.readLong();
|
||||
if (overwriteAvailability) {
|
||||
mAccumulatedChargeMicroCoulomb[index] = chargeUC;
|
||||
} else {
|
||||
LongMultiStateCounter multiStateCounter = null;
|
||||
if (in.readBoolean()) {
|
||||
multiStateCounter = LongMultiStateCounter.CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
if (index < mAccumulatedChargeMicroCoulomb.length) {
|
||||
setValueIfSupported(index, chargeUC);
|
||||
if (multiStateCounter != null) {
|
||||
if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
|
||||
mAccumulatedMultiStateChargeMicroCoulomb =
|
||||
new LongMultiStateCounter[numWrittenEntries];
|
||||
}
|
||||
mAccumulatedMultiStateChargeMicroCoulomb[index] = multiStateCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,20 +340,26 @@ 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)}.
|
||||
* Corresponding read performed by {@link #readSummaryFromParcel(Parcel)}.
|
||||
*/
|
||||
private void writeSummaryToParcel(Parcel out, boolean skipZero) {
|
||||
private void writeSummaryToParcel(Parcel out) {
|
||||
final int posOfNumWrittenEntries = out.dataPosition();
|
||||
out.writeInt(0);
|
||||
int numWrittenEntries = 0;
|
||||
// Write only the supported buckets (with non-zero charge, if applicable).
|
||||
for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) {
|
||||
final long charge = mAccumulatedChargeMicroCoulomb[index];
|
||||
if (charge < 0) continue;
|
||||
if (charge == 0 && skipZero) continue;
|
||||
if (charge <= 0) continue;
|
||||
|
||||
out.writeInt(index);
|
||||
out.writeLong(charge);
|
||||
if (mAccumulatedMultiStateChargeMicroCoulomb != null
|
||||
&& mAccumulatedMultiStateChargeMicroCoulomb[index] != null) {
|
||||
out.writeBoolean(true);
|
||||
mAccumulatedMultiStateChargeMicroCoulomb[index].writeToParcel(out, 0);
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
}
|
||||
numWrittenEntries++;
|
||||
}
|
||||
final int currPos = out.dataPosition();
|
||||
@@ -208,39 +368,86 @@ public class MeasuredEnergyStats {
|
||||
out.setDataPosition(currPos);
|
||||
}
|
||||
|
||||
/** Get number of possible buckets, including both standard and custom ones. */
|
||||
private int getNumberOfIndices() {
|
||||
return mAccumulatedChargeMicroCoulomb.length;
|
||||
}
|
||||
|
||||
|
||||
/** Updates the given standard power bucket with the given charge if accumulate is true. */
|
||||
public void updateStandardBucket(@StandardPowerBucket int bucket, long chargeDeltaUC) {
|
||||
updateStandardBucket(bucket, chargeDeltaUC, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given standard power bucket with the given charge if supported.
|
||||
* @param timestampMs elapsed realtime in milliseconds
|
||||
*/
|
||||
public void updateStandardBucket(@StandardPowerBucket int bucket, long chargeDeltaUC,
|
||||
long timestampMs) {
|
||||
checkValidStandardBucket(bucket);
|
||||
updateEntry(bucket, chargeDeltaUC);
|
||||
updateEntry(bucket, chargeDeltaUC, timestampMs);
|
||||
}
|
||||
|
||||
/** Updates the given custom power bucket with the given charge if accumulate is true. */
|
||||
public void updateCustomBucket(int customBucket, long chargeDeltaUC) {
|
||||
updateCustomBucket(customBucket, chargeDeltaUC, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given custom power bucket with the given charge if supported.
|
||||
* @param timestampMs elapsed realtime in milliseconds
|
||||
*/
|
||||
public void updateCustomBucket(int customBucket, long chargeDeltaUC, long timestampMs) {
|
||||
if (!isValidCustomBucket(customBucket)) {
|
||||
Slog.e(TAG, "Attempted to update invalid custom bucket " + customBucket);
|
||||
return;
|
||||
}
|
||||
final int index = customBucketToIndex(customBucket);
|
||||
updateEntry(index, chargeDeltaUC);
|
||||
updateEntry(index, chargeDeltaUC, timestampMs);
|
||||
}
|
||||
|
||||
/** Updates the given index with the given charge if accumulate is true. */
|
||||
private void updateEntry(int index, long chargeDeltaUC) {
|
||||
/** Updates the given bucket with the given charge delta. */
|
||||
private void updateEntry(int index, long chargeDeltaUC, long timestampMs) {
|
||||
if (mAccumulatedChargeMicroCoulomb[index] >= 0L) {
|
||||
mAccumulatedChargeMicroCoulomb[index] += chargeDeltaUC;
|
||||
if (mState != INVALID_STATE && mConfig.isSupportedMultiStateBucket(index)) {
|
||||
if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
|
||||
mAccumulatedMultiStateChargeMicroCoulomb =
|
||||
new LongMultiStateCounter[mAccumulatedChargeMicroCoulomb.length];
|
||||
}
|
||||
LongMultiStateCounter counter =
|
||||
mAccumulatedMultiStateChargeMicroCoulomb[index];
|
||||
if (counter == null) {
|
||||
counter = new LongMultiStateCounter(mConfig.mStateNames.length);
|
||||
mAccumulatedMultiStateChargeMicroCoulomb[index] = counter;
|
||||
counter.setState(mState, mStateChangeTimestampMs);
|
||||
counter.updateValue(0, mStateChangeTimestampMs);
|
||||
}
|
||||
counter.updateValue(mAccumulatedChargeMicroCoulomb[index], timestampMs);
|
||||
}
|
||||
} else {
|
||||
Slog.wtf(TAG, "Attempting to add " + chargeDeltaUC + " to unavailable bucket "
|
||||
+ getBucketName(index) + " whose value was "
|
||||
+ mConfig.getBucketName(index) + " whose value was "
|
||||
+ mAccumulatedChargeMicroCoulomb[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the "state" on all multi-state counters used by this MeasuredEnergyStats. Further
|
||||
* accumulated charge updates will assign the deltas to this state, until the state changes.
|
||||
*
|
||||
* If setState is never called on a MeasuredEnergyStats object, then it does not track
|
||||
* per-state usage.
|
||||
*/
|
||||
public void setState(int state, long timestampMs) {
|
||||
mState = state;
|
||||
mStateChangeTimestampMs = timestampMs;
|
||||
if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < mAccumulatedMultiStateChargeMicroCoulomb.length; i++) {
|
||||
LongMultiStateCounter counter = mAccumulatedMultiStateChargeMicroCoulomb[i];
|
||||
if (counter != null) {
|
||||
counter.setState(state, timestampMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return accumulated charge (in microcouloumb) for a standard power bucket since last reset.
|
||||
* Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable.
|
||||
@@ -251,6 +458,26 @@ public class MeasuredEnergyStats {
|
||||
return mAccumulatedChargeMicroCoulomb[bucket];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the accumulated charge (in microcouloumb) for the standard power bucket and
|
||||
* the specified state since last reset.
|
||||
*
|
||||
* Returns {@link android.os.BatteryStats#POWER_DATA_UNAVAILABLE} if this data is unavailable.
|
||||
*/
|
||||
public long getAccumulatedStandardBucketCharge(@StandardPowerBucket int bucket, int state) {
|
||||
if (!mConfig.isSupportedMultiStateBucket(bucket)) {
|
||||
return POWER_DATA_UNAVAILABLE;
|
||||
}
|
||||
if (mAccumulatedMultiStateChargeMicroCoulomb == null) {
|
||||
return 0;
|
||||
}
|
||||
final LongMultiStateCounter counter = mAccumulatedMultiStateChargeMicroCoulomb[bucket];
|
||||
if (counter == null) {
|
||||
return 0;
|
||||
}
|
||||
return counter.getCount(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return accumulated charge (in microcoulomb) for the a custom power bucket since last
|
||||
* reset.
|
||||
@@ -288,32 +515,6 @@ public class MeasuredEnergyStats {
|
||||
return POWER_BUCKET_SCREEN_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MeasuredEnergyStats object from a summary parcel.
|
||||
*
|
||||
* Corresponding write performed by
|
||||
* {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean, 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 (arraySize == 0) return null;
|
||||
|
||||
final String[] customBucketNames;
|
||||
if (in.readBoolean()) {
|
||||
customBucketNames = in.readStringArray();
|
||||
} else {
|
||||
customBucketNames = new String[0];
|
||||
}
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(
|
||||
new boolean[NUMBER_STANDARD_POWER_BUCKETS], customBucketNames);
|
||||
stats.readSummaryFromParcel(in, true);
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MeasuredEnergyStats using the template to determine which buckets are supported,
|
||||
* and populate this new object from the given parcel.
|
||||
@@ -322,44 +523,37 @@ public class MeasuredEnergyStats {
|
||||
* possible (not necessarily supported) standard and custom buckets.
|
||||
*
|
||||
* Corresponding write performed by
|
||||
* {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel, boolean, boolean)}.
|
||||
* {@link #writeSummaryToParcel(MeasuredEnergyStats, Parcel)}.
|
||||
*
|
||||
* @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).
|
||||
*
|
||||
* @see #createFromTemplate
|
||||
*/
|
||||
public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in,
|
||||
@Nullable MeasuredEnergyStats template) {
|
||||
public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(
|
||||
@Nullable Config config, Parcel in) {
|
||||
final int arraySize = in.readInt();
|
||||
// Check if any MeasuredEnergyStats exists on the parcel
|
||||
if (arraySize == 0) return null;
|
||||
|
||||
boolean includesCustomBucketNames = in.readBoolean();
|
||||
if (includesCustomBucketNames) {
|
||||
// Consume the array of custom bucket names. They are already included in the
|
||||
// template.
|
||||
in.readStringArray();
|
||||
}
|
||||
if (template == null) {
|
||||
if (config == null) {
|
||||
// Nothing supported anymore. Create placeholder object just to consume the parcel data.
|
||||
final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize);
|
||||
mes.readSummaryFromParcel(in, false);
|
||||
final MeasuredEnergyStats mes = new MeasuredEnergyStats(
|
||||
new Config(new boolean[arraySize], null, new int[0], new String[]{""}));
|
||||
mes.readSummaryFromParcel(in);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (arraySize != template.getNumberOfIndices()) {
|
||||
if (arraySize != config.getNumberOfBuckets()) {
|
||||
Slog.wtf(TAG, "Size of MeasuredEnergyStats parcel (" + arraySize
|
||||
+ ") does not match template (" + template.getNumberOfIndices() + ").");
|
||||
+ ") does not match config (" + config.getNumberOfBuckets() + ").");
|
||||
// Something is horribly wrong. Just consume the parcel and return null.
|
||||
final MeasuredEnergyStats mes = new MeasuredEnergyStats(arraySize);
|
||||
mes.readSummaryFromParcel(in, false);
|
||||
final MeasuredEnergyStats mes = new MeasuredEnergyStats(config);
|
||||
mes.readSummaryFromParcel(in);
|
||||
return null;
|
||||
}
|
||||
|
||||
final MeasuredEnergyStats stats = createFromTemplate(template);
|
||||
stats.readSummaryFromParcel(in, false);
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
stats.readSummaryFromParcel(in);
|
||||
if (stats.containsInterestingData()) {
|
||||
return stats;
|
||||
} else {
|
||||
@@ -379,28 +573,20 @@ public class MeasuredEnergyStats {
|
||||
/**
|
||||
* 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)}.
|
||||
* Corresponding read performed by {@link #createAndReadSummaryFromParcel}.
|
||||
*/
|
||||
public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats,
|
||||
Parcel dest, boolean skipZero, boolean skipCustomBucketNames) {
|
||||
public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats, Parcel dest) {
|
||||
if (stats == null) {
|
||||
dest.writeInt(0);
|
||||
return;
|
||||
}
|
||||
dest.writeInt(stats.getNumberOfIndices());
|
||||
if (!skipCustomBucketNames) {
|
||||
dest.writeBoolean(true);
|
||||
dest.writeStringArray(stats.getCustomBucketNames());
|
||||
} else {
|
||||
dest.writeBoolean(false);
|
||||
}
|
||||
stats.writeSummaryToParcel(dest, skipZero);
|
||||
dest.writeInt(stats.mConfig.getNumberOfBuckets());
|
||||
stats.writeSummaryToParcel(dest);
|
||||
}
|
||||
|
||||
/** Reset accumulated charges. */
|
||||
private void reset() {
|
||||
final int numIndices = getNumberOfIndices();
|
||||
final int numIndices = mConfig.getNumberOfBuckets();
|
||||
for (int index = 0; index < numIndices; index++) {
|
||||
setValueIfSupported(index, 0L);
|
||||
}
|
||||
@@ -431,46 +617,32 @@ public class MeasuredEnergyStats {
|
||||
return mAccumulatedChargeMicroCoulomb[index] != POWER_DATA_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/** Check if the supported power buckets are precisely those given. */
|
||||
public boolean isSupportEqualTo(
|
||||
@NonNull boolean[] queriedStandardBuckets, @Nullable String[] customBucketNames) {
|
||||
if (customBucketNames == null) {
|
||||
//In practice customBucketNames should never be null, but sanitize it just to be sure.
|
||||
customBucketNames = new String[0];
|
||||
}
|
||||
|
||||
final int numBuckets = getNumberOfIndices();
|
||||
final int numCustomBuckets = customBucketNames == null ? 0 : customBucketNames.length;
|
||||
if (numBuckets != NUMBER_STANDARD_POWER_BUCKETS + numCustomBuckets) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Arrays.equals(mCustomBucketNames, customBucketNames)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int stdBucket = 0; stdBucket < NUMBER_STANDARD_POWER_BUCKETS; stdBucket++) {
|
||||
if (isStandardBucketSupported(stdBucket) != queriedStandardBuckets[stdBucket]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getCustomBucketNames() {
|
||||
return mCustomBucketNames;
|
||||
}
|
||||
|
||||
/** Dump debug data. */
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.print(" ");
|
||||
for (int index = 0; index < mAccumulatedChargeMicroCoulomb.length; index++) {
|
||||
pw.print(getBucketName(index));
|
||||
pw.print(mConfig.getBucketName(index));
|
||||
pw.print(" : ");
|
||||
pw.print(mAccumulatedChargeMicroCoulomb[index]);
|
||||
if (!isIndexSupported(index)) {
|
||||
pw.print(" (unsupported)");
|
||||
}
|
||||
if (mAccumulatedMultiStateChargeMicroCoulomb != null) {
|
||||
final LongMultiStateCounter counter =
|
||||
mAccumulatedMultiStateChargeMicroCoulomb[index];
|
||||
if (counter != null) {
|
||||
pw.print(" [");
|
||||
for (int i = 0; i < mConfig.mStateNames.length; i++) {
|
||||
if (i != 0) {
|
||||
pw.print(" ");
|
||||
}
|
||||
pw.print(mConfig.mStateNames[i]);
|
||||
pw.print(": ");
|
||||
pw.print(counter.getCount(i));
|
||||
}
|
||||
pw.print("]");
|
||||
}
|
||||
}
|
||||
if (index != mAccumulatedChargeMicroCoulomb.length - 1) {
|
||||
pw.print(", ");
|
||||
}
|
||||
@@ -478,22 +650,6 @@ public class MeasuredEnergyStats {
|
||||
pw.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the index is a standard bucket, returns its name; otherwise returns its prefixed custom
|
||||
* bucket number.
|
||||
*/
|
||||
private String getBucketName(int index) {
|
||||
if (isValidStandardBucket(index)) {
|
||||
return DebugUtils.valueToString(MeasuredEnergyStats.class, "POWER_BUCKET_", index);
|
||||
}
|
||||
final int customBucket = indexToCustomBucket(index);
|
||||
StringBuilder name = new StringBuilder().append("CUSTOM_").append(customBucket);
|
||||
if (mCustomBucketNames != null && !TextUtils.isEmpty(mCustomBucketNames[customBucket])) {
|
||||
name.append('(').append(mCustomBucketNames[customBucket]).append(')');
|
||||
}
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
/** Get the number of custom power buckets on this device. */
|
||||
public int getNumberCustomPowerBuckets() {
|
||||
return mAccumulatedChargeMicroCoulomb.length - NUMBER_STANDARD_POWER_BUCKETS;
|
||||
|
||||
@@ -65,8 +65,9 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
|
||||
final boolean[] supportedStandardBuckets =
|
||||
new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
|
||||
Arrays.fill(supportedStandardBuckets, true);
|
||||
mGlobalMeasuredEnergyStats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
mMeasuredEnergyStatsConfig = new MeasuredEnergyStats.Config(supportedStandardBuckets,
|
||||
customBucketNames, new int[0], new String[]{""});
|
||||
mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(mMeasuredEnergyStatsConfig);
|
||||
}
|
||||
|
||||
public TimeBase getOnBatteryTimeBase() {
|
||||
|
||||
@@ -19,9 +19,12 @@ package com.android.internal.power;
|
||||
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
|
||||
|
||||
import static com.android.internal.power.MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_CPU;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_SCREEN_OTHER;
|
||||
import static com.android.internal.power.MeasuredEnergyStats.POWER_BUCKET_WIFI;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -56,55 +59,32 @@ public class MeasuredEnergyStatsTest {
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_WIFI},
|
||||
new String[]{"state0", "state1", "state3"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
|
||||
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
|
||||
if (supportedStandardBuckets[i]) {
|
||||
assertTrue(stats.isStandardBucketSupported(i));
|
||||
assertEquals(0L, stats.getAccumulatedStandardBucketCharge(i));
|
||||
for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) {
|
||||
if (supportedStandardBuckets[bucket]) {
|
||||
assertTrue(stats.isStandardBucketSupported(bucket));
|
||||
assertEquals(0L, stats.getAccumulatedStandardBucketCharge(bucket));
|
||||
} else {
|
||||
assertFalse(stats.isStandardBucketSupported(i));
|
||||
assertEquals(POWER_DATA_UNAVAILABLE, stats.getAccumulatedStandardBucketCharge(i));
|
||||
assertFalse(stats.isStandardBucketSupported(bucket));
|
||||
assertEquals(POWER_DATA_UNAVAILABLE,
|
||||
stats.getAccumulatedStandardBucketCharge(bucket));
|
||||
}
|
||||
if (bucket == POWER_BUCKET_SCREEN_ON) {
|
||||
assertThat(config.isSupportedMultiStateBucket(bucket)).isTrue();
|
||||
} else {
|
||||
assertThat(config.isSupportedMultiStateBucket(bucket)).isFalse();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < customBucketNames.length; i++) {
|
||||
assertEquals(0L, stats.getAccumulatedCustomBucketCharge(i));
|
||||
}
|
||||
assertThat(stats.getCustomBucketNames()).asList().containsExactly("A", "B");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromTemplate() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
final String[] customBucketNames = {"A", "B"};
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
stats.updateCustomBucket(0, 50);
|
||||
stats.updateCustomBucket(1, 60);
|
||||
|
||||
final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats);
|
||||
|
||||
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
|
||||
if (supportedStandardBuckets[i]) {
|
||||
assertTrue(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i));
|
||||
} else {
|
||||
assertFalse(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(POWER_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedStandardBucketCharge(i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < customBucketNames.length; i++) {
|
||||
assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(i));
|
||||
}
|
||||
assertThat(config.getCustomBucketNames()).asList().containsExactly("A", "B");
|
||||
assertThat(config.getStateNames()).asList().containsExactly("state0", "state1", "state3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -115,23 +95,32 @@ public class MeasuredEnergyStatsTest {
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
stats.updateCustomBucket(0, 50);
|
||||
stats.updateCustomBucket(1, 60);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[]{POWER_BUCKET_SCREEN_ON}, new String[]{"s0", "s1"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
|
||||
stats.setState(0, 1000);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10, 2000);
|
||||
stats.setState(1, 3000);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5, 4000);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40, 5000);
|
||||
stats.updateCustomBucket(0, 50, 6000);
|
||||
stats.updateCustomBucket(1, 60, 7000);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
stats.writeToParcel(parcel);
|
||||
|
||||
parcel.setDataPosition(0);
|
||||
MeasuredEnergyStats newStats = new MeasuredEnergyStats(parcel);
|
||||
MeasuredEnergyStats newStats = new MeasuredEnergyStats(config, parcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
|
||||
assertEquals(stats.getAccumulatedStandardBucketCharge(i),
|
||||
newStats.getAccumulatedStandardBucketCharge(i));
|
||||
for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) {
|
||||
assertEquals(stats.getAccumulatedStandardBucketCharge(bucket),
|
||||
newStats.getAccumulatedStandardBucketCharge(bucket));
|
||||
for (int state = 0; state < 2; state++) {
|
||||
assertEquals(stats.getAccumulatedStandardBucketCharge(bucket, state),
|
||||
newStats.getAccumulatedStandardBucketCharge(bucket, state));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < customBucketNames.length; i++) {
|
||||
assertEquals(stats.getAccumulatedCustomBucketCharge(i),
|
||||
@@ -142,6 +131,57 @@ public class MeasuredEnergyStatsTest {
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadConfigFromParcel() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
final String[] customBucketNames = {"A", "B"};
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_WIFI},
|
||||
new String[] {"state0", "state1", "state2"});
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.Config.writeToParcel(config, parcel);
|
||||
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
final MeasuredEnergyStats.Config newConfig = MeasuredEnergyStats.Config.createFromParcel(
|
||||
parcel);
|
||||
|
||||
assertThat(newConfig).isNotNull();
|
||||
for (int bucket = 0; bucket < NUMBER_STANDARD_POWER_BUCKETS; bucket++) {
|
||||
if (bucket == POWER_BUCKET_SCREEN_ON || bucket == POWER_BUCKET_SCREEN_OTHER) {
|
||||
assertThat(newConfig.isSupportedBucket(bucket)).isTrue();
|
||||
} else {
|
||||
assertThat(newConfig.isSupportedBucket(bucket)).isFalse();
|
||||
}
|
||||
if (bucket == POWER_BUCKET_SCREEN_ON) {
|
||||
assertThat(newConfig.isSupportedMultiStateBucket(bucket)).isTrue();
|
||||
} else {
|
||||
assertThat(newConfig.isSupportedMultiStateBucket(bucket)).isFalse();
|
||||
}
|
||||
}
|
||||
assertThat(newConfig.getCustomBucketNames()).isEqualTo(new String[]{"A", "B"});
|
||||
assertThat(newConfig.getStateNames()).isEqualTo(new String[]{"state0", "state1", "state2"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadConfigFromParcel_nullConfig() {
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.Config.writeToParcel(null, parcel);
|
||||
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
final MeasuredEnergyStats.Config newConfig = MeasuredEnergyStats.Config.createFromParcel(
|
||||
parcel);
|
||||
|
||||
assertThat(newConfig).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
@@ -150,8 +190,11 @@ public class MeasuredEnergyStatsTest {
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
@@ -159,9 +202,12 @@ public class MeasuredEnergyStatsTest {
|
||||
stats.updateCustomBucket(1, 60);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, false);
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
|
||||
|
||||
parcel.setDataPosition(0);
|
||||
MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel);
|
||||
|
||||
MeasuredEnergyStats newStats =
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(config, parcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
|
||||
assertEquals(stats.isStandardBucketSupported(i),
|
||||
@@ -175,48 +221,44 @@ public class MeasuredEnergyStatsTest {
|
||||
}
|
||||
assertEquals(POWER_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedCustomBucketCharge(customBucketNames.length + 1));
|
||||
assertThat(newStats.getCustomBucketNames()).asList().containsExactly("A", "B");
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel_existingTemplate() {
|
||||
public void testCreateAndReadSummaryFromParcel_configChange() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
final String[] customBucketNames = {"A", "B"};
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats template =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
template.updateCustomBucket(0, 50);
|
||||
|
||||
final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 7);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 63);
|
||||
stats.updateCustomBucket(0, 315);
|
||||
stats.updateCustomBucket(1, 316);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
stats.updateCustomBucket(0, 50);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true);
|
||||
|
||||
final boolean[] newsupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
newsupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
|
||||
newsupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true
|
||||
newsupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false
|
||||
final MeasuredEnergyStats newTemplate =
|
||||
new MeasuredEnergyStats(newsupportedStandardBuckets, customBucketNames);
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
|
||||
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true
|
||||
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false
|
||||
|
||||
final MeasuredEnergyStats.Config newConfig =
|
||||
new MeasuredEnergyStats.Config(newSupportedStandardBuckets, customBucketNames,
|
||||
new int[0], new String[]{"s"});
|
||||
|
||||
final MeasuredEnergyStats newStats =
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(newConfig, parcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
|
||||
if (!newsupportedStandardBuckets[i]) {
|
||||
if (!newSupportedStandardBuckets[i]) {
|
||||
assertFalse(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(POWER_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedStandardBucketCharge(i));
|
||||
@@ -235,81 +277,22 @@ public class MeasuredEnergyStatsTest {
|
||||
}
|
||||
assertEquals(POWER_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedCustomBucketCharge(customBucketNames.length + 1));
|
||||
assertThat(newStats.getCustomBucketNames()).asList().containsExactly("A", "B");
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel_skipZero() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
final String[] customBucketNames = {"A", "B"};
|
||||
Arrays.fill(supportedStandardBuckets, true);
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
// Accumulate charge in one bucket and one custom bucket, the rest should be zero
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 200);
|
||||
stats.updateCustomBucket(1, 60);
|
||||
|
||||
// Let's try parcelling with including zeros
|
||||
final Parcel includeZerosParcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, includeZerosParcel, false, false);
|
||||
includeZerosParcel.setDataPosition(0);
|
||||
|
||||
MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
|
||||
includeZerosParcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
|
||||
if (i == POWER_BUCKET_SCREEN_ON) {
|
||||
assertEquals(stats.isStandardBucketSupported(i),
|
||||
newStats.isStandardBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedStandardBucketCharge(i),
|
||||
newStats.getAccumulatedStandardBucketCharge(i));
|
||||
} else {
|
||||
assertTrue(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(0L, newStats.getAccumulatedStandardBucketCharge(i));
|
||||
}
|
||||
}
|
||||
assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0));
|
||||
assertEquals(stats.getAccumulatedCustomBucketCharge(1),
|
||||
newStats.getAccumulatedCustomBucketCharge(1));
|
||||
includeZerosParcel.recycle();
|
||||
|
||||
// Now let's try parcelling with skipping zeros
|
||||
final Parcel skipZerosParcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, skipZerosParcel, true, false);
|
||||
skipZerosParcel.setDataPosition(0);
|
||||
|
||||
newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(skipZerosParcel);
|
||||
|
||||
for (int i = 0; i < NUMBER_STANDARD_POWER_BUCKETS; i++) {
|
||||
if (i == POWER_BUCKET_SCREEN_ON) {
|
||||
assertEquals(stats.isStandardBucketSupported(i),
|
||||
newStats.isStandardBucketSupported(i));
|
||||
assertEquals(stats.getAccumulatedStandardBucketCharge(i),
|
||||
newStats.getAccumulatedStandardBucketCharge(i));
|
||||
} else {
|
||||
assertFalse(newStats.isStandardBucketSupported(i));
|
||||
assertEquals(POWER_DATA_UNAVAILABLE,
|
||||
newStats.getAccumulatedStandardBucketCharge(i));
|
||||
}
|
||||
}
|
||||
assertEquals(0L, newStats.getAccumulatedCustomBucketCharge(0));
|
||||
assertEquals(stats.getAccumulatedCustomBucketCharge(1),
|
||||
newStats.getAccumulatedCustomBucketCharge(1));
|
||||
skipZerosParcel.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndReadSummaryFromParcel_nullTemplate() {
|
||||
public void testCreateAndReadSummaryFromParcel_nullConfig() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
final String[] customBucketNames = {"A", "B"};
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
@@ -317,11 +300,11 @@ public class MeasuredEnergyStatsTest {
|
||||
stats.updateCustomBucket(1, 60);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true);
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
MeasuredEnergyStats newStats =
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, null);
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(null, parcel);
|
||||
assertNull(newStats);
|
||||
parcel.recycle();
|
||||
}
|
||||
@@ -334,30 +317,30 @@ public class MeasuredEnergyStatsTest {
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats template =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
template.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
template.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
template.updateCustomBucket(0, 50);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
|
||||
final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 0L);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 7L);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 0);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false, true);
|
||||
MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
|
||||
|
||||
final boolean[] newSupportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_ON] = true;
|
||||
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = true; // switched false > true
|
||||
newSupportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = false; // switched true > false
|
||||
final MeasuredEnergyStats newTemplate =
|
||||
new MeasuredEnergyStats(newSupportedStandardBuckets, customBucketNames);
|
||||
final MeasuredEnergyStats.Config newConfig =
|
||||
new MeasuredEnergyStats.Config(newSupportedStandardBuckets, customBucketNames,
|
||||
new int[0], new String[]{"s"});
|
||||
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
final MeasuredEnergyStats newStats =
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
|
||||
MeasuredEnergyStats.createAndReadSummaryFromParcel(newConfig, parcel);
|
||||
|
||||
// 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());
|
||||
@@ -372,30 +355,47 @@ public class MeasuredEnergyStatsTest {
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_DOZE, 30);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[]{POWER_BUCKET_SCREEN_ON, POWER_BUCKET_SCREEN_OTHER},
|
||||
new String[]{"s0", "s1"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
|
||||
stats.updateCustomBucket(0, 50);
|
||||
stats.updateCustomBucket(1, 60);
|
||||
stats.updateCustomBucket(0, 3);
|
||||
stats.setState(0, 1000);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10, 2000);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_DOZE, 30, 3000);
|
||||
stats.setState(1, 4000);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40, 5000);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 6, 6000);
|
||||
|
||||
assertEquals(15, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON));
|
||||
stats.updateCustomBucket(0, 50, 7000);
|
||||
stats.updateCustomBucket(1, 60, 8000);
|
||||
stats.updateCustomBucket(0, 3, 9000);
|
||||
|
||||
assertEquals(16, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON));
|
||||
assertEquals(POWER_DATA_UNAVAILABLE,
|
||||
stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_DOZE));
|
||||
assertEquals(40, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER));
|
||||
assertEquals(50 + 3, stats.getAccumulatedCustomBucketCharge(0));
|
||||
assertEquals(60, stats.getAccumulatedCustomBucketCharge(1));
|
||||
|
||||
// 10 + 6 * (4000-2000)/(6000-2000)
|
||||
assertEquals(13, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON, 0));
|
||||
// 6 * (6000-4000)/(6000-2000)
|
||||
assertEquals(3, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_ON, 1));
|
||||
|
||||
// POWER_BUCKET_SCREEN_OTHER was only present along with state=1
|
||||
assertEquals(0, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER, 0));
|
||||
assertEquals(40, stats.getAccumulatedStandardBucketCharge(POWER_BUCKET_SCREEN_OTHER, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsValidCustomBucket() {
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[]{"A", "B", "C"});
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[]{"A", "B", "C"},
|
||||
new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
assertFalse(stats.isValidCustomBucket(-1));
|
||||
assertTrue(stats.isValidCustomBucket(0));
|
||||
assertTrue(stats.isValidCustomBucket(1));
|
||||
@@ -403,8 +403,10 @@ public class MeasuredEnergyStatsTest {
|
||||
assertFalse(stats.isValidCustomBucket(3));
|
||||
assertFalse(stats.isValidCustomBucket(4));
|
||||
|
||||
final MeasuredEnergyStats boringStats =
|
||||
new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0]);
|
||||
final MeasuredEnergyStats.Config boringConfig =
|
||||
new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[0], new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats boringStats = new MeasuredEnergyStats(boringConfig);
|
||||
assertFalse(boringStats.isValidCustomBucket(-1));
|
||||
assertFalse(boringStats.isValidCustomBucket(0));
|
||||
assertFalse(boringStats.isValidCustomBucket(1));
|
||||
@@ -412,9 +414,11 @@ public class MeasuredEnergyStatsTest {
|
||||
|
||||
@Test
|
||||
public void testGetAccumulatedCustomBucketCharges() {
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[]{"A", "B", "C"});
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[]{"A", "B", "C"},
|
||||
new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
stats.updateCustomBucket(0, 50);
|
||||
stats.updateCustomBucket(1, 60);
|
||||
stats.updateCustomBucket(2, 13);
|
||||
@@ -430,8 +434,10 @@ public class MeasuredEnergyStatsTest {
|
||||
|
||||
@Test
|
||||
public void testGetAccumulatedCustomBucketCharges_empty() {
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0]);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[0], new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
|
||||
final long[] output = stats.getAccumulatedCustomBucketCharges();
|
||||
assertEquals(0, output.length);
|
||||
@@ -440,10 +446,15 @@ public class MeasuredEnergyStatsTest {
|
||||
@Test
|
||||
public void testGetNumberCustomChargeBuckets() {
|
||||
assertEquals(0,
|
||||
new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS], new String[0])
|
||||
new MeasuredEnergyStats(
|
||||
new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[0], new int[0], new String[]{"s"}))
|
||||
.getNumberCustomPowerBuckets());
|
||||
assertEquals(3,
|
||||
new MeasuredEnergyStats(
|
||||
new MeasuredEnergyStats.Config(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[]{"A", "B", "C"}, new int[0], new String[]{"s"}))
|
||||
.getNumberCustomPowerBuckets());
|
||||
assertEquals(3, new MeasuredEnergyStats(new boolean[NUMBER_STANDARD_POWER_BUCKETS],
|
||||
new String[]{"A", "B", "C"}).getNumberCustomPowerBuckets());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -454,8 +465,10 @@ public class MeasuredEnergyStatsTest {
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_DOZE] = false;
|
||||
supportedStandardBuckets[POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, customBucketNames);
|
||||
final MeasuredEnergyStats.Config config =
|
||||
new MeasuredEnergyStats.Config(supportedStandardBuckets, customBucketNames,
|
||||
new int[0], new String[]{"s"});
|
||||
final MeasuredEnergyStats stats = new MeasuredEnergyStats(config);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 10);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_ON, 5);
|
||||
stats.updateStandardBucket(POWER_BUCKET_SCREEN_OTHER, 40);
|
||||
@@ -500,83 +513,62 @@ public class MeasuredEnergyStatsTest {
|
||||
assertEquals(exp, MeasuredEnergyStats.getDisplayPowerBucket(Display.STATE_DOZE_SUSPEND));
|
||||
}
|
||||
|
||||
/** Test MeasuredEnergyStats#isSupportEqualTo */
|
||||
@Test
|
||||
public void testIsSupportEqualTo() {
|
||||
public void testConfig_isCompatible() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
Arrays.fill(supportedStandardBuckets, true);
|
||||
final String[] customBucketNames = {"A", "B"};
|
||||
final int[] supportedMultiStateBuckets = {POWER_BUCKET_CPU, POWER_BUCKET_WIFI};
|
||||
final String[] stateNames = {"s"};
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets.clone(),
|
||||
customBucketNames.clone());
|
||||
|
||||
final MeasuredEnergyStats.Config config = new MeasuredEnergyStats.Config(
|
||||
supportedStandardBuckets,
|
||||
customBucketNames,
|
||||
supportedMultiStateBuckets,
|
||||
stateNames);
|
||||
assertTrue(
|
||||
"All standard and custom bucket supports match",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, customBucketNames));
|
||||
config.isCompatible(
|
||||
new MeasuredEnergyStats.Config(
|
||||
supportedStandardBuckets,
|
||||
customBucketNames,
|
||||
supportedMultiStateBuckets,
|
||||
stateNames)));
|
||||
|
||||
boolean[] differentSupportedStandardBuckets = supportedStandardBuckets.clone();
|
||||
differentSupportedStandardBuckets[0] = !differentSupportedStandardBuckets[0];
|
||||
|
||||
assertFalse(
|
||||
"Standard bucket support mismatch",
|
||||
stats.isSupportEqualTo(differentSupportedStandardBuckets, customBucketNames));
|
||||
|
||||
config.isCompatible(
|
||||
new MeasuredEnergyStats.Config(
|
||||
differentSupportedStandardBuckets,
|
||||
customBucketNames,
|
||||
supportedMultiStateBuckets,
|
||||
stateNames)));
|
||||
assertFalse(
|
||||
"Custom bucket support mismatch",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"C", "B"}));
|
||||
|
||||
config.isCompatible(
|
||||
new MeasuredEnergyStats.Config(
|
||||
supportedStandardBuckets,
|
||||
new String[]{"C", "B"},
|
||||
supportedMultiStateBuckets,
|
||||
stateNames)));
|
||||
assertFalse(
|
||||
"Fewer custom buckets supported",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A"}));
|
||||
|
||||
"Multi-state bucket mismatch",
|
||||
config.isCompatible(
|
||||
new MeasuredEnergyStats.Config(
|
||||
supportedStandardBuckets,
|
||||
new String[]{"A"},
|
||||
new int[] {POWER_BUCKET_CPU, POWER_BUCKET_BLUETOOTH},
|
||||
stateNames)));
|
||||
assertFalse(
|
||||
"More custom bucket supported",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B", "C"}));
|
||||
|
||||
assertFalse(
|
||||
"Custom bucket support order changed",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"B", "A"}));
|
||||
}
|
||||
|
||||
/** Test MeasuredEnergyStats#isSupportEqualTo when holding a null array of custom buckets */
|
||||
@Test
|
||||
public void testIsSupportEqualTo_nullCustomBuckets() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets.clone(), null);
|
||||
|
||||
assertTrue(
|
||||
"Null custom bucket name lists should match",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, null));
|
||||
|
||||
assertTrue(
|
||||
"Null and empty custom buckets should match",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[0]));
|
||||
|
||||
assertFalse(
|
||||
"Null custom buckets should not match populated list",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"}));
|
||||
}
|
||||
|
||||
/** Test MeasuredEnergyStats#isSupportEqualTo when holding an empty array of custom buckets */
|
||||
@Test
|
||||
public void testIsSupportEqualTo_emptyCustomBuckets() {
|
||||
final boolean[] supportedStandardBuckets = new boolean[NUMBER_STANDARD_POWER_BUCKETS];
|
||||
|
||||
final MeasuredEnergyStats stats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets.clone(), new String[0]);
|
||||
|
||||
assertTrue(
|
||||
"Empty custom buckets should match",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[0]));
|
||||
|
||||
assertTrue(
|
||||
"Empty and null custom buckets should match",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, null));
|
||||
|
||||
assertFalse(
|
||||
"Empty custom buckets should not match populated list",
|
||||
stats.isSupportEqualTo(supportedStandardBuckets, new String[]{"A", "B"}));
|
||||
"Multi-state bucket state list mismatch",
|
||||
config.isCompatible(
|
||||
new MeasuredEnergyStats.Config(
|
||||
supportedStandardBuckets,
|
||||
new String[]{"A"},
|
||||
supportedMultiStateBuckets,
|
||||
new String[]{"s1", "s2"})));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user