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

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

Introduce BatteryUsageStats API

Bug: 158137862
Test: Start Settings app, navigate to Apps, pick an app, navigate to Battery

Change-Id: I8da8cc9501e01282b855f1bee6032911d91aaf77
parent 7c976c67
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

import android.annotation.IntDef;
import android.annotation.NonNull;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Interface for objects containing battery attribution data.
 *
 * @hide
 */
public abstract class BatteryConsumer {

    /**
     * Power usage component, describing the particular part of the system
     * responsible for power drain.
     *
     * @hide
     */
    @IntDef(prefix = {"POWER_COMPONENT_"}, value = {
            POWER_COMPONENT_CPU,
    })
    @Retention(RetentionPolicy.SOURCE)
    public static @interface PowerComponent {
    }

    public static final int POWER_COMPONENT_CPU = 0;

    public static final int POWER_COMPONENT_COUNT = 1;

    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;

    private final PowerComponents mPowerComponents;

    protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
        mPowerComponents = powerComponents;
    }

    /**
     * Total power consumed by this consumer, in mAh.
     */
    public double getConsumedPower() {
        return mPowerComponents.getTotalPowerConsumed();
    }

    /**
     * Returns the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
     *
     * @param componentId The ID of the power component, e.g.
     *                    {@link BatteryConsumer#POWER_COMPONENT_CPU}.
     * @return Amount of consumed power in mAh.
     */
    public double getConsumedPower(@PowerComponent int componentId) {
        return mPowerComponents.getConsumedPower(componentId);
    }

    /**
     * Returns the amount of drain attributed to the specified custom drain type.
     *
     * @param componentId The ID of the custom power component.
     * @return Amount of consumed power in mAh.
     */
    public double getConsumedPowerForCustomComponent(int componentId) {
        return mPowerComponents.getConsumedPowerForCustomComponent(componentId);
    }

    protected void writeToParcel(Parcel dest, int flags) {
        mPowerComponents.writeToParcel(dest, flags);
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -160,6 +160,22 @@ public final class BatteryStatsManager {
        mBatteryStats = batteryStats;
    }

    /**
     * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem
     * and per-UID basis.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.BATTERY_STATS)
    @NonNull
    public BatteryUsageStats getBatteryUsageStats() {
        try {
            return mBatteryStats.getBatteryUsageStats();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Indicates that the wifi connection RSSI has changed.
     *
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

parcelable BatteryUsageStats;
+138 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

import android.annotation.NonNull;
import android.annotation.SuppressLint;

import java.util.ArrayList;
import java.util.List;

/**
 * Contains a snapshot of battery attribution data, on a per-subsystem and per-UID basis.
 *
 * @hide
 */
public final class BatteryUsageStats implements Parcelable {
    private final double mConsumedPower;
    private final int mDischargePercentage;
    private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers;

    private BatteryUsageStats(@NonNull Builder builder) {
        mConsumedPower = builder.mConsumedPower;
        mDischargePercentage = builder.mDischargePercentage;
        mUidBatteryConsumers = builder.mUidBatteryConsumers;
    }

    /**
     * Portion of battery charge drained since BatteryStats reset (e.g. due to being fully
     * charged), as percentage of the full charge in the range [0:100]
     */
    public int getDischargePercentage() {
        return mDischargePercentage;
    }

    /**
     * Total amount of battery charge drained since BatteryStats reset (e.g. due to being fully
     * charged), in mAh
     */
    public double getConsumedPower() {
        return mConsumedPower;
    }

    @NonNull
    public List<UidBatteryConsumer> getUidBatteryConsumers() {
        return mUidBatteryConsumers;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    private BatteryUsageStats(@NonNull Parcel source) {
        mUidBatteryConsumers = new ArrayList<>();
        source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader());
        mConsumedPower = source.readDouble();
        mDischargePercentage = source.readInt();
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeParcelableList(mUidBatteryConsumers, flags);
        dest.writeDouble(mConsumedPower);
        dest.writeInt(mDischargePercentage);
    }

    @NonNull
    public static final Creator<BatteryUsageStats> CREATOR = new Creator<BatteryUsageStats>() {
        public BatteryUsageStats createFromParcel(@NonNull Parcel source) {
            return new BatteryUsageStats(source);
        }

        public BatteryUsageStats[] newArray(int size) {
            return new BatteryUsageStats[size];
        }
    };

    /**
     * Builder for BatteryUsageStats.
     */
    public static final class Builder {
        private double mConsumedPower;
        private int mDischargePercentage;
        private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers = new ArrayList<>();

        /**
         * Constructs a read-only object using the Builder values.
         */
        @NonNull
        public BatteryUsageStats build() {
            return new BatteryUsageStats(this);
        }

        /**
         * Sets the battery discharge amount since BatteryStats reset as percentage of the full
         * charge.
         */
        @SuppressLint("PercentageInt") // See b/174188159
        @NonNull
        public Builder setDischargePercentage(int dischargePercentage) {
            mDischargePercentage = dischargePercentage;
            return this;
        }

        /**
         * Sets the battery discharge amount since BatteryStats reset, in mAh.
         */
        @NonNull
        public Builder setConsumedPower(double consumedPower) {
            mConsumedPower = consumedPower;
            return this;
        }

        /**
         * Adds a UidBatteryConsumer, which represents battery attribution data for an
         * individual UID.
         */
        @NonNull
        public Builder addUidBatteryConsumer(@NonNull UidBatteryConsumer uidBatteryConsumer) {
            mUidBatteryConsumers.add(uidBatteryConsumer);
            return this;
        }
    }
}
+170 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;


import android.annotation.NonNull;

/**
 * Contains details of battery attribution data broken down to individual power drain types
 * such as CPU, RAM, GPU etc.
 *
 * @hide
 */
class PowerComponents {

    private final double mTotalPowerConsumed;
    private final double[] mPowerComponents;

    PowerComponents(@NonNull Builder builder) {
        mTotalPowerConsumed = builder.mTotalPowerConsumed;
        mPowerComponents = builder.mPowerComponents;
    }

    PowerComponents(@NonNull Parcel source) {
        mTotalPowerConsumed = source.readDouble();
        mPowerComponents = source.createDoubleArray();
    }

    /** Writes contents to Parcel */
    void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeDouble(mTotalPowerConsumed);
        dest.writeDoubleArray(mPowerComponents);
    }

    /**
     * Total power consumed by this consumer, in mAh.
     */
    public double getTotalPowerConsumed() {
        return mTotalPowerConsumed;
    }

    /**
     * Returns the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
     *
     * @param componentId The ID of the power component, e.g.
     *                    {@link BatteryConsumer#POWER_COMPONENT_CPU}.
     * @return Amount of consumed power in mAh.
     */
    public double getConsumedPower(@UidBatteryConsumer.PowerComponent int componentId) {
        if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
            throw new IllegalArgumentException(
                    "Unsupported power component ID: " + componentId);
        }
        try {
            return mPowerComponents[componentId];
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
        }
    }

    /**
     * Returns the amount of drain attributed to the specified custom drain type.
     *
     * @param componentId The ID of the custom power component.
     * @return Amount of consumed power in mAh.
     */
    public double getConsumedPowerForCustomComponent(int componentId) {
        if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
            throw new IllegalArgumentException(
                    "Unsupported custom power component ID: " + componentId);
        }
        try {
            return mPowerComponents[
                    BatteryConsumer.POWER_COMPONENT_COUNT + componentId
                            - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID];
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new IllegalArgumentException(
                    "Unsupported custom power component ID: " + componentId);
        }
    }

    /**
     * Builder for PowerComponents.
     */
    static final class Builder {
        private double mTotalPowerConsumed;
        private final double[] mPowerComponents;

        Builder(int customPowerComponentCount) {
            mPowerComponents = new double[BatteryConsumer.POWER_COMPONENT_COUNT
                    + customPowerComponentCount];
        }

        /**
         * Sets the sum amount of power consumed since BatteryStats reset.
         */
        @NonNull
        public Builder setTotalPowerConsumed(double totalPowerConsumed) {
            mTotalPowerConsumed = totalPowerConsumed;
            return this;
        }

        /**
         * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
         *
         * @param componentId    The ID of the power component, e.g.
         *                       {@link BatteryConsumer#POWER_COMPONENT_CPU}.
         * @param componentPower Amount of consumed power in mAh.
         */
        @NonNull
        public Builder setConsumedPower(@UidBatteryConsumer.PowerComponent int componentId,
                double componentPower) {
            if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
                throw new IllegalArgumentException(
                        "Unsupported power component ID: " + componentId);
            }
            try {
                mPowerComponents[componentId] = componentPower;
            } catch (ArrayIndexOutOfBoundsException e) {
                throw new IllegalArgumentException(
                        "Unsupported power component ID: " + componentId);
            }
            return this;
        }

        /**
         * Sets the amount of drain attributed to the specified custom drain type.
         *
         * @param componentId    The ID of the custom power component.
         * @param componentPower Amount of consumed power in mAh.
         */
        @NonNull
        public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
            if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
                throw new IllegalArgumentException(
                        "Unsupported custom power component ID: " + componentId);
            }
            try {
                mPowerComponents[BatteryConsumer.POWER_COMPONENT_COUNT + componentId
                        - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID] = componentPower;
            } catch (ArrayIndexOutOfBoundsException e) {
                throw new IllegalArgumentException(
                        "Unsupported custom power component ID: " + componentId);
            }
            return this;
        }

        /**
         * Creates a read-only object out of the Builder values.
         */
        @NonNull
        public PowerComponents build() {
            return new PowerComponents(this);
        }
    }
}
Loading