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
diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java
index 74c43d0..545bb26 100644
--- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java
+++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java
@@ -21,7 +21,6 @@
 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 @@
                 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 @@
                     anomalies.add(anomaly);
                 }
             }
-
         }
         return anomalies;
     }
 
     @VisibleForTesting
-    long getTotalDurationMs(BatteryStats.Timer timer, long rawRealtime) {
-        if (timer == null) {
-            return 0;
-        }
-        return timer.getTotalDurationMsLocked(rawRealtime);
+    long getCurrentDurationMs(BatteryStats.Uid uid, long elapsedRealtimeMs) {
+        BatteryStats.Timer timer = uid.getAggregatedPartialWakelockTimer();
+
+        return timer != null ? timer.getCurrentDurationMsLocked(elapsedRealtimeMs) : 0;
+    }
+
+    @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;
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java
index 386e162..19ab7d6 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java
@@ -31,7 +31,6 @@
 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 @@
     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 @@
     @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 @@
     @Mock
     private BatteryStats.Uid mTargetUid;
     @Mock
+    private BatteryStats.Uid mInactiveUid;
+    @Mock
     private BatteryUtils mBatteryUtils;
     @Mock
     private PackageManager mPackageManager;
@@ -101,9 +93,6 @@
     @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 @@
                 .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