Refactor anomaly detection
This cl refactor it so: 1. AnomayLoader could create its own BatteryStatsHelper if needed. 2. AnomalyDetector could detect the anomaly with a target package name 3. Remove FeatureProvider in AnomalyLoader and use AnomalyDetectionPolicy instead With this cl, we could add anomaly detection to battery usage page more easily. Bug: 36924669 Test: RunSettingsRoboTests Change-Id: I1ee09701de8b5c8855f44e447813760285794c89
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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<Anomaly> mWakeLockAnomalies;
|
||||
private List<Anomaly> 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<Anomaly> 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();
|
||||
}
|
||||
}
|
||||
|
@@ -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<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;
|
||||
@@ -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<Anomaly> 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<Anomaly> mAnomalies = mWakelockAnomalyDetector.detectAnomalies(mBatteryStatsHelper,
|
||||
TARGET_PACKAGE_NAME);
|
||||
|
||||
assertThat(mAnomalies).containsExactly(targetAnomaly);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -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<Anomaly> 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<Anomaly> mAnomalies = mWakeupAlarmAnomalyDetector.detectAnomalies(mBatteryStatsHelper,
|
||||
TARGET_PACKAGE_NAME);
|
||||
|
||||
assertThat(mAnomalies).containsExactly(targetAnomaly);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Reference in New Issue
Block a user