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

Commit 9a8a94c1 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Convert SensorPowerCalculator to work with BatteryUsageStats

Test: atest FrameworksCoreTests:com.android.internal.os.GnssPowerCalculatorTest
Test: atest FrameworksCoreTests:com.android.internal.os.SensorPowerCalculatorTest
Bug: 175644968
Bug: 173546795

Change-Id: I97cc3f75836bdcc719428dc2bb8d8464a609bf14
parent 352d5a43
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