Loading core/java/android/os/BatteryStats.java +18 −0 Original line number Diff line number Diff line Loading @@ -994,6 +994,15 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getScreenOnMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) of the uid's cpu usage, 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) used by this uid for each * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer Loading Loading @@ -2520,6 +2529,15 @@ 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. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ public abstract long getCpuMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) that each * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer Loading core/java/com/android/internal/os/BatteryStatsImpl.java +10 −0 Original line number Diff line number Diff line Loading @@ -6976,6 +6976,11 @@ public class BatteryStatsImpl extends BatteryStats { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE); } @Override public long getCpuMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU); } /** * Returns the consumption (in microcoulombs) that the given standard power bucket consumed. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable Loading Loading @@ -8482,6 +8487,11 @@ public class BatteryStatsImpl extends BatteryStats { 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]; Loading core/java/com/android/internal/os/CpuPowerCalculator.java +56 −42 Original line number Diff line number Diff line Loading @@ -85,12 +85,14 @@ public class CpuPowerCalculator extends PowerCalculator { builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, app.getBatteryStatsUid(), result); calculateApp(app, app.getBatteryStatsUid(), query, result); } } private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, Result result) { calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED, result); private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryUsageStatsQuery query, Result result) { calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED, query.shouldForceUsePowerProfileModel(), result); app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah) .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, result.durationMs) Loading @@ -112,7 +114,7 @@ public class CpuPowerCalculator extends PowerCalculator { } private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType, Result result) { calculatePowerAndDuration(u, statsType, result); calculatePowerAndDuration(u, statsType, false, result); app.cpuPowerMah = result.powerMah; app.cpuTimeMs = result.durationMs; Loading @@ -120,46 +122,16 @@ public class CpuPowerCalculator extends PowerCalculator { app.packageWithHighestDrain = result.packageWithHighestDrain; } private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType, Result result) { private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType, boolean forceUsePowerProfileModel, Result result) { long durationMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000; // Constant battery drain when CPU is active double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime()); // 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]); powerMah += power; if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " clusterTimeMs=" + cpuClusterTimes[cluster] + " power=" + formatCharge(power)); } } final double powerMah; final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC(); if (forceUsePowerProfileModel || consumptionUC == BatteryStats.POWER_DATA_UNAVAILABLE) { powerMah = calculateUidModeledPowerMah(u, statsType); } else { Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # " + mNumCpuClusters + " actual # " + cpuClusterTimes.length); } } // 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)); } powerMah += power; } powerMah = uCtoMah(consumptionUC); } if (DEBUG && (durationMs != 0 || powerMah != 0)) { Loading Loading @@ -208,6 +180,48 @@ public class CpuPowerCalculator extends PowerCalculator { result.packageWithHighestDrain = packageWithHighestDrain; } private double calculateUidModeledPowerMah(BatteryStats.Uid u, int statsType) { // Constant battery drain when CPU is active double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime()); // 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]); powerMah += power; if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " clusterTimeMs=" + cpuClusterTimes[cluster] + " power=" + formatCharge(power)); } } } else { Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # " + mNumCpuClusters + " actual # " + cpuClusterTimes.length); } } // 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)); } powerMah += power; } } return powerMah; } /** * Calculates active CPU power consumption. * Loading core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java +78 −8 Original line number Diff line number Diff line Loading @@ -19,18 +19,22 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.os.BatteryConsumer; import android.os.BatteryUsageStatsQuery; import android.os.Process; import android.os.UidBatteryConsumer; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.power.MeasuredEnergyStats; import org.junit.Before; import org.junit.Rule; import org.junit.Test; Loading Loading @@ -81,6 +85,10 @@ public class CpuPowerCalculatorTest { public void setUp() { MockitoAnnotations.initMocks(this); final boolean[] supportedPowerBuckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; supportedPowerBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true; mStatsRule.getBatteryStats() .setUserInfoProvider(mMockUserInfoProvider) .setKernelCpuSpeedReaders(mMockKernelCpuSpeedReaders) Loading @@ -88,7 +96,8 @@ public class CpuPowerCalculatorTest { .setKernelCpuUidClusterTimeReader(mMockKernelCpuUidClusterTimeReader) .setKernelCpuUidUserSysTimeReader(mMockKernelCpuUidUserSysTimeReader) .setKernelCpuUidActiveTimeReader(mMockKerneCpuUidActiveTimeReader) .setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader); .setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader) .initMeasuredEnergyStatsLocked(supportedPowerBuckets, 0); } @Test Loading @@ -103,28 +112,28 @@ public class CpuPowerCalculatorTest { // User/System CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(0); final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); // User/system time in microseconds callback.onUidCpuTime(APP_UID1, new long[]{1111000, 2222000}); callback.onUidCpuTime(APP_UID2, new long[]{3333000, 4444000}); return null; }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(any()); }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any()); // Active CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(0); final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, 1111L); callback.onUidCpuTime(APP_UID2, 3333L); return null; }).when(mMockKerneCpuUidActiveTimeReader).readDelta(any()); }).when(mMockKerneCpuUidActiveTimeReader).readDelta(anyBoolean(), any()); // Per-cluster CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(0); final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, new long[]{1111, 2222}); callback.onUidCpuTime(APP_UID2, new long[]{3333, 4444}); return null; }).when(mMockKernelCpuUidClusterTimeReader).readDelta(any()); }).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any()); mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, null); Loading @@ -134,7 +143,8 @@ public class CpuPowerCalculatorTest { CpuPowerCalculator calculator = new CpuPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(), calculator); UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1); assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU)) Loading @@ -150,4 +160,64 @@ public class CpuPowerCalculatorTest { .isWithin(PRECISION).of(2.672322); assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull(); } @Test public void testMeasuredEnergyBasedModel() { when(mMockUserInfoProvider.exists(anyInt())).thenReturn(true); when(mMockKernelCpuSpeedReaders[0].readDelta()).thenReturn(new long[]{1000, 2000}); when(mMockKernelCpuSpeedReaders[1].readDelta()).thenReturn(new long[]{3000, 4000}); when(mMockCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(false); // User/System CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); // User/system time in microseconds callback.onUidCpuTime(APP_UID1, new long[]{1111000, 2222000}); callback.onUidCpuTime(APP_UID2, new long[]{3333000, 4444000}); return null; }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any()); // Active CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, 1111L); callback.onUidCpuTime(APP_UID2, 3333L); return null; }).when(mMockKerneCpuUidActiveTimeReader).readDelta(anyBoolean(), any()); // Per-cluster CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, new long[]{1111, 2222}); callback.onUidCpuTime(APP_UID2, new long[]{3333, 4444}); return null; }).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any()); final long[] clusterChargesUC = new long[]{13577531, 24688642}; mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, clusterChargesUC); mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("foo").addCpuTimeLocked(4321, 1234); mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("bar").addCpuTimeLocked(5432, 2345); CpuPowerCalculator calculator = new CpuPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1); assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU)) .isEqualTo(3333); assertThat(uidConsumer1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU)) .isWithin(PRECISION).of(3.18877); assertThat(uidConsumer1.getPackageWithHighestDrain()).isEqualTo("bar"); UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2); assertThat(uidConsumer2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU)) .isEqualTo(7777); assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU)) .isWithin(PRECISION).of(7.44072); assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull(); } } Loading
core/java/android/os/BatteryStats.java +18 −0 Original line number Diff line number Diff line Loading @@ -994,6 +994,15 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getScreenOnMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) of the uid's cpu usage, 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) used by this uid for each * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer Loading Loading @@ -2520,6 +2529,15 @@ 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. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable. * * {@hide} */ public abstract long getCpuMeasuredBatteryConsumptionUC(); /** * Returns the battery consumption (in microcoulombs) that each * {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +10 −0 Original line number Diff line number Diff line Loading @@ -6976,6 +6976,11 @@ public class BatteryStatsImpl extends BatteryStats { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE); } @Override public long getCpuMeasuredBatteryConsumptionUC() { return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU); } /** * Returns the consumption (in microcoulombs) that the given standard power bucket consumed. * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable Loading Loading @@ -8482,6 +8487,11 @@ public class BatteryStatsImpl extends BatteryStats { 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]; Loading
core/java/com/android/internal/os/CpuPowerCalculator.java +56 −42 Original line number Diff line number Diff line Loading @@ -85,12 +85,14 @@ public class CpuPowerCalculator extends PowerCalculator { builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, app.getBatteryStatsUid(), result); calculateApp(app, app.getBatteryStatsUid(), query, result); } } private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, Result result) { calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED, result); private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, BatteryUsageStatsQuery query, Result result) { calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED, query.shouldForceUsePowerProfileModel(), result); app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah) .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, result.durationMs) Loading @@ -112,7 +114,7 @@ public class CpuPowerCalculator extends PowerCalculator { } private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType, Result result) { calculatePowerAndDuration(u, statsType, result); calculatePowerAndDuration(u, statsType, false, result); app.cpuPowerMah = result.powerMah; app.cpuTimeMs = result.durationMs; Loading @@ -120,46 +122,16 @@ public class CpuPowerCalculator extends PowerCalculator { app.packageWithHighestDrain = result.packageWithHighestDrain; } private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType, Result result) { private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType, boolean forceUsePowerProfileModel, Result result) { long durationMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000; // Constant battery drain when CPU is active double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime()); // 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]); powerMah += power; if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " clusterTimeMs=" + cpuClusterTimes[cluster] + " power=" + formatCharge(power)); } } final double powerMah; final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC(); if (forceUsePowerProfileModel || consumptionUC == BatteryStats.POWER_DATA_UNAVAILABLE) { powerMah = calculateUidModeledPowerMah(u, statsType); } else { Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # " + mNumCpuClusters + " actual # " + cpuClusterTimes.length); } } // 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)); } powerMah += power; } powerMah = uCtoMah(consumptionUC); } if (DEBUG && (durationMs != 0 || powerMah != 0)) { Loading Loading @@ -208,6 +180,48 @@ public class CpuPowerCalculator extends PowerCalculator { result.packageWithHighestDrain = packageWithHighestDrain; } private double calculateUidModeledPowerMah(BatteryStats.Uid u, int statsType) { // Constant battery drain when CPU is active double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime()); // 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]); powerMah += power; if (DEBUG) { Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " clusterTimeMs=" + cpuClusterTimes[cluster] + " power=" + formatCharge(power)); } } } else { Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # " + mNumCpuClusters + " actual # " + cpuClusterTimes.length); } } // 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)); } powerMah += power; } } return powerMah; } /** * Calculates active CPU power consumption. * Loading
core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java +78 −8 Original line number Diff line number Diff line Loading @@ -19,18 +19,22 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.os.BatteryConsumer; import android.os.BatteryUsageStatsQuery; import android.os.Process; import android.os.UidBatteryConsumer; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.power.MeasuredEnergyStats; import org.junit.Before; import org.junit.Rule; import org.junit.Test; Loading Loading @@ -81,6 +85,10 @@ public class CpuPowerCalculatorTest { public void setUp() { MockitoAnnotations.initMocks(this); final boolean[] supportedPowerBuckets = new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS]; supportedPowerBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true; mStatsRule.getBatteryStats() .setUserInfoProvider(mMockUserInfoProvider) .setKernelCpuSpeedReaders(mMockKernelCpuSpeedReaders) Loading @@ -88,7 +96,8 @@ public class CpuPowerCalculatorTest { .setKernelCpuUidClusterTimeReader(mMockKernelCpuUidClusterTimeReader) .setKernelCpuUidUserSysTimeReader(mMockKernelCpuUidUserSysTimeReader) .setKernelCpuUidActiveTimeReader(mMockKerneCpuUidActiveTimeReader) .setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader); .setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader) .initMeasuredEnergyStatsLocked(supportedPowerBuckets, 0); } @Test Loading @@ -103,28 +112,28 @@ public class CpuPowerCalculatorTest { // User/System CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(0); final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); // User/system time in microseconds callback.onUidCpuTime(APP_UID1, new long[]{1111000, 2222000}); callback.onUidCpuTime(APP_UID2, new long[]{3333000, 4444000}); return null; }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(any()); }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any()); // Active CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(0); final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, 1111L); callback.onUidCpuTime(APP_UID2, 3333L); return null; }).when(mMockKerneCpuUidActiveTimeReader).readDelta(any()); }).when(mMockKerneCpuUidActiveTimeReader).readDelta(anyBoolean(), any()); // Per-cluster CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(0); final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, new long[]{1111, 2222}); callback.onUidCpuTime(APP_UID2, new long[]{3333, 4444}); return null; }).when(mMockKernelCpuUidClusterTimeReader).readDelta(any()); }).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any()); mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, null); Loading @@ -134,7 +143,8 @@ public class CpuPowerCalculatorTest { CpuPowerCalculator calculator = new CpuPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(), calculator); UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1); assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU)) Loading @@ -150,4 +160,64 @@ public class CpuPowerCalculatorTest { .isWithin(PRECISION).of(2.672322); assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull(); } @Test public void testMeasuredEnergyBasedModel() { when(mMockUserInfoProvider.exists(anyInt())).thenReturn(true); when(mMockKernelCpuSpeedReaders[0].readDelta()).thenReturn(new long[]{1000, 2000}); when(mMockKernelCpuSpeedReaders[1].readDelta()).thenReturn(new long[]{3000, 4000}); when(mMockCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(false); // User/System CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); // User/system time in microseconds callback.onUidCpuTime(APP_UID1, new long[]{1111000, 2222000}); callback.onUidCpuTime(APP_UID2, new long[]{3333000, 4444000}); return null; }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any()); // Active CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, 1111L); callback.onUidCpuTime(APP_UID2, 3333L); return null; }).when(mMockKerneCpuUidActiveTimeReader).readDelta(anyBoolean(), any()); // Per-cluster CPU time doAnswer(invocation -> { final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1); callback.onUidCpuTime(APP_UID1, new long[]{1111, 2222}); callback.onUidCpuTime(APP_UID2, new long[]{3333, 4444}); return null; }).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any()); final long[] clusterChargesUC = new long[]{13577531, 24688642}; mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, clusterChargesUC); mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("foo").addCpuTimeLocked(4321, 1234); mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("bar").addCpuTimeLocked(5432, 2345); CpuPowerCalculator calculator = new CpuPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1); assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU)) .isEqualTo(3333); assertThat(uidConsumer1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU)) .isWithin(PRECISION).of(3.18877); assertThat(uidConsumer1.getPackageWithHighestDrain()).isEqualTo("bar"); UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2); assertThat(uidConsumer2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU)) .isEqualTo(7777); assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU)) .isWithin(PRECISION).of(7.44072); assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull(); } }