Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f15e41d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "ScreenPowerCalculator is responsible for smearing" into sc-dev

parents cd347c4b 2ad7cd41
Loading
Loading
Loading
Loading
+2 −65
Original line number Diff line number Diff line
@@ -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,44 +579,10 @@ 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.
     */
@@ -681,33 +645,6 @@ public class BatteryStatsHelper {
        return timeMs * 1000;
    }

    @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;
+64 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+10 −13
Original line number Diff line number Diff line
@@ -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;
        }