Attribute per Uid Modem Energy Consumption with Rx/Tx data.
If a device has Modem Energy Consumption data alongside ModemActivityInfo, the per Uid attribution of the Modem Energy Consumption is further refined using granular time-in-state info of ModemActivityInfo. Fixes: 259154416 Test: atest MobileRadioPowerCalculatorTest Change-Id: I085fb52fba6fcc131138997db5e631c210d909f0
This commit is contained in:
@@ -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},
|
||||
@@ -12003,8 +12021,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();
|
||||
@@ -12012,6 +12029,8 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
uidEstimatedConsumptionMah = null;
|
||||
}
|
||||
|
||||
RxTxConsumption rxTxConsumption = null;
|
||||
boolean attributeWithModemActivityInfo = false;
|
||||
if (deltaInfo != null) {
|
||||
mHasModemReporting = true;
|
||||
mModemActivity.getOrCreateIdleTimeCounter()
|
||||
@@ -12057,7 +12076,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);
|
||||
@@ -12121,12 +12144,23 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
(totalAppRadioTimeUs * appPackets) / totalPackets;
|
||||
u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
|
||||
|
||||
// Distribute mobile radio charge consumption based on app radio
|
||||
// active time
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
uidEstimatedConsumptionMah.incrementValue(u.getUid(),
|
||||
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
|
||||
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
|
||||
@@ -12164,54 +12198,95 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
mMobileRadioActiveUnknownCount.addCountLocked(1);
|
||||
}
|
||||
|
||||
|
||||
// Update the EnergyConsumerStats information.
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
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 +=
|
||||
mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
|
||||
totalRadioTimeMs);
|
||||
|
||||
// Estimate idle power consumption at each signal strength level
|
||||
final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
|
||||
for (int strengthLevel = 0; strengthLevel < numSignalStrengthLevels;
|
||||
strengthLevel++) {
|
||||
final long strengthLevelDurationMs =
|
||||
mPhoneSignalStrengthsTimer[strengthLevel].getTimeSinceMarkLocked(
|
||||
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(
|
||||
elapsedRealtimeMs * 1000) / 1000;
|
||||
mPhoneSignalStrengthsTimer[strengthLevel].setMark(elapsedRealtimeMs);
|
||||
|
||||
mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
|
||||
totalEstimatedConsumptionMah +=
|
||||
mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
|
||||
strengthLevelDurationMs, strengthLevel);
|
||||
mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
|
||||
totalRadioTimeMs);
|
||||
|
||||
// Estimate idle power consumption at each signal strength level
|
||||
final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
|
||||
for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) {
|
||||
final long strengthLevelDurationMs =
|
||||
mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked(
|
||||
elapsedRealtimeMs * 1000) / 1000;
|
||||
mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs);
|
||||
|
||||
totalEstimatedConsumptionMah +=
|
||||
mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
|
||||
strengthLevelDurationMs, lvl);
|
||||
}
|
||||
|
||||
// Estimate total active radio power consumption since last mark.
|
||||
final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
|
||||
elapsedRealtimeMs * 1000) / 1000;
|
||||
mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
|
||||
totalEstimatedConsumptionMah +=
|
||||
mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
|
||||
}
|
||||
|
||||
// Estimate total active radio power consumption since last mark.
|
||||
final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
|
||||
elapsedRealtimeMs * 1000) / 1000;
|
||||
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)
|
||||
@@ -12261,6 +12336,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
|
||||
@@ -12270,6 +12355,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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12289,9 +12384,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12301,6 +12415,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -14762,6 +14915,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];
|
||||
@@ -14797,6 +14957,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;
|
||||
@@ -14810,6 +15004,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
|
||||
@@ -14826,6 +15023,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(',');
|
||||
@@ -14903,6 +15101,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();
|
||||
|
||||
@@ -14971,6 +15172,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -270,25 +270,28 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -574,8 +574,10 @@ public class MobileRadioPowerCalculatorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasuredEnergyBasedModel() {
|
||||
public void testMeasuredEnergyBasedModel_mobileRadioActiveTimeModel() {
|
||||
mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
|
||||
.setPerUidModemModel(
|
||||
BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME)
|
||||
.initMeasuredEnergyStatsLocked();
|
||||
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
|
||||
|
||||
@@ -637,6 +639,263 @@ public class MobileRadioPowerCalculatorTest {
|
||||
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testMeasuredEnergyBasedModel_modemActivityInfoRxTxModel() {
|
||||
mStatsRule.setTestPowerProfile(R.xml.power_profile_test_modem_calculator_multiactive)
|
||||
.setPerUidModemModel(
|
||||
BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX)
|
||||
.initMeasuredEnergyStatsLocked();
|
||||
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
|
||||
|
||||
// Scan for a cell
|
||||
stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE,
|
||||
TelephonyManager.SIM_STATE_READY,
|
||||
2000, 2000);
|
||||
|
||||
// Found a cell
|
||||
stats.notePhoneStateLocked(ServiceState.STATE_IN_SERVICE, TelephonyManager.SIM_STATE_READY,
|
||||
5000, 5000);
|
||||
|
||||
ArrayList<CellSignalStrength> perRatCellStrength = new ArrayList();
|
||||
CellSignalStrength gsmSignalStrength = mock(CellSignalStrength.class);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(
|
||||
SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||
perRatCellStrength.add(gsmSignalStrength);
|
||||
|
||||
// Note cell signal strength
|
||||
SignalStrength signalStrength = mock(SignalStrength.class);
|
||||
when(signalStrength.getCellSignalStrengths()).thenReturn(perRatCellStrength);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 5000, 5000);
|
||||
|
||||
stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
|
||||
8_000_000_000L, APP_UID, 8000, 8000);
|
||||
|
||||
// Note established network
|
||||
stats.noteNetworkInterfaceForTransports("cellular",
|
||||
new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
|
||||
|
||||
// Spend some time in each signal strength level. It doesn't matter how long.
|
||||
// The ModemActivityInfo reported level residency should be trusted over the BatteryStats
|
||||
// timers.
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(
|
||||
SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 8111, 8111);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_POOR);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110);
|
||||
|
||||
stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
|
||||
9_500_000_000L, APP_UID2, 9500, 9500);
|
||||
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GREAT);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
|
||||
|
||||
// Note application network activity
|
||||
NetworkStats networkStats = new NetworkStats(10000, 1)
|
||||
.addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
|
||||
METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 300, 10, 100))
|
||||
.addEntry(new NetworkStats.Entry("cellular", APP_UID2, 0, 0,
|
||||
METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 500, 50, 2000, 30, 111));
|
||||
mStatsRule.setNetworkStats(networkStats);
|
||||
|
||||
ActivityStatsTechSpecificInfo cdmaInfo = new ActivityStatsTechSpecificInfo(
|
||||
AccessNetwork.CDMA2000, ServiceState.FREQUENCY_RANGE_UNKNOWN,
|
||||
new int[]{10, 11, 12, 13, 14}, 15);
|
||||
ActivityStatsTechSpecificInfo lteInfo = new ActivityStatsTechSpecificInfo(
|
||||
AccessNetwork.EUTRAN, ServiceState.FREQUENCY_RANGE_UNKNOWN,
|
||||
new int[]{20, 21, 22, 23, 24}, 25);
|
||||
ActivityStatsTechSpecificInfo nrLowFreqInfo = new ActivityStatsTechSpecificInfo(
|
||||
AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_LOW,
|
||||
new int[]{30, 31, 32, 33, 34}, 35);
|
||||
ActivityStatsTechSpecificInfo nrMidFreqInfo = new ActivityStatsTechSpecificInfo(
|
||||
AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MID,
|
||||
new int[]{40, 41, 42, 43, 44}, 45);
|
||||
ActivityStatsTechSpecificInfo nrHighFreqInfo = new ActivityStatsTechSpecificInfo(
|
||||
AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_HIGH,
|
||||
new int[]{50, 51, 52, 53, 54}, 55);
|
||||
ActivityStatsTechSpecificInfo nrMmwaveFreqInfo = new ActivityStatsTechSpecificInfo(
|
||||
AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MMWAVE,
|
||||
new int[]{60, 61, 62, 63, 64}, 65);
|
||||
|
||||
ActivityStatsTechSpecificInfo[] ratInfos =
|
||||
new ActivityStatsTechSpecificInfo[]{cdmaInfo, lteInfo, nrLowFreqInfo, nrMidFreqInfo,
|
||||
nrHighFreqInfo, nrMmwaveFreqInfo};
|
||||
|
||||
ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000, ratInfos);
|
||||
stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000,
|
||||
mNetworkStatsManager);
|
||||
|
||||
mStatsRule.setTime(10_000, 10_000);
|
||||
|
||||
MobileRadioPowerCalculator calculator =
|
||||
new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
|
||||
|
||||
mStatsRule.apply(calculator);
|
||||
|
||||
BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
|
||||
assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isWithin(PRECISION).of(2.77778);
|
||||
assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.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
|
||||
// LTE [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
|
||||
// [800, 1200, 1600, 2000, 2400, 2000] mA . [20, 21, 22, 23, 24, 25] ms = 230000 mA-ms
|
||||
// 5G Low Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
|
||||
// (nrFrequency="LOW" values was not defined so fall back to nrFrequency="DEFAULT")
|
||||
// [999, 1333, 1888, 2222, 2666, 2222] mA . [30, 31, 32, 33, 34, 35] ms = 373449 mA-ms
|
||||
// 5G Mid Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
|
||||
// (nrFrequency="MID" values was not defined so fall back to nrFrequency="DEFAULT")
|
||||
// [999, 1333, 1888, 2222, 2666, 2222] mA . [40, 41, 42, 43, 44, 45] ms = 486749 mA-ms
|
||||
// 5G High Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
|
||||
// [1818, 2727, 3636, 4545, 5454, 2727] mA . [50, 51, 52, 53, 54, 55] ms = 1104435 mA-ms
|
||||
// 5G Mmwave Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
|
||||
// [2345, 3456, 4567, 5678, 6789, 3456] mA . [60, 61, 62, 63, 64, 65] ms = 1651520 mA-ms
|
||||
// _________________
|
||||
// = 3957753 mA-ms estimated active consumption
|
||||
//
|
||||
// Idle drain rate * idle duration
|
||||
// 360 mA * 3000 ms = 1080000 mA-ms
|
||||
// Sleep drain rate * sleep duration
|
||||
// 70 mA * 2000 ms = 140000 mA-ms
|
||||
// _________________
|
||||
// = 5177753 mA-ms estimated total consumption
|
||||
//
|
||||
// 2.77778 mA-h measured total consumption * 3957753 / 5177753 = 2.123268 mA-h
|
||||
BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
|
||||
assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isWithin(PRECISION).of(2.123268);
|
||||
assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
|
||||
|
||||
// 240 ms Rx Time, 1110 ms Tx Time, 1350 ms active time
|
||||
// 150 App 1 Rx Packets, 10 App 1 Tx packets
|
||||
// 50 App 2 Rx Packets, 30 App 2 Tx packets
|
||||
// 200 total Rx Packets, 40 total Tx packets
|
||||
// 623985 mA-ms Rx consumption, 3333768 mA-ms Tx consumption
|
||||
//
|
||||
// Rx Power consumption * Ratio of App1 / Total Rx Packets:
|
||||
// 623985 * 150 / 200 = 467988.75 mA-ms App 1 Rx Power Consumption
|
||||
//
|
||||
// App 1 Tx Packets + App 1 Rx Packets * Ratio of Tx / Total active time
|
||||
// 10 + 150 * 1110 / 1350 = 133.3333 Estimated App 1 Rx/Tx Packets during Tx
|
||||
// Total Tx Packets + Total Rx Packets * Ratio of Tx / Total active time
|
||||
// 40 + 200 * 1110 / 1350 = 204.44444 Estimated Total Rx/Tx Packets during Tx
|
||||
// Tx Power consumption * Ratio of App 1 / Total Estimated Tx Packets:
|
||||
// 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
|
||||
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
|
||||
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isWithin(PRECISION).of(1.41749);
|
||||
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);
|
||||
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasuredEnergyBasedModel_modemActivityInfoRxTxModel_legacyPowerProfile() {
|
||||
mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
|
||||
.setPerUidModemModel(
|
||||
BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX)
|
||||
.initMeasuredEnergyStatsLocked();
|
||||
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
|
||||
|
||||
// Scan for a cell
|
||||
stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE,
|
||||
TelephonyManager.SIM_STATE_READY,
|
||||
2000, 2000);
|
||||
|
||||
ArrayList<CellSignalStrength> perRatCellStrength = new ArrayList();
|
||||
CellSignalStrength gsmSignalStrength = mock(CellSignalStrength.class);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(
|
||||
SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||
perRatCellStrength.add(gsmSignalStrength);
|
||||
|
||||
// Found a cell
|
||||
stats.notePhoneStateLocked(ServiceState.STATE_IN_SERVICE, TelephonyManager.SIM_STATE_READY,
|
||||
5000, 5000);
|
||||
|
||||
// Note cell signal strength
|
||||
SignalStrength signalStrength = mock(SignalStrength.class);
|
||||
when(signalStrength.getCellSignalStrengths()).thenReturn(perRatCellStrength);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 5000, 5000);
|
||||
|
||||
stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
|
||||
8_000_000_000L, APP_UID, 8000, 8000);
|
||||
|
||||
// Note established network
|
||||
stats.noteNetworkInterfaceForTransports("cellular",
|
||||
new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
|
||||
|
||||
// Spend some time in each signal strength level. It doesn't matter how long.
|
||||
// The ModemActivityInfo reported level residency should be trusted over the BatteryStats
|
||||
// timers.
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(
|
||||
SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 8111, 8111);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_POOR);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110);
|
||||
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GREAT);
|
||||
stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
|
||||
|
||||
// Note application network activity
|
||||
NetworkStats networkStats = new NetworkStats(10000, 1)
|
||||
.addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
|
||||
METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
|
||||
mStatsRule.setNetworkStats(networkStats);
|
||||
|
||||
ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
|
||||
new int[]{100, 200, 300, 400, 500}, 600);
|
||||
stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000, mNetworkStatsManager);
|
||||
|
||||
mStatsRule.setTime(12_000, 12_000);
|
||||
|
||||
MobileRadioPowerCalculator calculator =
|
||||
new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
|
||||
|
||||
mStatsRule.apply(calculator);
|
||||
|
||||
BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
|
||||
// 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
|
||||
assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isWithin(PRECISION).of(2.77778);
|
||||
assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.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
|
||||
assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isWithin(PRECISION).of(2.04170);
|
||||
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);
|
||||
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
|
||||
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasuredEnergyBasedModel_byProcessState() {
|
||||
mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user