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

Commit d23c73f0 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Android (Google) Code Review
Browse files

Merge "Convert SensorPowerCalculator to work with BatteryUsageStats"

parents 6c09cd99 9a8a94c1
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ public abstract class BatteryConsumer {
            POWER_COMPONENT_FLASHLIGHT,
            POWER_COMPONENT_MOBILE_RADIO,
            POWER_COMPONENT_SYSTEM_SERVICES,
            POWER_COMPONENT_SENSORS,
            POWER_COMPONENT_GNSS,
    })
    @Retention(RetentionPolicy.SOURCE)
    public static @interface PowerComponent {
@@ -59,8 +61,10 @@ public abstract class BatteryConsumer {
    public static final int POWER_COMPONENT_FLASHLIGHT = 6;
    public static final int POWER_COMPONENT_SYSTEM_SERVICES = 7;
    public static final int POWER_COMPONENT_MOBILE_RADIO = 8;
    public static final int POWER_COMPONENT_SENSORS = 9;
    public static final int POWER_COMPONENT_GNSS = 10;

    public static final int POWER_COMPONENT_COUNT = 9;
    public static final int POWER_COMPONENT_COUNT = 11;

    public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
@@ -90,6 +94,8 @@ public abstract class BatteryConsumer {
            TIME_COMPONENT_CAMERA,
            TIME_COMPONENT_FLASHLIGHT,
            TIME_COMPONENT_MOBILE_RADIO,
            TIME_COMPONENT_SENSORS,
            TIME_COMPONENT_GNSS,
    })
    @Retention(RetentionPolicy.SOURCE)
    public static @interface TimeComponent {
@@ -104,8 +110,10 @@ public abstract class BatteryConsumer {
    public static final int TIME_COMPONENT_VIDEO = 6;
    public static final int TIME_COMPONENT_FLASHLIGHT = 7;
    public static final int TIME_COMPONENT_MOBILE_RADIO = 8;
    public static final int TIME_COMPONENT_SENSORS = 9;
    public static final int TIME_COMPONENT_GNSS = 10;

    public static final int TIME_COMPONENT_COUNT = 9;
    public static final int TIME_COMPONENT_COUNT = 11;

    public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
    public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
+2 −1
Original line number Diff line number Diff line
@@ -339,8 +339,9 @@ public class BatteryStatsHelper {
            }
            mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
            mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
            mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile,
            mPowerCalculators.add(new SensorPowerCalculator(
                    mContext.getSystemService(SensorManager.class)));
            mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile));
            mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile));
            mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile));
            mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile));
+2 −1
Original line number Diff line number Diff line
@@ -62,8 +62,9 @@ public class BatteryUsageStatsProvider {
                }
                mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile,
                mPowerCalculators.add(new SensorPowerCalculator(
                        mContext.getSystemService(SensorManager.class)));
                mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile));
                mPowerCalculators.add(new AudioPowerCalculator(mPowerProfile));
+124 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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 com.android.internal.os;

import android.location.GnssSignalQuality;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.util.SparseArray;

import java.util.List;

/**
 * Estimates the amount of power consumed by the GNSS (e.g. GPS).
 */
public class GnssPowerCalculator extends PowerCalculator {
    private final double mAveragePowerGnssOn;
    private final double[] mAveragePowerPerSignalQuality;

    public GnssPowerCalculator(PowerProfile profile) {
        mAveragePowerGnssOn = profile.getAveragePowerOrDefault(PowerProfile.POWER_GPS_ON, -1);
        mAveragePowerPerSignalQuality =
                new double[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
        for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
            mAveragePowerPerSignalQuality[i] = profile.getAveragePower(
                    PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i);
        }
    }

    @Override
    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
            SparseArray<UserHandle> asUsers) {
        final double averageGnssPowerMa = getAverageGnssPower(batteryStats, rawRealtimeUs,
                BatteryStats.STATS_SINCE_CHARGED);
        final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
                builder.getUidBatteryConsumerBuilders();
        for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
            calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, query,
                    averageGnssPowerMa);
        }
    }

    private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
            double averageGnssPowerMa) {
        final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
        double powerMah = computePower(durationMs, averageGnssPowerMa);
        app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_GNSS, durationMs)
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS, powerMah);
    }

    @Override
    public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
        double averageGnssPowerMa = getAverageGnssPower(batteryStats, rawRealtimeUs, statsType);
        for (int i = sippers.size() - 1; i >= 0; i--) {
            final BatterySipper app = sippers.get(i);
            if (app.drainType == BatterySipper.DrainType.APP) {
                calculateApp(app, app.uidObj, rawRealtimeUs, statsType, averageGnssPowerMa);
            }
        }
    }

    protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
            int statsType, double averageGnssPowerMa) {
        final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
        double powerMah = computePower(durationMs, averageGnssPowerMa);

        app.gpsTimeMs = durationMs;
        app.gpsPowerMah = powerMah;
    }

    private long computeDuration(BatteryStats.Uid u, long rawRealtimeUs, int statsType) {
        final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
        final BatteryStats.Uid.Sensor sensor = sensorStats.get(BatteryStats.Uid.Sensor.GPS);
        if (sensor == null) {
            return 0;
        }

        final BatteryStats.Timer timer = sensor.getSensorTime();
        return timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
    }

    private double computePower(long sensorTime, double averageGnssPowerMa) {
        return (sensorTime * averageGnssPowerMa) / (1000 * 60 * 60);
    }

    private double getAverageGnssPower(BatteryStats stats, long rawRealtimeUs, int statsType) {
        double averagePower = mAveragePowerGnssOn;
        if (averagePower != -1) {
            return averagePower;
        }
        averagePower = 0;
        long totalTime = 0;
        double totalPower = 0;
        for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
            long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType);
            totalTime += timePerLevel;
            totalPower += mAveragePowerPerSignalQuality[i] * timePerLevel;
        }
        if (totalTime != 0) {
            averagePower = totalPower / totalTime;
        }
        return averagePower;
    }
}
+50 −52
Original line number Diff line number Diff line
@@ -17,81 +17,79 @@ package com.android.internal.os;

import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.location.GnssSignalQuality;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.UserHandle;
import android.os.BatteryUsageStatsQuery;
import android.os.UidBatteryConsumer;
import android.util.SparseArray;

import java.util.List;

public class SensorPowerCalculator extends PowerCalculator {
    private final PowerProfile mPowerProfile;
    private final List<Sensor> mSensors;
    private double mGpsPower;
    private final SparseArray<Sensor> mSensors;

    public SensorPowerCalculator(PowerProfile profile, SensorManager sensorManager) {
        mPowerProfile = profile;
        mSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
    public SensorPowerCalculator(SensorManager sensorManager) {
        List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
        mSensors = new SparseArray<>(sensors.size());
        for (int i = 0; i < sensors.size(); i++) {
            Sensor sensor = sensors.get(i);
            mSensors.put(sensor.getHandle(), sensor);
        }
    }

    @Override
    public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
        mGpsPower = getAverageGpsPower(batteryStats, rawRealtimeUs, statsType);
        super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
    protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
        app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SENSORS,
                        calculateDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED))
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SENSORS,
                        calculatePowerMah(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED));
    }

    @Override
    protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
            long rawUptimeUs, int statsType) {
        // Process Sensor usage
        app.sensorPowerMah = calculatePowerMah(u, rawRealtimeUs, statsType);
    }

    private long calculateDuration(BatteryStats.Uid u, long rawRealtimeUs, int statsType) {
        long durationMs = 0;
        final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
        final int NSE = sensorStats.size();
        for (int ise = 0; ise < NSE; ise++) {
            final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise);
            final int sensorHandle = sensorStats.keyAt(ise);
            final BatteryStats.Timer timer = sensor.getSensorTime();
            final long sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;

            switch (sensorHandle) {
                case BatteryStats.Uid.Sensor.GPS:
                    app.gpsTimeMs = sensorTime;
                    app.gpsPowerMah = (app.gpsTimeMs * mGpsPower) / (1000 * 60 * 60);
                    break;
                default:
                    final int sensorsCount = mSensors.size();
                    for (int i = 0; i < sensorsCount; i++) {
                        final Sensor s = mSensors.get(i);
                        if (s.getHandle() == sensorHandle) {
                            app.sensorPowerMah += (sensorTime * s.getPower()) / (1000 * 60 * 60);
                            break;
            if (sensorHandle == BatteryStats.Uid.Sensor.GPS) {
                continue;
            }

            final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise);
            final BatteryStats.Timer timer = sensor.getSensorTime();
            durationMs += timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
        }
                    break;
            }
        return durationMs;
    }

    private double calculatePowerMah(BatteryStats.Uid u, long rawRealtimeUs, int statsType) {
        double powerMah = 0;
        final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
        final int count = sensorStats.size();
        for (int ise = 0; ise < count; ise++) {
            final int sensorHandle = sensorStats.keyAt(ise);
            // TODO(b/178127364): remove BatteryStats.Uid.Sensor.GPS and references to it.
            if (sensorHandle == BatteryStats.Uid.Sensor.GPS) {
                continue;
            }

    private double getAverageGpsPower(BatteryStats stats, long rawRealtimeUs,
            int statsType) {
        double averagePower =
                mPowerProfile.getAveragePowerOrDefault(PowerProfile.POWER_GPS_ON, -1);
        if (averagePower != -1) {
            return averagePower;
            final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise);
            final BatteryStats.Timer timer = sensor.getSensorTime();
            final long sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
            if (sensorTime != 0) {
                Sensor s = mSensors.get(sensorHandle);
                if (s != null) {
                    powerMah += (sensorTime * s.getPower()) / (1000 * 60 * 60);
                }
        averagePower = 0;
        long totalTime = 0;
        double totalPower = 0;
        for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
            long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType);
            totalTime += timePerLevel;
            totalPower +=
                    mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
                            * timePerLevel;
            }
        if (totalTime != 0) {
            averagePower = totalPower / totalTime;
        }
        return averagePower;
        return powerMah;
    }
}
Loading