Loading core/java/android/os/BatteryConsumer.java +5 −0 Original line number Diff line number Diff line Loading @@ -756,6 +756,11 @@ public abstract class BatteryConsumer { mPowerComponentsBuilder = new PowerComponents.Builder(data); } @Nullable public Key[] getKeys(@PowerComponent int componentId) { return mData.getKeys(componentId); } @Nullable public Key getKey(@PowerComponent int componentId, @ProcessState int processState) { return mData.getKey(componentId, processState); Loading core/java/android/os/BatteryStats.java +11 −0 Original line number Diff line number Diff line Loading @@ -660,6 +660,7 @@ public abstract class BatteryStats implements Parcelable { mapUidProcessStateToBatteryConsumerProcessState(int processState) { switch (processState) { case BatteryStats.Uid.PROCESS_STATE_TOP: case BatteryStats.Uid.PROCESS_STATE_FOREGROUND: return BatteryConsumer.PROCESS_STATE_FOREGROUND; case BatteryStats.Uid.PROCESS_STATE_BACKGROUND: case BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING: Loading Loading @@ -1027,6 +1028,16 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getCpuMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) of the uid's cpu usage when in the * specified process state. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ public abstract long getCpuMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState); /** * Returns the battery consumption (in microcoulombs) of the uid's GNSS usage, derived from * on device power measurement data. Loading core/java/android/os/BatteryUsageStatsQuery.java +4 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,10 @@ public final class BatteryUsageStatsQuery implements Parcelable { return (mFlags & FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0; } public boolean isProcessStateDataNeeded() { return (mFlags & FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0; } /** * Returns the client's tolerance for stale battery stats. The data is allowed to be up to * this many milliseconds out-of-date. Loading core/java/com/android/internal/os/BatteryStatsImpl.java +28 −0 Original line number Diff line number Diff line Loading @@ -588,6 +588,10 @@ public class BatteryStatsImpl extends BatteryStats { procState = u.mProcessState; } if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) { continue; } final long timestampMs = mClock.elapsedRealtime(); final LongArrayMultiStateCounter onBatteryCounter = u.getProcStateTimeCounter().getCounter(); Loading Loading @@ -8599,6 +8603,23 @@ public class BatteryStatsImpl extends BatteryStats { return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket); } /** * Returns the battery consumption (in microcoulombs) of this uid for a standard power * bucket and a process state, such as Uid.PROCESS_STATE_TOP. */ @GuardedBy("mBsi") public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket, int processState) { if (mBsi.mGlobalMeasuredEnergyStats == null || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) { return POWER_DATA_UNAVAILABLE; } if (mUidMeasuredEnergyStats == null) { return 0L; // It is supported, but was never filled, so it must be 0 } return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket, processState); } @GuardedBy("mBsi") @Override public long[] getCustomConsumerMeasuredBatteryConsumptionUC() { Loading @@ -8625,6 +8646,13 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("mBsi") @Override public long getCpuMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState) { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU, processState); } @Override public long getGnssMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS); Loading core/java/com/android/internal/os/CpuPowerCalculator.java +121 −29 Original line number Diff line number Diff line Loading @@ -25,11 +25,13 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import java.util.Arrays; import java.util.List; public class CpuPowerCalculator extends PowerCalculator { private static final String TAG = "CpuPowerCalculator"; private static final boolean DEBUG = BatteryStatsHelper.DEBUG; private static final BatteryConsumer.Key[] UNINITIALIZED_KEYS = new BatteryConsumer.Key[0]; private final int mNumCpuClusters; // Time-in-state based CPU power estimation model computes the estimated power Loading @@ -44,13 +46,16 @@ public class CpuPowerCalculator extends PowerCalculator { private final UsageBasedPowerEstimator[] mPerClusterPowerEstimators; // Multiple estimators per cluster: one per available scaling frequency. Note that different // clusters have different sets of frequencies and corresponding power consumption averages. private final UsageBasedPowerEstimator[][] mPerCpuFreqPowerEstimators; private final UsageBasedPowerEstimator[][] mPerCpuFreqPowerEstimatorsByCluster; // Flattened array of estimators across clusters private final UsageBasedPowerEstimator[] mPerCpuFreqPowerEstimators; private static class Result { public long durationMs; public double powerMah; public long durationFgMs; public String packageWithHighestDrain; public double[] perProcStatePowerMah; } public CpuPowerCalculator(PowerProfile profile) { Loading @@ -65,14 +70,23 @@ public class CpuPowerCalculator extends PowerCalculator { profile.getAveragePowerForCpuCluster(cluster)); } mPerCpuFreqPowerEstimators = new UsageBasedPowerEstimator[mNumCpuClusters][]; int freqCount = 0; for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { freqCount += profile.getNumSpeedStepsInCpuCluster(cluster); } mPerCpuFreqPowerEstimatorsByCluster = new UsageBasedPowerEstimator[mNumCpuClusters][]; mPerCpuFreqPowerEstimators = new UsageBasedPowerEstimator[freqCount]; int index = 0; for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { final int speedsForCluster = profile.getNumSpeedStepsInCpuCluster(cluster); mPerCpuFreqPowerEstimators[cluster] = new UsageBasedPowerEstimator[speedsForCluster]; mPerCpuFreqPowerEstimatorsByCluster[cluster] = new UsageBasedPowerEstimator[speedsForCluster]; for (int speed = 0; speed < speedsForCluster; speed++) { mPerCpuFreqPowerEstimators[cluster][speed] = new UsageBasedPowerEstimator( final UsageBasedPowerEstimator estimator = new UsageBasedPowerEstimator( profile.getAveragePowerForCpuCore(cluster, speed)); mPerCpuFreqPowerEstimatorsByCluster[cluster][speed] = estimator; mPerCpuFreqPowerEstimators[index++] = estimator; } } } Loading @@ -82,12 +96,20 @@ public class CpuPowerCalculator extends PowerCalculator { long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { double totalPowerMah = 0; BatteryConsumer.Key[] keys = UNINITIALIZED_KEYS; Result result = new Result(); final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, app.getBatteryStatsUid(), query, result); if (keys == UNINITIALIZED_KEYS) { if (query.isProcessStateDataNeeded()) { keys = app.getKeys(BatteryConsumer.POWER_COMPONENT_CPU); } else { keys = null; } } calculateApp(app, app.getBatteryStatsUid(), query, result, keys); totalPowerMah += result.powerMah; } Loading @@ -105,7 +127,7 @@ public class CpuPowerCalculator extends PowerCalculator { } private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryUsageStatsQuery query, Result result) { BatteryUsageStatsQuery query, Result result, BatteryConsumer.Key[] keys) { final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(consumptionUC, query); calculatePowerAndDuration(u, powerModel, consumptionUC, BatteryStats.STATS_SINCE_CHARGED, Loading @@ -114,6 +136,75 @@ public class CpuPowerCalculator extends PowerCalculator { app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah, powerModel) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU, result.durationMs) .setPackageWithHighestDrain(result.packageWithHighestDrain); if (query.isProcessStateDataNeeded() && keys != null) { switch (powerModel) { case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY: calculateMeasuredPowerPerProcessState(app, u, keys); break; case BatteryConsumer.POWER_MODEL_POWER_PROFILE: calculateModeledPowerPerProcessState(app, u, keys, result); break; } } } private void calculateMeasuredPowerPerProcessState(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryConsumer.Key[] keys) { for (BatteryConsumer.Key key : keys) { // The key for "PROCESS_STATE_ANY" has already been populated with the // full energy across all states. We don't want to override it with // the energy for "other" states, which excludes the tracked states like // foreground, background etc. if (key.processState == BatteryConsumer.PROCESS_STATE_ANY) { continue; } final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC(key.processState); if (consumptionUC != 0) { app.setConsumedPower(key, uCtoMah(consumptionUC), BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); } } } private void calculateModeledPowerPerProcessState(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryConsumer.Key[] keys, Result result) { if (result.perProcStatePowerMah == null) { result.perProcStatePowerMah = new double[BatteryConsumer.PROCESS_STATE_COUNT]; } else { Arrays.fill(result.perProcStatePowerMah, 0); } for (int uidProcState = 0; uidProcState < BatteryStats.Uid.NUM_PROCESS_STATE; uidProcState++) { @BatteryConsumer.ProcessState int procState = BatteryStats.mapUidProcessStateToBatteryConsumerProcessState(uidProcState); if (procState == BatteryConsumer.PROCESS_STATE_ANY) { continue; } // TODO(b/191921016): use per-state CPU active time final long cpuActiveTime = 0; // TODO(b/191921016): use per-state CPU cluster times final long[] cpuClusterTimes = null; final long[] cpuFreqTimes = u.getCpuFreqTimes(BatteryStats.STATS_SINCE_CHARGED, uidProcState); if (cpuActiveTime != 0 || cpuClusterTimes != null || cpuFreqTimes != null) { result.perProcStatePowerMah[procState] += calculateUidModeledPowerMah(u, cpuActiveTime, cpuClusterTimes, cpuFreqTimes); } } for (BatteryConsumer.Key key : keys) { if (key.processState == BatteryConsumer.PROCESS_STATE_ANY) { continue; } app.setConsumedPower(key, result.perProcStatePowerMah[key.processState], BatteryConsumer.POWER_MODEL_POWER_PROFILE); } } @Override Loading Loading @@ -205,16 +296,21 @@ public class CpuPowerCalculator extends PowerCalculator { * Calculates CPU power consumed by the specified app, using the PowerProfile model. */ public double calculateUidModeledPowerMah(BatteryStats.Uid u, int statsType) { return calculateUidModeledPowerMah(u, u.getCpuActiveTime(), u.getCpuClusterTimes(), u.getCpuFreqTimes(statsType)); } private double calculateUidModeledPowerMah(BatteryStats.Uid u, long cpuActiveTime, long[] cpuClusterTimes, long[] cpuFreqTimes) { // Constant battery drain when CPU is active double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime()); double powerMah = calculateActiveCpuPowerMah(cpuActiveTime); // Additional per-cluster battery drain long[] cpuClusterTimes = u.getCpuClusterTimes(); if (cpuClusterTimes != null) { if (cpuClusterTimes.length == mNumCpuClusters) { for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { double power = calculatePerCpuClusterPowerMah(cluster, cpuClusterTimes[cluster]); final double power = mPerClusterPowerEstimators[cluster] .calculatePower(cpuClusterTimes[cluster]); powerMah += power; if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster Loading @@ -228,21 +324,17 @@ public class CpuPowerCalculator extends PowerCalculator { } } // Additional per-frequency battery drain for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { final int speedsForCluster = mPerCpuFreqPowerEstimators[cluster].length; for (int speed = 0; speed < speedsForCluster; speed++) { final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType); final double power = calculatePerCpuFreqPowerMah(cluster, speed, timeUs / 1000); if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #" + speed + " timeUs=" + timeUs + " power=" + formatCharge(power)); if (cpuFreqTimes != null) { if (cpuFreqTimes.length == mPerCpuFreqPowerEstimators.length) { for (int i = 0; i < cpuFreqTimes.length; i++) { powerMah += mPerCpuFreqPowerEstimators[i].calculatePower(cpuFreqTimes[i]); } powerMah += power; } else { Log.w(TAG, "UID " + u.getUid() + " CPU freq # mismatch: Power Profile # " + mPerCpuFreqPowerEstimators.length + " actual # " + cpuFreqTimes.length); } } return powerMah; } Loading Loading @@ -277,7 +369,7 @@ public class CpuPowerCalculator extends PowerCalculator { */ public double calculatePerCpuFreqPowerMah(int cluster, int speedStep, long clusterSpeedDurationsMs) { return mPerCpuFreqPowerEstimators[cluster][speedStep].calculatePower( return mPerCpuFreqPowerEstimatorsByCluster[cluster][speedStep].calculatePower( clusterSpeedDurationsMs); } } Loading
core/java/android/os/BatteryConsumer.java +5 −0 Original line number Diff line number Diff line Loading @@ -756,6 +756,11 @@ public abstract class BatteryConsumer { mPowerComponentsBuilder = new PowerComponents.Builder(data); } @Nullable public Key[] getKeys(@PowerComponent int componentId) { return mData.getKeys(componentId); } @Nullable public Key getKey(@PowerComponent int componentId, @ProcessState int processState) { return mData.getKey(componentId, processState); Loading
core/java/android/os/BatteryStats.java +11 −0 Original line number Diff line number Diff line Loading @@ -660,6 +660,7 @@ public abstract class BatteryStats implements Parcelable { mapUidProcessStateToBatteryConsumerProcessState(int processState) { switch (processState) { case BatteryStats.Uid.PROCESS_STATE_TOP: case BatteryStats.Uid.PROCESS_STATE_FOREGROUND: return BatteryConsumer.PROCESS_STATE_FOREGROUND; case BatteryStats.Uid.PROCESS_STATE_BACKGROUND: case BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING: Loading Loading @@ -1027,6 +1028,16 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getCpuMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) of the uid's cpu usage when in the * specified process state. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ public abstract long getCpuMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState); /** * Returns the battery consumption (in microcoulombs) of the uid's GNSS usage, derived from * on device power measurement data. Loading
core/java/android/os/BatteryUsageStatsQuery.java +4 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,10 @@ public final class BatteryUsageStatsQuery implements Parcelable { return (mFlags & FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0; } public boolean isProcessStateDataNeeded() { return (mFlags & FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0; } /** * Returns the client's tolerance for stale battery stats. The data is allowed to be up to * this many milliseconds out-of-date. Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +28 −0 Original line number Diff line number Diff line Loading @@ -588,6 +588,10 @@ public class BatteryStatsImpl extends BatteryStats { procState = u.mProcessState; } if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) { continue; } final long timestampMs = mClock.elapsedRealtime(); final LongArrayMultiStateCounter onBatteryCounter = u.getProcStateTimeCounter().getCounter(); Loading Loading @@ -8599,6 +8603,23 @@ public class BatteryStatsImpl extends BatteryStats { return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket); } /** * Returns the battery consumption (in microcoulombs) of this uid for a standard power * bucket and a process state, such as Uid.PROCESS_STATE_TOP. */ @GuardedBy("mBsi") public long getMeasuredBatteryConsumptionUC(@StandardPowerBucket int bucket, int processState) { if (mBsi.mGlobalMeasuredEnergyStats == null || !mBsi.mGlobalMeasuredEnergyStats.isStandardBucketSupported(bucket)) { return POWER_DATA_UNAVAILABLE; } if (mUidMeasuredEnergyStats == null) { return 0L; // It is supported, but was never filled, so it must be 0 } return mUidMeasuredEnergyStats.getAccumulatedStandardBucketCharge(bucket, processState); } @GuardedBy("mBsi") @Override public long[] getCustomConsumerMeasuredBatteryConsumptionUC() { Loading @@ -8625,6 +8646,13 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("mBsi") @Override public long getCpuMeasuredBatteryConsumptionUC( @BatteryConsumer.ProcessState int processState) { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU, processState); } @Override public long getGnssMeasuredBatteryConsumptionUC() { return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_GNSS); Loading
core/java/com/android/internal/os/CpuPowerCalculator.java +121 −29 Original line number Diff line number Diff line Loading @@ -25,11 +25,13 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import java.util.Arrays; import java.util.List; public class CpuPowerCalculator extends PowerCalculator { private static final String TAG = "CpuPowerCalculator"; private static final boolean DEBUG = BatteryStatsHelper.DEBUG; private static final BatteryConsumer.Key[] UNINITIALIZED_KEYS = new BatteryConsumer.Key[0]; private final int mNumCpuClusters; // Time-in-state based CPU power estimation model computes the estimated power Loading @@ -44,13 +46,16 @@ public class CpuPowerCalculator extends PowerCalculator { private final UsageBasedPowerEstimator[] mPerClusterPowerEstimators; // Multiple estimators per cluster: one per available scaling frequency. Note that different // clusters have different sets of frequencies and corresponding power consumption averages. private final UsageBasedPowerEstimator[][] mPerCpuFreqPowerEstimators; private final UsageBasedPowerEstimator[][] mPerCpuFreqPowerEstimatorsByCluster; // Flattened array of estimators across clusters private final UsageBasedPowerEstimator[] mPerCpuFreqPowerEstimators; private static class Result { public long durationMs; public double powerMah; public long durationFgMs; public String packageWithHighestDrain; public double[] perProcStatePowerMah; } public CpuPowerCalculator(PowerProfile profile) { Loading @@ -65,14 +70,23 @@ public class CpuPowerCalculator extends PowerCalculator { profile.getAveragePowerForCpuCluster(cluster)); } mPerCpuFreqPowerEstimators = new UsageBasedPowerEstimator[mNumCpuClusters][]; int freqCount = 0; for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { freqCount += profile.getNumSpeedStepsInCpuCluster(cluster); } mPerCpuFreqPowerEstimatorsByCluster = new UsageBasedPowerEstimator[mNumCpuClusters][]; mPerCpuFreqPowerEstimators = new UsageBasedPowerEstimator[freqCount]; int index = 0; for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { final int speedsForCluster = profile.getNumSpeedStepsInCpuCluster(cluster); mPerCpuFreqPowerEstimators[cluster] = new UsageBasedPowerEstimator[speedsForCluster]; mPerCpuFreqPowerEstimatorsByCluster[cluster] = new UsageBasedPowerEstimator[speedsForCluster]; for (int speed = 0; speed < speedsForCluster; speed++) { mPerCpuFreqPowerEstimators[cluster][speed] = new UsageBasedPowerEstimator( final UsageBasedPowerEstimator estimator = new UsageBasedPowerEstimator( profile.getAveragePowerForCpuCore(cluster, speed)); mPerCpuFreqPowerEstimatorsByCluster[cluster][speed] = estimator; mPerCpuFreqPowerEstimators[index++] = estimator; } } } Loading @@ -82,12 +96,20 @@ public class CpuPowerCalculator extends PowerCalculator { long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { double totalPowerMah = 0; BatteryConsumer.Key[] keys = UNINITIALIZED_KEYS; Result result = new Result(); final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, app.getBatteryStatsUid(), query, result); if (keys == UNINITIALIZED_KEYS) { if (query.isProcessStateDataNeeded()) { keys = app.getKeys(BatteryConsumer.POWER_COMPONENT_CPU); } else { keys = null; } } calculateApp(app, app.getBatteryStatsUid(), query, result, keys); totalPowerMah += result.powerMah; } Loading @@ -105,7 +127,7 @@ public class CpuPowerCalculator extends PowerCalculator { } private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryUsageStatsQuery query, Result result) { BatteryUsageStatsQuery query, Result result, BatteryConsumer.Key[] keys) { final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC(); final int powerModel = getPowerModel(consumptionUC, query); calculatePowerAndDuration(u, powerModel, consumptionUC, BatteryStats.STATS_SINCE_CHARGED, Loading @@ -114,6 +136,75 @@ public class CpuPowerCalculator extends PowerCalculator { app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah, powerModel) .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CPU, result.durationMs) .setPackageWithHighestDrain(result.packageWithHighestDrain); if (query.isProcessStateDataNeeded() && keys != null) { switch (powerModel) { case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY: calculateMeasuredPowerPerProcessState(app, u, keys); break; case BatteryConsumer.POWER_MODEL_POWER_PROFILE: calculateModeledPowerPerProcessState(app, u, keys, result); break; } } } private void calculateMeasuredPowerPerProcessState(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryConsumer.Key[] keys) { for (BatteryConsumer.Key key : keys) { // The key for "PROCESS_STATE_ANY" has already been populated with the // full energy across all states. We don't want to override it with // the energy for "other" states, which excludes the tracked states like // foreground, background etc. if (key.processState == BatteryConsumer.PROCESS_STATE_ANY) { continue; } final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC(key.processState); if (consumptionUC != 0) { app.setConsumedPower(key, uCtoMah(consumptionUC), BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); } } } private void calculateModeledPowerPerProcessState(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryConsumer.Key[] keys, Result result) { if (result.perProcStatePowerMah == null) { result.perProcStatePowerMah = new double[BatteryConsumer.PROCESS_STATE_COUNT]; } else { Arrays.fill(result.perProcStatePowerMah, 0); } for (int uidProcState = 0; uidProcState < BatteryStats.Uid.NUM_PROCESS_STATE; uidProcState++) { @BatteryConsumer.ProcessState int procState = BatteryStats.mapUidProcessStateToBatteryConsumerProcessState(uidProcState); if (procState == BatteryConsumer.PROCESS_STATE_ANY) { continue; } // TODO(b/191921016): use per-state CPU active time final long cpuActiveTime = 0; // TODO(b/191921016): use per-state CPU cluster times final long[] cpuClusterTimes = null; final long[] cpuFreqTimes = u.getCpuFreqTimes(BatteryStats.STATS_SINCE_CHARGED, uidProcState); if (cpuActiveTime != 0 || cpuClusterTimes != null || cpuFreqTimes != null) { result.perProcStatePowerMah[procState] += calculateUidModeledPowerMah(u, cpuActiveTime, cpuClusterTimes, cpuFreqTimes); } } for (BatteryConsumer.Key key : keys) { if (key.processState == BatteryConsumer.PROCESS_STATE_ANY) { continue; } app.setConsumedPower(key, result.perProcStatePowerMah[key.processState], BatteryConsumer.POWER_MODEL_POWER_PROFILE); } } @Override Loading Loading @@ -205,16 +296,21 @@ public class CpuPowerCalculator extends PowerCalculator { * Calculates CPU power consumed by the specified app, using the PowerProfile model. */ public double calculateUidModeledPowerMah(BatteryStats.Uid u, int statsType) { return calculateUidModeledPowerMah(u, u.getCpuActiveTime(), u.getCpuClusterTimes(), u.getCpuFreqTimes(statsType)); } private double calculateUidModeledPowerMah(BatteryStats.Uid u, long cpuActiveTime, long[] cpuClusterTimes, long[] cpuFreqTimes) { // Constant battery drain when CPU is active double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime()); double powerMah = calculateActiveCpuPowerMah(cpuActiveTime); // Additional per-cluster battery drain long[] cpuClusterTimes = u.getCpuClusterTimes(); if (cpuClusterTimes != null) { if (cpuClusterTimes.length == mNumCpuClusters) { for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { double power = calculatePerCpuClusterPowerMah(cluster, cpuClusterTimes[cluster]); final double power = mPerClusterPowerEstimators[cluster] .calculatePower(cpuClusterTimes[cluster]); powerMah += power; if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster Loading @@ -228,21 +324,17 @@ public class CpuPowerCalculator extends PowerCalculator { } } // Additional per-frequency battery drain for (int cluster = 0; cluster < mNumCpuClusters; cluster++) { final int speedsForCluster = mPerCpuFreqPowerEstimators[cluster].length; for (int speed = 0; speed < speedsForCluster; speed++) { final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType); final double power = calculatePerCpuFreqPowerMah(cluster, speed, timeUs / 1000); if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #" + speed + " timeUs=" + timeUs + " power=" + formatCharge(power)); if (cpuFreqTimes != null) { if (cpuFreqTimes.length == mPerCpuFreqPowerEstimators.length) { for (int i = 0; i < cpuFreqTimes.length; i++) { powerMah += mPerCpuFreqPowerEstimators[i].calculatePower(cpuFreqTimes[i]); } powerMah += power; } else { Log.w(TAG, "UID " + u.getUid() + " CPU freq # mismatch: Power Profile # " + mPerCpuFreqPowerEstimators.length + " actual # " + cpuFreqTimes.length); } } return powerMah; } Loading Loading @@ -277,7 +369,7 @@ public class CpuPowerCalculator extends PowerCalculator { */ public double calculatePerCpuFreqPowerMah(int cluster, int speedStep, long clusterSpeedDurationsMs) { return mPerCpuFreqPowerEstimators[cluster][speedStep].calculatePower( return mPerCpuFreqPowerEstimatorsByCluster[cluster][speedStep].calculatePower( clusterSpeedDurationsMs); } }