From 4789053d52cdb92c44ccee76c7e4babc2bbbb3dc Mon Sep 17 00:00:00 2001 From: Michael Wachenschwanz Date: Thu, 12 Jan 2023 23:19:05 -0800 Subject: [PATCH] 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 --- core/java/android/os/BatteryStats.java | 9 +++ .../internal/power/EnergyConsumerStats.java | 4 +- .../stats/BatteryExternalStatsWorker.java | 1 + .../server/power/stats/BatteryStatsImpl.java | 52 ++++++++++-- .../power/stats/PhonePowerCalculator.java | 25 ++++-- .../stats/MobileRadioPowerCalculatorTest.java | 81 ++++++++++++++----- 6 files changed, 135 insertions(+), 37 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 547d406751f95..083b4f6a3bf54 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -2903,6 +2903,15 @@ public abstract class BatteryStats { */ public abstract long getMobileRadioEnergyConsumptionUC(); + /** + * 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 * device power measurement data. diff --git a/core/java/com/android/internal/power/EnergyConsumerStats.java b/core/java/com/android/internal/power/EnergyConsumerStats.java index 8cf17cdaab83b..e2098dd11531b 100644 --- a/core/java/com/android/internal/power/EnergyConsumerStats.java +++ b/core/java/com/android/internal/power/EnergyConsumerStats.java @@ -59,7 +59,8 @@ public class EnergyConsumerStats { public static final int POWER_BUCKET_GNSS = 6; public static final int POWER_BUCKET_MOBILE_RADIO = 7; public static final int POWER_BUCKET_CAMERA = 8; - public static final int NUMBER_STANDARD_POWER_BUCKETS = 9; // Buckets above this are custom. + 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 = { POWER_BUCKET_UNKNOWN, @@ -72,6 +73,7 @@ public class EnergyConsumerStats { POWER_BUCKET_GNSS, POWER_BUCKET_MOBILE_RADIO, POWER_BUCKET_CAMERA, + POWER_BUCKET_PHONE, }) @Retention(RetentionPolicy.SOURCE) public @interface StandardPowerBucket { diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java index 3fcb08a580007..2fbf3fbc6881e 100644 --- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java @@ -900,6 +900,7 @@ public class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStat break; case EnergyConsumerType.MOBILE_RADIO: buckets[EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO] = true; + buckets[EnergyConsumerStats.POWER_BUCKET_PHONE] = true; break; case EnergyConsumerType.DISPLAY: buckets[EnergyConsumerStats.POWER_BUCKET_SCREEN_ON] = true; diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index f9482dd2b0287..2fb5ceccf6a37 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -178,7 +178,7 @@ public class BatteryStatsImpl extends BatteryStats { // TODO: remove "tcp" from network methods, since we measure total stats. // Current on-disk Parcel version. Must be updated when the format of the parcelable changes - public static final int VERSION = 211; + public static final int VERSION = 212; // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks @@ -5740,6 +5740,9 @@ public class BatteryStatsImpl extends BatteryStats { HistoryItem.STATE2_PHONE_IN_CALL_FLAG); mPhoneOn = true; mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs); + if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) { + scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO); + } } } @@ -5750,6 +5753,7 @@ public class BatteryStatsImpl extends BatteryStats { HistoryItem.STATE2_PHONE_IN_CALL_FLAG); mPhoneOn = false; mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs); + scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO); } } @@ -7423,6 +7427,12 @@ public class BatteryStatsImpl extends BatteryStats { return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO); } + @GuardedBy("this") + @Override + public long getPhoneEnergyConsumptionUC() { + return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_PHONE); + } + @GuardedBy("this") @Override public long getScreenOnEnergyConsumptionUC() { @@ -12051,17 +12061,36 @@ public class BatteryStatsImpl extends BatteryStats { } 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) { return; } final SparseDoubleArray uidEstimatedConsumptionMah; + final long dataConsumedChargeUC; if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) { + // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the + // numerator for long rounding. + final long phoneConsumedChargeUC = + (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2) + / totalRadioDurationMs; + dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC; + mGlobalEnergyConsumerStats.updateStandardBucket( - EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC); + EnergyConsumerStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC); + mGlobalEnergyConsumerStats.updateStandardBucket( + EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC); uidEstimatedConsumptionMah = new SparseDoubleArray(); } else { uidEstimatedConsumptionMah = null; + dataConsumedChargeUC = POWER_DATA_UNAVAILABLE; } RxTxConsumption rxTxConsumption = null; @@ -12250,13 +12279,9 @@ public class BatteryStatsImpl extends BatteryStats { totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah; } else { // Estimate total active radio power consumption since last mark. - final long totalRadioTimeMs = - mMobileRadioActiveTimer.getTimeSinceMarkLocked( - elapsedRealtimeMs * 1000) / 1000; - mMobileRadioActiveTimer.setMark(elapsedRealtimeMs); totalEstimatedConsumptionMah += mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah( - totalRadioTimeMs); + totalRadioDurationMs); // Estimate idle power consumption at each signal strength level final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length; @@ -12279,7 +12304,7 @@ public class BatteryStatsImpl extends BatteryStats { mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs); } distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, - consumedChargeUC, uidEstimatedConsumptionMah, + dataConsumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah, elapsedRealtimeMs); } } @@ -15041,6 +15066,8 @@ public class BatteryStatsImpl extends BatteryStats { "record_usage_history"; public static final String KEY_PER_UID_MODEM_POWER_MODEL = "per_uid_modem_power_model"; + public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION = + "phone_on_external_stats_collection"; public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME = "mobile_radio_active_time"; @@ -15089,6 +15116,7 @@ public class BatteryStatsImpl extends BatteryStats { @PerUidModemPowerModel private static final int DEFAULT_PER_UID_MODEM_MODEL = PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX; + private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true; 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 @@ -15106,6 +15134,8 @@ public class BatteryStatsImpl extends BatteryStats { public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS; public boolean RECORD_USAGE_HISTORY = DEFAULT_RECORD_USAGE_HISTORY; public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL; + public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION = + DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -15187,6 +15217,10 @@ public class BatteryStatsImpl extends BatteryStats { ""); PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel); + PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean( + KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION, + DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION); + updateBatteryChargedDelayMsLocked(); onChange(); @@ -15256,6 +15290,8 @@ public class BatteryStatsImpl extends BatteryStats { pw.println(RECORD_USAGE_HISTORY); pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("="); pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL)); + pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("="); + pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION); } } diff --git a/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java b/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java index bb893331c8cd7..79ec6e27d9f64 100644 --- a/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java +++ b/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java @@ -42,14 +42,27 @@ public class PhonePowerCalculator extends PowerCalculator { @Override public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { + final long energyConsumerUC = batteryStats.getPhoneEnergyConsumptionUC(); + final int powerModel = getPowerModel(energyConsumerUC, query); + final long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000; - final double phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs); - if (phoneOnPower != 0) { - builder.getAggregateBatteryConsumerBuilder( - BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower) - .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs); + + final double phoneOnPower; + switch (powerModel) { + case BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION: + phoneOnPower = uCtoMah(energyConsumerUC); + break; + case BatteryConsumer.POWER_MODEL_POWER_PROFILE: + default: + phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs); } + + if (phoneOnPower == 0.0) return; + + builder.getAggregateBatteryConsumerBuilder( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) + .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower, powerModel) + .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs); } } diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java index d059472d677a9..2e647c4ef78da 100644 --- a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java +++ b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java @@ -602,6 +602,8 @@ public class MobileRadioPowerCalculatorTest { stats.noteNetworkInterfaceForTransports("cellular", new int[]{NetworkCapabilities.TRANSPORT_CELLULAR}); + stats.notePhoneOnLocked(9800, 9800); + // Note application network activity NetworkStats networkStats = new NetworkStats(10000, 1) .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0, @@ -614,27 +616,34 @@ public class MobileRadioPowerCalculatorTest { mStatsRule.setTime(12_000, 12_000); - MobileRadioPowerCalculator calculator = + MobileRadioPowerCalculator mobileRadioPowerCalculator = new MobileRadioPowerCalculator(mStatsRule.getPowerProfile()); - - mStatsRule.apply(calculator); + PhonePowerCalculator phonePowerCalculator = + new PhonePowerCalculator(mStatsRule.getPowerProfile()); + mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator); BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer(); // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh + // 1800ms data duration / 2000 total duration * 2.77778 mAh = 2.5 + // 200ms phone on duration / 2000 total duration * 2.77778 mAh = 0.27777 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)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); + assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE)) + .isWithin(PRECISION).of(0.27778); + assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE)) + .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer(); 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)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID); 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)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); } @@ -649,6 +658,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, -1, + 0, 0); + // Scan for a cell stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE, TelephonyManager.SIM_STATE_READY, @@ -686,6 +698,9 @@ public class MobileRadioPowerCalculatorTest { stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333); when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE); stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666); + + stats.notePhoneOnLocked(9000, 9000); + when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD); stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110); @@ -732,16 +747,24 @@ public class MobileRadioPowerCalculatorTest { mStatsRule.setTime(10_000, 10_000); - MobileRadioPowerCalculator calculator = + MobileRadioPowerCalculator mobileRadioPowerCalculator = new MobileRadioPowerCalculator(mStatsRule.getPowerProfile()); - - mStatsRule.apply(calculator); + PhonePowerCalculator phonePowerCalculator = + new PhonePowerCalculator(mStatsRule.getPowerProfile()); + mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator); BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer(); + // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh + // 9000ms data duration / 10000 total duration * 2.77778 mAh = 2.5 + // 1000ms phone on duration / 10000 total duration * 2.77778 mAh = 0.27777 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)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); + assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE)) + .isWithin(PRECISION).of(0.27778); + assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE)) + .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); // CDMA2000 [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration // [720, 1080, 1440, 1800, 2160, 1440] mA . [10, 11, 12, 13, 14, 15] ms = 111600 mA-ms @@ -767,10 +790,10 @@ public class MobileRadioPowerCalculatorTest { // _________________ // = 5177753 mA-ms estimated total consumption // - // 2.77778 mA-h measured total consumption * 3957753 / 5177753 = 2.123268 mA-h + // 2.5 mA-h measured total consumption * 3957753 / 5177753 = 1.91094 mA-h BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer(); assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(2.123268); + .isWithin(PRECISION).of(1.91094); assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); @@ -791,17 +814,17 @@ public class MobileRadioPowerCalculatorTest { // 3333768 * 133.33333 / 204.44444 = 2174196.52174 mA-ms App 1 Tx Power Consumption // // Total App Power consumption * Ratio of App 1 / Total Estimated Power Consumption - // 2.123268 * (467988.75 + 2174196.52174) / 3957753 = 1.41749 App 1 Power Consumption + // 1.91094 * (467988.75 + 2174196.52174) / 3957753 = 1.27574 App 1 Power Consumption UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID); assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(1.41749); + .isWithin(PRECISION).of(1.27574); assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); // Rest should go to the other app UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2); assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(0.705778); + .isWithin(PRECISION).of(0.63520); assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); } @@ -814,6 +837,9 @@ public class MobileRadioPowerCalculatorTest { .initMeasuredEnergyStatsLocked(); BatteryStatsImpl stats = mStatsRule.getBatteryStats(); + stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, -1, + 0, 0); + // Scan for a cell stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE, TelephonyManager.SIM_STATE_READY, @@ -851,6 +877,9 @@ public class MobileRadioPowerCalculatorTest { stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333); when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE); stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666); + + stats.notePhoneOnLocked(9000, 9000); + when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD); stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110); when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GREAT); @@ -868,30 +897,38 @@ public class MobileRadioPowerCalculatorTest { mStatsRule.setTime(12_000, 12_000); - MobileRadioPowerCalculator calculator = - new MobileRadioPowerCalculator(mStatsRule.getPowerProfile()); - mStatsRule.apply(calculator); + MobileRadioPowerCalculator mobileRadioPowerCalculator = + new MobileRadioPowerCalculator(mStatsRule.getPowerProfile()); + PhonePowerCalculator phonePowerCalculator = + new PhonePowerCalculator(mStatsRule.getPowerProfile()); + mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator); BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer(); // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh + // 9000ms data duration / 10000 total duration * 2.77778 mAh = 2.5 + // 1000ms phone on duration / 10000 total duration * 2.77778 mAh = 0.27777 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)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); + assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE)) + .isWithin(PRECISION).of(0.27778); + assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE)) + .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer(); // Estimated Rx/Tx modem consumption = 0.94 mAh // Estimated total modem consumption = 1.27888 mAh - // 2.77778 * 0.94 / 1.27888 = 2.04170 mAh + // 2.5 * 0.94 / 1.27888 = 1.83754 mAh assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(2.04170); + .isWithin(PRECISION).of(1.83754); assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID); assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(2.04170); + .isWithin(PRECISION).of(1.83754); assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION); }