diff options
| author | Dmitri Plotnikov <dplotnikov@google.com> | 2021-09-09 17:52:19 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2021-09-09 17:52:19 +0000 |
| commit | bfc3bb8d0c17253a6ce93f8e4e83dac8070eb349 (patch) | |
| tree | 343344ddbc96e6c7f56ce2b3cd4eb9d72b70e2f3 /core/java | |
| parent | edea4d6795469840ba6c9064275edc0de6d2c27d (diff) | |
| parent | cadeaf8b249acd38ca2e1f2e32c9d26c55626081 (diff) | |
Merge "Use CursorWindow to hold BatteryConsumer data"
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/os/AggregateBatteryConsumer.java | 60 | ||||
| -rw-r--r-- | core/java/android/os/BatteryConsumer.java | 174 | ||||
| -rw-r--r-- | core/java/android/os/BatteryUsageStats.java | 184 | ||||
| -rw-r--r-- | core/java/android/os/PowerComponents.java | 366 | ||||
| -rw-r--r-- | core/java/android/os/UidBatteryConsumer.java | 117 | ||||
| -rw-r--r-- | core/java/android/os/UserBatteryConsumer.java | 57 |
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); } /** |
