Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cadeaf8b authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Use CursorWindow to hold BatteryConsumer data

Bug: 192004350
Test: atest BatteryUsageStatsProtoTests:BatteryUsageStatsPulledTest
      atest FrameworksCoreTests:BatteryUsageStatsTest

Change-Id: I2a285de7ceeb2297ab950b114da45d537ad22706
parent da143d4a
Loading
Loading
Loading
Loading
+21 −39
Original line number Diff line number Diff line
@@ -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;
    }

    @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];
    public void dump(PrintWriter pw, boolean skipEmptyComponents) {
        mPowerComponents.dump(pw, skipEmptyComponents);
    }
            };

    @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);
        }

+159 −15
Original line number Diff line number Diff line
@@ -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,15 +324,153 @@ public abstract class BatteryConsumer {
        return (long) (powerMah * (10 * 3600 / 1000) + 0.5);
    }

    protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
        final PowerComponents.Builder mPowerComponentsBuilder;
    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);
        }

        public BaseBuilder(@NonNull String[] customPowerComponentNames,
                boolean includePowerModels) {
            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentNames,
        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<?>> {
        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);

            mPowerComponentsBuilder = new PowerComponents.Builder(data);
        }

        /**
         * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
         *
+123 −61

File changed.

Preview size limit exceeded, changes collapsed.

+153 −213

File changed.

Preview size limit exceeded, changes collapsed.

+47 −70
Original line number Diff line number Diff line
@@ -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);
        }
    }
Loading