diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java index a515e06b102..0aad7ba20c3 100644 --- a/src/com/android/settings/fuelgauge/BatteryUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryUtils.java @@ -41,6 +41,7 @@ import java.util.List; * Utils for battery operation */ public class BatteryUtils { + public static final int UID_NULL = -1; @Retention(RetentionPolicy.SOURCE) @IntDef({StatusType.FOREGROUND, StatusType.BACKGROUND, @@ -274,6 +275,22 @@ public class BatteryUtils { } + /** + * Find package uid from package name + * + * @param packageName used to find the uid + * @return uid for packageName, or {@link #UID_NULL} if exception happens or + * {@code packageName} is null + */ + public int getPackageUid(String packageName) { + try { + return packageName == null ? UID_NULL : mPackageManager.getPackageUid(packageName, + PackageManager.GET_META_DATA); + } catch (PackageManager.NameNotFoundException e) { + return UID_NULL; + } + } + public long convertUsToMs(long timeUs) { return timeUs / 1000; } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 4a4d28c5a13..d88655f5634 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -90,5 +90,6 @@ public interface PowerUsageFeatureProvider { /** * Check whether a specific anomaly detector is enabled */ + //TODO(b/62096650): remove this method and use AnomalyDetectionPolicy instead boolean isAnomalyDetectorEnabled(@Anomaly.AnomalyType int type); } diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java index 603bca02e8f..7dbae36bba8 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicy.java @@ -108,4 +108,14 @@ public class AnomalyDetectionPolicy { wakeupAlarmThreshold = mParserWrapper.getLong(KEY_WAKEUP_ALARM_THRESHOLD, 60); } + public boolean isAnomalyDetectorEnabled(@Anomaly.AnomalyType int type) { + switch (type) { + case Anomaly.AnomalyType.WAKE_LOCK: + return wakeLockDetectionEnabled; + case Anomaly.AnomalyType.WAKEUP_ALARM: + return wakeupAlarmDetectionEnabled; + default: + return false; // Disabled when no this type + } + } } diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java index 1ffdd9fc5a8..b182a03d867 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java @@ -17,11 +17,12 @@ package com.android.settings.fuelgauge.anomaly; import android.content.Context; +import android.os.BatteryStats; +import android.os.Bundle; +import android.os.UserManager; import android.support.annotation.VisibleForTesting; import com.android.internal.os.BatteryStatsHelper; -import com.android.settings.fuelgauge.PowerUsageFeatureProvider; -import com.android.settings.overlay.FeatureFactory; import com.android.settings.utils.AsyncLoader; import java.util.ArrayList; @@ -33,16 +34,45 @@ import java.util.List; */ public class AnomalyLoader extends AsyncLoader> { private BatteryStatsHelper mBatteryStatsHelper; - private PowerUsageFeatureProvider mPowerUsageFeatureProvider; + private String mPackageName; + private UserManager mUserManager; @VisibleForTesting AnomalyUtils mAnomalyUtils; + @VisibleForTesting + AnomalyDetectionPolicy mPolicy; + /** + * Create {@link AnomalyLoader} that runs anomaly check for all apps. + */ public AnomalyLoader(Context context, BatteryStatsHelper batteryStatsHelper) { + this(context, batteryStatsHelper, null, new AnomalyDetectionPolicy(context)); + + } + + /** + * Create {@link AnomalyLoader} with {@code packageName}, so this loader will only + * detect anomalies related to {@code packageName}, or check all apps if {@code packageName} + * is {@code null}. + * + * This constructor will create {@link BatteryStatsHelper} in background thread. + * + * @param context + * @param packageName if set, only finds anomalies for this package. If {@code null}, + * detects all anomalies of this type. + */ + public AnomalyLoader(Context context, String packageName) { + this(context, null, packageName, new AnomalyDetectionPolicy(context)); + } + + @VisibleForTesting + AnomalyLoader(Context context, BatteryStatsHelper batteryStatsHelper, + String packageName, AnomalyDetectionPolicy policy) { super(context); mBatteryStatsHelper = batteryStatsHelper; - mPowerUsageFeatureProvider = FeatureFactory.getFactory( - context).getPowerUsageFeatureProvider(context); + mPackageName = packageName; mAnomalyUtils = AnomalyUtils.getInstance(context); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mPolicy = policy; } @Override @@ -51,11 +81,18 @@ public class AnomalyLoader extends AsyncLoader> { @Override public List loadInBackground() { + if (mBatteryStatsHelper == null) { + mBatteryStatsHelper = new BatteryStatsHelper(getContext()); + mBatteryStatsHelper.create((Bundle) null); + mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, + mUserManager.getUserProfiles()); + } + final List anomalies = new ArrayList<>(); for (@Anomaly.AnomalyType int type : Anomaly.ANOMALY_TYPE_LIST) { - if (mPowerUsageFeatureProvider.isAnomalyDetectorEnabled(type)) { + if (mPolicy.isAnomalyDetectorEnabled(type)) { anomalies.addAll(mAnomalyUtils.getAnomalyDetector(type).detectAnomalies( - mBatteryStatsHelper)); + mBatteryStatsHelper, mPackageName)); } } diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/AnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/AnomalyDetector.java index b04ea660b8d..1921bef4e12 100644 --- a/src/com/android/settings/fuelgauge/anomaly/checker/AnomalyDetector.java +++ b/src/com/android/settings/fuelgauge/anomaly/checker/AnomalyDetector.java @@ -17,11 +17,30 @@ package com.android.settings.fuelgauge.anomaly.checker; +import android.annotation.Nullable; + import com.android.internal.os.BatteryStatsHelper; import com.android.settings.fuelgauge.anomaly.Anomaly; import java.util.List; public interface AnomalyDetector { + /** + * Detect whether there is anomaly among all the applications in the device + * + * @param batteryStatsHelper used to detect the anomaly + * @return anomaly list + */ List detectAnomalies(BatteryStatsHelper batteryStatsHelper); + + /** + * Detect whether application with {@code targetPackageName} has anomaly. When + * {@code targetPackageName} is null, start detection among all the applications. + * + * @param batteryStatsHelper used to detect the anomaly + * @param targetPackageName represents the app need to be detected + * @return anomaly list + */ + List detectAnomalies(BatteryStatsHelper batteryStatsHelper, + @Nullable String targetPackageName); } diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java index 12f5b8c79dc..8568d3720a5 100644 --- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java +++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java @@ -63,17 +63,27 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { @Override public List detectAnomalies(BatteryStatsHelper batteryStatsHelper) { + return detectAnomalies(batteryStatsHelper, null); + } + + @Override + public List detectAnomalies(BatteryStatsHelper batteryStatsHelper, + String targetPackageName) { final List batterySippers = batteryStatsHelper.getUsageList(); final List anomalies = new ArrayList<>(); final long rawRealtime = SystemClock.elapsedRealtime(); + final int targetUid = mBatteryUtils.getPackageUid(targetPackageName); // Check the app one by one for (int i = 0, size = batterySippers.size(); i < size; i++) { final BatterySipper sipper = batterySippers.get(i); final BatteryStats.Uid uid = sipper.uidObj; - if (uid == null) { + if (uid == null + || mBatteryUtils.shouldHideSipper(sipper) + || (targetUid != BatteryUtils.UID_NULL && targetUid != uid.getUid())) { continue; } + final ArrayMap wakelocks = uid.getWakelockStats(); long maxPartialWakeLockMs = 0; @@ -88,10 +98,9 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { getTotalDurationMs(timer, rawRealtime)); } - // Report it if wakelock time is too long and it is not a hidden batterysipper - // TODO: add more attributes to detect wakelock anomaly - if (maxPartialWakeLockMs > mWakeLockThresholdMs - && !mBatteryUtils.shouldHideSipper(sipper)) { + // Report application as anomaly if wakelock time is too long + // TODO(b/38233034): add more attributes to detect wakelock anomaly + if (maxPartialWakeLockMs > mWakeLockThresholdMs) { final String packageName = mBatteryUtils.getPackageName(uid.getUid()); final CharSequence displayName = Utils.getApplicationLabel(mContext, packageName); diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java index b97fd46d1fb..83b8d9a52c5 100644 --- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java +++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java @@ -57,16 +57,25 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { @Override public List detectAnomalies(BatteryStatsHelper batteryStatsHelper) { + return detectAnomalies(batteryStatsHelper, null); + } + + @Override + public List detectAnomalies(BatteryStatsHelper batteryStatsHelper, + String targetPackageName) { final List batterySippers = batteryStatsHelper.getUsageList(); final List anomalies = new ArrayList<>(); final long totalRunningHours = mBatteryUtils.calculateRunningTimeBasedOnStatsType( batteryStatsHelper, BatteryStats.STATS_SINCE_CHARGED) / DateUtils.HOUR_IN_MILLIS; + final int targetUid = mBatteryUtils.getPackageUid(targetPackageName); if (totalRunningHours != 0) { for (int i = 0, size = batterySippers.size(); i < size; i++) { final BatterySipper sipper = batterySippers.get(i); final BatteryStats.Uid uid = sipper.uidObj; - if (uid == null || mBatteryUtils.shouldHideSipper(sipper)) { + if (uid == null + || mBatteryUtils.shouldHideSipper(sipper) + || (targetUid != BatteryUtils.UID_NULL && targetUid != uid.getUid())) { continue; } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java index 2cd6b9ef473..c872961fe06 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyDetectionPolicyTest.java @@ -36,6 +36,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.util.ReflectionHelpers; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @@ -57,18 +58,7 @@ public class AnomalyDetectionPolicyTest { @Test public void testInit_containsDataFromSettings() { - Settings.Global.putString(mContext.getContentResolver(), - Settings.Global.ANOMALY_DETECTION_CONSTANTS, ANOMALY_DETECTION_CONSTANTS_VALUE); - // Mock it to avoid noSuchMethodError - doReturn(true).when(mKeyValueListParserWrapper).getBoolean( - AnomalyDetectionPolicy.KEY_ANOMALY_DETECTION_ENABLED, true); - doReturn(false).when(mKeyValueListParserWrapper).getBoolean( - AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, true); - doReturn(true).when(mKeyValueListParserWrapper).getBoolean( - AnomalyDetectionPolicy.KEY_WAKEUP_ALARM_DETECTION_ENABLED, true); - - AnomalyDetectionPolicy anomalyDetectionPolicy = new AnomalyDetectionPolicy(mContext, - mKeyValueListParserWrapper); + AnomalyDetectionPolicy anomalyDetectionPolicy = createAnomalyPolicyWithConfig(); assertThat(anomalyDetectionPolicy.anomalyDetectionEnabled).isTrue(); assertThat(anomalyDetectionPolicy.wakeLockDetectionEnabled).isFalse(); @@ -94,4 +84,30 @@ public class AnomalyDetectionPolicyTest { assertThat(anomalyDetectionPolicy.wakeupAlarmDetectionEnabled).isTrue(); assertThat(anomalyDetectionPolicy.wakeupAlarmThreshold).isEqualTo(60); } + + @Test + public void testIsAnomalyDetectorEnabled() { + AnomalyDetectionPolicy anomalyDetectionPolicy = createAnomalyPolicyWithConfig(); + + assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled( + Anomaly.AnomalyType.WAKE_LOCK)).isFalse(); + assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled( + Anomaly.AnomalyType.WAKEUP_ALARM)).isTrue(); + } + + private AnomalyDetectionPolicy createAnomalyPolicyWithConfig() { + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.ANOMALY_DETECTION_CONSTANTS, ANOMALY_DETECTION_CONSTANTS_VALUE); + // Mock it to avoid noSuchMethodError + doReturn(true).when(mKeyValueListParserWrapper).getBoolean( + AnomalyDetectionPolicy.KEY_ANOMALY_DETECTION_ENABLED, true); + doReturn(false).when(mKeyValueListParserWrapper).getBoolean( + AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, true); + doReturn(true).when(mKeyValueListParserWrapper).getBoolean( + AnomalyDetectionPolicy.KEY_WAKEUP_ALARM_DETECTION_ENABLED, true); + + return new AnomalyDetectionPolicy(mContext, mKeyValueListParserWrapper); + } + + } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java index e6c995511a3..1ca29a1ae77 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java @@ -19,16 +19,19 @@ package com.android.settings.fuelgauge.anomaly; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; +import android.os.UserManager; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector; +import com.android.settings.fuelgauge.anomaly.checker.WakeupAlarmAnomalyDetector; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; @@ -51,25 +54,39 @@ public class AnomalyLoaderTest { private BatteryStatsHelper mBatteryStatsHelper; @Mock private WakeLockAnomalyDetector mWakeLockAnomalyDetector; + @Mock + private WakeupAlarmAnomalyDetector mWakeupAlarmAnomalyDetector; + @Mock + private AnomalyDetectionPolicy mAnomalyDetectionPolicy; + @Mock + private UserManager mUserManager; private Anomaly mWakeLockAnomaly; + private Anomaly mWakeupAlarmAnomaly; private List mWakeLockAnomalies; + private List mWakeupAlarmAnomalies; private AnomalyLoader mAnomalyLoader; - private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { MockitoAnnotations.initMocks(this); FakeFeatureFactory.setupForTest(mContext); - mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + doReturn(true).when(mAnomalyDetectionPolicy).isAnomalyDetectorEnabled(anyInt()); + doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE); mWakeLockAnomalies = new ArrayList<>(); - mWakeLockAnomaly = new Anomaly.Builder() - .setType(Anomaly.AnomalyType.WAKE_LOCK) - .build(); + mWakeLockAnomaly = createAnomaly(Anomaly.AnomalyType.WAKE_LOCK); mWakeLockAnomalies.add(mWakeLockAnomaly); + doReturn(mWakeLockAnomalies).when(mWakeLockAnomalyDetector).detectAnomalies(any(), any()); - mAnomalyLoader = new AnomalyLoader(mContext, mBatteryStatsHelper); + mWakeupAlarmAnomalies = new ArrayList<>(); + mWakeupAlarmAnomaly = createAnomaly(Anomaly.AnomalyType.WAKEUP_ALARM); + mWakeupAlarmAnomalies.add(mWakeupAlarmAnomaly); + doReturn(mWakeupAlarmAnomalies).when(mWakeupAlarmAnomalyDetector).detectAnomalies(any(), + any()); + + mAnomalyLoader = new AnomalyLoader(mContext, mBatteryStatsHelper, null, + mAnomalyDetectionPolicy); mAnomalyLoader.mAnomalyUtils = spy(new AnomalyUtils(mContext)); } @@ -77,12 +94,17 @@ public class AnomalyLoaderTest { public void testLoadInBackground_containsValidAnomalies() { doReturn(mWakeLockAnomalyDetector).when(mAnomalyLoader.mAnomalyUtils).getAnomalyDetector( Anomaly.AnomalyType.WAKE_LOCK); - doReturn(mWakeLockAnomalies).when(mWakeLockAnomalyDetector).detectAnomalies(any()); - when(mFeatureFactory.powerUsageFeatureProvider.isAnomalyDetectorEnabled( - Anomaly.AnomalyType.WAKE_LOCK)).thenReturn(true); + doReturn(mWakeupAlarmAnomalyDetector).when(mAnomalyLoader.mAnomalyUtils).getAnomalyDetector( + Anomaly.AnomalyType.WAKEUP_ALARM); List anomalies = mAnomalyLoader.loadInBackground(); - assertThat(anomalies).containsExactly(mWakeLockAnomaly); + assertThat(anomalies).containsExactly(mWakeLockAnomaly, mWakeupAlarmAnomaly); + } + + private Anomaly createAnomaly(@Anomaly.AnomalyType int type) { + return new Anomaly.Builder() + .setType(type) + .build(); } } 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 b0b0b99bd5b..2996e4de6f2 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 @@ -55,16 +55,20 @@ import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class WakeLockAnomalyDetectorTest { + private static final String TARGET_PACKAGE_NAME = "com.android.app"; private static final long ANOMALY_WAKELOCK_TIME_MS = 2 * DateUtils.HOUR_IN_MILLIS; private static final long NORMAL_WAKELOCK_TIME_MS = DateUtils.SECOND_IN_MILLIS; private static final long WAKELOCK_THRESHOLD_MS = DateUtils.HOUR_IN_MILLIS; private static final int ANOMALY_UID = 111; private static final int NORMAL_UID = 222; + private static final int TARGET_UID = 333; @Mock private BatteryStatsHelper mBatteryStatsHelper; @Mock private BatterySipper mAnomalySipper; @Mock + private BatterySipper mTargetSipper; + @Mock private BatteryStats.Timer mAnomalyTimer; @Mock private BatteryStats.Uid.Wakelock mAnomalyWakelock; @@ -73,12 +77,18 @@ public class WakeLockAnomalyDetectorTest { @Mock private BatteryStats.Timer mNormalTimer; @Mock + private BatteryStats.Timer mTargetTimer; + @Mock private BatteryStats.Uid.Wakelock mNormalWakelock; @Mock + private BatteryStats.Uid.Wakelock mTargetWakelock; + @Mock private BatteryStats.Uid mAnomalyUid; @Mock private BatteryStats.Uid mNormalUid; @Mock + private BatteryStats.Uid mTargetUid; + @Mock private BatteryUtils mBatteryUtils; @Mock private PackageManager mPackageManager; @@ -89,6 +99,7 @@ public class WakeLockAnomalyDetectorTest { private ArrayMap mAnomalyWakelocks; private ArrayMap mNormalWakelocks; + private ArrayMap mTargetWakelocks; private WakeLockAnomalyDetector mWakelockAnomalyDetector; private Context mContext; private List mUsageList; @@ -119,29 +130,58 @@ public class WakeLockAnomalyDetectorTest { doReturn(mNormalWakelocks).when(mNormalUid).getWakelockStats(); 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(TARGET_UID).when(mTargetUid).getUid(); + mUsageList = new ArrayList<>(); mUsageList.add(mAnomalySipper); mUsageList.add(mNormalSipper); + mUsageList.add(mTargetSipper); doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList(); mWakelockAnomalyDetector = spy(new WakeLockAnomalyDetector(mContext, mPolicy)); mWakelockAnomalyDetector.mBatteryUtils = mBatteryUtils; 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 public void testDetectAnomalies_containsAnomaly_detectIt() { + doReturn(BatteryUtils.UID_NULL).when(mBatteryUtils).getPackageUid(nullable(String.class)); final Anomaly anomaly = new Anomaly.Builder() .setUid(ANOMALY_UID) .setType(Anomaly.AnomalyType.WAKE_LOCK) .build(); + final Anomaly targetAnomaly = new Anomaly.Builder() + .setUid(TARGET_UID) + .setType(Anomaly.AnomalyType.WAKE_LOCK) + .build(); List mAnomalies = mWakelockAnomalyDetector.detectAnomalies(mBatteryStatsHelper); - assertThat(mAnomalies).containsExactly(anomaly); + assertThat(mAnomalies).containsExactly(anomaly, targetAnomaly); + } + + @Test + public void testDetectAnomalies_containsTargetpackage_detectIt() { + doReturn(TARGET_UID).when(mBatteryUtils).getPackageUid(TARGET_PACKAGE_NAME); + final Anomaly targetAnomaly = new Anomaly.Builder() + .setUid(TARGET_UID) + .setType(Anomaly.AnomalyType.WAKE_LOCK) + .build(); + + List mAnomalies = mWakelockAnomalyDetector.detectAnomalies(mBatteryStatsHelper, + TARGET_PACKAGE_NAME); + + assertThat(mAnomalies).containsExactly(targetAnomaly); } @Test diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java index 2e1b7fb13f9..39725963ae0 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java @@ -18,6 +18,7 @@ package com.android.settings.fuelgauge.anomaly.checker; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; @@ -56,8 +57,10 @@ import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class WakeupAlarmAnomalyDetectorTest { + private static final String TARGET_PACKAGE_NAME = "com.android.app"; private static final int ANOMALY_UID = 111; private static final int NORMAL_UID = 222; + private static final int TARGET_UID = 333; private static final long RUNNING_TIME_MS = 2 * DateUtils.HOUR_IN_MILLIS; private static final int ANOMALY_WAKEUP_COUNT = 500; private static final int NORMAL_WAKEUP_COUNT = 50; @@ -68,10 +71,14 @@ public class WakeupAlarmAnomalyDetectorTest { @Mock private BatterySipper mNormalSipper; @Mock + private BatterySipper mTargetSipper; + @Mock private BatteryStats.Uid mAnomalyUid; @Mock private BatteryStats.Uid mNormalUid; @Mock + private BatteryStats.Uid mTargetUid; + @Mock private BatteryUtils mBatteryUtils; @Mock private ApplicationInfo mApplicationInfo; @@ -101,10 +108,13 @@ public class WakeupAlarmAnomalyDetectorTest { doReturn(ANOMALY_UID).when(mAnomalyUid).getUid(); mNormalSipper.uidObj = mNormalUid; doReturn(NORMAL_UID).when(mNormalUid).getUid(); + mTargetSipper.uidObj = mTargetUid; + doReturn(TARGET_UID).when(mTargetUid).getUid(); mUsageList = new ArrayList<>(); mUsageList.add(mAnomalySipper); mUsageList.add(mNormalSipper); + mUsageList.add(mTargetSipper); doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList(); mWakeupAlarmAnomalyDetector = spy(new WakeupAlarmAnomalyDetector(mContext, mPolicy)); @@ -113,18 +123,45 @@ public class WakeupAlarmAnomalyDetectorTest { @Test public void testDetectAnomalies_containsAnomaly_detectIt() { + doReturn(-1).when(mBatteryUtils).getPackageUid(nullable(String.class)); doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid( mAnomalyUid); + doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid( + mTargetUid); doReturn(NORMAL_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid( mNormalUid); final Anomaly anomaly = new Anomaly.Builder() .setUid(ANOMALY_UID) .setType(Anomaly.AnomalyType.WAKEUP_ALARM) .build(); + final Anomaly targetAnomaly = new Anomaly.Builder() + .setUid(TARGET_UID) + .setType(Anomaly.AnomalyType.WAKEUP_ALARM) + .build(); List mAnomalies = mWakeupAlarmAnomalyDetector.detectAnomalies(mBatteryStatsHelper); - assertThat(mAnomalies).containsExactly(anomaly); + assertThat(mAnomalies).containsExactly(anomaly, targetAnomaly); + } + + @Test + public void testDetectAnomalies_detectTargetAnomaly_detectIt() { + doReturn(TARGET_UID).when(mBatteryUtils).getPackageUid(TARGET_PACKAGE_NAME); + doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid( + mAnomalyUid); + doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid( + mTargetUid); + doReturn(NORMAL_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid( + mNormalUid); + final Anomaly targetAnomaly = new Anomaly.Builder() + .setUid(TARGET_UID) + .setType(Anomaly.AnomalyType.WAKEUP_ALARM) + .build(); + + List mAnomalies = mWakeupAlarmAnomalyDetector.detectAnomalies(mBatteryStatsHelper, + TARGET_PACKAGE_NAME); + + assertThat(mAnomalies).containsExactly(targetAnomaly); } @Test