Add battery history to BatteryStatsUsage
Bug: 173745486 Test: atest FrameworksCoreTests:com.android.internal.os.BatteryUsageStatsProviderTest Change-Id: Icfd9e49b68f1be99312c88ac889b06aa669367ef
This commit is contained in:
@@ -20,6 +20,9 @@ import android.annotation.NonNull;
|
||||
import android.util.Range;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.os.BatteryStatsHistory;
|
||||
import com.android.internal.os.BatteryStatsHistoryIterator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,12 +40,16 @@ public final class BatteryUsageStats implements Parcelable {
|
||||
private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers;
|
||||
private final ArrayList<SystemBatteryConsumer> mSystemBatteryConsumers;
|
||||
private final ArrayList<UserBatteryConsumer> mUserBatteryConsumers;
|
||||
private final Parcel mHistoryBuffer;
|
||||
private final List<BatteryStats.HistoryTag> mHistoryTagPool;
|
||||
|
||||
private BatteryUsageStats(@NonNull Builder builder) {
|
||||
mStatsStartRealtimeMs = builder.mStatsStartRealtimeMs;
|
||||
mDischargePercentage = builder.mDischargePercentage;
|
||||
mDischargedPowerLowerBound = builder.mDischargedPowerLowerBoundMah;
|
||||
mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
|
||||
mHistoryBuffer = builder.mHistoryBuffer;
|
||||
mHistoryTagPool = builder.mHistoryTagPool;
|
||||
|
||||
double totalPower = 0;
|
||||
|
||||
@@ -125,6 +132,19 @@ public final class BatteryUsageStats implements Parcelable {
|
||||
return mUserBatteryConsumers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for {@link android.os.BatteryStats.HistoryItem}'s.
|
||||
*/
|
||||
@NonNull
|
||||
public BatteryStatsHistoryIterator iterateBatteryStatsHistory() {
|
||||
if (mHistoryBuffer == null) {
|
||||
throw new IllegalStateException(
|
||||
"Battery history was not requested in the BatteryUsageStatsQuery");
|
||||
}
|
||||
return new BatteryStatsHistoryIterator(new BatteryStatsHistory(mHistoryBuffer),
|
||||
mHistoryTagPool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
@@ -142,6 +162,29 @@ public final class BatteryUsageStats implements Parcelable {
|
||||
source.readParcelableList(mSystemBatteryConsumers, getClass().getClassLoader());
|
||||
mUserBatteryConsumers = new ArrayList<>();
|
||||
source.readParcelableList(mUserBatteryConsumers, getClass().getClassLoader());
|
||||
if (source.readBoolean()) {
|
||||
mHistoryBuffer = Parcel.obtain();
|
||||
mHistoryBuffer.setDataSize(0);
|
||||
mHistoryBuffer.setDataPosition(0);
|
||||
|
||||
int historyBufferSize = source.readInt();
|
||||
int curPos = source.dataPosition();
|
||||
mHistoryBuffer.appendFrom(source, curPos, historyBufferSize);
|
||||
source.setDataPosition(curPos + historyBufferSize);
|
||||
|
||||
int historyTagCount = source.readInt();
|
||||
mHistoryTagPool = new ArrayList<>(historyTagCount);
|
||||
for (int i = 0; i < historyTagCount; i++) {
|
||||
BatteryStats.HistoryTag tag = new BatteryStats.HistoryTag();
|
||||
tag.string = source.readString();
|
||||
tag.uid = source.readInt();
|
||||
tag.poolIdx = source.readInt();
|
||||
mHistoryTagPool.add(tag);
|
||||
}
|
||||
} else {
|
||||
mHistoryBuffer = null;
|
||||
mHistoryTagPool = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,6 +197,23 @@ public final class BatteryUsageStats implements Parcelable {
|
||||
dest.writeParcelableList(mUidBatteryConsumers, flags);
|
||||
dest.writeParcelableList(mSystemBatteryConsumers, flags);
|
||||
dest.writeParcelableList(mUserBatteryConsumers, flags);
|
||||
if (mHistoryBuffer != null) {
|
||||
dest.writeBoolean(true);
|
||||
|
||||
final int historyBufferSize = mHistoryBuffer.dataSize();
|
||||
dest.writeInt(historyBufferSize);
|
||||
dest.appendFrom(mHistoryBuffer, 0, historyBufferSize);
|
||||
|
||||
dest.writeInt(mHistoryTagPool.size());
|
||||
for (int i = mHistoryTagPool.size() - 1; i >= 0; i--) {
|
||||
final BatteryStats.HistoryTag tag = mHistoryTagPool.get(i);
|
||||
dest.writeString(tag.string);
|
||||
dest.writeInt(tag.uid);
|
||||
dest.writeInt(tag.poolIdx);
|
||||
}
|
||||
} else {
|
||||
dest.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -183,6 +243,8 @@ public final class BatteryUsageStats implements Parcelable {
|
||||
new SparseArray<>();
|
||||
private final SparseArray<UserBatteryConsumer.Builder> mUserBatteryConsumerBuilders =
|
||||
new SparseArray<>();
|
||||
private Parcel mHistoryBuffer;
|
||||
private List<BatteryStats.HistoryTag> mHistoryTagPool;
|
||||
|
||||
public Builder(int customPowerComponentCount, int customTimeComponentCount) {
|
||||
mCustomPowerComponentCount = customPowerComponentCount;
|
||||
@@ -226,6 +288,17 @@ public final class BatteryUsageStats implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parceled recent history.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setBatteryHistory(Parcel historyBuffer,
|
||||
List<BatteryStats.HistoryTag> historyTagPool) {
|
||||
mHistoryBuffer = historyBuffer;
|
||||
mHistoryTagPool = historyTagPool;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or returns a exiting UidBatteryConsumer, which represents battery attribution
|
||||
* data for an individual UID.
|
||||
|
||||
@@ -40,6 +40,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
|
||||
*/
|
||||
@IntDef(flag = true, prefix = { "FLAG_BATTERY_USAGE_STATS_" }, value = {
|
||||
FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL,
|
||||
FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface BatteryUsageStatsFlags {}
|
||||
@@ -53,6 +54,12 @@ public final class BatteryUsageStatsQuery implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL = 1;
|
||||
|
||||
/**
|
||||
* Indicates that battery history should be included in the BatteryUsageStats.
|
||||
* @hide
|
||||
*/
|
||||
public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY = 2;
|
||||
|
||||
private final int mFlags;
|
||||
@NonNull
|
||||
private final int[] mUserIds;
|
||||
@@ -146,10 +153,10 @@ public final class BatteryUsageStatsQuery implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets flags to modify the behavior of {@link BatteryStatsManager#getBatteryUsageStats}.
|
||||
* Requests that battery history be included in the BatteryUsageStats.
|
||||
*/
|
||||
public Builder setFlags(@BatteryUsageStatsFlags int flags) {
|
||||
mFlags = flags;
|
||||
public Builder includeBatteryHistory() {
|
||||
mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public class BatteryStatsHistoryIterator {
|
||||
private final String[] mReadHistoryStrings;
|
||||
private final int[] mReadHistoryUids;
|
||||
|
||||
BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history,
|
||||
public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history,
|
||||
@NonNull List<BatteryStats.HistoryTag> historyTagPool) {
|
||||
mBatteryStatsHistory = history;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Uses accumulated battery stats data and PowerCalculators to produce power
|
||||
@@ -152,6 +153,20 @@ public class BatteryUsageStatsProvider {
|
||||
query);
|
||||
}
|
||||
|
||||
if ((query.getFlags()
|
||||
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY) != 0) {
|
||||
ArrayList<BatteryStats.HistoryTag> tags = new ArrayList<>(
|
||||
mStats.mHistoryTagPool.size());
|
||||
for (Map.Entry<BatteryStats.HistoryTag, Integer> entry :
|
||||
mStats.mHistoryTagPool.entrySet()) {
|
||||
final BatteryStats.HistoryTag tag = entry.getKey();
|
||||
tag.poolIdx = entry.getValue();
|
||||
tags.add(tag);
|
||||
}
|
||||
|
||||
batteryUsageStatsBuilder.setBatteryHistory(mStats.mHistoryBuffer, tags);
|
||||
}
|
||||
|
||||
return batteryUsageStatsBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,11 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.BatteryUsageStatsQuery;
|
||||
import android.os.Parcel;
|
||||
import android.os.Process;
|
||||
import android.os.UidBatteryConsumer;
|
||||
|
||||
@@ -73,4 +76,86 @@ public class BatteryUsageStatsProviderTest {
|
||||
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
|
||||
.isEqualTo(10 * MINUTE_IN_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteAndReadHistory() {
|
||||
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
|
||||
batteryStats.setRecordAllHistoryLocked(true);
|
||||
batteryStats.forceRecordAllHistory();
|
||||
|
||||
batteryStats.setNoAutoReset(true);
|
||||
|
||||
batteryStats.setBatteryStateLocked(BatteryManager.BATTERY_STATUS_DISCHARGING, 100,
|
||||
/* plugType */ 0, 90, 72, 3700, 3_600_000, 4_000_000, 0, 1_000_000,
|
||||
1_000_000, 1_000_000);
|
||||
|
||||
batteryStats.noteAlarmStartLocked("foo", null, APP_UID, 3_000_000, 2_000_000);
|
||||
batteryStats.noteAlarmFinishLocked("foo", null, APP_UID, 3_001_000, 2_001_000);
|
||||
|
||||
Context context = InstrumentationRegistry.getContext();
|
||||
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, batteryStats);
|
||||
|
||||
final BatteryUsageStats batteryUsageStats =
|
||||
provider.getBatteryUsageStats(
|
||||
new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build());
|
||||
|
||||
Parcel in = Parcel.obtain();
|
||||
batteryUsageStats.writeToParcel(in, 0);
|
||||
final byte[] bytes = in.marshall();
|
||||
|
||||
Parcel out = Parcel.obtain();
|
||||
out.unmarshall(bytes, 0, bytes.length);
|
||||
out.setDataPosition(0);
|
||||
|
||||
BatteryUsageStats unparceled = BatteryUsageStats.CREATOR.createFromParcel(out);
|
||||
|
||||
final BatteryStatsHistoryIterator iterator =
|
||||
unparceled.iterateBatteryStatsHistory();
|
||||
BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
|
||||
|
||||
assertThat(iterator.next(item)).isTrue();
|
||||
assertHistoryItem(item,
|
||||
BatteryStats.HistoryItem.CMD_RESET, BatteryStats.HistoryItem.EVENT_NONE,
|
||||
null, 0, 3_600_000, 90, 1_000_000);
|
||||
|
||||
assertThat(iterator.next(item)).isTrue();
|
||||
assertHistoryItem(item,
|
||||
BatteryStats.HistoryItem.CMD_UPDATE, BatteryStats.HistoryItem.EVENT_NONE,
|
||||
null, 0, 3_600_000, 90, 1_000_000);
|
||||
|
||||
assertThat(iterator.next(item)).isTrue();
|
||||
assertHistoryItem(item,
|
||||
BatteryStats.HistoryItem.CMD_UPDATE, BatteryStats.HistoryItem.EVENT_NONE,
|
||||
null, 0, 3_600_000, 90, 2_000_000);
|
||||
|
||||
assertThat(iterator.next(item)).isTrue();
|
||||
assertHistoryItem(item,
|
||||
BatteryStats.HistoryItem.CMD_UPDATE,
|
||||
BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_START,
|
||||
"foo", APP_UID, 3_600_000, 90, 3_000_000);
|
||||
|
||||
assertThat(iterator.next(item)).isTrue();
|
||||
assertHistoryItem(item,
|
||||
BatteryStats.HistoryItem.CMD_UPDATE,
|
||||
BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_FINISH,
|
||||
"foo", APP_UID, 3_600_000, 90, 3_001_000);
|
||||
|
||||
assertThat(iterator.next(item)).isFalse();
|
||||
}
|
||||
|
||||
private void assertHistoryItem(BatteryStats.HistoryItem item, int command, int eventCode,
|
||||
String tag, int uid, int batteryChargeUah, int batteryLevel, long elapsedTimeMs) {
|
||||
assertThat(item.cmd).isEqualTo(command);
|
||||
assertThat(item.eventCode).isEqualTo(eventCode);
|
||||
if (tag == null) {
|
||||
assertThat(item.eventTag).isNull();
|
||||
} else {
|
||||
assertThat(item.eventTag.string).isEqualTo(tag);
|
||||
assertThat(item.eventTag.uid).isEqualTo(uid);
|
||||
}
|
||||
assertThat(item.batteryChargeUah).isEqualTo(batteryChargeUah);
|
||||
assertThat(item.batteryLevel).isEqualTo(batteryLevel);
|
||||
|
||||
assertThat(item.time).isEqualTo(elapsedTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user