diff options
3 files changed, 76 insertions, 78 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index a21c68b4f01a..fcf8bb4e748b 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -41,7 +41,6 @@ import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; -import android.util.SparseLongArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; @@ -379,6 +378,7 @@ public class BatteryStatsHelper { mMaxDrainedPower = (mStats.getHighDischargeAmountSinceCharge() * mPowerProfile.getBatteryCapacity()) / 100; + // Create list of (almost all) sippers, calculate their usage, and put them in mUsageList. processAppUsage(asUsers); Collections.sort(mUsageList); @@ -556,8 +556,7 @@ public class BatteryStatsHelper { } /** - * Mark the {@link BatterySipper} that we should hide and smear the screen usage based on - * foreground activity time. + * Mark the {@link BatterySipper} that we should hide. * * @param sippers sipper list that need to check and remove * @return the total power of the hidden items of {@link BatterySipper} @@ -565,7 +564,6 @@ public class BatteryStatsHelper { */ public double removeHiddenBatterySippers(List<BatterySipper> sippers) { double proportionalSmearPowerMah = 0; - BatterySipper screenSipper = null; for (int i = sippers.size() - 1; i >= 0; i--) { final BatterySipper sipper = sippers.get(i); sipper.shouldHide = shouldHideSipper(sipper); @@ -581,45 +579,11 @@ public class BatteryStatsHelper { proportionalSmearPowerMah += sipper.totalPowerMah; } } - - if (sipper.drainType == BatterySipper.DrainType.SCREEN) { - screenSipper = sipper; - } } - - smearScreenBatterySipper(sippers, screenSipper); - return proportionalSmearPowerMah; } /** - * Smear the screen on power usage among {@code sippers}, based on ratio of foreground activity - * time. - */ - public void smearScreenBatterySipper(List<BatterySipper> sippers, BatterySipper screenSipper) { - long totalActivityTimeMs = 0; - final SparseLongArray activityTimeArray = new SparseLongArray(); - for (int i = 0, size = sippers.size(); i < size; i++) { - final BatteryStats.Uid uid = sippers.get(i).uidObj; - if (uid != null) { - final long timeMs = getProcessForegroundTimeMs(uid, - BatteryStats.STATS_SINCE_CHARGED); - activityTimeArray.put(uid.getUid(), timeMs); - totalActivityTimeMs += timeMs; - } - } - - if (screenSipper != null && totalActivityTimeMs >= 10 * DateUtils.MINUTE_IN_MILLIS) { - final double screenPowerMah = screenSipper.totalPowerMah; - for (int i = 0, size = sippers.size(); i < size; i++) { - final BatterySipper sipper = sippers.get(i); - sipper.screenPowerMah = screenPowerMah * activityTimeArray.get(sipper.getUid(), 0) - / totalActivityTimeMs; - } - } - } - - /** * Check whether we should hide the battery sipper. */ public boolean shouldHideSipper(BatterySipper sipper) { @@ -682,33 +646,6 @@ public class BatteryStatsHelper { } @VisibleForTesting - public long getForegroundActivityTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs) { - final BatteryStats.Timer timer = uid.getForegroundActivityTimer(); - if (timer != null) { - return timer.getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); - } - - return 0; - } - - @VisibleForTesting - public long getProcessForegroundTimeMs(BatteryStats.Uid uid, int which) { - final long rawRealTimeUs = convertMsToUs(SystemClock.elapsedRealtime()); - final int foregroundTypes[] = {BatteryStats.Uid.PROCESS_STATE_TOP}; - - long timeUs = 0; - for (int type : foregroundTypes) { - final long localTime = uid.getProcessStateTime(type, rawRealTimeUs, which); - timeUs += localTime; - } - - // Return the min value of STATE_TOP time and foreground activity time, since both of these - // time have some errors. - return convertUsToMs( - Math.min(timeUs, getForegroundActivityTotalTimeUs(uid, rawRealTimeUs))); - } - - @VisibleForTesting public void setPackageManager(PackageManager packageManager) { mPackageManager = packageManager; } diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java index 25f6b4d16971..9c4a26724ba8 100644 --- a/core/java/com/android/internal/os/ScreenPowerCalculator.java +++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java @@ -21,9 +21,14 @@ import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.SystemBatteryConsumer; +import android.os.SystemClock; import android.os.UserHandle; +import android.text.format.DateUtils; import android.util.Log; import android.util.SparseArray; +import android.util.SparseLongArray; + +import com.android.internal.annotations.VisibleForTesting; import java.util.List; @@ -57,6 +62,7 @@ public class ScreenPowerCalculator extends PowerCalculator { .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah); } + // TODO(b/178140704): Attribute screen usage similar to smearScreenBatterySipper. } /** @@ -73,6 +79,8 @@ public class ScreenPowerCalculator extends PowerCalculator { bs.usageTimeMs = durationMs; bs.sumPower(); sippers.add(bs); + + smearScreenBatterySipper(sippers, bs); } } @@ -96,4 +104,60 @@ public class ScreenPowerCalculator extends PowerCalculator { } return power; } + + /** + * Smear the screen on power usage among {@code sippers}, based on ratio of foreground activity + * time, and store this in the {@link BatterySipper#screenPowerMah} field. + */ + @VisibleForTesting + public void smearScreenBatterySipper(List<BatterySipper> sippers, BatterySipper screenSipper) { + + long totalActivityTimeMs = 0; + final SparseLongArray activityTimeArray = new SparseLongArray(); + for (int i = sippers.size() - 1; i >= 0; i--) { + final BatteryStats.Uid uid = sippers.get(i).uidObj; + if (uid != null) { + final long timeMs = getProcessForegroundTimeMs(uid); + activityTimeArray.put(uid.getUid(), timeMs); + totalActivityTimeMs += timeMs; + } + } + + if (screenSipper != null && totalActivityTimeMs >= 10 * DateUtils.MINUTE_IN_MILLIS) { + final double screenPowerMah = screenSipper.totalPowerMah; + for (int i = sippers.size() - 1; i >= 0; i--) { + final BatterySipper sipper = sippers.get(i); + sipper.screenPowerMah = screenPowerMah * activityTimeArray.get(sipper.getUid(), 0) + / totalActivityTimeMs; + } + } + } + + /** Get the minimum of the uid's ForegroundActivity time and its TOP time. */ + @VisibleForTesting + public long getProcessForegroundTimeMs(BatteryStats.Uid uid) { + final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000; + final int[] foregroundTypes = {BatteryStats.Uid.PROCESS_STATE_TOP}; + + long timeUs = 0; + for (int type : foregroundTypes) { + final long localTime = uid.getProcessStateTime(type, rawRealTimeUs, + BatteryStats.STATS_SINCE_CHARGED); + timeUs += localTime; + } + + // Return the min value of STATE_TOP time and foreground activity time, since both of these + // time have some errors. + return Math.min(timeUs, getForegroundActivityTotalTimeUs(uid, rawRealTimeUs)) / 1000; + } + + /** Get the ForegroundActivity time of the given uid. */ + @VisibleForTesting + public long getForegroundActivityTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs) { + final BatteryStats.Timer timer = uid.getForegroundActivityTimer(); + if (timer == null) { + return 0; + } + return timer.getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); + } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java index fbe16f2c39d1..d2107eaefefc 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java @@ -21,12 +21,10 @@ import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -194,7 +192,6 @@ public class BatteryStatsHelperTest extends TestCase { sippers.add(mBluetoothBatterySipper); sippers.add(mIdleBatterySipper); doReturn(true).when(mBatteryStatsHelper).isTypeSystem(mSystemBatterySipper); - doNothing().when(mBatteryStatsHelper).smearScreenBatterySipper(any(), any()); final double totalUsage = mBatteryStatsHelper.removeHiddenBatterySippers(sippers); @@ -208,19 +205,20 @@ public class BatteryStatsHelperTest extends TestCase { @Test public void testSmearScreenBatterySipper() { + final ScreenPowerCalculator spc = spy(ScreenPowerCalculator.class); final BatterySipper sipperNull = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY_ZERO, - BATTERY_APP_USAGE, 0 /* uid */, true /* isUidNull */); + BATTERY_APP_USAGE, 0 /* uid */, true /* isUidNull */, spc); final BatterySipper sipperBg = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY_ZERO, - BATTERY_APP_USAGE, 1 /* uid */, false /* isUidNull */); + BATTERY_APP_USAGE, 1 /* uid */, false /* isUidNull */, spc); final BatterySipper sipperFg = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY, - BATTERY_APP_USAGE, 2 /* uid */, false /* isUidNull */); + BATTERY_APP_USAGE, 2 /* uid */, false /* isUidNull */, spc); final List<BatterySipper> sippers = new ArrayList<>(); sippers.add(sipperNull); sippers.add(sipperBg); sippers.add(sipperFg); - mBatteryStatsHelper.smearScreenBatterySipper(sippers, mScreenBatterySipper); + spc.smearScreenBatterySipper(sippers, mScreenBatterySipper); assertThat(sipperNull.screenPowerMah).isWithin(PRECISION).of(0); assertThat(sipperBg.screenPowerMah).isWithin(PRECISION).of(0); @@ -249,13 +247,13 @@ public class BatteryStatsHelperTest extends TestCase { @Test public void testGetProcessForegroundTimeMs_largerActivityTime_returnMinTime() { - doReturn(TIME_STATE_FOREGROUND_US + 500).when(mBatteryStatsHelper) + final ScreenPowerCalculator spc = spy(ScreenPowerCalculator.class); + doReturn(TIME_STATE_FOREGROUND_US + 500).when(spc) .getForegroundActivityTotalTimeUs(eq(mUid), anyLong()); doReturn(TIME_STATE_FOREGROUND_US).when(mUid).getProcessStateTime(eq(PROCESS_STATE_TOP), anyLong(), anyInt()); - final long time = mBatteryStatsHelper.getProcessForegroundTimeMs(mUid, - BatteryStats.STATS_SINCE_CHARGED); + final long time = spc.getProcessForegroundTimeMs(mUid); assertThat(time).isEqualTo(TIME_STATE_FOREGROUND_MS); } @@ -291,15 +289,14 @@ public class BatteryStatsHelperTest extends TestCase { } private BatterySipper createTestSmearBatterySipper(long activityTime, double totalPowerMah, - int uidCode, boolean isUidNull) { + int uidCode, boolean isUidNull, ScreenPowerCalculator spc) { final BatterySipper sipper = mock(BatterySipper.class); sipper.drainType = BatterySipper.DrainType.APP; sipper.totalPowerMah = totalPowerMah; doReturn(uidCode).when(sipper).getUid(); if (!isUidNull) { final BatteryStats.Uid uid = mock(BatteryStats.Uid.class, RETURNS_DEEP_STUBS); - doReturn(activityTime).when(mBatteryStatsHelper).getProcessForegroundTimeMs(eq(uid), - anyInt()); + doReturn(activityTime).when(spc).getProcessForegroundTimeMs(eq(uid)); doReturn(uidCode).when(uid).getUid(); sipper.uidObj = uid; } |