summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorDmitri Plotnikov <dplotnikov@google.com>2021-09-09 17:52:19 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-09-09 17:52:19 +0000
commitbfc3bb8d0c17253a6ce93f8e4e83dac8070eb349 (patch)
tree343344ddbc96e6c7f56ce2b3cd4eb9d72b70e2f3 /core/java
parentedea4d6795469840ba6c9064275edc0de6d2c27d (diff)
parentcadeaf8b249acd38ca2e1f2e32c9d26c55626081 (diff)
Merge "Use CursorWindow to hold BatteryConsumer data"
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/os/AggregateBatteryConsumer.java60
-rw-r--r--core/java/android/os/BatteryConsumer.java174
-rw-r--r--core/java/android/os/BatteryUsageStats.java184
-rw-r--r--core/java/android/os/PowerComponents.java366
-rw-r--r--core/java/android/os/UidBatteryConsumer.java117
-rw-r--r--core/java/android/os/UserBatteryConsumer.java57
6 files changed, 518 insertions, 440 deletions
diff --git a/core/java/android/os/AggregateBatteryConsumer.java b/core/java/android/os/AggregateBatteryConsumer.java
index 802387c675b5..e088f306cd98 100644
--- a/core/java/android/os/AggregateBatteryConsumer.java
+++ b/core/java/android/os/AggregateBatteryConsumer.java
@@ -31,51 +31,33 @@ import java.io.PrintWriter;
*
* {@hide}
*/
-public final class AggregateBatteryConsumer extends BatteryConsumer implements Parcelable {
+public final class AggregateBatteryConsumer extends BatteryConsumer {
+ static final int CONSUMER_TYPE_AGGREGATE = 0;
- private final double mConsumedPowerMah;
+ static final int COLUMN_INDEX_SCOPE = BatteryConsumer.COLUMN_COUNT;
+ static final int COLUMN_INDEX_CONSUMED_POWER = COLUMN_INDEX_SCOPE + 1;
+ static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 2;
- public AggregateBatteryConsumer(@NonNull Builder builder) {
- super(builder.mPowerComponentsBuilder.build());
- mConsumedPowerMah = builder.mConsumedPowerMah;
+ AggregateBatteryConsumer(BatteryConsumerData data) {
+ super(data);
}
- private AggregateBatteryConsumer(@NonNull Parcel source) {
- super(new PowerComponents(source));
- mConsumedPowerMah = source.readDouble();
+ private AggregateBatteryConsumer(@NonNull Builder builder) {
+ super(builder.mData, builder.mPowerComponentsBuilder.build());
}
- @Override
- public void dump(PrintWriter pw, boolean skipEmptyComponents) {
- mPowerComponents.dump(pw, skipEmptyComponents);
+ int getScope() {
+ return mData.getInt(COLUMN_INDEX_SCOPE);
}
@Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeDouble(mConsumedPowerMah);
- }
-
- @Override
- public int describeContents() {
- return 0;
+ public void dump(PrintWriter pw, boolean skipEmptyComponents) {
+ mPowerComponents.dump(pw, skipEmptyComponents);
}
- @NonNull
- public static final Creator<AggregateBatteryConsumer> CREATOR =
- new Creator<AggregateBatteryConsumer>() {
- public AggregateBatteryConsumer createFromParcel(@NonNull Parcel source) {
- return new AggregateBatteryConsumer(source);
- }
-
- public AggregateBatteryConsumer[] newArray(int size) {
- return new AggregateBatteryConsumer[size];
- }
- };
-
@Override
public double getConsumedPower() {
- return mConsumedPowerMah;
+ return mData.getDouble(COLUMN_INDEX_CONSUMED_POWER);
}
/** Serializes this object to XML */
@@ -83,7 +65,7 @@ public final class AggregateBatteryConsumer extends BatteryConsumer implements P
@BatteryUsageStats.AggregateBatteryConsumerScope int scope) throws IOException {
serializer.startTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_SCOPE, scope);
- serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, mConsumedPowerMah);
+ serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, getConsumedPower());
mPowerComponents.writeToXml(serializer);
serializer.endTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
}
@@ -119,17 +101,16 @@ public final class AggregateBatteryConsumer extends BatteryConsumer implements P
* Builder for DeviceBatteryConsumer.
*/
public static final class Builder extends BaseBuilder<AggregateBatteryConsumer.Builder> {
- private double mConsumedPowerMah;
-
- public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) {
- super(customPowerComponentNames, includePowerModels);
+ public Builder(BatteryConsumer.BatteryConsumerData data, int scope) {
+ super(data, CONSUMER_TYPE_AGGREGATE);
+ data.putInt(COLUMN_INDEX_SCOPE, scope);
}
/**
* Sets the total power included in this aggregate.
*/
public Builder setConsumedPower(double consumedPowerMah) {
- mConsumedPowerMah = consumedPowerMah;
+ mData.putDouble(COLUMN_INDEX_CONSUMED_POWER, consumedPowerMah);
return this;
}
@@ -137,7 +118,8 @@ public final class AggregateBatteryConsumer extends BatteryConsumer implements P
* Adds power and usage duration from the supplied AggregateBatteryConsumer.
*/
public void add(AggregateBatteryConsumer aggregateBatteryConsumer) {
- mConsumedPowerMah += aggregateBatteryConsumer.mConsumedPowerMah;
+ setConsumedPower(mData.getDouble(COLUMN_INDEX_CONSUMED_POWER)
+ + aggregateBatteryConsumer.getConsumedPower());
mPowerComponentsBuilder.addPowerAndDuration(aggregateBatteryConsumer.mPowerComponents);
}
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index da94d74e5ae8..34f079a8982c 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -19,6 +19,8 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.database.CursorWindow;
+import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
@@ -32,6 +34,8 @@ import java.lang.annotation.RetentionPolicy;
*/
public abstract class BatteryConsumer {
+ private static final String TAG = "BatteryConsumer";
+
/**
* Power usage component, describing the particular part of the system
* responsible for power drain.
@@ -147,12 +151,22 @@ public abstract class BatteryConsumer {
*/
public static final int POWER_MODEL_MEASURED_ENERGY = 2;
+ static final int COLUMN_INDEX_BATTERY_CONSUMER_TYPE = 0;
+ static final int COLUMN_COUNT = 1;
+
+ protected final BatteryConsumerData mData;
protected final PowerComponents mPowerComponents;
- protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
+ protected BatteryConsumer(BatteryConsumerData data, @NonNull PowerComponents powerComponents) {
+ mData = data;
mPowerComponents = powerComponents;
}
+ public BatteryConsumer(BatteryConsumerData data) {
+ mData = data;
+ mPowerComponents = new PowerComponents(data);
+ }
+
/**
* Total power consumed by this consumer, in mAh.
*/
@@ -192,11 +206,7 @@ public abstract class BatteryConsumer {
}
public int getCustomPowerComponentCount() {
- return mPowerComponents.getCustomPowerComponentCount();
- }
-
- void setCustomPowerComponentNames(String[] customPowerComponentNames) {
- mPowerComponents.setCustomPowerComponentNames(customPowerComponentNames);
+ return mData.layout.customPowerComponentCount;
}
/**
@@ -231,10 +241,6 @@ public abstract class BatteryConsumer {
return mPowerComponents.getUsageDurationForCustomComponentMillis(componentId);
}
- protected void writeToParcel(Parcel dest, int flags) {
- mPowerComponents.writeToParcel(dest, flags);
- }
-
/**
* Returns the name of the specified component. Intended for logging and debugging.
*/
@@ -318,13 +324,151 @@ public abstract class BatteryConsumer {
return (long) (powerMah * (10 * 3600 / 1000) + 0.5);
}
+ static class BatteryConsumerData {
+ private final CursorWindow mCursorWindow;
+ private final int mCursorRow;
+ public final BatteryConsumerDataLayout layout;
+
+ BatteryConsumerData(CursorWindow cursorWindow, int cursorRow,
+ BatteryConsumerDataLayout layout) {
+ mCursorWindow = cursorWindow;
+ mCursorRow = cursorRow;
+ this.layout = layout;
+ }
+
+ @Nullable
+ static BatteryConsumerData create(CursorWindow cursorWindow,
+ BatteryConsumerDataLayout layout) {
+ int cursorRow = cursorWindow.getNumRows();
+ if (!cursorWindow.allocRow()) {
+ Slog.e(TAG, "Cannot allocate BatteryConsumerData: too many UIDs: " + cursorRow);
+ cursorRow = -1;
+ }
+ return new BatteryConsumerData(cursorWindow, cursorRow, layout);
+ }
+
+ void putInt(int columnIndex, int value) {
+ if (mCursorRow == -1) {
+ return;
+ }
+ mCursorWindow.putLong(value, mCursorRow, columnIndex);
+ }
+
+ int getInt(int columnIndex) {
+ if (mCursorRow == -1) {
+ return 0;
+ }
+ return mCursorWindow.getInt(mCursorRow, columnIndex);
+ }
+
+ void putDouble(int columnIndex, double value) {
+ if (mCursorRow == -1) {
+ return;
+ }
+ mCursorWindow.putDouble(value, mCursorRow, columnIndex);
+ }
+
+ double getDouble(int columnIndex) {
+ if (mCursorRow == -1) {
+ return 0;
+ }
+ return mCursorWindow.getDouble(mCursorRow, columnIndex);
+ }
+
+ void putLong(int columnIndex, long value) {
+ if (mCursorRow == -1) {
+ return;
+ }
+ mCursorWindow.putLong(value, mCursorRow, columnIndex);
+ }
+
+ long getLong(int columnIndex) {
+ if (mCursorRow == -1) {
+ return 0;
+ }
+ return mCursorWindow.getLong(mCursorRow, columnIndex);
+ }
+
+ void putString(int columnIndex, String value) {
+ if (mCursorRow == -1) {
+ return;
+ }
+ mCursorWindow.putString(value, mCursorRow, columnIndex);
+ }
+
+ String getString(int columnIndex) {
+ if (mCursorRow == -1) {
+ return null;
+ }
+ return mCursorWindow.getString(mCursorRow, columnIndex);
+ }
+ }
+
+ static class BatteryConsumerDataLayout {
+ public final String[] customPowerComponentNames;
+ public final int customPowerComponentCount;
+ public final boolean powerModelsIncluded;
+
+ public final int consumedPowerColumn;
+ public final int firstConsumedPowerColumn;
+ public final int firstCustomConsumedPowerColumn;
+ public final int firstUsageDurationColumn;
+ public final int firstCustomUsageDurationColumn;
+ public final int firstPowerModelColumn;
+ public final int columnCount;
+
+ private BatteryConsumerDataLayout(int firstColumn, String[] customPowerComponentNames,
+ boolean powerModelsIncluded) {
+ this.customPowerComponentNames = customPowerComponentNames;
+ this.customPowerComponentCount = customPowerComponentNames.length;
+ this.powerModelsIncluded = powerModelsIncluded;
+
+ int columnIndex = firstColumn;
+ consumedPowerColumn = columnIndex++;
+
+ firstConsumedPowerColumn = columnIndex;
+ columnIndex += BatteryConsumer.POWER_COMPONENT_COUNT;
+
+ firstCustomConsumedPowerColumn = columnIndex;
+ columnIndex += customPowerComponentCount;
+
+ firstUsageDurationColumn = columnIndex;
+ columnIndex += BatteryConsumer.POWER_COMPONENT_COUNT;
+
+ firstCustomUsageDurationColumn = columnIndex;
+ columnIndex += customPowerComponentCount;
+
+ if (powerModelsIncluded) {
+ firstPowerModelColumn = columnIndex;
+ columnIndex += BatteryConsumer.POWER_COMPONENT_COUNT;
+ } else {
+ firstPowerModelColumn = -1;
+ }
+
+ columnCount = columnIndex;
+ }
+ }
+
+ static BatteryConsumerDataLayout createBatteryConsumerDataLayout(
+ String[] customPowerComponentNames, boolean includePowerModels) {
+ int columnCount = BatteryConsumer.COLUMN_COUNT;
+ columnCount = Math.max(columnCount, AggregateBatteryConsumer.COLUMN_COUNT);
+ columnCount = Math.max(columnCount, UidBatteryConsumer.COLUMN_COUNT);
+ columnCount = Math.max(columnCount, UserBatteryConsumer.COLUMN_COUNT);
+
+ return new BatteryConsumerDataLayout(columnCount, customPowerComponentNames,
+ includePowerModels);
+ }
+
protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
- final PowerComponents.Builder mPowerComponentsBuilder;
+ protected final BatteryConsumer.BatteryConsumerData mData;
+ protected final PowerComponents.Builder mPowerComponentsBuilder;
+
+ public BaseBuilder(BatteryConsumer.BatteryConsumerData data, int consumerType) {
+ mData = data;
+ data.putLong(COLUMN_INDEX_BATTERY_CONSUMER_TYPE, consumerType);
- public BaseBuilder(@NonNull String[] customPowerComponentNames,
- boolean includePowerModels) {
- mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentNames,
- includePowerModels);
+ mPowerComponentsBuilder = new PowerComponents.Builder(data);
}
/**
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index a7b67ef4b208..591b665f97a2 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -18,6 +18,8 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.database.Cursor;
+import android.database.CursorWindow;
import android.util.Range;
import android.util.SparseArray;
import android.util.TypedXmlPullParser;
@@ -31,6 +33,7 @@ import com.android.internal.os.PowerCalculator;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.Closeable;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -51,7 +54,7 @@ import java.util.List;
*
* @hide
*/
-public final class BatteryUsageStats implements Parcelable {
+public final class BatteryUsageStats implements Parcelable, Closeable {
/**
* Scope of battery stats included in a BatteryConsumer: the entire device, just
@@ -110,6 +113,9 @@ public final class BatteryUsageStats implements Parcelable {
static final String XML_ATTR_TIME_IN_FOREGROUND = "time_in_foreground";
static final String XML_ATTR_TIME_IN_BACKGROUND = "time_in_background";
+ // We need about 700 bytes per UID
+ private static final long BATTERY_CONSUMER_CURSOR_WINDOW_SIZE = 5_000 * 700;
+
private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
private final int mDischargePercentage;
@@ -122,11 +128,13 @@ public final class BatteryUsageStats implements Parcelable {
private final long mBatteryTimeRemainingMs;
private final long mChargeTimeRemainingMs;
private final String[] mCustomPowerComponentNames;
+ private final boolean mIncludesPowerModels;
private final List<UidBatteryConsumer> mUidBatteryConsumers;
private final List<UserBatteryConsumer> mUserBatteryConsumers;
private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
private final Parcel mHistoryBuffer;
private final List<BatteryStats.HistoryTag> mHistoryTagPool;
+ private CursorWindow mBatteryConsumersCursorWindow;
private BatteryUsageStats(@NonNull Builder builder) {
mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
@@ -141,6 +149,8 @@ public final class BatteryUsageStats implements Parcelable {
mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
+ mIncludesPowerModels = builder.mIncludePowerModels;
+ mBatteryConsumersCursorWindow = builder.mBatteryConsumersCursorWindow;
double totalPowerMah = 0;
final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
@@ -309,38 +319,43 @@ public final class BatteryUsageStats implements Parcelable {
mBatteryTimeRemainingMs = source.readLong();
mChargeTimeRemainingMs = source.readLong();
mCustomPowerComponentNames = source.readStringArray();
+ mIncludesPowerModels = source.readBoolean();
+
+ mBatteryConsumersCursorWindow = CursorWindow.newFromParcel(source);
+ BatteryConsumer.BatteryConsumerDataLayout dataLayout =
+ BatteryConsumer.createBatteryConsumerDataLayout(mCustomPowerComponentNames,
+ mIncludesPowerModels);
+
+ final int numRows = mBatteryConsumersCursorWindow.getNumRows();
+
mAggregateBatteryConsumers =
new AggregateBatteryConsumer[AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT];
- for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) {
- mAggregateBatteryConsumers[i] =
- AggregateBatteryConsumer.CREATOR.createFromParcel(source);
- mAggregateBatteryConsumers[i].setCustomPowerComponentNames(mCustomPowerComponentNames);
- }
-
- // UidBatteryConsumers are included as a blob to avoid a TransactionTooLargeException
- final Parcel blob = Parcel.obtain();
- final byte[] bytes = source.readBlob();
- blob.unmarshall(bytes, 0, bytes.length);
- blob.setDataPosition(0);
-
- final int uidCount = blob.readInt();
- mUidBatteryConsumers = new ArrayList<>(uidCount);
- for (int i = 0; i < uidCount; i++) {
- final UidBatteryConsumer consumer =
- UidBatteryConsumer.CREATOR.createFromParcel(blob);
- consumer.setCustomPowerComponentNames(mCustomPowerComponentNames);
- mUidBatteryConsumers.add(consumer);
- }
- blob.recycle();
-
- int userCount = source.readInt();
- mUserBatteryConsumers = new ArrayList<>(userCount);
- for (int i = 0; i < userCount; i++) {
- final UserBatteryConsumer consumer =
- UserBatteryConsumer.CREATOR.createFromParcel(source);
- consumer.setCustomPowerComponentNames(mCustomPowerComponentNames);
- mUserBatteryConsumers.add(consumer);
+ mUidBatteryConsumers = new ArrayList<>(numRows);
+ mUserBatteryConsumers = new ArrayList<>();
+
+ for (int i = 0; i < numRows; i++) {
+ final BatteryConsumer.BatteryConsumerData data =
+ new BatteryConsumer.BatteryConsumerData(mBatteryConsumersCursorWindow, i,
+ dataLayout);
+
+ int consumerType = mBatteryConsumersCursorWindow.getInt(i,
+ BatteryConsumer.COLUMN_INDEX_BATTERY_CONSUMER_TYPE);
+ switch (consumerType) {
+ case AggregateBatteryConsumer.CONSUMER_TYPE_AGGREGATE: {
+ final AggregateBatteryConsumer consumer = new AggregateBatteryConsumer(data);
+ mAggregateBatteryConsumers[consumer.getScope()] = consumer;
+ break;
+ }
+ case UidBatteryConsumer.CONSUMER_TYPE_UID: {
+ mUidBatteryConsumers.add(new UidBatteryConsumer(data));
+ break;
+ }
+ case UserBatteryConsumer.CONSUMER_TYPE_USER:
+ mUserBatteryConsumers.add(new UserBatteryConsumer(data));
+ break;
+ }
}
+
if (source.readBoolean()) {
final byte[] historyBlob = source.readBlob();
@@ -374,26 +389,9 @@ public final class BatteryUsageStats implements Parcelable {
dest.writeLong(mBatteryTimeRemainingMs);
dest.writeLong(mChargeTimeRemainingMs);
dest.writeStringArray(mCustomPowerComponentNames);
- for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) {
- mAggregateBatteryConsumers[i].writeToParcel(dest, flags);
- }
-
- // UidBatteryConsumers are included as a blob, because each UidBatteryConsumer
- // takes > 300 bytes, so a typical number of UIDs in the system, 300 would result
- // in a 90 kB Parcel, which is not safe to pass in a binder transaction because
- // of the possibility of TransactionTooLargeException
- final Parcel blob = Parcel.obtain();
- blob.writeInt(mUidBatteryConsumers.size());
- for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) {
- mUidBatteryConsumers.get(i).writeToParcel(blob, flags);
- }
- dest.writeBlob(blob.marshall());
- blob.recycle();
+ dest.writeBoolean(mIncludesPowerModels);
+ mBatteryConsumersCursorWindow.writeToParcel(dest, flags);
- dest.writeInt(mUserBatteryConsumers.size());
- for (int i = mUserBatteryConsumers.size() - 1; i >= 0; i--) {
- mUserBatteryConsumers.get(i).writeToParcel(dest, flags);
- }
if (mHistoryBuffer != null) {
dest.writeBoolean(true);
dest.writeBlob(mHistoryBuffer.marshall());
@@ -682,8 +680,7 @@ public final class BatteryUsageStats implements Parcelable {
i++;
}
- builder = new Builder(
- customComponentNames.toArray(new String[0]), true);
+ builder = new Builder(customComponentNames.toArray(new String[0]), true);
builder.setStatsStartTimestamp(
parser.getAttributeLong(null, XML_ATTR_START_TIMESTAMP));
@@ -733,13 +730,29 @@ public final class BatteryUsageStats implements Parcelable {
return builder.build();
}
+ @Override
+ public void close() throws IOException {
+ mBatteryConsumersCursorWindow.close();
+ mBatteryConsumersCursorWindow = null;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (mBatteryConsumersCursorWindow != null) {
+ mBatteryConsumersCursorWindow.close();
+ }
+ super.finalize();
+ }
+
/**
* Builder for BatteryUsageStats.
*/
public static final class Builder {
+ private final CursorWindow mBatteryConsumersCursorWindow;
@NonNull
private final String[] mCustomPowerComponentNames;
private final boolean mIncludePowerModels;
+ private final BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
private long mStatsStartTimestampMs;
private long mStatsEndTimestampMs;
private long mStatsDurationMs = -1;
@@ -762,12 +775,22 @@ public final class BatteryUsageStats implements Parcelable {
this(customPowerComponentNames, false);
}
- public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) {
+ public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) {
+ mBatteryConsumersCursorWindow =
+ new CursorWindow(null, BATTERY_CONSUMER_CURSOR_WINDOW_SIZE);
+ mBatteryConsumerDataLayout =
+ BatteryConsumer.createBatteryConsumerDataLayout(customPowerComponentNames,
+ includePowerModels);
+ mBatteryConsumersCursorWindow.setNumColumns(mBatteryConsumerDataLayout.columnCount);
+
mCustomPowerComponentNames = customPowerComponentNames;
mIncludePowerModels = includePowerModels;
- for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) {
- mAggregateBatteryConsumersBuilders[i] = new AggregateBatteryConsumer.Builder(
- customPowerComponentNames, includePowerModels);
+ for (int scope = 0; scope < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; scope++) {
+ final BatteryConsumer.BatteryConsumerData data =
+ BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+ mBatteryConsumerDataLayout);
+ mAggregateBatteryConsumersBuilders[scope] =
+ new AggregateBatteryConsumer.Builder(data, scope);
}
}
@@ -892,8 +915,10 @@ public final class BatteryUsageStats implements Parcelable {
int uid = batteryStatsUid.getUid();
UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
if (builder == null) {
- builder = new UidBatteryConsumer.Builder(mCustomPowerComponentNames,
- mIncludePowerModels, batteryStatsUid);
+ final BatteryConsumer.BatteryConsumerData data =
+ BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+ mBatteryConsumerDataLayout);
+ builder = new UidBatteryConsumer.Builder(data, batteryStatsUid);
mUidBatteryConsumerBuilders.put(uid, builder);
}
return builder;
@@ -908,8 +933,10 @@ public final class BatteryUsageStats implements Parcelable {
public UidBatteryConsumer.Builder getOrCreateUidBatteryConsumerBuilder(int uid) {
UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
if (builder == null) {
- builder = new UidBatteryConsumer.Builder(mCustomPowerComponentNames,
- mIncludePowerModels, uid);
+ final BatteryConsumer.BatteryConsumerData data =
+ BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+ mBatteryConsumerDataLayout);
+ builder = new UidBatteryConsumer.Builder(data, uid);
mUidBatteryConsumerBuilders.put(uid, builder);
}
return builder;
@@ -923,8 +950,10 @@ public final class BatteryUsageStats implements Parcelable {
public UserBatteryConsumer.Builder getOrCreateUserBatteryConsumerBuilder(int userId) {
UserBatteryConsumer.Builder builder = mUserBatteryConsumerBuilders.get(userId);
if (builder == null) {
- builder = new UserBatteryConsumer.Builder(mCustomPowerComponentNames,
- mIncludePowerModels, userId);
+ final BatteryConsumer.BatteryConsumerData data =
+ BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+ mBatteryConsumerDataLayout);
+ builder = new UserBatteryConsumer.Builder(data, userId);
mUserBatteryConsumerBuilders.put(userId, builder);
}
return builder;
@@ -988,5 +1017,38 @@ public final class BatteryUsageStats implements Parcelable {
return this;
}
+
+ /**
+ * Dumps raw contents of the cursor window for debugging.
+ */
+ void dump(PrintWriter writer) {
+ final int numRows = mBatteryConsumersCursorWindow.getNumRows();
+ int numColumns = mBatteryConsumerDataLayout.columnCount;
+ for (int i = 0; i < numRows; i++) {
+ StringBuilder sb = new StringBuilder();
+ for (int j = 0; j < numColumns; j++) {
+ final int type = mBatteryConsumersCursorWindow.getType(i, j);
+ switch (type) {
+ case Cursor.FIELD_TYPE_NULL:
+ sb.append("null, ");
+ break;
+ case Cursor.FIELD_TYPE_INTEGER:
+ sb.append(mBatteryConsumersCursorWindow.getInt(i, j)).append(", ");
+ break;
+ case Cursor.FIELD_TYPE_FLOAT:
+ sb.append(mBatteryConsumersCursorWindow.getFloat(i, j)).append(", ");
+ break;
+ case Cursor.FIELD_TYPE_STRING:
+ sb.append(mBatteryConsumersCursorWindow.getString(i, j)).append(", ");
+ break;
+ case Cursor.FIELD_TYPE_BLOB:
+ sb.append("BLOB, ");
+ break;
+ }
+ }
+ sb.setLength(sb.length() - 2);
+ writer.println(sb);
+ }
+ }
}
}
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index db3d13bdb07b..259e6739b23a 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -30,7 +30,6 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.Arrays;
/**
* Contains details of battery attribution data broken down to individual power drain types
@@ -39,61 +38,21 @@ import java.util.Arrays;
* @hide
*/
class PowerComponents {
- private static final int CUSTOM_POWER_COMPONENT_OFFSET = BatteryConsumer.POWER_COMPONENT_COUNT
- - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
-
- private final double mConsumedPowerMah;
- @NonNull
- private final double[] mPowerComponentsMah;
- @NonNull
- private final long[] mUsageDurationsMs;
- private final int mCustomPowerComponentCount;
- @Nullable
- private final byte[] mPowerModels;
- // Not written to Parcel and must be explicitly restored during the parent object's unparceling
- private String[] mCustomPowerComponentNames;
+ private final BatteryConsumer.BatteryConsumerData mData;
PowerComponents(@NonNull Builder builder) {
- mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
- mCustomPowerComponentCount = mCustomPowerComponentNames.length;
- mPowerComponentsMah = builder.mPowerComponentsMah;
- mUsageDurationsMs = builder.mUsageDurationsMs;
- mConsumedPowerMah = builder.getTotalPower();
- mPowerModels = builder.getPowerModels();
+ mData = builder.mData;
}
- PowerComponents(@NonNull Parcel source) {
- mConsumedPowerMah = source.readDouble();
- mCustomPowerComponentCount = source.readInt();
- mPowerComponentsMah = source.createDoubleArray();
- mUsageDurationsMs = source.createLongArray();
- if (source.readBoolean()) {
- mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
- source.readByteArray(mPowerModels);
- } else {
- mPowerModels = null;
- }
- }
-
- /** Writes contents to Parcel */
- void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeDouble(mConsumedPowerMah);
- dest.writeInt(mCustomPowerComponentCount);
- dest.writeDoubleArray(mPowerComponentsMah);
- dest.writeLongArray(mUsageDurationsMs);
- if (mPowerModels != null) {
- dest.writeBoolean(true);
- dest.writeByteArray(mPowerModels);
- } else {
- dest.writeBoolean(false);
- }
+ PowerComponents(BatteryConsumer.BatteryConsumerData data) {
+ mData = data;
}
/**
* Total power consumed by this consumer, in mAh.
*/
public double getConsumedPower() {
- return mConsumedPowerMah;
+ return mData.getDouble(mData.layout.consumedPowerColumn);
}
/**
@@ -108,11 +67,7 @@ class PowerComponents {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
}
- try {
- return mPowerComponentsMah[componentId];
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
- }
+ return mData.getDouble(mData.layout.firstConsumedPowerColumn + componentId);
}
/**
@@ -122,30 +77,20 @@ class PowerComponents {
* @return Amount of consumed power in mAh.
*/
public double getConsumedPowerForCustomComponent(int componentId) {
- if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
- && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
- try {
- return mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException(
- "Unsupported custom power component ID: " + componentId);
- }
+ final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ if (index >= 0 && index < mData.layout.customPowerComponentCount) {
+ return mData.getDouble(mData.layout.firstCustomConsumedPowerColumn + index);
} else {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
}
}
- void setCustomPowerComponentNames(String[] customPowerComponentNames) {
- mCustomPowerComponentNames = customPowerComponentNames;
- }
-
public String getCustomPowerComponentName(int componentId) {
- if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
- && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
+ final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ if (index >= 0 && index < mData.layout.customPowerComponentCount) {
try {
- return mCustomPowerComponentNames[componentId
- - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID];
+ return mData.layout.customPowerComponentNames[index];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
@@ -156,17 +101,13 @@ class PowerComponents {
}
}
- public boolean hasPowerModels() {
- return mPowerModels != null;
- }
-
@BatteryConsumer.PowerModel
- int getPowerModel(@BatteryConsumer.PowerComponent int component) {
- if (!hasPowerModels()) {
+ int getPowerModel(@BatteryConsumer.PowerComponent int componentId) {
+ if (!mData.layout.powerModelsIncluded) {
throw new IllegalStateException(
"Power model IDs were not requested in the BatteryUsageStatsQuery");
}
- return mPowerModels[component];
+ return mData.getInt(mData.layout.firstPowerModelColumn + componentId);
}
/**
@@ -181,11 +122,7 @@ class PowerComponents {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
}
- try {
- return mUsageDurationsMs[componentId];
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
- }
+ return mData.getLong(mData.layout.firstUsageDurationColumn + componentId);
}
/**
@@ -195,35 +132,15 @@ class PowerComponents {
* @return Amount of time in milliseconds.
*/
public long getUsageDurationForCustomComponentMillis(int componentId) {
- if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
- throw new IllegalArgumentException(
- "Unsupported custom power component ID: " + componentId);
- }
- try {
- return mUsageDurationsMs[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
- } catch (ArrayIndexOutOfBoundsException e) {
+ final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ if (index >= 0 && index < mData.layout.customPowerComponentCount) {
+ return mData.getLong(mData.layout.firstCustomUsageDurationColumn + index);
+ } else {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
}
}
- public int getCustomPowerComponentCount() {
- return mCustomPowerComponentCount;
- }
-
- /**
- * Returns the largest usage duration among all power components.
- */
- public long getMaxComponentUsageDurationMillis() {
- long max = 0;
- for (int i = mUsageDurationsMs.length - 1; i >= 0; i--) {
- if (mUsageDurationsMs[i] > max) {
- max = mUsageDurationsMs[i];
- }
- }
- return max;
- }
-
public void dump(PrintWriter pw, boolean skipEmptyComponents) {
String separator = "";
for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
@@ -232,13 +149,14 @@ class PowerComponents {
if (skipEmptyComponents && componentPower == 0) {
continue;
}
- pw.print(separator); separator = " ";
+ pw.print(separator);
+ separator = " ";
pw.print(BatteryConsumer.powerComponentIdToString(componentId));
pw.print("=");
PowerCalculator.printPowerMah(pw, componentPower);
}
- final int customComponentCount = getCustomPowerComponentCount();
+ final int customComponentCount = mData.layout.customPowerComponentCount;
for (int customComponentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
customComponentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
+ customComponentCount;
@@ -248,7 +166,8 @@ class PowerComponents {
if (skipEmptyComponents && customComponentPower == 0) {
continue;
}
- pw.print(separator); separator = " ";
+ pw.print(separator);
+ separator = " ";
pw.print(getCustomPowerComponentName(customComponentId));
pw.print("=");
PowerCalculator.printPowerMah(pw, customComponentPower);
@@ -272,11 +191,29 @@ class PowerComponents {
private boolean writeStatsProtoImpl(@Nullable ProtoOutputStream proto) {
boolean interestingData = false;
- for (int idx = 0; idx < mPowerComponentsMah.length; idx++) {
- final int componentId = idx < BatteryConsumer.POWER_COMPONENT_COUNT ?
- idx : idx - CUSTOM_POWER_COMPONENT_OFFSET;
- final long powerDeciCoulombs = convertMahToDeciCoulombs(mPowerComponentsMah[idx]);
- final long durationMs = mUsageDurationsMs[idx];
+ for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
+ componentId++) {
+ final long powerDeciCoulombs = convertMahToDeciCoulombs(getConsumedPower(componentId));
+ final long durationMs = getUsageDurationMillis(componentId);
+
+ if (powerDeciCoulombs == 0 && durationMs == 0) {
+ // No interesting data. Make sure not to even write the COMPONENT int.
+ continue;
+ }
+
+ interestingData = true;
+ if (proto == null) {
+ // We're just asked whether there is data, not to actually write it. And there is.
+ return true;
+ }
+
+ writePowerComponent(proto, componentId, powerDeciCoulombs, durationMs);
+ }
+ for (int idx = 0; idx < mData.layout.customPowerComponentCount; idx++) {
+ final int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + idx;
+ final long powerDeciCoulombs =
+ convertMahToDeciCoulombs(getConsumedPowerForCustomComponent(componentId));
+ final long durationMs = getUsageDurationForCustomComponentMillis(componentId);
if (powerDeciCoulombs == 0 && durationMs == 0) {
// No interesting data. Make sure not to even write the COMPONENT int.
@@ -289,25 +226,30 @@ class PowerComponents {
return true;
}
- final long token =
- proto.start(BatteryUsageStatsAtomsProto.BatteryConsumerData.POWER_COMPONENTS);
- proto.write(
- BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
- .COMPONENT,
- componentId);
- proto.write(
- BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
- .POWER_DECI_COULOMBS,
- powerDeciCoulombs);
- proto.write(
- BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
- .DURATION_MILLIS,
- durationMs);
- proto.end(token);
+ writePowerComponent(proto, componentId, powerDeciCoulombs, durationMs);
}
return interestingData;
}
+ private void writePowerComponent(ProtoOutputStream proto, int componentId,
+ long powerDeciCoulombs, long durationMs) {
+ final long token =
+ proto.start(BatteryUsageStatsAtomsProto.BatteryConsumerData.POWER_COMPONENTS);
+ proto.write(
+ BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
+ .COMPONENT,
+ componentId);
+ proto.write(
+ BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
+ .POWER_DECI_COULOMBS,
+ powerDeciCoulombs);
+ proto.write(
+ BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
+ .DURATION_MILLIS,
+ durationMs);
+ proto.end(token);
+ }
+
void writeToXml(TypedXmlSerializer serializer) throws IOException {
serializer.startTag(null, BatteryUsageStats.XML_TAG_POWER_COMPONENTS);
for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
@@ -326,15 +268,15 @@ class PowerComponents {
if (durationMs != 0) {
serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_DURATION, durationMs);
}
- if (mPowerModels != null) {
+ if (mData.layout.powerModelsIncluded) {
serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_MODEL,
- mPowerModels[componentId]);
+ getPowerModel(componentId));
}
serializer.endTag(null, BatteryUsageStats.XML_TAG_COMPONENT);
}
- final int customComponentEnd =
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + mCustomPowerComponentCount;
+ final int customComponentEnd = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
+ + mData.layout.customPowerComponentCount;
for (int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
componentId < customComponentEnd;
componentId++) {
@@ -430,22 +372,15 @@ class PowerComponents {
static final class Builder {
private static final byte POWER_MODEL_UNINITIALIZED = -1;
- private final double[] mPowerComponentsMah;
- private final String[] mCustomPowerComponentNames;
- private final long[] mUsageDurationsMs;
- private final byte[] mPowerModels;
-
- Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) {
- mCustomPowerComponentNames = customPowerComponentNames;
- int powerComponentCount =
- BatteryConsumer.POWER_COMPONENT_COUNT + mCustomPowerComponentNames.length;
- mPowerComponentsMah = new double[powerComponentCount];
- mUsageDurationsMs = new long[powerComponentCount];
- if (includePowerModels) {
- mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
- Arrays.fill(mPowerModels, POWER_MODEL_UNINITIALIZED);
- } else {
- mPowerModels = null;
+ private final BatteryConsumer.BatteryConsumerData mData;
+
+ Builder(BatteryConsumer.BatteryConsumerData data) {
+ mData = data;
+ if (mData.layout.powerModelsIncluded) {
+ for (int i = 0; i < BatteryConsumer.POWER_COMPONENT_COUNT; i++) {
+ mData.putLong(mData.layout.firstPowerModelColumn + i,
+ POWER_MODEL_UNINITIALIZED);
+ }
}
}
@@ -463,15 +398,11 @@ class PowerComponents {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
}
- try {
- mPowerComponentsMah[componentId] = componentPower;
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException(
- "Unsupported power component ID: " + componentId);
- }
- if (mPowerModels != null) {
- mPowerModels[componentId] = (byte) powerModel;
+ mData.putDouble(mData.layout.firstConsumedPowerColumn + componentId, componentPower);
+ if (mData.layout.powerModelsIncluded) {
+ mData.putLong(mData.layout.firstPowerModelColumn + componentId, powerModel);
}
+
return this;
}
@@ -483,19 +414,12 @@ class PowerComponents {
*/
@NonNull
public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
- if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
- && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
- try {
- mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId] =
- componentPower;
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException(
- "Unsupported custom power component ID: " + componentId);
- }
- } else {
+ final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ if (index < 0 || index >= mData.layout.customPowerComponentCount) {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
}
+ mData.putDouble(mData.layout.firstCustomConsumedPowerColumn + index, componentPower);
return this;
}
@@ -513,12 +437,8 @@ class PowerComponents {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
}
- try {
- mUsageDurationsMs[componentId] = componentUsageDurationMillis;
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException(
- "Unsupported power component ID: " + componentId);
- }
+ mData.putLong(mData.layout.firstUsageDurationColumn + componentId,
+ componentUsageDurationMillis);
return this;
}
@@ -531,51 +451,67 @@ class PowerComponents {
@NonNull
public Builder setUsageDurationForCustomComponentMillis(int componentId,
long componentUsageDurationMillis) {
- if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
- throw new IllegalArgumentException(
- "Unsupported custom power component ID: " + componentId);
- }
- try {
- mUsageDurationsMs[CUSTOM_POWER_COMPONENT_OFFSET + componentId] =
- componentUsageDurationMillis;
- } catch (ArrayIndexOutOfBoundsException e) {
+ final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ if (index < 0 || index >= mData.layout.customPowerComponentCount) {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
}
+
+ mData.putLong(mData.layout.firstCustomUsageDurationColumn + index,
+ componentUsageDurationMillis);
return this;
}
public void addPowerAndDuration(PowerComponents.Builder other) {
- addPowerAndDuration(other.mPowerComponentsMah, other.mUsageDurationsMs,
- other.mPowerModels);
+ addPowerAndDuration(other.mData);
}
public void addPowerAndDuration(PowerComponents other) {
- addPowerAndDuration(other.mPowerComponentsMah, other.mUsageDurationsMs,
- other.mPowerModels);
+ addPowerAndDuration(other.mData);
}
- private void addPowerAndDuration(double[] powerComponentsMah,
- long[] usageDurationsMs, byte[] powerModels) {
- if (mPowerComponentsMah.length != powerComponentsMah.length) {
+ private void addPowerAndDuration(BatteryConsumer.BatteryConsumerData otherData) {
+ if (mData.layout.customPowerComponentCount
+ != otherData.layout.customPowerComponentCount) {
throw new IllegalArgumentException(
- "Number of power components does not match: " + powerComponentsMah.length
- + ", expected: " + mPowerComponentsMah.length);
+ "Number of power components does not match: "
+ + otherData.layout.customPowerComponentCount
+ + ", expected: " + mData.layout.customPowerComponentCount);
}
- for (int i = mPowerComponentsMah.length - 1; i >= 0; i--) {
- mPowerComponentsMah[i] += powerComponentsMah[i];
+ for (int i = BatteryConsumer.POWER_COMPONENT_COUNT - 1; i >= 0; i--) {
+ final int powerColumnIndex = mData.layout.firstConsumedPowerColumn + i;
+ mData.putDouble(powerColumnIndex,
+ mData.getDouble(powerColumnIndex)
+ + otherData.getDouble(powerColumnIndex));
+
+ final int durationColumnIndex = mData.layout.firstUsageDurationColumn + i;
+ mData.putLong(durationColumnIndex,
+ mData.getLong(durationColumnIndex)
+ + otherData.getLong(durationColumnIndex));
}
- for (int i = mUsageDurationsMs.length - 1; i >= 0; i--) {
- mUsageDurationsMs[i] += usageDurationsMs[i];
+
+ for (int i = mData.layout.customPowerComponentCount - 1; i >= 0; i--) {
+ final int powerColumnIndex = mData.layout.firstCustomConsumedPowerColumn + i;
+ mData.putDouble(powerColumnIndex,
+ mData.getDouble(powerColumnIndex) + otherData.getDouble(powerColumnIndex));
+
+ final int usageColumnIndex = mData.layout.firstCustomUsageDurationColumn + i;
+ mData.putLong(usageColumnIndex,
+ mData.getLong(usageColumnIndex) + otherData.getLong(usageColumnIndex)
+ );
}
- if (mPowerModels != null && powerModels != null) {
- for (int i = mPowerModels.length - 1; i >= 0; i--) {
- if (mPowerModels[i] == POWER_MODEL_UNINITIALIZED) {
- mPowerModels[i] = powerModels[i];
- } else if (mPowerModels[i] != powerModels[i]
- && powerModels[i] != POWER_MODEL_UNINITIALIZED) {
- mPowerModels[i] = BatteryConsumer.POWER_MODEL_UNDEFINED;
+
+ if (mData.layout.powerModelsIncluded && otherData.layout.powerModelsIncluded) {
+ for (int i = BatteryConsumer.POWER_COMPONENT_COUNT - 1; i >= 0; i--) {
+ final int columnIndex = mData.layout.firstPowerModelColumn + i;
+ int powerModel = mData.getInt(columnIndex);
+ int otherPowerModel = otherData.getInt(columnIndex);
+ if (powerModel == POWER_MODEL_UNINITIALIZED) {
+ mData.putLong(columnIndex, otherPowerModel);
+ } else if (powerModel != otherPowerModel
+ && otherPowerModel != POWER_MODEL_UNINITIALIZED) {
+ mData.putLong(columnIndex, BatteryConsumer.POWER_MODEL_UNDEFINED);
}
}
}
@@ -587,23 +523,15 @@ class PowerComponents {
*/
public double getTotalPower() {
double totalPowerMah = 0;
- for (int i = mPowerComponentsMah.length - 1; i >= 0; i--) {
- totalPowerMah += mPowerComponentsMah[i];
+ for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
+ componentId++) {
+ totalPowerMah +=
+ mData.getDouble(mData.layout.firstConsumedPowerColumn + componentId);
}
- return totalPowerMah;
- }
-
- private byte[] getPowerModels() {
- if (mPowerModels == null) {
- return null;
- }
-
- byte[] powerModels = new byte[mPowerModels.length];
- for (int i = mPowerModels.length - 1; i >= 0; i--) {
- powerModels[i] = mPowerModels[i] != POWER_MODEL_UNINITIALIZED ? mPowerModels[i]
- : BatteryConsumer.POWER_MODEL_UNDEFINED;
+ for (int i = 0; i < mData.layout.customPowerComponentCount; i++) {
+ totalPowerMah += mData.getDouble(mData.layout.firstCustomConsumedPowerColumn + i);
}
- return powerModels;
+ return totalPowerMah;
}
/**
@@ -611,6 +539,18 @@ class PowerComponents {
*/
@NonNull
public PowerComponents build() {
+ mData.putDouble(mData.layout.consumedPowerColumn, getTotalPower());
+
+ if (mData.layout.powerModelsIncluded) {
+ for (int i = BatteryConsumer.POWER_COMPONENT_COUNT - 1; i >= 0; i--) {
+ final int powerModel = mData.getInt(mData.layout.firstPowerModelColumn + i);
+ if (powerModel == POWER_MODEL_UNINITIALIZED) {
+ mData.putInt(mData.layout.firstPowerModelColumn + i,
+ BatteryConsumer.POWER_MODEL_UNDEFINED);
+ }
+ }
+ }
+
return new PowerComponents(this);
}
}
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index bfc4f73835d9..f9f44631a015 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -38,7 +38,9 @@ import java.lang.annotation.RetentionPolicy;
*
* @hide
*/
-public final class UidBatteryConsumer extends BatteryConsumer implements Parcelable {
+public final class UidBatteryConsumer extends BatteryConsumer {
+
+ static final int CONSUMER_TYPE_UID = 1;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
@@ -66,19 +68,27 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
*/
public static final int STATE_BACKGROUND = 1;
- private final int mUid;
- @Nullable
- private final String mPackageWithHighestDrain;
- private final long mTimeInForegroundMs;
- private final long mTimeInBackgroundMs;
+ static final int COLUMN_INDEX_UID = BatteryConsumer.COLUMN_COUNT;
+ static final int COLUMN_INDEX_PACKAGE_WITH_HIGHEST_DRAIN = COLUMN_INDEX_UID + 1;
+ static final int COLUMN_INDEX_TIME_IN_FOREGROUND = COLUMN_INDEX_UID + 2;
+ static final int COLUMN_INDEX_TIME_IN_BACKGROUND = COLUMN_INDEX_UID + 3;
+ static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 4;
+
+ UidBatteryConsumer(BatteryConsumerData data) {
+ super(data);
+ }
+
+ private UidBatteryConsumer(@NonNull Builder builder) {
+ super(builder.mData, builder.mPowerComponentsBuilder.build());
+ }
public int getUid() {
- return mUid;
+ return mData.getInt(COLUMN_INDEX_UID);
}
@Nullable
public String getPackageWithHighestDrain() {
- return mPackageWithHighestDrain;
+ return mData.getString(COLUMN_INDEX_PACKAGE_WITH_HIGHEST_DRAIN);
}
/**
@@ -87,41 +97,13 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
public long getTimeInStateMs(@State int state) {
switch (state) {
case STATE_BACKGROUND:
- return mTimeInBackgroundMs;
+ return mData.getInt(COLUMN_INDEX_TIME_IN_BACKGROUND);
case STATE_FOREGROUND:
- return mTimeInForegroundMs;
+ return mData.getInt(COLUMN_INDEX_TIME_IN_FOREGROUND);
}
return 0;
}
- private UidBatteryConsumer(@NonNull Builder builder) {
- super(builder.mPowerComponentsBuilder.build());
- mUid = builder.mUid;
- mPackageWithHighestDrain = builder.mPackageWithHighestDrain;
- mTimeInForegroundMs = builder.mTimeInForegroundMs;
- mTimeInBackgroundMs = builder.mTimeInBackgroundMs;
- }
-
- private UidBatteryConsumer(@NonNull Parcel source) {
- super(new PowerComponents(source));
- mUid = source.readInt();
- mPackageWithHighestDrain = source.readString();
- mTimeInForegroundMs = source.readLong();
- mTimeInBackgroundMs = source.readLong();
- }
-
- /**
- * Writes the contents into a Parcel.
- */
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mUid);
- dest.writeString(mPackageWithHighestDrain);
- dest.writeLong(mTimeInForegroundMs);
- dest.writeLong(mTimeInBackgroundMs);
- }
-
@Override
public void dump(PrintWriter pw, boolean skipEmptyComponents) {
final double consumedPower = getConsumedPower();
@@ -134,20 +116,8 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
pw.print(" ) ");
}
- @NonNull
- public static final Creator<UidBatteryConsumer> CREATOR = new Creator<UidBatteryConsumer>() {
- public UidBatteryConsumer createFromParcel(@NonNull Parcel source) {
- return new UidBatteryConsumer(source);
- }
-
- public UidBatteryConsumer[] newArray(int size) {
- return new UidBatteryConsumer[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
+ static UidBatteryConsumer create(BatteryConsumerData data) {
+ return new UidBatteryConsumer(data);
}
/** Serializes this object to XML */
@@ -158,14 +128,15 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
serializer.startTag(null, BatteryUsageStats.XML_TAG_UID);
serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_UID, getUid());
- if (!TextUtils.isEmpty(mPackageWithHighestDrain)) {
+ final String packageWithHighestDrain = getPackageWithHighestDrain();
+ if (!TextUtils.isEmpty(packageWithHighestDrain)) {
serializer.attribute(null, BatteryUsageStats.XML_ATTR_HIGHEST_DRAIN_PACKAGE,
- mPackageWithHighestDrain);
+ packageWithHighestDrain);
}
serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_FOREGROUND,
- mTimeInForegroundMs);
+ getTimeInStateMs(STATE_FOREGROUND));
serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_BACKGROUND,
- mTimeInBackgroundMs);
+ getTimeInStateMs(STATE_BACKGROUND));
mPowerComponents.writeToXml(serializer);
serializer.endTag(null, BatteryUsageStats.XML_TAG_UID);
}
@@ -209,22 +180,20 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
private final BatteryStats.Uid mBatteryStatsUid;
private final int mUid;
private String mPackageWithHighestDrain = PACKAGE_NAME_UNINITIALIZED;
- public long mTimeInForegroundMs;
- public long mTimeInBackgroundMs;
private boolean mExcludeFromBatteryUsageStats;
- public Builder(@NonNull String[] customPowerComponentNames,
- boolean includePowerModels, @NonNull BatteryStats.Uid batteryStatsUid) {
- super(customPowerComponentNames, includePowerModels);
+ public Builder(BatteryConsumerData data, @NonNull BatteryStats.Uid batteryStatsUid) {
+ super(data, CONSUMER_TYPE_UID);
mBatteryStatsUid = batteryStatsUid;
mUid = batteryStatsUid.getUid();
+ data.putLong(COLUMN_INDEX_UID, mUid);
}
- public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels,
- int uid) {
- super(customPowerComponentNames, includePowerModels);
+ public Builder(BatteryConsumerData data, int uid) {
+ super(data, CONSUMER_TYPE_UID);
mBatteryStatsUid = null;
mUid = uid;
+ data.putLong(COLUMN_INDEX_UID, mUid);
}
@NonNull
@@ -258,10 +227,10 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
public Builder setTimeInStateMs(@State int state, long timeInStateMs) {
switch (state) {
case STATE_FOREGROUND:
- mTimeInForegroundMs = timeInStateMs;
+ mData.putLong(COLUMN_INDEX_TIME_IN_FOREGROUND, timeInStateMs);
break;
case STATE_BACKGROUND:
- mTimeInBackgroundMs = timeInStateMs;
+ mData.putLong(COLUMN_INDEX_TIME_IN_BACKGROUND, timeInStateMs);
break;
default:
throw new IllegalArgumentException("Unsupported state: " + state);
@@ -282,13 +251,18 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
*/
public Builder add(UidBatteryConsumer consumer) {
mPowerComponentsBuilder.addPowerAndDuration(consumer.mPowerComponents);
- mTimeInBackgroundMs += consumer.mTimeInBackgroundMs;
- mTimeInForegroundMs += consumer.mTimeInForegroundMs;
+
+ setTimeInStateMs(STATE_FOREGROUND,
+ mData.getLong(COLUMN_INDEX_TIME_IN_FOREGROUND)
+ + consumer.getTimeInStateMs(STATE_FOREGROUND));
+ setTimeInStateMs(STATE_BACKGROUND,
+ mData.getLong(COLUMN_INDEX_TIME_IN_BACKGROUND)
+ + consumer.getTimeInStateMs(STATE_BACKGROUND));
if (mPackageWithHighestDrain == PACKAGE_NAME_UNINITIALIZED) {
- mPackageWithHighestDrain = consumer.mPackageWithHighestDrain;
+ mPackageWithHighestDrain = consumer.getPackageWithHighestDrain();
} else if (!TextUtils.equals(mPackageWithHighestDrain,
- consumer.mPackageWithHighestDrain)) {
+ consumer.getPackageWithHighestDrain())) {
// Consider combining two UidBatteryConsumers with this distribution
// of power drain between packages:
// (package1=100, package2=10) and (package1=100, package2=101).
@@ -317,6 +291,9 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
if (mPackageWithHighestDrain == PACKAGE_NAME_UNINITIALIZED) {
mPackageWithHighestDrain = null;
}
+ if (mPackageWithHighestDrain != null) {
+ mData.putString(COLUMN_INDEX_PACKAGE_WITH_HIGHEST_DRAIN, mPackageWithHighestDrain);
+ }
return new UidBatteryConsumer(this);
}
}
diff --git a/core/java/android/os/UserBatteryConsumer.java b/core/java/android/os/UserBatteryConsumer.java
index b508a8cd98ae..c2d20a6c771f 100644
--- a/core/java/android/os/UserBatteryConsumer.java
+++ b/core/java/android/os/UserBatteryConsumer.java
@@ -35,37 +35,30 @@ import java.util.List;
*
* {@hide}
*/
-public class UserBatteryConsumer extends BatteryConsumer implements Parcelable {
- private final int mUserId;
+public class UserBatteryConsumer extends BatteryConsumer {
+ static final int CONSUMER_TYPE_USER = 2;
- public int getUserId() {
- return mUserId;
- }
+ private static final int COLUMN_INDEX_USER_ID = BatteryConsumer.COLUMN_COUNT;
- private UserBatteryConsumer(@NonNull UserBatteryConsumer.Builder builder) {
- super(builder.mPowerComponentsBuilder.build());
- mUserId = builder.mUserId;
+ static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 1;
+
+ UserBatteryConsumer(BatteryConsumerData data) {
+ super(data);
}
- private UserBatteryConsumer(Parcel in) {
- super(new PowerComponents(in));
- mUserId = in.readInt();
+ private UserBatteryConsumer(@NonNull UserBatteryConsumer.Builder builder) {
+ super(builder.mData, builder.mPowerComponentsBuilder.build());
}
- /**
- * Writes the contents into a Parcel.
- */
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mUserId);
+ public int getUserId() {
+ return mData.getInt(COLUMN_INDEX_USER_ID);
}
@Override
public void dump(PrintWriter pw, boolean skipEmptyComponents) {
final double consumedPower = getConsumedPower();
pw.print("User ");
- pw.print(mUserId);
+ pw.print(getUserId());
pw.print(": ");
PowerCalculator.printPowerMah(pw, consumedPower);
pw.print(" ( ");
@@ -73,24 +66,6 @@ public class UserBatteryConsumer extends BatteryConsumer implements Parcelable {
pw.print(" ) ");
}
- public static final Creator<UserBatteryConsumer> CREATOR =
- new Creator<UserBatteryConsumer>() {
- @Override
- public UserBatteryConsumer createFromParcel(Parcel in) {
- return new UserBatteryConsumer(in);
- }
-
- @Override
- public UserBatteryConsumer[] newArray(int size) {
- return new UserBatteryConsumer[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
/** Serializes this object to XML */
void writeToXml(TypedXmlSerializer serializer) throws IOException {
if (getConsumedPower() == 0) {
@@ -131,13 +106,11 @@ public class UserBatteryConsumer extends BatteryConsumer implements Parcelable {
* Builder for UserBatteryConsumer.
*/
public static final class Builder extends BaseBuilder<Builder> {
- private final int mUserId;
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
- Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels,
- int userId) {
- super(customPowerComponentNames, includePowerModels);
- mUserId = userId;
+ Builder(BatteryConsumerData data, int userId) {
+ super(data, CONSUMER_TYPE_USER);
+ data.putLong(COLUMN_INDEX_USER_ID, userId);
}
/**