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

Commit 1481bb02 authored by Michael Wachenschwanz's avatar Michael Wachenschwanz
Browse files

Proportionally attribute Mobile Radio Energy Consumption to Phone usage.

Proportionally split out the energy consumption of phone usage from the
rest of the mobile radio energy consumption.

Fixes: 244603408
Test: atest MobileRadioPowerCalculator
Change-Id: I5db49ea7c88cfd502db36265ae5a6555f728d2f7
Merged-In: I5db49ea7c88cfd502db36265ae5a6555f728d2f7
(cherry picked from commit 4789053d)
parent 5a6351fa
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -2807,6 +2807,15 @@ public abstract class BatteryStats implements Parcelable {
     */
     */
    public abstract long getMobileRadioMeasuredBatteryConsumptionUC();
    public abstract long getMobileRadioMeasuredBatteryConsumptionUC();


    /**
     * Returns the battery consumption (in microcoulombs) of the phone calls, derived from on device
     * power measurement data.
     * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
     *
     * {@hide}
     */
    public abstract long getPhoneEnergyConsumptionUC();

    /**
    /**
     * Returns the battery consumption (in microcoulombs) of the screen while on, derived from on
     * Returns the battery consumption (in microcoulombs) of the screen while on, derived from on
     * device power measurement data.
     * device power measurement data.
+44 −9
Original line number Original line Diff line number Diff line
@@ -167,7 +167,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
    // Current on-disk Parcel version. Must be updated when the format of the parcelable changes
    // Current on-disk Parcel version. Must be updated when the format of the parcelable changes
    public static final int VERSION = 210;
    public static final int VERSION = 211;
    // The maximum number of names wakelocks we will keep track of
    // The maximum number of names wakelocks we will keep track of
    // per uid; once the limit is reached, we batch the remaining wakelocks
    // per uid; once the limit is reached, we batch the remaining wakelocks
@@ -6514,6 +6514,9 @@ public class BatteryStatsImpl extends BatteryStats {
            addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
            addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
            mPhoneOn = true;
            mPhoneOn = true;
            mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
            mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
            if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
                scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
            }
        }
        }
    }
    }
@@ -6532,6 +6535,7 @@ public class BatteryStatsImpl extends BatteryStats {
            addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
            addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
            mPhoneOn = false;
            mPhoneOn = false;
            mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
            mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
            scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
        }
        }
    }
    }
@@ -8507,6 +8511,12 @@ public class BatteryStatsImpl extends BatteryStats {
        return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
        return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO);
    }
    }
    @GuardedBy("this")
    @Override
    public long getPhoneEnergyConsumptionUC() {
        return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_PHONE);
    }
    @GuardedBy("this")
    @GuardedBy("this")
    @Override
    @Override
    public long getScreenOnMeasuredBatteryConsumptionUC() {
    public long getScreenOnMeasuredBatteryConsumptionUC() {
@@ -13751,18 +13761,36 @@ public class BatteryStatsImpl extends BatteryStats {
        }
        }
        synchronized (this) {
        synchronized (this) {
            final long totalRadioDurationMs =
                    mMobileRadioActiveTimer.getTimeSinceMarkLocked(
                            elapsedRealtimeMs * 1000) / 1000;
            mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
            final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
                    mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
            mPhoneOnTimer.setMark(elapsedRealtimeMs);
            if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
            if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
                return;
                return;
            }
            }
            final SparseDoubleArray uidEstimatedConsumptionMah;
            final SparseDoubleArray uidEstimatedConsumptionMah;
            final long dataConsumedChargeUC;
            if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null
            if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null
                    && mGlobalMeasuredEnergyStats != null) {
                    && mGlobalMeasuredEnergyStats != null) {
                // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
                // numerator for long rounding.
                final long phoneConsumedChargeUC =
                        (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
                                / totalRadioDurationMs;
                dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
                mGlobalMeasuredEnergyStats.updateStandardBucket(
                mGlobalMeasuredEnergyStats.updateStandardBucket(
                        MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC);
                        MeasuredEnergyStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
                mGlobalMeasuredEnergyStats.updateStandardBucket(
                        MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
                uidEstimatedConsumptionMah = new SparseDoubleArray();
                uidEstimatedConsumptionMah = new SparseDoubleArray();
            } else {
            } else {
                uidEstimatedConsumptionMah = null;
                uidEstimatedConsumptionMah = null;
                dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
            }
            }
            if (deltaInfo != null) {
            if (deltaInfo != null) {
@@ -13922,14 +13950,9 @@ public class BatteryStatsImpl extends BatteryStats {
                // Update the MeasuredEnergyStats information.
                // Update the MeasuredEnergyStats information.
                if (uidEstimatedConsumptionMah != null) {
                if (uidEstimatedConsumptionMah != null) {
                    double totalEstimatedConsumptionMah = 0.0;
                    double totalEstimatedConsumptionMah = 0.0;
                    // Estimate total active radio power consumption since last mark.
                    final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked(
                            elapsedRealtimeMs * 1000) / 1000;
                    mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
                    totalEstimatedConsumptionMah +=
                    totalEstimatedConsumptionMah +=
                            mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
                            mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
                                    totalRadioTimeMs);
                                    totalRadioDurationMs);
                    // Estimate idle power consumption at each signal strength level
                    // Estimate idle power consumption at each signal strength level
                    final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
                    final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
@@ -13953,7 +13976,7 @@ public class BatteryStatsImpl extends BatteryStats {
                            mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
                            mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
                    distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
                    distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
                            consumedChargeUC, uidEstimatedConsumptionMah,
                            dataConsumedChargeUC, uidEstimatedConsumptionMah,
                            totalEstimatedConsumptionMah, elapsedRealtimeMs);
                            totalEstimatedConsumptionMah, elapsedRealtimeMs);
                }
                }
@@ -16685,6 +16708,8 @@ public class BatteryStatsImpl extends BatteryStats {
        public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
        public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
        public static final String KEY_BATTERY_CHARGED_DELAY_MS =
        public static final String KEY_BATTERY_CHARGED_DELAY_MS =
                "battery_charged_delay_ms";
                "battery_charged_delay_ms";
        public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
                "phone_on_external_stats_collection";
        private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
        private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
        private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
        private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
@@ -16697,6 +16722,7 @@ public class BatteryStatsImpl extends BatteryStats {
        private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
        private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
        private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
        private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
        private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
        private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
        private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
        public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
        public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
        /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
        /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
@@ -16712,6 +16738,8 @@ public class BatteryStatsImpl extends BatteryStats {
        public int MAX_HISTORY_FILES;
        public int MAX_HISTORY_FILES;
        public int MAX_HISTORY_BUFFER; /*Bytes*/
        public int MAX_HISTORY_BUFFER; /*Bytes*/
        public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
        public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
        public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
                DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
        private ContentResolver mResolver;
        private ContentResolver mResolver;
        private final KeyValueListParser mParser = new KeyValueListParser(',');
        private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -16788,6 +16816,11 @@ public class BatteryStatsImpl extends BatteryStats {
                                DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
                                DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
                                : DEFAULT_MAX_HISTORY_BUFFER_KB)
                                : DEFAULT_MAX_HISTORY_BUFFER_KB)
                        * 1024;
                        * 1024;
                PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
                        KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
                        DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
                updateBatteryChargedDelayMsLocked();
                updateBatteryChargedDelayMsLocked();
            }
            }
        }
        }
@@ -16842,6 +16875,8 @@ public class BatteryStatsImpl extends BatteryStats {
            pw.println(MAX_HISTORY_BUFFER/1024);
            pw.println(MAX_HISTORY_BUFFER/1024);
            pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
            pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
            pw.println(BATTERY_CHARGED_DELAY_MS);
            pw.println(BATTERY_CHARGED_DELAY_MS);
            pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
            pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
        }
        }
    }
    }
+19 −6
Original line number Original line Diff line number Diff line
@@ -40,14 +40,27 @@ public class PhonePowerCalculator extends PowerCalculator {
    @Override
    @Override
    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
            long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
        final long energyConsumerUC = batteryStats.getPhoneEnergyConsumptionUC();
        final int powerModel = getPowerModel(energyConsumerUC, query);

        final long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs,
        final long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs,
                BatteryStats.STATS_SINCE_CHARGED) / 1000;
                BatteryStats.STATS_SINCE_CHARGED) / 1000;
        final double phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs);
        final double phoneOnPower;
        if (phoneOnPower != 0) {
        switch (powerModel) {
            case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
                phoneOnPower = uCtoMah(energyConsumerUC);
                break;
            case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
            default:
                phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs);
        }

        if (phoneOnPower == 0.0)  return;

        builder.getAggregateBatteryConsumerBuilder(
        builder.getAggregateBatteryConsumerBuilder(
                        BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
                        BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
                    .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower)
                .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower, powerModel)
                .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs);
                .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs);
        }

    }
    }
}
}
+3 −1
Original line number Original line Diff line number Diff line
@@ -59,7 +59,9 @@ public class MeasuredEnergyStats {
    public static final int POWER_BUCKET_BLUETOOTH = 5;
    public static final int POWER_BUCKET_BLUETOOTH = 5;
    public static final int POWER_BUCKET_GNSS = 6;
    public static final int POWER_BUCKET_GNSS = 6;
    public static final int POWER_BUCKET_MOBILE_RADIO = 7;
    public static final int POWER_BUCKET_MOBILE_RADIO = 7;
    public static final int NUMBER_STANDARD_POWER_BUCKETS = 8; // Buckets above this are custom.
    public static final int POWER_BUCKET_CAMERA = 8;
    public static final int POWER_BUCKET_PHONE = 9;
    public static final int NUMBER_STANDARD_POWER_BUCKETS = 10;  // Buckets above this are custom.


    @IntDef(prefix = {"POWER_BUCKET_"}, value = {
    @IntDef(prefix = {"POWER_BUCKET_"}, value = {
            POWER_BUCKET_UNKNOWN,
            POWER_BUCKET_UNKNOWN,
+14 −6
Original line number Original line Diff line number Diff line
@@ -245,6 +245,8 @@ public class MobileRadioPowerCalculatorTest {
        stats.noteNetworkInterfaceForTransports("cellular",
        stats.noteNetworkInterfaceForTransports("cellular",
                new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
                new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});


        stats.notePhoneOnLocked(9800, 9800);

        // Note application network activity
        // Note application network activity
        NetworkStats networkStats = new NetworkStats(10000, 1)
        NetworkStats networkStats = new NetworkStats(10000, 1)
                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
@@ -257,27 +259,33 @@ public class MobileRadioPowerCalculatorTest {


        mStatsRule.setTime(12_000, 12_000);
        mStatsRule.setTime(12_000, 12_000);


        MobileRadioPowerCalculator calculator =
        MobileRadioPowerCalculator mobileRadioPowerCalculator =
                new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
                new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());

        PhonePowerCalculator phonePowerCalculator =
        mStatsRule.apply(calculator);
                new PhonePowerCalculator(mStatsRule.getPowerProfile());
        mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator);


        UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
        UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
        assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
        assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
                .isWithin(PRECISION).of(1.53934);
                .isWithin(PRECISION).of(1.38541);
        assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
        assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);


        BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
        BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
        // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
        // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
        assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
        assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
                .isWithin(PRECISION).of(2.77778);
                .isWithin(PRECISION).of(2.5);
        assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
        assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);


        assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE))
                .isWithin(PRECISION).of(0.27778);
        assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE))
                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);

        BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
        BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
        assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
        assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
                .isWithin(PRECISION).of(1.53934);
                .isWithin(PRECISION).of(1.38541);
        assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
        assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
    }
    }
Loading