Loading services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +241 −38 Original line number Diff line number Diff line Loading @@ -310,6 +310,24 @@ public class BatteryStatsImpl extends BatteryStats { /** Container for Rail Energy Data stats. */ private final RailStats mTmpRailStats = new RailStats(); /** * Estimate UID modem power usage based on their estimated mobile radio active time. */ public static final int PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME = 1; /** * Estimate UID modem power consumption by proportionally attributing estimated Rx and Tx * power consumption individually. * ModemActivityInfo must be available. */ public static final int PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX = 2; @IntDef(flag = true, prefix = "PER_UID_MODEM_MODEL_", value = { PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME, PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX, }) @Retention(RetentionPolicy.SOURCE) public @interface PerUidModemPowerModel { } /** * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader}, * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader}, Loading Loading @@ -12038,8 +12056,7 @@ public class BatteryStatsImpl extends BatteryStats { } final SparseDoubleArray uidEstimatedConsumptionMah; if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null && mGlobalEnergyConsumerStats != null) { if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) { mGlobalEnergyConsumerStats.updateStandardBucket( EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC); uidEstimatedConsumptionMah = new SparseDoubleArray(); Loading @@ -12047,6 +12064,8 @@ public class BatteryStatsImpl extends BatteryStats { uidEstimatedConsumptionMah = null; } RxTxConsumption rxTxConsumption = null; boolean attributeWithModemActivityInfo = false; if (deltaInfo != null) { mHasModemReporting = true; mModemActivity.getOrCreateIdleTimeCounter() Loading Loading @@ -12092,7 +12111,11 @@ public class BatteryStatsImpl extends BatteryStats { mTmpRailStats.resetCellularTotalEnergyUsed(); } incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs); rxTxConsumption = incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs); attributeWithModemActivityInfo = mConstants.PER_UID_MODEM_MODEL == PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX && rxTxConsumption != null; } long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000); Loading Loading @@ -12156,12 +12179,23 @@ public class BatteryStatsImpl extends BatteryStats { (totalAppRadioTimeUs * appPackets) / totalPackets; u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs); if (uidEstimatedConsumptionMah != null) { final double uidConsumptionMah; if (attributeWithModemActivityInfo) { // Distribute measured mobile radio charge consumption based on // rx/tx packets and estimated rx/tx charge consumption. uidConsumptionMah = smearModemActivityInfoRxTxConsumptionMah( rxTxConsumption, entry.getRxPackets(), entry.getTxPackets(), totalRxPackets, totalTxPackets); } else { // Distribute mobile radio charge consumption based on app radio // active time if (uidEstimatedConsumptionMah != null) { uidEstimatedConsumptionMah.incrementValue(u.getUid(), uidConsumptionMah = mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah( appRadioTimeUs / 1000)); appRadioTimeUs / 1000); } uidEstimatedConsumptionMah.incrementValue(u.getUid(), uidConsumptionMah); } // Remove this app from the totals, so that we don't lose any time Loading Loading @@ -12199,13 +12233,25 @@ public class BatteryStatsImpl extends BatteryStats { mMobileRadioActiveUnknownCount.addCountLocked(1); } // Update the EnergyConsumerStats information. if (uidEstimatedConsumptionMah != null) { double totalEstimatedConsumptionMah = 0.0; if (attributeWithModemActivityInfo) { // Estimate inactive modem power consumption and combine with previously // estimated active power consumption for an estimate of total modem // power consumption. final long sleepTimeMs = deltaInfo.getSleepTimeMillis(); final long idleTimeMs = deltaInfo.getIdleTimeMillis(); final double inactiveConsumptionMah = mMobileRadioPowerCalculator.calcInactiveStatePowerMah(sleepTimeMs, idleTimeMs); totalEstimatedConsumptionMah += inactiveConsumptionMah; totalEstimatedConsumptionMah += rxTxConsumption.rxConsumptionMah; totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah; } else { // Estimate total active radio power consumption since last mark. final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked( final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000) / 1000; mMobileRadioActiveTimer.setMark(elapsedRealtimeMs); totalEstimatedConsumptionMah += Loading @@ -12214,16 +12260,15 @@ public class BatteryStatsImpl extends BatteryStats { // Estimate idle power consumption at each signal strength level final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length; for (int strengthLevel = 0; strengthLevel < numSignalStrengthLevels; strengthLevel++) { for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) { final long strengthLevelDurationMs = mPhoneSignalStrengthsTimer[strengthLevel].getTimeSinceMarkLocked( mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked( elapsedRealtimeMs * 1000) / 1000; mPhoneSignalStrengthsTimer[strengthLevel].setMark(elapsedRealtimeMs); mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs); totalEstimatedConsumptionMah += mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah( strengthLevelDurationMs, strengthLevel); strengthLevelDurationMs, lvl); } // Estimate total active radio power consumption since last mark. Loading @@ -12232,21 +12277,51 @@ public class BatteryStatsImpl extends BatteryStats { mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs); totalEstimatedConsumptionMah += mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs); } distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah, elapsedRealtimeMs); } } } } delta = null; private static class RxTxConsumption { public final double rxConsumptionMah; public final long rxDurationMs; public final double txConsumptionMah; public final long txDurationMs; /** * Represents the ratio between time spent transmitting and the total active time. */ public final double txToTotalRatio; RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs) { rxConsumptionMah = rxMah; rxDurationMs = rxMs; txConsumptionMah = txMah; txDurationMs = txMs; final long activeDurationMs = txDurationMs + rxDurationMs; if (activeDurationMs == 0) { txToTotalRatio = 0.0; } else { txToTotalRatio = ((double) txDurationMs) / activeDurationMs; } } } @GuardedBy("this") private void incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs) { final int infoSize = deltaInfo.getSpecificInfoLength(); @Nullable private RxTxConsumption incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs) { double rxConsumptionMah = 0.0; long rxDurationMs = 0; double txConsumptionMah = 0.0; long txDurationMs = 0; final int infoSize = deltaInfo.getSpecificInfoLength(); if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0) == AccessNetworkConstants.AccessNetworkType.UNKNOWN && deltaInfo.getSpecificInfoFrequencyRange(0) Loading Loading @@ -12296,6 +12371,16 @@ public class BatteryStatsImpl extends BatteryStats { + (totalLvlDurationMs / 2)) / totalLvlDurationMs; ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs); frequencyDurationMs += durationMs; if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent transmitting in a // particular state. final double txStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcTxStatePowerMah(rat, freq, level, proportionalTxDurationMs); txConsumptionMah += txStatePowerConsumptionMah; txDurationMs += proportionalTxDurationMs; } } final long totalRxDuration = deltaInfo.getReceiveTimeMillis(); // Smear HAL provided Rx power duration based on active modem Loading @@ -12305,6 +12390,16 @@ public class BatteryStatsImpl extends BatteryStats { (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs / 2)) / totalActiveTimeMs; ratStats.incrementRxDuration(freq, proportionalRxDurationMs); if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent receiving in a particular // state. final double rxStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcRxStatePowerMah(rat, freq, proportionalRxDurationMs); rxConsumptionMah += rxStatePowerConsumptionMah; rxDurationMs += proportionalRxDurationMs; } } } Loading @@ -12324,9 +12419,28 @@ public class BatteryStatsImpl extends BatteryStats { final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq); ratStats.incrementRxDuration(freq, rxTimeMs); if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent receiving in a particular state. final double rxStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcRxStatePowerMah(ratBucket, freq, rxTimeMs); rxConsumptionMah += rxStatePowerConsumptionMah; rxDurationMs += rxTimeMs; } final int numTxLvl = txTimesMs.length; for (int lvl = 0; lvl < numTxLvl; lvl++) { ratStats.incrementTxDuration(freq, lvl, txTimesMs[lvl]); final long txTimeMs = txTimesMs[lvl]; ratStats.incrementTxDuration(freq, lvl, txTimeMs); if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent transmitting in a particular // state. final double txStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcTxStatePowerMah(ratBucket, freq, lvl, txTimeMs); txConsumptionMah += txStatePowerConsumptionMah; txDurationMs += txTimeMs; } } } } Loading @@ -12336,6 +12450,45 @@ public class BatteryStatsImpl extends BatteryStats { if (ratStats == null) continue; ratStats.setMark(elapsedRealtimeMs); } if (isMobileRadioEnergyConsumerSupportedLocked()) { return new RxTxConsumption(rxConsumptionMah, rxDurationMs, txConsumptionMah, txDurationMs); } else { return null; } } /** * Smear modem Rx/Tx power consumption calculated from {@link ModemActivityInfo} using Rx/Tx * packets. * * @return the combine Rx/Tx smeared power consumption in milliamp-hours. */ private double smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption, long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets) { // Distribute measured mobile radio charge consumption based on // rx/tx packets and estimated rx/tx charge consumption. double consumptionMah = 0.0; if (totalRxPackets != 0) { // Proportionally distribute receive battery consumption. consumptionMah += rxTxConsumption.rxConsumptionMah * rxPackets / totalRxPackets; } if (totalTxPackets != 0 || (totalRxPackets != 0 && rxTxConsumption.txToTotalRatio != 0.0)) { // ModemActivityInfo Tx time represents time spent both transmitting and receiving. // There is currently no way to distinguish how many Rx packets were received during // Rx time vs Tx time. // Assumption: The number of packets received while transmitting is proportional // to the time spent transmitting over total active time. final double totalPacketsDuringTxTime = totalTxPackets + rxTxConsumption.txToTotalRatio * totalRxPackets; final double packetsDuringTxTime = txPackets + rxTxConsumption.txToTotalRatio * rxPackets; consumptionMah += rxTxConsumption.txConsumptionMah * packetsDuringTxTime / totalPacketsDuringTxTime; } return consumptionMah; } /** Loading Loading @@ -14844,6 +14997,13 @@ public class BatteryStatsImpl extends BatteryStats { } } @GuardedBy("this") private boolean isMobileRadioEnergyConsumerSupportedLocked() { if (mGlobalEnergyConsumerStats == null) return false; return mGlobalEnergyConsumerStats.isStandardBucketSupported( EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO); } @NonNull private static String[] getBatteryConsumerProcessStateNames() { String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT]; Loading Loading @@ -14879,6 +15039,40 @@ public class BatteryStatsImpl extends BatteryStats { "battery_charged_delay_ms"; public static final String KEY_RECORD_USAGE_HISTORY = "record_usage_history"; public static final String KEY_PER_UID_MODEM_POWER_MODEL = "per_uid_modem_power_model"; public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME = "mobile_radio_active_time"; public static final String PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME = "modem_activity_info_rx_tx"; /** Convert {@link PerUidModemPowerModel} to string */ public String getPerUidModemModelName(@PerUidModemPowerModel int model) { switch(model) { case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME: return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME; case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX: return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME; default: Slog.w(TAG, "Unexpected per uid modem model (" + model + ")"); return "unknown_" + model; } } /** Convert string to {@link PerUidModemPowerModel} */ @PerUidModemPowerModel public int getPerUidModemModel(String name) { switch(name) { case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME: return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME; case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME: return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX; default: Slog.w(TAG, "Unexpected per uid modem model name (" + name + ")"); return DEFAULT_PER_UID_MODEM_MODEL; } } private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true; private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000; Loading @@ -14892,6 +15086,9 @@ public class BatteryStatsImpl extends BatteryStats { 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 boolean DEFAULT_RECORD_USAGE_HISTORY = false; @PerUidModemPowerModel private static final int DEFAULT_PER_UID_MODEM_MODEL = PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX; 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 Loading @@ -14908,6 +15105,7 @@ public class BatteryStatsImpl extends BatteryStats { public int MAX_HISTORY_BUFFER; /*Bytes*/ 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; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); Loading Loading @@ -14985,6 +15183,9 @@ public class BatteryStatsImpl extends BatteryStats { * 1024; RECORD_USAGE_HISTORY = mParser.getBoolean( KEY_RECORD_USAGE_HISTORY, DEFAULT_RECORD_USAGE_HISTORY); final String perUidModemModel = mParser.getString(KEY_PER_UID_MODEM_POWER_MODEL, ""); PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel); updateBatteryChargedDelayMsLocked(); Loading Loading @@ -15053,6 +15254,8 @@ public class BatteryStatsImpl extends BatteryStats { pw.println(BATTERY_CHARGED_DELAY_MS); pw.print(KEY_RECORD_USAGE_HISTORY); pw.print("="); pw.println(RECORD_USAGE_HISTORY); pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("="); pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL)); } } services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java +26 −7 Original line number Diff line number Diff line Loading @@ -270,24 +270,27 @@ public class MobileRadioPowerCalculator extends PowerCalculator { // Calculate the inactive modem power consumption. final BatteryStats.ControllerActivityCounter modemActivity = batteryStats.getModemControllerActivity(); if (modemActivity != null && (mSleepPowerEstimator != null || mIdlePowerEstimator != null)) { double inactivePowerMah = Double.NaN; if (modemActivity != null) { final long sleepDurationMs = modemActivity.getSleepTimeCounter().getCountLocked( BatteryStats.STATS_SINCE_CHARGED); total.remainingPowerMah += mSleepPowerEstimator.calculatePower(sleepDurationMs); final long idleDurationMs = modemActivity.getIdleTimeCounter().getCountLocked( BatteryStats.STATS_SINCE_CHARGED); total.remainingPowerMah += mIdlePowerEstimator.calculatePower(idleDurationMs); } else { inactivePowerMah = calcInactiveStatePowerMah(sleepDurationMs, idleDurationMs); } if (Double.isNaN(inactivePowerMah)) { // Modem activity counters unavailable. Use legacy calculations for inactive usage. final long scanningTimeMs = batteryStats.getPhoneSignalScanningTime(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000; total.remainingPowerMah += calcScanTimePowerMah(scanningTimeMs); inactivePowerMah = calcScanTimePowerMah(scanningTimeMs); for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) { long strengthTimeMs = batteryStats.getPhoneSignalStrengthTime(i, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000; total.remainingPowerMah += calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i); inactivePowerMah += calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i); } } if (!Double.isNaN(inactivePowerMah)) { total.remainingPowerMah += inactivePowerMah; } } Loading Loading @@ -508,6 +511,22 @@ public class MobileRadioPowerCalculator extends PowerCalculator { return consumptionMah; } /** * Calculates active transmit radio power consumption (in milliamp-hours) from the given state's * duration. */ public double calcInactiveStatePowerMah(long sleepDurationMs, long idleDurationMs) { if (mSleepPowerEstimator == null || mIdlePowerEstimator == null) return Double.NaN; final double sleepConsumptionMah = mSleepPowerEstimator.calculatePower(sleepDurationMs); final double idleConsumptionMah = mIdlePowerEstimator.calculatePower(idleDurationMs); if (DEBUG) { Log.d(TAG, "Calculated sleep consumption " + sleepConsumptionMah + " mAH from a duration of " + sleepDurationMs + " ms and idle consumption " + idleConsumptionMah + " mAH from a duration of " + idleDurationMs); } return sleepConsumptionMah + idleConsumptionMah; } /** * Calculates active radio power consumption (in milliamp-hours) from active radio duration. */ Loading services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java +7 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,13 @@ public class BatteryUsageStatsRule implements TestRule { return this; } public BatteryUsageStatsRule setPerUidModemModel(int perUidModemModel) { synchronized (mBatteryStats) { mBatteryStats.setPerUidModemModel(perUidModemModel); } return this; } /** Call only after setting the power profile information. */ public BatteryUsageStatsRule initMeasuredEnergyStatsLocked() { return initMeasuredEnergyStatsLocked(new String[0]); Loading services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java +260 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java +7 −0 Original line number Diff line number Diff line Loading @@ -213,6 +213,13 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { return this; } @GuardedBy("this") public MockBatteryStatsImpl setPerUidModemModel(int perUidModemModel) { mConstants.PER_UID_MODEM_MODEL = perUidModemModel; mConstants.onChange(); return this; } public int getAndClearExternalStatsSyncFlags() { final int flags = mExternalStatsSync.flags; mExternalStatsSync.flags = 0; Loading Loading
services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +241 −38 Original line number Diff line number Diff line Loading @@ -310,6 +310,24 @@ public class BatteryStatsImpl extends BatteryStats { /** Container for Rail Energy Data stats. */ private final RailStats mTmpRailStats = new RailStats(); /** * Estimate UID modem power usage based on their estimated mobile radio active time. */ public static final int PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME = 1; /** * Estimate UID modem power consumption by proportionally attributing estimated Rx and Tx * power consumption individually. * ModemActivityInfo must be available. */ public static final int PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX = 2; @IntDef(flag = true, prefix = "PER_UID_MODEM_MODEL_", value = { PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME, PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX, }) @Retention(RetentionPolicy.SOURCE) public @interface PerUidModemPowerModel { } /** * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader}, * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader}, Loading Loading @@ -12038,8 +12056,7 @@ public class BatteryStatsImpl extends BatteryStats { } final SparseDoubleArray uidEstimatedConsumptionMah; if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null && mGlobalEnergyConsumerStats != null) { if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) { mGlobalEnergyConsumerStats.updateStandardBucket( EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC); uidEstimatedConsumptionMah = new SparseDoubleArray(); Loading @@ -12047,6 +12064,8 @@ public class BatteryStatsImpl extends BatteryStats { uidEstimatedConsumptionMah = null; } RxTxConsumption rxTxConsumption = null; boolean attributeWithModemActivityInfo = false; if (deltaInfo != null) { mHasModemReporting = true; mModemActivity.getOrCreateIdleTimeCounter() Loading Loading @@ -12092,7 +12111,11 @@ public class BatteryStatsImpl extends BatteryStats { mTmpRailStats.resetCellularTotalEnergyUsed(); } incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs); rxTxConsumption = incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs); attributeWithModemActivityInfo = mConstants.PER_UID_MODEM_MODEL == PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX && rxTxConsumption != null; } long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000); Loading Loading @@ -12156,12 +12179,23 @@ public class BatteryStatsImpl extends BatteryStats { (totalAppRadioTimeUs * appPackets) / totalPackets; u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs); if (uidEstimatedConsumptionMah != null) { final double uidConsumptionMah; if (attributeWithModemActivityInfo) { // Distribute measured mobile radio charge consumption based on // rx/tx packets and estimated rx/tx charge consumption. uidConsumptionMah = smearModemActivityInfoRxTxConsumptionMah( rxTxConsumption, entry.getRxPackets(), entry.getTxPackets(), totalRxPackets, totalTxPackets); } else { // Distribute mobile radio charge consumption based on app radio // active time if (uidEstimatedConsumptionMah != null) { uidEstimatedConsumptionMah.incrementValue(u.getUid(), uidConsumptionMah = mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah( appRadioTimeUs / 1000)); appRadioTimeUs / 1000); } uidEstimatedConsumptionMah.incrementValue(u.getUid(), uidConsumptionMah); } // Remove this app from the totals, so that we don't lose any time Loading Loading @@ -12199,13 +12233,25 @@ public class BatteryStatsImpl extends BatteryStats { mMobileRadioActiveUnknownCount.addCountLocked(1); } // Update the EnergyConsumerStats information. if (uidEstimatedConsumptionMah != null) { double totalEstimatedConsumptionMah = 0.0; if (attributeWithModemActivityInfo) { // Estimate inactive modem power consumption and combine with previously // estimated active power consumption for an estimate of total modem // power consumption. final long sleepTimeMs = deltaInfo.getSleepTimeMillis(); final long idleTimeMs = deltaInfo.getIdleTimeMillis(); final double inactiveConsumptionMah = mMobileRadioPowerCalculator.calcInactiveStatePowerMah(sleepTimeMs, idleTimeMs); totalEstimatedConsumptionMah += inactiveConsumptionMah; totalEstimatedConsumptionMah += rxTxConsumption.rxConsumptionMah; totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah; } else { // Estimate total active radio power consumption since last mark. final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked( final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000) / 1000; mMobileRadioActiveTimer.setMark(elapsedRealtimeMs); totalEstimatedConsumptionMah += Loading @@ -12214,16 +12260,15 @@ public class BatteryStatsImpl extends BatteryStats { // Estimate idle power consumption at each signal strength level final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length; for (int strengthLevel = 0; strengthLevel < numSignalStrengthLevels; strengthLevel++) { for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) { final long strengthLevelDurationMs = mPhoneSignalStrengthsTimer[strengthLevel].getTimeSinceMarkLocked( mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked( elapsedRealtimeMs * 1000) / 1000; mPhoneSignalStrengthsTimer[strengthLevel].setMark(elapsedRealtimeMs); mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs); totalEstimatedConsumptionMah += mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah( strengthLevelDurationMs, strengthLevel); strengthLevelDurationMs, lvl); } // Estimate total active radio power consumption since last mark. Loading @@ -12232,21 +12277,51 @@ public class BatteryStatsImpl extends BatteryStats { mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs); totalEstimatedConsumptionMah += mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs); } distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah, elapsedRealtimeMs); } } } } delta = null; private static class RxTxConsumption { public final double rxConsumptionMah; public final long rxDurationMs; public final double txConsumptionMah; public final long txDurationMs; /** * Represents the ratio between time spent transmitting and the total active time. */ public final double txToTotalRatio; RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs) { rxConsumptionMah = rxMah; rxDurationMs = rxMs; txConsumptionMah = txMah; txDurationMs = txMs; final long activeDurationMs = txDurationMs + rxDurationMs; if (activeDurationMs == 0) { txToTotalRatio = 0.0; } else { txToTotalRatio = ((double) txDurationMs) / activeDurationMs; } } } @GuardedBy("this") private void incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs) { final int infoSize = deltaInfo.getSpecificInfoLength(); @Nullable private RxTxConsumption incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs) { double rxConsumptionMah = 0.0; long rxDurationMs = 0; double txConsumptionMah = 0.0; long txDurationMs = 0; final int infoSize = deltaInfo.getSpecificInfoLength(); if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0) == AccessNetworkConstants.AccessNetworkType.UNKNOWN && deltaInfo.getSpecificInfoFrequencyRange(0) Loading Loading @@ -12296,6 +12371,16 @@ public class BatteryStatsImpl extends BatteryStats { + (totalLvlDurationMs / 2)) / totalLvlDurationMs; ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs); frequencyDurationMs += durationMs; if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent transmitting in a // particular state. final double txStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcTxStatePowerMah(rat, freq, level, proportionalTxDurationMs); txConsumptionMah += txStatePowerConsumptionMah; txDurationMs += proportionalTxDurationMs; } } final long totalRxDuration = deltaInfo.getReceiveTimeMillis(); // Smear HAL provided Rx power duration based on active modem Loading @@ -12305,6 +12390,16 @@ public class BatteryStatsImpl extends BatteryStats { (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs / 2)) / totalActiveTimeMs; ratStats.incrementRxDuration(freq, proportionalRxDurationMs); if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent receiving in a particular // state. final double rxStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcRxStatePowerMah(rat, freq, proportionalRxDurationMs); rxConsumptionMah += rxStatePowerConsumptionMah; rxDurationMs += proportionalRxDurationMs; } } } Loading @@ -12324,9 +12419,28 @@ public class BatteryStatsImpl extends BatteryStats { final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq); ratStats.incrementRxDuration(freq, rxTimeMs); if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent receiving in a particular state. final double rxStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcRxStatePowerMah(ratBucket, freq, rxTimeMs); rxConsumptionMah += rxStatePowerConsumptionMah; rxDurationMs += rxTimeMs; } final int numTxLvl = txTimesMs.length; for (int lvl = 0; lvl < numTxLvl; lvl++) { ratStats.incrementTxDuration(freq, lvl, txTimesMs[lvl]); final long txTimeMs = txTimesMs[lvl]; ratStats.incrementTxDuration(freq, lvl, txTimeMs); if (isMobileRadioEnergyConsumerSupportedLocked()) { // Accumulate the power cost of time spent transmitting in a particular // state. final double txStatePowerConsumptionMah = mMobileRadioPowerCalculator.calcTxStatePowerMah(ratBucket, freq, lvl, txTimeMs); txConsumptionMah += txStatePowerConsumptionMah; txDurationMs += txTimeMs; } } } } Loading @@ -12336,6 +12450,45 @@ public class BatteryStatsImpl extends BatteryStats { if (ratStats == null) continue; ratStats.setMark(elapsedRealtimeMs); } if (isMobileRadioEnergyConsumerSupportedLocked()) { return new RxTxConsumption(rxConsumptionMah, rxDurationMs, txConsumptionMah, txDurationMs); } else { return null; } } /** * Smear modem Rx/Tx power consumption calculated from {@link ModemActivityInfo} using Rx/Tx * packets. * * @return the combine Rx/Tx smeared power consumption in milliamp-hours. */ private double smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption, long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets) { // Distribute measured mobile radio charge consumption based on // rx/tx packets and estimated rx/tx charge consumption. double consumptionMah = 0.0; if (totalRxPackets != 0) { // Proportionally distribute receive battery consumption. consumptionMah += rxTxConsumption.rxConsumptionMah * rxPackets / totalRxPackets; } if (totalTxPackets != 0 || (totalRxPackets != 0 && rxTxConsumption.txToTotalRatio != 0.0)) { // ModemActivityInfo Tx time represents time spent both transmitting and receiving. // There is currently no way to distinguish how many Rx packets were received during // Rx time vs Tx time. // Assumption: The number of packets received while transmitting is proportional // to the time spent transmitting over total active time. final double totalPacketsDuringTxTime = totalTxPackets + rxTxConsumption.txToTotalRatio * totalRxPackets; final double packetsDuringTxTime = txPackets + rxTxConsumption.txToTotalRatio * rxPackets; consumptionMah += rxTxConsumption.txConsumptionMah * packetsDuringTxTime / totalPacketsDuringTxTime; } return consumptionMah; } /** Loading Loading @@ -14844,6 +14997,13 @@ public class BatteryStatsImpl extends BatteryStats { } } @GuardedBy("this") private boolean isMobileRadioEnergyConsumerSupportedLocked() { if (mGlobalEnergyConsumerStats == null) return false; return mGlobalEnergyConsumerStats.isStandardBucketSupported( EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO); } @NonNull private static String[] getBatteryConsumerProcessStateNames() { String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT]; Loading Loading @@ -14879,6 +15039,40 @@ public class BatteryStatsImpl extends BatteryStats { "battery_charged_delay_ms"; public static final String KEY_RECORD_USAGE_HISTORY = "record_usage_history"; public static final String KEY_PER_UID_MODEM_POWER_MODEL = "per_uid_modem_power_model"; public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME = "mobile_radio_active_time"; public static final String PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME = "modem_activity_info_rx_tx"; /** Convert {@link PerUidModemPowerModel} to string */ public String getPerUidModemModelName(@PerUidModemPowerModel int model) { switch(model) { case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME: return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME; case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX: return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME; default: Slog.w(TAG, "Unexpected per uid modem model (" + model + ")"); return "unknown_" + model; } } /** Convert string to {@link PerUidModemPowerModel} */ @PerUidModemPowerModel public int getPerUidModemModel(String name) { switch(name) { case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME: return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME; case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME: return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX; default: Slog.w(TAG, "Unexpected per uid modem model name (" + name + ")"); return DEFAULT_PER_UID_MODEM_MODEL; } } private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true; private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000; Loading @@ -14892,6 +15086,9 @@ public class BatteryStatsImpl extends BatteryStats { 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 boolean DEFAULT_RECORD_USAGE_HISTORY = false; @PerUidModemPowerModel private static final int DEFAULT_PER_UID_MODEM_MODEL = PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX; 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 Loading @@ -14908,6 +15105,7 @@ public class BatteryStatsImpl extends BatteryStats { public int MAX_HISTORY_BUFFER; /*Bytes*/ 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; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); Loading Loading @@ -14985,6 +15183,9 @@ public class BatteryStatsImpl extends BatteryStats { * 1024; RECORD_USAGE_HISTORY = mParser.getBoolean( KEY_RECORD_USAGE_HISTORY, DEFAULT_RECORD_USAGE_HISTORY); final String perUidModemModel = mParser.getString(KEY_PER_UID_MODEM_POWER_MODEL, ""); PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel); updateBatteryChargedDelayMsLocked(); Loading Loading @@ -15053,6 +15254,8 @@ public class BatteryStatsImpl extends BatteryStats { pw.println(BATTERY_CHARGED_DELAY_MS); pw.print(KEY_RECORD_USAGE_HISTORY); pw.print("="); pw.println(RECORD_USAGE_HISTORY); pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("="); pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL)); } }
services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java +26 −7 Original line number Diff line number Diff line Loading @@ -270,24 +270,27 @@ public class MobileRadioPowerCalculator extends PowerCalculator { // Calculate the inactive modem power consumption. final BatteryStats.ControllerActivityCounter modemActivity = batteryStats.getModemControllerActivity(); if (modemActivity != null && (mSleepPowerEstimator != null || mIdlePowerEstimator != null)) { double inactivePowerMah = Double.NaN; if (modemActivity != null) { final long sleepDurationMs = modemActivity.getSleepTimeCounter().getCountLocked( BatteryStats.STATS_SINCE_CHARGED); total.remainingPowerMah += mSleepPowerEstimator.calculatePower(sleepDurationMs); final long idleDurationMs = modemActivity.getIdleTimeCounter().getCountLocked( BatteryStats.STATS_SINCE_CHARGED); total.remainingPowerMah += mIdlePowerEstimator.calculatePower(idleDurationMs); } else { inactivePowerMah = calcInactiveStatePowerMah(sleepDurationMs, idleDurationMs); } if (Double.isNaN(inactivePowerMah)) { // Modem activity counters unavailable. Use legacy calculations for inactive usage. final long scanningTimeMs = batteryStats.getPhoneSignalScanningTime(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000; total.remainingPowerMah += calcScanTimePowerMah(scanningTimeMs); inactivePowerMah = calcScanTimePowerMah(scanningTimeMs); for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) { long strengthTimeMs = batteryStats.getPhoneSignalStrengthTime(i, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000; total.remainingPowerMah += calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i); inactivePowerMah += calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i); } } if (!Double.isNaN(inactivePowerMah)) { total.remainingPowerMah += inactivePowerMah; } } Loading Loading @@ -508,6 +511,22 @@ public class MobileRadioPowerCalculator extends PowerCalculator { return consumptionMah; } /** * Calculates active transmit radio power consumption (in milliamp-hours) from the given state's * duration. */ public double calcInactiveStatePowerMah(long sleepDurationMs, long idleDurationMs) { if (mSleepPowerEstimator == null || mIdlePowerEstimator == null) return Double.NaN; final double sleepConsumptionMah = mSleepPowerEstimator.calculatePower(sleepDurationMs); final double idleConsumptionMah = mIdlePowerEstimator.calculatePower(idleDurationMs); if (DEBUG) { Log.d(TAG, "Calculated sleep consumption " + sleepConsumptionMah + " mAH from a duration of " + sleepDurationMs + " ms and idle consumption " + idleConsumptionMah + " mAH from a duration of " + idleDurationMs); } return sleepConsumptionMah + idleConsumptionMah; } /** * Calculates active radio power consumption (in milliamp-hours) from active radio duration. */ Loading
services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java +7 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,13 @@ public class BatteryUsageStatsRule implements TestRule { return this; } public BatteryUsageStatsRule setPerUidModemModel(int perUidModemModel) { synchronized (mBatteryStats) { mBatteryStats.setPerUidModemModel(perUidModemModel); } return this; } /** Call only after setting the power profile information. */ public BatteryUsageStatsRule initMeasuredEnergyStatsLocked() { return initMeasuredEnergyStatsLocked(new String[0]); Loading
services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java +260 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java +7 −0 Original line number Diff line number Diff line Loading @@ -213,6 +213,13 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { return this; } @GuardedBy("this") public MockBatteryStatsImpl setPerUidModemModel(int perUidModemModel) { mConstants.PER_UID_MODEM_MODEL = perUidModemModel; mConstants.onChange(); return this; } public int getAndClearExternalStatsSyncFlags() { final int flags = mExternalStatsSync.flags; mExternalStatsSync.flags = 0; Loading