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

Commit c2baa294 authored by jackqdyulei's avatar jackqdyulei
Browse files

Update wakelock detector

1. Use new API: getSubTimer().getTotalDurationMsLocked(), which returns
the wakelock running time in the background.
2. Add code to detect whether app is currently holding wakelocks, by
using API: getCurrentDurationMsLocked

Bug: 38233034
Test: RunSettingsRoboTests
Change-Id: If69b751acf5741ff8df2c905642c008a0a2b32e6
parent ea46967c
Loading
Loading
Loading
Loading
+15 −23
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.content.pm.PackageManager;
import android.os.BatteryStats;
import android.os.SystemClock;
import android.support.annotation.VisibleForTesting;
import android.util.ArrayMap;

import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -87,23 +86,10 @@ public class WakeLockAnomalyDetector implements AnomalyDetector {
                continue;
            }

            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks =
                    uid.getWakelockStats();
            long maxPartialWakeLockMs = 0;
            final long currentDurationMs = getCurrentDurationMs(uid, rawRealtime);
            final long backgroundDurationMs = getBackgroundTotalDurationMs(uid, rawRealtime);

            for (int iw = wakelocks.size() - 1; iw >= 0; iw--) {
                final BatteryStats.Timer timer = wakelocks.valueAt(iw).getWakeTime(
                        BatteryStats.WAKE_TYPE_PARTIAL);
                if (timer == null) {
                    continue;
                }
                maxPartialWakeLockMs = Math.max(maxPartialWakeLockMs,
                        getTotalDurationMs(timer, rawRealtime));
            }

            // Report application as anomaly if wakelock time is too long
            // TODO(b/38233034): add more attributes to detect wakelock anomaly
            if (maxPartialWakeLockMs > mWakeLockThresholdMs) {
            if (backgroundDurationMs > mWakeLockThresholdMs && currentDurationMs != 0) {
                final String packageName = mBatteryUtils.getPackageName(uid.getUid());
                final CharSequence displayName = Utils.getApplicationLabel(mContext,
                        packageName);
@@ -119,16 +105,22 @@ public class WakeLockAnomalyDetector implements AnomalyDetector {
                    anomalies.add(anomaly);
                }
            }

        }
        return anomalies;
    }

    @VisibleForTesting
    long getTotalDurationMs(BatteryStats.Timer timer, long rawRealtime) {
        if (timer == null) {
            return 0;
    long getCurrentDurationMs(BatteryStats.Uid uid, long elapsedRealtimeMs) {
        BatteryStats.Timer timer = uid.getAggregatedPartialWakelockTimer();

        return timer != null ? timer.getCurrentDurationMsLocked(elapsedRealtimeMs) : 0;
    }
        return timer.getTotalDurationMsLocked(rawRealtime);

    @VisibleForTesting
    long getBackgroundTotalDurationMs(BatteryStats.Uid uid, long elapsedRealtimeMs) {
        BatteryStats.Timer timer = uid.getAggregatedPartialWakelockTimer();
        BatteryStats.Timer subTimer = timer != null ? timer.getSubTimer() : null;

        return subTimer != null ? subTimer.getTotalDurationMsLocked(elapsedRealtimeMs) : 0;
    }
}
+28 −37
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.BatteryStats;
import android.text.format.DateUtils;
import android.util.ArrayMap;

import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -64,6 +63,7 @@ public class WakeLockAnomalyDetectorTest {
    private static final int ANOMALY_UID = 111;
    private static final int NORMAL_UID = 222;
    private static final int TARGET_UID = 333;
    private static final int INACTIVE_UID = 444;
    @Mock
    private BatteryStatsHelper mBatteryStatsHelper;
    @Mock
@@ -71,19 +71,9 @@ public class WakeLockAnomalyDetectorTest {
    @Mock
    private BatterySipper mTargetSipper;
    @Mock
    private BatteryStats.Timer mAnomalyTimer;
    @Mock
    private BatteryStats.Uid.Wakelock mAnomalyWakelock;
    @Mock
    private BatterySipper mNormalSipper;
    @Mock
    private BatteryStats.Timer mNormalTimer;
    @Mock
    private BatteryStats.Timer mTargetTimer;
    @Mock
    private BatteryStats.Uid.Wakelock mNormalWakelock;
    @Mock
    private BatteryStats.Uid.Wakelock mTargetWakelock;
    private BatterySipper mInactiveSipper;
    @Mock
    private BatteryStats.Uid mAnomalyUid;
    @Mock
@@ -91,6 +81,8 @@ public class WakeLockAnomalyDetectorTest {
    @Mock
    private BatteryStats.Uid mTargetUid;
    @Mock
    private BatteryStats.Uid mInactiveUid;
    @Mock
    private BatteryUtils mBatteryUtils;
    @Mock
    private PackageManager mPackageManager;
@@ -101,9 +93,6 @@ public class WakeLockAnomalyDetectorTest {
    @Mock
    private AnomalyAction mAnomalyAction;

    private ArrayMap<String, BatteryStats.Uid.Wakelock> mAnomalyWakelocks;
    private ArrayMap<String, BatteryStats.Uid.Wakelock> mNormalWakelocks;
    private ArrayMap<String, BatteryStats.Uid.Wakelock> mTargetWakelocks;
    private WakeLockAnomalyDetector mWakelockAnomalyDetector;
    private Context mContext;
    private List<BatterySipper> mUsageList;
@@ -121,42 +110,44 @@ public class WakeLockAnomalyDetectorTest {
                .getApplicationInfo(nullable(String.class), anyInt());
        doReturn(true).when(mAnomalyAction).isActionActive(any());

        mWakelockAnomalyDetector = spy(new WakeLockAnomalyDetector(mContext, mPolicy));
        mWakelockAnomalyDetector.mBatteryUtils = mBatteryUtils;
        mWakelockAnomalyDetector.mAnomalyAction = mAnomalyAction;

        mAnomalySipper.uidObj = mAnomalyUid;
        mAnomalyWakelocks = new ArrayMap<>();
        mAnomalyWakelocks.put("", mAnomalyWakelock);
        doReturn(mAnomalyWakelocks).when(mAnomalyUid).getWakelockStats();
        doReturn(mAnomalyTimer).when(mAnomalyWakelock).getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
        doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector)
                .getBackgroundTotalDurationMs(eq(mAnomalyUid), anyLong());
        doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector).getCurrentDurationMs(
                eq(mAnomalyUid), anyLong());
        doReturn(ANOMALY_UID).when(mAnomalyUid).getUid();

        mNormalSipper.uidObj = mNormalUid;
        mNormalWakelocks = new ArrayMap<>();
        mNormalWakelocks.put("", mNormalWakelock);
        doReturn(mNormalTimer).when(mNormalWakelock).getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
        doReturn(mNormalWakelocks).when(mNormalUid).getWakelockStats();
        doReturn(NORMAL_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector)
                .getBackgroundTotalDurationMs(eq(mNormalUid), anyLong());
        doReturn(0L).when(mWakelockAnomalyDetector).getCurrentDurationMs(eq(mNormalUid),
                anyLong());
        doReturn(NORMAL_UID).when(mNormalUid).getUid();

        mTargetSipper.uidObj = mTargetUid;
        mTargetWakelocks = new ArrayMap<>();
        mTargetWakelocks.put("", mTargetWakelock);
        doReturn(mTargetTimer).when(mTargetWakelock).getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
        doReturn(mTargetWakelocks).when(mTargetUid).getWakelockStats();
        doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector)
                .getBackgroundTotalDurationMs(eq(mTargetUid), anyLong());
        doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector).getCurrentDurationMs(
                eq(mTargetUid), anyLong());
        doReturn(TARGET_UID).when(mTargetUid).getUid();

        mInactiveSipper.uidObj = mInactiveUid;
        doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector)
                .getBackgroundTotalDurationMs(eq(mInactiveUid), anyLong());
        doReturn(0L).when(mWakelockAnomalyDetector).getCurrentDurationMs(eq(mInactiveUid),
                anyLong());
        doReturn(INACTIVE_UID).when(mInactiveUid).getUid();

        mUsageList = new ArrayList<>();
        mUsageList.add(mAnomalySipper);
        mUsageList.add(mNormalSipper);
        mUsageList.add(mTargetSipper);
        mUsageList.add(mInactiveSipper);
        doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList();

        mWakelockAnomalyDetector = spy(new WakeLockAnomalyDetector(mContext, mPolicy));
        mWakelockAnomalyDetector.mBatteryUtils = mBatteryUtils;
        mWakelockAnomalyDetector.mAnomalyAction = mAnomalyAction;
        doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector).getTotalDurationMs(
                eq(mAnomalyTimer), anyLong());
        doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector).getTotalDurationMs(
                eq(mTargetTimer), anyLong());
        doReturn(NORMAL_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector).getTotalDurationMs(
                eq(mNormalTimer), anyLong());
    }

    @Test