Merge "BatteryStats measured energy for Wifi & Bluetooth" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
56a4ea5684
@@ -986,13 +986,13 @@ public abstract class BatteryStats implements Parcelable {
|
||||
public abstract void getDeferredJobsLineLocked(StringBuilder sb, int which);
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of the screen while on and uid active,
|
||||
* Returns the battery consumption (in microcoulombs) of bluetooth for this uid,
|
||||
* derived from on device power measurement data.
|
||||
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public abstract long getScreenOnMeasuredBatteryConsumptionUC();
|
||||
public abstract long getBluetoothMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of the uid's cpu usage, derived from
|
||||
@@ -1003,6 +1003,24 @@ public abstract class BatteryStats implements Parcelable {
|
||||
*/
|
||||
public abstract long getCpuMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of the screen while on and uid active,
|
||||
* derived from on device power measurement data.
|
||||
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public abstract long getScreenOnMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of wifi for this uid,
|
||||
* derived from on device power measurement data.
|
||||
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public abstract long getWifiMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) used by this uid for each
|
||||
* {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
|
||||
@@ -2505,11 +2523,29 @@ public abstract class BatteryStats implements Parcelable {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returned value if power data is unavailable
|
||||
* Returned value if power data is unavailable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final long POWER_DATA_UNAVAILABLE = -1;
|
||||
public static final long POWER_DATA_UNAVAILABLE = -1L;
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of bluetooth, derived from on
|
||||
* device power measurement data.
|
||||
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public abstract long getBluetoothMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of the cpu, derived from on device power
|
||||
* measurement data.
|
||||
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public abstract long getCpuMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of the screen while on, derived from on
|
||||
@@ -2530,13 +2566,13 @@ public abstract class BatteryStats implements Parcelable {
|
||||
public abstract long getScreenDozeMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) of the cpu, derived from on device power
|
||||
* measurement data.
|
||||
* Returns the battery consumption (in microcoulombs) of wifi, derived from on
|
||||
* device power measurement data.
|
||||
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public abstract long getCpuMeasuredBatteryConsumptionUC();
|
||||
public abstract long getWifiMeasuredBatteryConsumptionUC();
|
||||
|
||||
/**
|
||||
* Returns the battery consumption (in microcoulombs) that each
|
||||
|
||||
@@ -110,7 +110,7 @@ public final class WifiActivityEnergyInfo implements Parcelable {
|
||||
}
|
||||
// Calculate energy used using PowerProfile.
|
||||
PowerProfile powerProfile = new PowerProfile(context);
|
||||
final double rxIdleCurrent = powerProfile.getAveragePower(
|
||||
final double idleCurrent = powerProfile.getAveragePower(
|
||||
PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
|
||||
final double rxCurrent = powerProfile.getAveragePower(
|
||||
PowerProfile.POWER_WIFI_CONTROLLER_RX);
|
||||
@@ -121,7 +121,7 @@ public final class WifiActivityEnergyInfo implements Parcelable {
|
||||
|
||||
return (long) ((txDurationMillis * txCurrent
|
||||
+ rxDurationMillis * rxCurrent
|
||||
+ idleDurationMillis * rxIdleCurrent)
|
||||
+ idleDurationMillis * idleCurrent)
|
||||
* voltage);
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
|
||||
|
||||
// Current on-disk Parcel version
|
||||
static final int VERSION = 194;
|
||||
static final int VERSION = 195;
|
||||
|
||||
// The maximum number of names wakelocks we will keep track of
|
||||
// per uid; once the limit is reached, we batch the remaining wakelocks
|
||||
@@ -1009,8 +1009,12 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
|
||||
/** Last known screen state. Needed for apportioning display energy. */
|
||||
int mScreenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
|
||||
/** Bluetooth Power calculator for attributing measured bluetooth charge consumption to uids */
|
||||
@Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
|
||||
/** Cpu Power calculator for attributing measured cpu charge consumption to uids */
|
||||
@Nullable CpuPowerCalculator mCpuPowerCalculator = null;
|
||||
/** Wifi Power calculator for attributing measured wifi charge consumption to uids */
|
||||
@Nullable WifiPowerCalculator mWifiPowerCalculator = null;
|
||||
|
||||
/**
|
||||
* These provide time bases that discount the time the device is plugged
|
||||
@@ -6966,6 +6970,16 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBluetoothMeasuredBatteryConsumptionUC() {
|
||||
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCpuMeasuredBatteryConsumptionUC() {
|
||||
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getScreenOnMeasuredBatteryConsumptionUC() {
|
||||
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
|
||||
@@ -6977,8 +6991,8 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCpuMeasuredBatteryConsumptionUC() {
|
||||
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
|
||||
public long getWifiMeasuredBatteryConsumptionUC() {
|
||||
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7815,6 +7829,26 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBluetoothMeasuredBatteryConsumptionUC() {
|
||||
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCpuMeasuredBatteryConsumptionUC() {
|
||||
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getScreenOnMeasuredBatteryConsumptionUC() {
|
||||
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getWifiMeasuredBatteryConsumptionUC() {
|
||||
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
|
||||
* since last marked. Also sets the mark time for both these timers.
|
||||
@@ -8482,16 +8516,6 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getScreenOnMeasuredBatteryConsumptionUC() {
|
||||
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCpuMeasuredBatteryConsumptionUC() {
|
||||
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
|
||||
}
|
||||
|
||||
void initNetworkActivityLocked() {
|
||||
detachIfNotNull(mNetworkByteActivityCounters);
|
||||
mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
|
||||
@@ -11437,7 +11461,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
* @param info The energy information from the WiFi controller.
|
||||
*/
|
||||
public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
|
||||
long elapsedRealtimeMs, long uptimeMs) {
|
||||
final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
|
||||
if (DEBUG_ENERGY) {
|
||||
Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
|
||||
}
|
||||
@@ -11459,9 +11483,21 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
if (delta != null) {
|
||||
mNetworkStatsPool.release(delta);
|
||||
}
|
||||
if (mIgnoreNextExternalStats) {
|
||||
// TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
|
||||
// global one) here like we do for display. But I'm not sure it's worth the
|
||||
// complicated code for a codepath that shouldn't ever actually happen in real
|
||||
// life.
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final ArrayMap<Uid, Double> uidEstimatedConsumptionMah =
|
||||
(mGlobalMeasuredEnergyStats != null
|
||||
&& mWifiPowerCalculator != null && consumedChargeUC > 0) ?
|
||||
new ArrayMap<>() : null;
|
||||
double totalEstimatedConsumptionMah = 0;
|
||||
|
||||
SparseLongArray rxPackets = new SparseLongArray();
|
||||
SparseLongArray txPackets = new SparseLongArray();
|
||||
long totalTxPackets = 0;
|
||||
@@ -11496,6 +11532,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
|
||||
entry.rxPackets);
|
||||
|
||||
// TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
|
||||
rxPackets.put(u.getUid(), entry.rxPackets);
|
||||
|
||||
// Sum the total number of packets so that the Rx Power can
|
||||
@@ -11515,12 +11552,42 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
|
||||
entry.txPackets);
|
||||
|
||||
// TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
|
||||
txPackets.put(u.getUid(), entry.txPackets);
|
||||
|
||||
// Sum the total number of packets so that the Tx Power can
|
||||
// be evenly distributed amongst the apps.
|
||||
totalTxPackets += entry.txPackets;
|
||||
}
|
||||
|
||||
// Calculate consumed energy for this uid. Only do so if WifiReporting isn't
|
||||
// enabled (if it is, we'll do it later instead using info).
|
||||
if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
|
||||
final long uidRunningMs = u.mWifiRunningTimer
|
||||
.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
|
||||
if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
|
||||
|
||||
final long uidScanMs = u.mWifiScanTimer
|
||||
.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
|
||||
if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
|
||||
|
||||
long uidBatchScanMs = 0;
|
||||
for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
|
||||
if (u.mWifiBatchedScanTimer[bn] != null) {
|
||||
long bnMs = u.mWifiBatchedScanTimer[bn]
|
||||
.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
|
||||
if (bnMs > 0) {
|
||||
u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
|
||||
}
|
||||
uidBatchScanMs += bnMs;
|
||||
}
|
||||
}
|
||||
|
||||
addDoubleToUidMap(uidEstimatedConsumptionMah, u,
|
||||
mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
|
||||
entry.rxPackets, entry.txPackets,
|
||||
uidRunningMs, uidScanMs, uidBatchScanMs));
|
||||
}
|
||||
}
|
||||
mNetworkStatsPool.release(delta);
|
||||
delta = null;
|
||||
@@ -11581,15 +11648,14 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
for (int i = 0; i < uidStatsSize; i++) {
|
||||
final Uid uid = mUidStats.valueAt(i);
|
||||
|
||||
long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
|
||||
final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
|
||||
elapsedRealtimeMs * 1000) / 1000;
|
||||
long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
|
||||
long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
|
||||
if (scanTimeSinceMarkMs > 0) {
|
||||
// Set the new mark so that next time we get new data since this point.
|
||||
uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
|
||||
|
||||
long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
|
||||
long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
|
||||
|
||||
// Our total scan time is more than the reported Tx/Rx time.
|
||||
// This is possible because the cost of a scan is approximate.
|
||||
// Let's normalize the result so that we evenly blame each app
|
||||
@@ -11623,6 +11689,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
|
||||
// Distribute evenly the power consumed while Idle to each app holding a WiFi
|
||||
// lock.
|
||||
long myIdleTimeMs = 0;
|
||||
final long wifiLockTimeSinceMarkMs =
|
||||
uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
|
||||
elapsedRealtimeMs * 1000) / 1000;
|
||||
@@ -11630,8 +11697,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
// Set the new mark so that next time we get new data since this point.
|
||||
uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
|
||||
|
||||
final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
|
||||
/ totalWifiLockTimeMs;
|
||||
myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
|
||||
if (DEBUG_ENERGY) {
|
||||
Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": "
|
||||
+ myIdleTimeMs + " ms");
|
||||
@@ -11639,6 +11705,12 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
|
||||
.addCountLocked(myIdleTimeMs);
|
||||
}
|
||||
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
|
||||
scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
|
||||
addDoubleToUidMap(uidEstimatedConsumptionMah, uid, uidEstMah);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_ENERGY) {
|
||||
@@ -11658,6 +11730,11 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
|
||||
.addCountLocked(myTxTimeMs);
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
addDoubleToUidMap(uidEstimatedConsumptionMah, uid,
|
||||
mWifiPowerCalculator.calcPowerFromControllerDataMah(
|
||||
0, myTxTimeMs, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// Distribute the remaining Rx power appropriately between all apps that received
|
||||
@@ -11672,6 +11749,11 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
|
||||
.addCountLocked(myRxTimeMs);
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
addDoubleToUidMap(uidEstimatedConsumptionMah, uid,
|
||||
mWifiPowerCalculator.calcPowerFromControllerDataMah(
|
||||
myRxTimeMs, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
|
||||
@@ -11690,10 +11772,11 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
// POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
|
||||
final double opVolt = mPowerProfile.getAveragePower(
|
||||
PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
|
||||
double controllerMaMs = 0;
|
||||
if (opVolt != 0) {
|
||||
// We store the power drain as mAms.
|
||||
mWifiActivity.getPowerCounter().addCountLocked(
|
||||
(long) (info.getControllerEnergyUsedMicroJoules() / opVolt));
|
||||
controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
|
||||
mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
|
||||
}
|
||||
// Converting uWs to mAms.
|
||||
// Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
|
||||
@@ -11705,6 +11788,29 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
(monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
|
||||
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
|
||||
mTmpRailStats.resetWifiTotalEnergyUsed();
|
||||
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
|
||||
mWifiPowerCalculator.calcPowerFromControllerDataMah(
|
||||
rxTimeMs, txTimeMs, idleTimeMs));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the MeasuredEnergyStats information.
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
mGlobalMeasuredEnergyStats.updateStandardBucket(
|
||||
MeasuredEnergyStats.POWER_BUCKET_WIFI, consumedChargeUC);
|
||||
|
||||
// Now calculate the consumption for each uid, according to its proportional usage.
|
||||
if (!mHasWifiReporting) {
|
||||
final long globalTimeMs = mGlobalWifiRunningTimer
|
||||
.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
|
||||
mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
|
||||
totalEstimatedConsumptionMah = mWifiPowerCalculator
|
||||
.calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
|
||||
}
|
||||
distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_WIFI,
|
||||
consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11948,7 +12054,7 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
* @param info The energy information from the bluetooth controller.
|
||||
*/
|
||||
public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
|
||||
long elapsedRealtimeMs, long uptimeMs) {
|
||||
final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
|
||||
if (DEBUG_ENERGY) {
|
||||
Slog.d(TAG, "Updating bluetooth stats: " + info);
|
||||
}
|
||||
@@ -11980,6 +12086,11 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms");
|
||||
}
|
||||
|
||||
final ArrayMap<Uid, Double> uidEstimatedConsumptionMah =
|
||||
(mGlobalMeasuredEnergyStats != null
|
||||
&& mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
|
||||
new ArrayMap<>() : null;
|
||||
|
||||
long totalScanTimeMs = 0;
|
||||
|
||||
final int uidCount = mUidStats.size();
|
||||
@@ -12038,6 +12149,12 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
|
||||
counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
|
||||
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
addDoubleToUidMap(uidEstimatedConsumptionMah, u,
|
||||
mBluetoothPowerCalculator.calculatePowerMah(
|
||||
scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
|
||||
}
|
||||
|
||||
leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
|
||||
leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
|
||||
}
|
||||
@@ -12098,6 +12215,11 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
|
||||
}
|
||||
counter.getRxTimeCounter().addCountLocked(timeRxMs);
|
||||
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
addDoubleToUidMap(uidEstimatedConsumptionMah, u,
|
||||
mBluetoothPowerCalculator.calculatePowerMah(timeRxMs, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (totalTxBytes > 0 && txBytes > 0) {
|
||||
@@ -12106,6 +12228,11 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
|
||||
}
|
||||
counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
|
||||
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
addDoubleToUidMap(uidEstimatedConsumptionMah, u,
|
||||
mBluetoothPowerCalculator.calculatePowerMah(0, timeTxMs, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12117,12 +12244,26 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
// POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
|
||||
final double opVolt = mPowerProfile.getAveragePower(
|
||||
PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
|
||||
double controllerMaMs = 0;
|
||||
if (opVolt != 0) {
|
||||
controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
|
||||
/ opVolt;
|
||||
// We store the power drain as mAms.
|
||||
mBluetoothActivity.getPowerCounter().addCountLocked(
|
||||
(long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
|
||||
/ opVolt));
|
||||
mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
|
||||
}
|
||||
|
||||
// Update the MeasuredEnergyStats information.
|
||||
if (uidEstimatedConsumptionMah != null) {
|
||||
mGlobalMeasuredEnergyStats.updateStandardBucket(
|
||||
MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
|
||||
|
||||
double totalEstimatedMah
|
||||
= mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
|
||||
totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
|
||||
distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH,
|
||||
consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah);
|
||||
}
|
||||
|
||||
mLastBluetoothActivityInfo.set(info);
|
||||
}
|
||||
|
||||
@@ -12311,37 +12452,17 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
// If multidisplay becomes a reality, this is probably more reasonable than pooling.
|
||||
|
||||
// On the first pass, collect total time since mark so that we can normalize power.
|
||||
long totalFgTimeMs = 0L;
|
||||
final ArrayMap<Uid, Long> fgTimeMsArray = new ArrayMap<>();
|
||||
final ArrayMap<Uid, Double> fgTimeUsArray = new ArrayMap<>();
|
||||
final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
|
||||
// TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
|
||||
final int uidStatsSize = mUidStats.size();
|
||||
for (int i = 0; i < uidStatsSize; i++) {
|
||||
final Uid uid = mUidStats.valueAt(i);
|
||||
final long fgTimeMs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true) / 1000;
|
||||
if (fgTimeMs == 0) continue;
|
||||
fgTimeMsArray.put(uid, fgTimeMs);
|
||||
totalFgTimeMs += fgTimeMs;
|
||||
}
|
||||
long totalDisplayChargeMC = chargeUC / 1000; // not final
|
||||
|
||||
// Actually assign and distribute power usage to apps based on their fg time since mark.
|
||||
// TODO(b/175726326): Decide on 'energy' units and make sure algorithm won't overflow.
|
||||
final long fgTimeArraySize = fgTimeMsArray.size();
|
||||
for (int i = 0; i < fgTimeArraySize; i++) {
|
||||
final Uid uid = fgTimeMsArray.keyAt(i);
|
||||
final long fgTimeMs = fgTimeMsArray.valueAt(i);
|
||||
|
||||
// Using long division: "appEnergy = totalEnergy * appFg/totalFg + 0.5" with rounding
|
||||
final long appDisplayChargeMC =
|
||||
(totalDisplayChargeMC * fgTimeMs + (totalFgTimeMs / 2))
|
||||
/ totalFgTimeMs;
|
||||
uid.addChargeToStandardBucketLocked(appDisplayChargeMC * 1000, powerBucket);
|
||||
|
||||
// To mitigate round-off errors, remove this app from numerator & denominator totals
|
||||
totalDisplayChargeMC -= appDisplayChargeMC;
|
||||
totalFgTimeMs -= fgTimeMs;
|
||||
final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
|
||||
if (fgTimeUs == 0) continue;
|
||||
fgTimeUsArray.put(uid, (double) fgTimeUs);
|
||||
}
|
||||
distributeEnergyToUidsLocked(powerBucket, chargeUC, fgTimeUsArray, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -12388,6 +12509,54 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes energy (for the given bucket) to each uid according to the following formula:
|
||||
* blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
|
||||
* <p>Does nothing if ratioDenominator is 0.
|
||||
*
|
||||
* <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
|
||||
* so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
|
||||
*
|
||||
* <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
|
||||
* use the same units as totalConsumedChargeUC (which must be in microcoulombs).
|
||||
*
|
||||
* <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
|
||||
* totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
|
||||
* than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
|
||||
*/
|
||||
// TODO(b/182845832): Use some sort of "SparseDoubleArray" instead of ArrayMap<Uid, Double>.
|
||||
private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
|
||||
long totalConsumedChargeUC, ArrayMap<Uid, Double> ratioNumerators,
|
||||
double minRatioDenominator) {
|
||||
|
||||
// If the sum of all app usage was greater than the total, use that instead:
|
||||
double sumRatioNumerators = 0;
|
||||
for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
|
||||
sumRatioNumerators += ratioNumerators.valueAt(i);
|
||||
}
|
||||
final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
|
||||
if (ratioDenominator <= 0) return;
|
||||
|
||||
for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
|
||||
final Uid uid = ratioNumerators.keyAt(i);
|
||||
final double ratioNumerator = ratioNumerators.valueAt(i);
|
||||
final long uidActualUC
|
||||
= (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
|
||||
uid.addChargeToStandardBucketLocked(uidActualUC, bucket);
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds the summand to the value stored in uidMap for the given uid. */
|
||||
// TODO(b/182845832): Use some sort of "SparseDoubleArray" instead of ArrayMap<Uid, Double>.
|
||||
private static void addDoubleToUidMap(ArrayMap<Uid, Double> uidMap, Uid uid, double summand) {
|
||||
if (uidMap == null) return;
|
||||
final Double oldVal = uidMap.get(uid);
|
||||
if (oldVal != null) {
|
||||
summand += oldVal;
|
||||
}
|
||||
uidMap.put(uid, summand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and record Rail Energy data.
|
||||
*/
|
||||
@@ -14222,15 +14391,20 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
if (mGlobalMeasuredEnergyStats == null) {
|
||||
mGlobalMeasuredEnergyStats =
|
||||
new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
|
||||
return;
|
||||
} else {
|
||||
supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo(
|
||||
supportedStandardBuckets, numCustomBuckets);
|
||||
}
|
||||
|
||||
if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH]) {
|
||||
mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
|
||||
}
|
||||
if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU]) {
|
||||
mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
|
||||
}
|
||||
if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_WIFI]) {
|
||||
mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
|
||||
}
|
||||
}
|
||||
|
||||
if (supportedBucketMismatch) {
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
*/
|
||||
package com.android.internal.os;
|
||||
|
||||
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
|
||||
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryStats.ControllerActivityCounter;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.BatteryUsageStatsQuery;
|
||||
import android.os.Process;
|
||||
@@ -65,17 +68,19 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
builder.getUidBatteryConsumerBuilders();
|
||||
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
|
||||
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
|
||||
calculateApp(app, total);
|
||||
calculateApp(app, total, query);
|
||||
if (app.getUid() == Process.BLUETOOTH_UID) {
|
||||
app.excludeFromBatteryUsageStats();
|
||||
systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
|
||||
}
|
||||
}
|
||||
|
||||
final BatteryStats.ControllerActivityCounter activityCounter =
|
||||
final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
|
||||
POWER_DATA_UNAVAILABLE : batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
|
||||
final ControllerActivityCounter activityCounter =
|
||||
batteryStats.getBluetoothControllerActivity();
|
||||
final long systemDurationMs = calculateDuration(activityCounter);
|
||||
final double systemPowerMah = calculatePower(activityCounter);
|
||||
final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
|
||||
|
||||
// Subtract what the apps used, but clamp to 0.
|
||||
final long systemComponentDurationMs = Math.max(0, systemDurationMs - total.durationMs);
|
||||
@@ -91,11 +96,16 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
systemComponentPowerMah);
|
||||
}
|
||||
|
||||
private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total) {
|
||||
final BatteryStats.ControllerActivityCounter activityCounter =
|
||||
private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total,
|
||||
BatteryUsageStatsQuery query) {
|
||||
|
||||
final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
|
||||
POWER_DATA_UNAVAILABLE :
|
||||
app.getBatteryStatsUid().getBluetoothMeasuredBatteryConsumptionUC();
|
||||
final ControllerActivityCounter activityCounter =
|
||||
app.getBatteryStatsUid().getBluetoothControllerActivity();
|
||||
final long durationMs = calculateDuration(activityCounter);
|
||||
final double powerMah = calculatePower(activityCounter);
|
||||
final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
|
||||
|
||||
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH, durationMs)
|
||||
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah);
|
||||
@@ -121,10 +131,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
}
|
||||
|
||||
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
|
||||
final BatteryStats.ControllerActivityCounter activityCounter =
|
||||
final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
|
||||
final ControllerActivityCounter activityCounter =
|
||||
batteryStats.getBluetoothControllerActivity();
|
||||
final double systemPowerMah = calculatePower(activityCounter);
|
||||
final long systemDurationMs = calculateDuration(activityCounter);
|
||||
final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
|
||||
|
||||
// Subtract what the apps used, but clamp to 0.
|
||||
final double powerMah = Math.max(0, systemPowerMah - total.powerMah);
|
||||
@@ -152,10 +163,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
|
||||
private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType,
|
||||
PowerAndDuration total) {
|
||||
final BatteryStats.ControllerActivityCounter activityCounter =
|
||||
u.getBluetoothControllerActivity();
|
||||
|
||||
final long measuredChargeUC = u.getBluetoothMeasuredBatteryConsumptionUC();
|
||||
final ControllerActivityCounter activityCounter = u.getBluetoothControllerActivity();
|
||||
final long durationMs = calculateDuration(activityCounter);
|
||||
final double powerMah = calculatePower(activityCounter);
|
||||
final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
|
||||
|
||||
app.bluetoothRunningTimeMs = durationMs;
|
||||
app.bluetoothPowerMah = powerMah;
|
||||
@@ -166,7 +178,7 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
total.powerMah += powerMah;
|
||||
}
|
||||
|
||||
private long calculateDuration(BatteryStats.ControllerActivityCounter counter) {
|
||||
private long calculateDuration(ControllerActivityCounter counter) {
|
||||
if (counter == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -176,7 +188,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
+ counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
|
||||
}
|
||||
|
||||
private double calculatePower(BatteryStats.ControllerActivityCounter counter) {
|
||||
/** Returns bluetooth power usage based on the best data available. */
|
||||
private double calculatePowerMah(long measuredChargeUC, ControllerActivityCounter counter) {
|
||||
if (measuredChargeUC != POWER_DATA_UNAVAILABLE) {
|
||||
return uCtoMah(measuredChargeUC);
|
||||
}
|
||||
if (counter == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -195,6 +211,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
|
||||
final long txTimeMs =
|
||||
counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
|
||||
return calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
|
||||
}
|
||||
|
||||
/** Returns estimated bluetooth power usage based on usage times. */
|
||||
public double calculatePowerMah(long rxTimeMs, long txTimeMs, long idleTimeMs) {
|
||||
return ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
|
||||
/ (1000 * 60 * 60);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.android.internal.os;
|
||||
|
||||
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
|
||||
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryUsageStats;
|
||||
@@ -79,11 +81,6 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
|
||||
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
|
||||
|
||||
// batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
|
||||
// so always check this field.
|
||||
final boolean hasWifiPowerReporting =
|
||||
mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
|
||||
|
||||
final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
|
||||
builder.getOrCreateSystemBatteryConsumerBuilder(
|
||||
SystemBatteryConsumer.DRAIN_TYPE_WIFI);
|
||||
@@ -97,7 +94,8 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
|
||||
calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), rawRealtimeUs,
|
||||
BatteryStats.STATS_SINCE_CHARGED,
|
||||
hasWifiPowerReporting);
|
||||
batteryStats.hasWifiActivityReporting(),
|
||||
query.shouldForceUsePowerProfileModel());
|
||||
|
||||
totalAppDurationMs += powerDurationAndTraffic.durationMs;
|
||||
totalAppPowerMah += powerDurationAndTraffic.powerMah;
|
||||
@@ -115,7 +113,9 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
|
||||
calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs,
|
||||
BatteryStats.STATS_SINCE_CHARGED,
|
||||
hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
|
||||
batteryStats.hasWifiActivityReporting(),
|
||||
query.shouldForceUsePowerProfileModel(),
|
||||
totalAppDurationMs, totalAppPowerMah);
|
||||
|
||||
systemBatteryConsumerBuilder
|
||||
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
|
||||
@@ -135,11 +135,6 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
|
||||
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
|
||||
|
||||
// batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
|
||||
// so always check this field.
|
||||
final boolean hasWifiPowerReporting =
|
||||
mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
|
||||
|
||||
final BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
|
||||
|
||||
long totalAppDurationMs = 0;
|
||||
@@ -149,7 +144,7 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
final BatterySipper app = sippers.get(i);
|
||||
if (app.drainType == BatterySipper.DrainType.APP) {
|
||||
calculateApp(powerDurationAndTraffic, app.uidObj, rawRealtimeUs, statsType,
|
||||
hasWifiPowerReporting);
|
||||
batteryStats.hasWifiActivityReporting(), /* force use power model*/ false);
|
||||
|
||||
totalAppDurationMs += powerDurationAndTraffic.durationMs;
|
||||
totalAppPowerMah += powerDurationAndTraffic.powerMah;
|
||||
@@ -169,7 +164,8 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
}
|
||||
|
||||
calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs, statsType,
|
||||
hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
|
||||
batteryStats.hasWifiActivityReporting(), /* force use power model*/ false,
|
||||
totalAppDurationMs, totalAppPowerMah);
|
||||
|
||||
bs.wifiRunningTimeMs += powerDurationAndTraffic.durationMs;
|
||||
bs.wifiPowerMah += powerDurationAndTraffic.powerMah;
|
||||
@@ -180,8 +176,9 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
}
|
||||
|
||||
private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic, BatteryStats.Uid u,
|
||||
long rawRealtimeUs,
|
||||
int statsType, boolean hasWifiPowerReporting) {
|
||||
long rawRealtimeUs, int statsType,
|
||||
boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel) {
|
||||
|
||||
powerDurationAndTraffic.wifiRxPackets = u.getNetworkActivityPackets(
|
||||
BatteryStats.NETWORK_WIFI_RX_DATA,
|
||||
statsType);
|
||||
@@ -195,7 +192,14 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
BatteryStats.NETWORK_WIFI_TX_DATA,
|
||||
statsType);
|
||||
|
||||
if (hasWifiPowerReporting) {
|
||||
final long measuredChargeUC = u.getWifiMeasuredBatteryConsumptionUC();
|
||||
final boolean isMeasuredPowerAvailable
|
||||
= !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
|
||||
if (isMeasuredPowerAvailable) {
|
||||
powerDurationAndTraffic.powerMah = uCtoMah(measuredChargeUC);
|
||||
}
|
||||
|
||||
if (hasWifiActivityReporting && mHasWifiPowerController) {
|
||||
final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
|
||||
if (counter != null) {
|
||||
final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
|
||||
@@ -203,9 +207,10 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
|
||||
|
||||
powerDurationAndTraffic.durationMs = idleTime + rxTime + txTime;
|
||||
powerDurationAndTraffic.powerMah = mIdlePowerEstimator.calculatePower(idleTime)
|
||||
+ mTxPowerEstimator.calculatePower(txTime)
|
||||
+ mRxPowerEstimator.calculatePower(rxTime);
|
||||
if (!isMeasuredPowerAvailable) {
|
||||
powerDurationAndTraffic.powerMah
|
||||
= calcPowerFromControllerDataMah(rxTime, txTime, idleTime);
|
||||
}
|
||||
|
||||
if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
|
||||
Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime
|
||||
@@ -214,21 +219,20 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final double wifiPacketPower = (
|
||||
powerDurationAndTraffic.wifiRxPackets + powerDurationAndTraffic.wifiTxPackets)
|
||||
* mWifiPowerPerPacket;
|
||||
final long wifiRunningTime = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
|
||||
final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
|
||||
long batchScanTimeMs = 0;
|
||||
for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
|
||||
batchScanTimeMs += u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
|
||||
}
|
||||
|
||||
powerDurationAndTraffic.durationMs = wifiRunningTime;
|
||||
powerDurationAndTraffic.powerMah = wifiPacketPower
|
||||
+ mPowerOnPowerEstimator.calculatePower(wifiRunningTime)
|
||||
+ mScanPowerEstimator.calculatePower(wifiScanTimeMs)
|
||||
+ mBatchScanPowerEstimator.calculatePower(batchScanTimeMs);
|
||||
|
||||
if (!isMeasuredPowerAvailable) {
|
||||
final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
|
||||
long batchTimeMs = 0;
|
||||
for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
|
||||
batchTimeMs += u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
|
||||
}
|
||||
powerDurationAndTraffic.powerMah = calcPowerWithoutControllerDataMah(
|
||||
powerDurationAndTraffic.wifiRxPackets,
|
||||
powerDurationAndTraffic.wifiTxPackets,
|
||||
wifiRunningTime, wifiScanTimeMs, batchTimeMs);
|
||||
}
|
||||
|
||||
if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
|
||||
Log.d(TAG, "UID " + u.getUid() + ": power=" + formatCharge(
|
||||
@@ -238,12 +242,20 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
}
|
||||
|
||||
private void calculateRemaining(PowerDurationAndTraffic powerDurationAndTraffic,
|
||||
BatteryStats stats, long rawRealtimeUs,
|
||||
int statsType, boolean hasWifiPowerReporting, long totalAppDurationMs,
|
||||
double totalAppPowerMah) {
|
||||
BatteryStats stats, long rawRealtimeUs, int statsType,
|
||||
boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel,
|
||||
long totalAppDurationMs, double totalAppPowerMah) {
|
||||
|
||||
long totalDurationMs;
|
||||
double totalPowerMah;
|
||||
if (hasWifiPowerReporting) {
|
||||
double totalPowerMah = 0;
|
||||
|
||||
final long measuredChargeUC = stats.getWifiMeasuredBatteryConsumptionUC();
|
||||
final boolean isMeasuredPowerAvailable
|
||||
= !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
|
||||
if (isMeasuredPowerAvailable) {
|
||||
totalPowerMah = uCtoMah(measuredChargeUC);
|
||||
}
|
||||
if (hasWifiActivityReporting && mHasWifiPowerController) {
|
||||
final BatteryStats.ControllerActivityCounter counter =
|
||||
stats.getWifiControllerActivity();
|
||||
|
||||
@@ -253,17 +265,19 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
|
||||
totalDurationMs = idleTimeMs + rxTimeMs + txTimeMs;
|
||||
|
||||
totalPowerMah =
|
||||
counter.getPowerCounter().getCountLocked(statsType) / (double) (1000 * 60 * 60);
|
||||
if (totalPowerMah == 0) {
|
||||
// Some controllers do not report power drain, so we can calculate it here.
|
||||
totalPowerMah = mIdlePowerEstimator.calculatePower(idleTimeMs)
|
||||
+ mTxPowerEstimator.calculatePower(txTimeMs)
|
||||
+ mRxPowerEstimator.calculatePower(rxTimeMs);
|
||||
if (!isMeasuredPowerAvailable) {
|
||||
totalPowerMah = counter.getPowerCounter().getCountLocked(statsType)
|
||||
/ (double) (1000 * 60 * 60);
|
||||
if (totalPowerMah == 0) {
|
||||
// Some controllers do not report power drain, so we can calculate it here.
|
||||
totalPowerMah = calcPowerFromControllerDataMah(rxTimeMs, txTimeMs, idleTimeMs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
totalDurationMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType) / 1000;
|
||||
totalPowerMah = mPowerOnPowerEstimator.calculatePower(totalDurationMs);
|
||||
if (!isMeasuredPowerAvailable) {
|
||||
totalPowerMah = calcGlobalPowerWithoutControllerDataMah(totalDurationMs);
|
||||
}
|
||||
}
|
||||
|
||||
powerDurationAndTraffic.durationMs = Math.max(0, totalDurationMs - totalAppDurationMs);
|
||||
@@ -274,6 +288,29 @@ public class WifiPowerCalculator extends PowerCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns (global or uid) estimated wifi power used using WifiControllerActivity data. */
|
||||
public double calcPowerFromControllerDataMah(long rxTimeMs, long txTimeMs, long idleTimeMs) {
|
||||
return mRxPowerEstimator.calculatePower(rxTimeMs)
|
||||
+ mTxPowerEstimator.calculatePower(txTimeMs)
|
||||
+ mIdlePowerEstimator.calculatePower(idleTimeMs);
|
||||
}
|
||||
|
||||
/** Returns per-uid estimated wifi power used using non-WifiControllerActivity data. */
|
||||
public double calcPowerWithoutControllerDataMah(long rxPackets, long txPackets,
|
||||
long wifiRunningTimeMs, long wifiScanTimeMs, long wifiBatchScanTimeMs) {
|
||||
return
|
||||
(rxPackets + txPackets) * mWifiPowerPerPacket
|
||||
+ mPowerOnPowerEstimator.calculatePower(wifiRunningTimeMs)
|
||||
+ mScanPowerEstimator.calculatePower(wifiScanTimeMs)
|
||||
+ mBatchScanPowerEstimator.calculatePower(wifiBatchScanTimeMs);
|
||||
|
||||
}
|
||||
|
||||
/** Returns global estimated wifi power used using non-WifiControllerActivity data. */
|
||||
public double calcGlobalPowerWithoutControllerDataMah(long globalWifiRunningTimeMs) {
|
||||
return mPowerOnPowerEstimator.calculatePower(globalWifiRunningTimeMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return estimated power per Wi-Fi packet in mAh/packet where 1 packet = 2 KB.
|
||||
*/
|
||||
|
||||
@@ -52,7 +52,9 @@ public class MeasuredEnergyStats {
|
||||
public static final int POWER_BUCKET_SCREEN_DOZE = 1;
|
||||
public static final int POWER_BUCKET_SCREEN_OTHER = 2;
|
||||
public static final int POWER_BUCKET_CPU = 3;
|
||||
public static final int NUMBER_STANDARD_POWER_BUCKETS = 4; // Buckets above this are custom.
|
||||
public static final int POWER_BUCKET_WIFI = 4;
|
||||
public static final int POWER_BUCKET_BLUETOOTH = 5;
|
||||
public static final int NUMBER_STANDARD_POWER_BUCKETS = 6; // Buckets above this are custom.
|
||||
|
||||
@IntDef(prefix = {"POWER_BUCKET_"}, value = {
|
||||
POWER_BUCKET_UNKNOWN,
|
||||
@@ -60,6 +62,8 @@ public class MeasuredEnergyStats {
|
||||
POWER_BUCKET_SCREEN_DOZE,
|
||||
POWER_BUCKET_SCREEN_OTHER,
|
||||
POWER_BUCKET_CPU,
|
||||
POWER_BUCKET_WIFI,
|
||||
POWER_BUCKET_BLUETOOTH,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface StandardPowerBucket {
|
||||
|
||||
@@ -33,11 +33,15 @@ import android.util.SparseArray;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.power.MeasuredEnergyStats;
|
||||
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class BatteryUsageStatsRule implements TestRule {
|
||||
private final PowerProfile mPowerProfile;
|
||||
private final MockClocks mMockClocks = new MockClocks();
|
||||
@@ -98,6 +102,16 @@ public class BatteryUsageStatsRule implements TestRule {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Call only after setting the power profile information. */
|
||||
public BatteryUsageStatsRule initMeasuredEnergyStatsLocked(int numCustom) {
|
||||
final boolean[] supportedStandardBuckets =
|
||||
new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
|
||||
Arrays.fill(supportedStandardBuckets, true);
|
||||
mBatteryStats.initMeasuredEnergyStatsLocked(supportedStandardBuckets, numCustom);
|
||||
mBatteryStats.informThatAllExternalStatsAreFlushed();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BatteryUsageStatsRule startWithScreenOn(boolean screenOn) {
|
||||
mScreenOn = screenOn;
|
||||
return this;
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryUsageStatsQuery;
|
||||
import android.os.Process;
|
||||
import android.os.SystemBatteryConsumer;
|
||||
|
||||
@@ -60,7 +61,8 @@ public class BluetoothPowerCalculatorTest {
|
||||
BluetoothPowerCalculator calculator =
|
||||
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
|
||||
|
||||
mStatsRule.apply(calculator);
|
||||
mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
|
||||
calculator);
|
||||
|
||||
assertBluetoothPowerAndDuration(
|
||||
mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID),
|
||||
@@ -91,7 +93,8 @@ public class BluetoothPowerCalculatorTest {
|
||||
BluetoothPowerCalculator calculator =
|
||||
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
|
||||
|
||||
mStatsRule.apply(calculator);
|
||||
mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
|
||||
calculator);
|
||||
|
||||
assertBluetoothPowerAndDuration(
|
||||
mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID),
|
||||
|
||||
@@ -46,6 +46,7 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
|
||||
initTimersAndCounters();
|
||||
|
||||
setExternalStatsSyncLocked(new DummyExternalStatsSync());
|
||||
informThatAllExternalStatsAreFlushed();
|
||||
|
||||
final boolean[] supportedStandardBuckets =
|
||||
new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package com.android.internal.os;
|
||||
|
||||
|
||||
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkStats;
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryUsageStatsQuery;
|
||||
import android.os.Process;
|
||||
import android.os.SystemBatteryConsumer;
|
||||
import android.os.UidBatteryConsumer;
|
||||
@@ -50,10 +53,11 @@ public class WifiPowerCalculatorTest {
|
||||
.setAveragePower(PowerProfile.POWER_WIFI_ON, 360.0)
|
||||
.setAveragePower(PowerProfile.POWER_WIFI_SCAN, 480.0)
|
||||
.setAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, 720.0)
|
||||
.setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 1080.0);
|
||||
.setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 1080.0)
|
||||
.initMeasuredEnergyStatsLocked(0);
|
||||
|
||||
@Test
|
||||
public void testPowerControllerBasedModel() {
|
||||
/** Sets up a batterystats object with pre-populated network values. */
|
||||
private BatteryStatsImpl setupTestNetworkNumbers() {
|
||||
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
|
||||
|
||||
batteryStats.noteNetworkInterfaceForTransports("wifi",
|
||||
@@ -64,13 +68,25 @@ public class WifiPowerCalculatorTest {
|
||||
.insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
|
||||
mStatsRule.setNetworkStats(networkStats);
|
||||
|
||||
WifiActivityEnergyInfo energyInfo = new WifiActivityEnergyInfo(10000,
|
||||
WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 1000, 2000, 3000, 4000);
|
||||
return batteryStats;
|
||||
}
|
||||
|
||||
batteryStats.updateWifiState(energyInfo, 1000, 1000);
|
||||
/** Sets up an WifiActivityEnergyInfo for ActivityController-model-based tests. */
|
||||
private WifiActivityEnergyInfo setupPowerControllerBasedModelEnergyNumbersInfo() {
|
||||
return new WifiActivityEnergyInfo(10000,
|
||||
WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 1000, 2000, 3000, 4000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPowerControllerBasedModel_nonMeasured() {
|
||||
final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
|
||||
final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
|
||||
|
||||
batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000);
|
||||
|
||||
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
|
||||
mStatsRule.apply(calculator);
|
||||
mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
|
||||
calculator);
|
||||
|
||||
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
|
||||
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
|
||||
@@ -87,30 +103,54 @@ public class WifiPowerCalculatorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimerBasedModel() {
|
||||
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
|
||||
public void testPowerControllerBasedModel_measured() {
|
||||
final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
|
||||
final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
|
||||
|
||||
batteryStats.noteNetworkInterfaceForTransports("wifi",
|
||||
new int[]{NetworkCapabilities.TRANSPORT_WIFI});
|
||||
batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000);
|
||||
|
||||
NetworkStats networkStats = new NetworkStats(10000, 1)
|
||||
.insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
|
||||
.insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
|
||||
mStatsRule.setNetworkStats(networkStats);
|
||||
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
|
||||
mStatsRule.apply(calculator);
|
||||
|
||||
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
|
||||
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
|
||||
.isEqualTo(1423);
|
||||
/* Same ratio as in testPowerControllerBasedModel_nonMeasured but scaled by 1_000_000uC. */
|
||||
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
|
||||
.isWithin(PRECISION).of(0.2214666 / (0.2214666 + 0.645200) * 1_000_000 / 3600000);
|
||||
|
||||
SystemBatteryConsumer systemConsumer =
|
||||
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
|
||||
assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
|
||||
.isEqualTo(5577);
|
||||
/* Same ratio as in testPowerControllerBasedModel_nonMeasured but scaled by 1_000_000uC. */
|
||||
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
|
||||
.isWithin(PRECISION).of(0.645200 / (0.2214666 + 0.645200) * 1_000_000 / 3600000);
|
||||
}
|
||||
|
||||
/** Sets up batterystats object with prepopulated network & timer data for Timer-model tests. */
|
||||
private BatteryStatsImpl setupTimerBasedModelTestNumbers() {
|
||||
final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
|
||||
batteryStats.noteWifiScanStartedLocked(APP_UID, 1000, 1000);
|
||||
batteryStats.noteWifiScanStoppedLocked(APP_UID, 2000, 2000);
|
||||
batteryStats.noteWifiRunningLocked(new WorkSource(APP_UID), 3000, 3000);
|
||||
batteryStats.noteWifiStoppedLocked(new WorkSource(APP_UID), 4000, 4000);
|
||||
batteryStats.noteWifiRunningLocked(new WorkSource(Process.WIFI_UID), 1111, 2222);
|
||||
batteryStats.noteWifiStoppedLocked(new WorkSource(Process.WIFI_UID), 3333, 4444);
|
||||
return batteryStats;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimerBasedModel_nonMeasured() {
|
||||
final BatteryStatsImpl batteryStats = setupTimerBasedModelTestNumbers();
|
||||
|
||||
// Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
|
||||
// on the packet counts.
|
||||
batteryStats.updateWifiState(/* energyInfo */ null, 1000, 1000);
|
||||
batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000);
|
||||
|
||||
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
|
||||
mStatsRule.apply(calculator);
|
||||
mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
|
||||
calculator);
|
||||
|
||||
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
|
||||
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
|
||||
@@ -125,4 +165,31 @@ public class WifiPowerCalculatorTest {
|
||||
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
|
||||
.isWithin(PRECISION).of(0.8759216);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimerBasedModel_measured() {
|
||||
final BatteryStatsImpl batteryStats = setupTimerBasedModelTestNumbers();
|
||||
|
||||
// Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
|
||||
// on the packet counts.
|
||||
batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000);
|
||||
|
||||
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
|
||||
mStatsRule.apply(calculator);
|
||||
|
||||
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
|
||||
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
|
||||
.isEqualTo(1000);
|
||||
/* Same ratio as in testTimerBasedModel_nonMeasured but scaled by 1_000_000uC. */
|
||||
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
|
||||
.isWithin(PRECISION).of(0.8231573 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000);
|
||||
|
||||
SystemBatteryConsumer systemConsumer =
|
||||
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
|
||||
assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
|
||||
.isEqualTo(2222);
|
||||
/* Same ratio as in testTimerBasedModel_nonMeasured but scaled by 1_000_000uC. */
|
||||
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
|
||||
.isWithin(PRECISION).of(0.8759216 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,9 +589,9 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
Slog.w(TAG, "exception reading modem stats: " + e.getCause());
|
||||
}
|
||||
|
||||
final MeasuredEnergySnapshot.MeasuredEnergyDeltaData measuredEnergyDelta;
|
||||
final MeasuredEnergySnapshot.MeasuredEnergyDeltaData measuredEnergyDeltas;
|
||||
if (mMeasuredEnergySnapshot == null || futureECRs == null) {
|
||||
measuredEnergyDelta = null;
|
||||
measuredEnergyDeltas = null;
|
||||
} else {
|
||||
final int voltageMv;
|
||||
synchronized (mStats) {
|
||||
@@ -610,7 +610,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
ecrs = null;
|
||||
}
|
||||
|
||||
measuredEnergyDelta = mMeasuredEnergySnapshot.updateAndGetDelta(ecrs, voltageMv);
|
||||
measuredEnergyDeltas = mMeasuredEnergySnapshot.updateAndGetDelta(ecrs, voltageMv);
|
||||
}
|
||||
|
||||
final long elapsedRealtime = SystemClock.elapsedRealtime();
|
||||
@@ -633,10 +633,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
}
|
||||
|
||||
final long[] cpuClusterChargeUC;
|
||||
if (measuredEnergyDelta == null) {
|
||||
if (measuredEnergyDeltas == null) {
|
||||
cpuClusterChargeUC = null;
|
||||
} else {
|
||||
cpuClusterChargeUC = measuredEnergyDelta.cpuClusterChargeUC;
|
||||
cpuClusterChargeUC = measuredEnergyDeltas.cpuClusterChargeUC;
|
||||
}
|
||||
mStats.updateCpuTimeLocked(onBattery, onBatteryScreenOff, cpuClusterChargeUC);
|
||||
}
|
||||
@@ -650,9 +650,9 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
mStats.updateRpmStatsLocked(elapsedRealtimeUs);
|
||||
}
|
||||
|
||||
// Inform mStats about each applicable measured energy.
|
||||
if (measuredEnergyDelta != null) {
|
||||
final long displayChargeUC = measuredEnergyDelta.displayChargeUC;
|
||||
// Inform mStats about each applicable measured energy (unless addressed elsewhere).
|
||||
if (measuredEnergyDeltas != null) {
|
||||
final long displayChargeUC = measuredEnergyDeltas.displayChargeUC;
|
||||
if (displayChargeUC != MeasuredEnergySnapshot.UNAVAILABLE) {
|
||||
// If updating, pass in what BatteryExternalStatsWorker thinks screenState is.
|
||||
mStats.updateDisplayMeasuredEnergyStatsLocked(displayChargeUC, screenState,
|
||||
@@ -660,19 +660,23 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
}
|
||||
}
|
||||
// Inform mStats about each applicable custom energy bucket.
|
||||
if (measuredEnergyDelta != null
|
||||
&& measuredEnergyDelta.otherTotalChargeUC != null) {
|
||||
if (measuredEnergyDeltas != null
|
||||
&& measuredEnergyDeltas.otherTotalChargeUC != null) {
|
||||
// Iterate over the custom (EnergyConsumerType.OTHER) ordinals.
|
||||
for (int ord = 0; ord < measuredEnergyDelta.otherTotalChargeUC.length; ord++) {
|
||||
long totalEnergy = measuredEnergyDelta.otherTotalChargeUC[ord];
|
||||
SparseLongArray uidEnergies = measuredEnergyDelta.otherUidChargesUC[ord];
|
||||
for (int ord = 0; ord < measuredEnergyDeltas.otherTotalChargeUC.length; ord++) {
|
||||
long totalEnergy = measuredEnergyDeltas.otherTotalChargeUC[ord];
|
||||
SparseLongArray uidEnergies = measuredEnergyDeltas.otherUidChargesUC[ord];
|
||||
mStats.updateCustomMeasuredEnergyStatsLocked(ord, totalEnergy, uidEnergies);
|
||||
}
|
||||
}
|
||||
|
||||
if (bluetoothInfo != null) {
|
||||
if (bluetoothInfo.isValid()) {
|
||||
mStats.updateBluetoothStateLocked(bluetoothInfo, elapsedRealtime, uptime);
|
||||
final long btChargeUC = measuredEnergyDeltas != null
|
||||
? measuredEnergyDeltas.bluetoothChargeUC
|
||||
: MeasuredEnergySnapshot.UNAVAILABLE;
|
||||
mStats.updateBluetoothStateLocked(bluetoothInfo,
|
||||
btChargeUC, elapsedRealtime, uptime);
|
||||
} else {
|
||||
Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo);
|
||||
}
|
||||
@@ -684,10 +688,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
|
||||
if (wifiInfo != null) {
|
||||
if (wifiInfo.isValid()) {
|
||||
// TODO: wifiEnergyDelta = measuredEnergyDelta.consumerTypeEnergyUJ
|
||||
// .get(EnergyConsumerType.WIFI, MeasuredEnergySnapshot.UNAVAILABLE)
|
||||
mStats.updateWifiState(extractDeltaLocked(wifiInfo)
|
||||
/*, TODO: wifiEnergyDelta */, elapsedRealtime, uptime);
|
||||
final long wifiChargeUC = measuredEnergyDeltas != null ?
|
||||
measuredEnergyDeltas.wifiChargeUC : MeasuredEnergySnapshot.UNAVAILABLE;
|
||||
mStats.updateWifiState(
|
||||
extractDeltaLocked(wifiInfo), wifiChargeUC, elapsedRealtime, uptime);
|
||||
} else {
|
||||
Slog.w(TAG, "wifi info is invalid: " + wifiInfo);
|
||||
}
|
||||
@@ -820,13 +824,19 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
final EnergyConsumer consumer = idToConsumer.valueAt(idx);
|
||||
switch (consumer.type) {
|
||||
case EnergyConsumerType.BLUETOOTH:
|
||||
buckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH] = true;
|
||||
break;
|
||||
case EnergyConsumerType.CPU_CLUSTER:
|
||||
buckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true;
|
||||
break;
|
||||
case EnergyConsumerType.DISPLAY:
|
||||
buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON] = true;
|
||||
buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE] = true;
|
||||
buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_OTHER] = true;
|
||||
break;
|
||||
case EnergyConsumerType.CPU_CLUSTER:
|
||||
buckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true;
|
||||
case EnergyConsumerType.WIFI:
|
||||
buckets[MeasuredEnergyStats.POWER_BUCKET_WIFI] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -864,13 +874,18 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
|
||||
}
|
||||
|
||||
final IntArray energyConsumerIds = new IntArray();
|
||||
if ((flags & UPDATE_BT) != 0) {
|
||||
addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.BLUETOOTH);
|
||||
}
|
||||
if ((flags & UPDATE_CPU) != 0) {
|
||||
addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.CPU_CLUSTER);
|
||||
}
|
||||
if ((flags & UPDATE_DISPLAY) != 0) {
|
||||
addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.DISPLAY);
|
||||
}
|
||||
// TODO: Wifi, Bluetooth, etc., go here
|
||||
if ((flags & UPDATE_WIFI) != 0) {
|
||||
addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.WIFI);
|
||||
}
|
||||
|
||||
if (energyConsumerIds.size() == 0) {
|
||||
return null;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.am;
|
||||
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
|
||||
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.bluetooth.BluetoothActivityEnergyInfo;
|
||||
@@ -1927,7 +1928,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
final long elapsedRealtime = SystemClock.elapsedRealtime();
|
||||
final long uptime = SystemClock.uptimeMillis();
|
||||
mHandler.post(() -> {
|
||||
mStats.updateWifiState(info, elapsedRealtime, uptime);
|
||||
mStats.updateWifiState(info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1945,7 +1946,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
final long uptime = SystemClock.uptimeMillis();
|
||||
mHandler.post(() -> {
|
||||
synchronized (mStats) {
|
||||
mStats.updateBluetoothStateLocked(info, elapsedRealtime, uptime);
|
||||
mStats.updateBluetoothStateLocked(
|
||||
info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class MeasuredEnergySnapshot {
|
||||
|
||||
private static final int MILLIVOLTS_PER_VOLT = 1000;
|
||||
|
||||
public static final long UNAVAILABLE = -1L;
|
||||
public static final long UNAVAILABLE = android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
|
||||
|
||||
/** Map of {@link EnergyConsumer#id} to its corresponding {@link EnergyConsumer}. */
|
||||
private final SparseArray<EnergyConsumer> mEnergyConsumers;
|
||||
@@ -109,12 +109,18 @@ public class MeasuredEnergySnapshot {
|
||||
|
||||
/** Class for returning the relevant data calculated from the measured energy delta */
|
||||
static class MeasuredEnergyDeltaData {
|
||||
/** The chargeUC for {@link EnergyConsumerType#DISPLAY}. */
|
||||
public long displayChargeUC = UNAVAILABLE;
|
||||
/** The chargeUC for {@link EnergyConsumerType#BLUETOOTH}. */
|
||||
public long bluetoothChargeUC = UNAVAILABLE;
|
||||
|
||||
/** The chargeUC for {@link EnergyConsumerType#CPU_CLUSTER}s. */
|
||||
public long[] cpuClusterChargeUC = null;
|
||||
|
||||
/** The chargeUC for {@link EnergyConsumerType#DISPLAY}. */
|
||||
public long displayChargeUC = UNAVAILABLE;
|
||||
|
||||
/** The chargeUC for {@link EnergyConsumerType#WIFI}. */
|
||||
public long wifiChargeUC = UNAVAILABLE;
|
||||
|
||||
/** Map of {@link EnergyConsumerType#OTHER} ordinals to their total chargeUC. */
|
||||
public @Nullable long[] otherTotalChargeUC = null;
|
||||
|
||||
@@ -196,8 +202,8 @@ public class MeasuredEnergySnapshot {
|
||||
|
||||
final long deltaChargeUC = calculateChargeConsumedUC(deltaUJ, avgVoltageMV);
|
||||
switch (type) {
|
||||
case EnergyConsumerType.DISPLAY:
|
||||
output.displayChargeUC = deltaChargeUC;
|
||||
case EnergyConsumerType.BLUETOOTH:
|
||||
output.bluetoothChargeUC = deltaChargeUC;
|
||||
break;
|
||||
|
||||
case EnergyConsumerType.CPU_CLUSTER:
|
||||
@@ -207,6 +213,14 @@ public class MeasuredEnergySnapshot {
|
||||
output.cpuClusterChargeUC[ordinal] = deltaChargeUC;
|
||||
break;
|
||||
|
||||
case EnergyConsumerType.DISPLAY:
|
||||
output.displayChargeUC = deltaChargeUC;
|
||||
break;
|
||||
|
||||
case EnergyConsumerType.WIFI:
|
||||
output.wifiChargeUC = deltaChargeUC;
|
||||
break;
|
||||
|
||||
case EnergyConsumerType.OTHER:
|
||||
if (output.otherTotalChargeUC == null) {
|
||||
output.otherTotalChargeUC = new long[getNumOtherOrdinals()];
|
||||
@@ -215,6 +229,7 @@ public class MeasuredEnergySnapshot {
|
||||
output.otherTotalChargeUC[ordinal] = deltaChargeUC;
|
||||
output.otherUidChargesUC[ordinal] = otherUidCharges;
|
||||
break;
|
||||
|
||||
default:
|
||||
Slog.w(TAG, "Ignoring consumer " + consumer.name + " of unknown type " + type);
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package com.android.server.am;
|
||||
|
||||
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL;
|
||||
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_BT;
|
||||
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
|
||||
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
|
||||
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -39,6 +41,7 @@ import android.util.SparseArray;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.os.BatteryStatsImpl;
|
||||
import com.android.internal.os.PowerProfile;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -61,7 +64,7 @@ public class BatteryExternalStatsWorkerTest {
|
||||
public void setUp() {
|
||||
final Context context = InstrumentationRegistry.getContext();
|
||||
|
||||
mBatteryStatsImpl = new TestBatteryStatsImpl();
|
||||
mBatteryStatsImpl = new TestBatteryStatsImpl(context);
|
||||
mPowerStatsInternal = new TestPowerStatsInternal();
|
||||
mBatteryExternalStatsWorker = new BatteryExternalStatsWorker(new TestInjector(context),
|
||||
mBatteryStatsImpl);
|
||||
@@ -72,13 +75,24 @@ public class BatteryExternalStatsWorkerTest {
|
||||
final int numCpuClusters = 4;
|
||||
final int numOther = 3;
|
||||
|
||||
final IntArray tempAllIds = new IntArray();
|
||||
// Add some energy consumers used by BatteryExternalStatsWorker.
|
||||
final IntArray tempAllIds = new IntArray();
|
||||
|
||||
final int displayId = mPowerStatsInternal.addEnergyConsumer(EnergyConsumerType.DISPLAY, 0,
|
||||
"display");
|
||||
tempAllIds.add(displayId);
|
||||
mPowerStatsInternal.incrementEnergyConsumption(displayId, 12345);
|
||||
|
||||
final int wifiId = mPowerStatsInternal.addEnergyConsumer(EnergyConsumerType.WIFI, 0,
|
||||
"wifi");
|
||||
tempAllIds.add(wifiId);
|
||||
mPowerStatsInternal.incrementEnergyConsumption(wifiId, 23456);
|
||||
|
||||
final int btId = mPowerStatsInternal.addEnergyConsumer(EnergyConsumerType.BLUETOOTH, 0,
|
||||
"bt");
|
||||
tempAllIds.add(btId);
|
||||
mPowerStatsInternal.incrementEnergyConsumption(btId, 34567);
|
||||
|
||||
final int[] cpuClusterIds = new int[numCpuClusters];
|
||||
for (int i = 0; i < numCpuClusters; i++) {
|
||||
cpuClusterIds[i] = mPowerStatsInternal.addEnergyConsumer(
|
||||
@@ -109,6 +123,18 @@ public class BatteryExternalStatsWorkerTest {
|
||||
assertEquals(1, displayResults.length);
|
||||
assertEquals(displayId, displayResults[0].id);
|
||||
|
||||
final EnergyConsumerResult[] wifiResults =
|
||||
mBatteryExternalStatsWorker.getMeasuredEnergyLocked(UPDATE_WIFI).getNow(null);
|
||||
// Results should only have the wifi energy consumer
|
||||
assertEquals(1, wifiResults.length);
|
||||
assertEquals(wifiId, wifiResults[0].id);
|
||||
|
||||
final EnergyConsumerResult[] bluetoothResults =
|
||||
mBatteryExternalStatsWorker.getMeasuredEnergyLocked(UPDATE_BT).getNow(null);
|
||||
// Results should only have the bluetooth energy consumer
|
||||
assertEquals(1, bluetoothResults.length);
|
||||
assertEquals(btId, bluetoothResults[0].id);
|
||||
|
||||
final EnergyConsumerResult[] cpuResults =
|
||||
mBatteryExternalStatsWorker.getMeasuredEnergyLocked(UPDATE_CPU).getNow(null);
|
||||
// Results should only have the cpu cluster energy consumers
|
||||
@@ -148,6 +174,9 @@ public class BatteryExternalStatsWorkerTest {
|
||||
}
|
||||
|
||||
public class TestBatteryStatsImpl extends BatteryStatsImpl {
|
||||
public TestBatteryStatsImpl(Context context) {
|
||||
mPowerProfile = new PowerProfile(context, true /* forTest */);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestPowerStatsInternal extends PowerStatsInternal {
|
||||
|
||||
Reference in New Issue
Block a user