From 0dce3c076410e7a14b236a8bbd74083c01325e92 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Wed, 3 May 2017 15:15:41 -0700 Subject: [PATCH] Add framework for anomaly detection flags This cl adds isAnomalyDetectorEnabled(type), which decides whether to turn on specific check with that type. Added method is used in AnomalyLoader. Bug: 36924669 Test: RunSettingsRoboTests Change-Id: I71c6acb1c58c24453a1936c5c36f59fe4e86cfd4 --- .../fuelgauge/PowerUsageFeatureProvider.java | 6 ++ .../fuelgauge/PowerUsageFeatureProviderImpl.java | 6 ++ .../settings/fuelgauge/anomaly/Anomaly.java | 3 + .../settings/fuelgauge/anomaly/AnomalyLoader.java | 19 ++++- .../settings/fuelgauge/anomaly/AnomalyUtils.java | 19 ++++- .../fuelgauge/anomaly/AnomalyLoaderTest.java | 88 ++++++++++++++++++++++ .../fuelgauge/anomaly/AnomalyUtilsTest.java | 7 ++ 7 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 91bb9854b3..4a4d28c5a1 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.database.Cursor; import android.net.Uri; import com.android.internal.os.BatterySipper; +import com.android.settings.fuelgauge.anomaly.Anomaly; /** * Feature Provider used in power usage @@ -85,4 +86,9 @@ public interface PowerUsageFeatureProvider { * Returns the the estimate in the cursor as a long or -1 if the cursor is null */ long getTimeRemainingEstimate(Cursor cursor); + + /** + * Check whether a specific anomaly detector is enabled + */ + boolean isAnomalyDetectorEnabled(@Anomaly.AnomalyType int type); } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index 4ebe10fde9..2cc6899601 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -24,6 +24,7 @@ import android.net.Uri; import android.os.Process; import com.android.internal.os.BatterySipper; import com.android.internal.util.ArrayUtils; +import com.android.settings.fuelgauge.anomaly.Anomaly; public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider { @@ -111,4 +112,9 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider public long getTimeRemainingEstimate(Cursor cursor) { return 0; } + + @Override + public boolean isAnomalyDetectorEnabled(@Anomaly.AnomalyType int type) { + return false; + } } diff --git a/src/com/android/settings/fuelgauge/anomaly/Anomaly.java b/src/com/android/settings/fuelgauge/anomaly/Anomaly.java index d5a2e14961..8aff86144e 100644 --- a/src/com/android/settings/fuelgauge/anomaly/Anomaly.java +++ b/src/com/android/settings/fuelgauge/anomaly/Anomaly.java @@ -45,6 +45,9 @@ public class Anomaly implements Parcelable { int FORCE_STOP = 0; } + @AnomalyType + public static final int[] ANOMALY_TYPE_LIST = {AnomalyType.WAKE_LOCK}; + /** * Type of this this anomaly */ diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java index f530035f81..1ffdd9fc5a 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java @@ -17,9 +17,11 @@ package com.android.settings.fuelgauge.anomaly; import android.content.Context; +import android.support.annotation.VisibleForTesting; import com.android.internal.os.BatteryStatsHelper; -import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector; +import com.android.settings.fuelgauge.PowerUsageFeatureProvider; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.utils.AsyncLoader; import java.util.ArrayList; @@ -29,13 +31,18 @@ import java.util.List; * Loader to compute which apps are anomaly and return a anomaly list. It will return * an empty list if there is no anomaly. */ -//TODO(b/36924669): add test for this file, for now it seems there is nothing to test public class AnomalyLoader extends AsyncLoader> { private BatteryStatsHelper mBatteryStatsHelper; + private PowerUsageFeatureProvider mPowerUsageFeatureProvider; + @VisibleForTesting + AnomalyUtils mAnomalyUtils; public AnomalyLoader(Context context, BatteryStatsHelper batteryStatsHelper) { super(context); mBatteryStatsHelper = batteryStatsHelper; + mPowerUsageFeatureProvider = FeatureFactory.getFactory( + context).getPowerUsageFeatureProvider(context); + mAnomalyUtils = AnomalyUtils.getInstance(context); } @Override @@ -45,8 +52,12 @@ public class AnomalyLoader extends AsyncLoader> { @Override public List loadInBackground() { final List anomalies = new ArrayList<>(); - anomalies.addAll(new WakeLockAnomalyDetector(getContext()) - .detectAnomalies(mBatteryStatsHelper)); + for (@Anomaly.AnomalyType int type : Anomaly.ANOMALY_TYPE_LIST) { + if (mPowerUsageFeatureProvider.isAnomalyDetectorEnabled(type)) { + anomalies.addAll(mAnomalyUtils.getAnomalyDetector(type).detectAnomalies( + mBatteryStatsHelper)); + } + } return anomalies; } diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java index a6efab5024..e55d485bbd 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java @@ -21,6 +21,8 @@ import android.support.annotation.VisibleForTesting; import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; import com.android.settings.fuelgauge.anomaly.action.ForceStopAction; +import com.android.settings.fuelgauge.anomaly.checker.AnomalyDetector; +import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector; /** * Utility class for anomaly detection @@ -47,7 +49,7 @@ public class AnomalyUtils { * * @return corresponding {@link AnomalyAction}, or null if cannot find it. */ - public final AnomalyAction getAnomalyAction(@Anomaly.AnomalyType int anomalyType) { + public AnomalyAction getAnomalyAction(@Anomaly.AnomalyType int anomalyType) { switch (anomalyType) { case Anomaly.AnomalyType.WAKE_LOCK: return new ForceStopAction(mContext); @@ -55,4 +57,19 @@ public class AnomalyUtils { return null; } } + + /** + * Return the corresponding {@link AnomalyDetector} according to + * {@link com.android.settings.fuelgauge.anomaly.Anomaly.AnomalyType} + * + * @return corresponding {@link AnomalyDetector}, or null if cannot find it. + */ + public AnomalyDetector getAnomalyDetector(@Anomaly.AnomalyType int anomalyType) { + switch (anomalyType) { + case Anomaly.AnomalyType.WAKE_LOCK: + return new WakeLockAnomalyDetector(mContext); + default: + return null; + } + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java new file mode 100644 index 0000000000..843b747d73 --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyLoaderTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.fuelgauge.anomaly; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; + +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.testutils.FakeFeatureFactory; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class AnomalyLoaderTest { + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private BatteryStatsHelper mBatteryStatsHelper; + private WakeLockAnomalyDetector mWakeLockAnomalyDetector; + private Anomaly mWakeLockAnomaly; + private List mWakeLockAnomalies; + private AnomalyLoader mAnomalyLoader; + private FakeFeatureFactory mFeatureFactory; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + FakeFeatureFactory.setupForTest(mContext); + mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + + mWakeLockAnomalyDetector = spy(new WakeLockAnomalyDetector(mContext)); + mWakeLockAnomalies = new ArrayList<>(); + mWakeLockAnomaly = new Anomaly.Builder() + .setType(Anomaly.AnomalyType.WAKE_LOCK) + .build(); + mWakeLockAnomalies.add(mWakeLockAnomaly); + + mAnomalyLoader = new AnomalyLoader(mContext, mBatteryStatsHelper); + mAnomalyLoader.mAnomalyUtils = spy(new AnomalyUtils(mContext)); + } + + @Test + 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); + + List anomalies = mAnomalyLoader.loadInBackground(); + + assertThat(anomalies).containsExactly(mWakeLockAnomaly); + } +} diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyUtilsTest.java index ae211ce88d..6303b180af 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyUtilsTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.fuelgauge.anomaly.action.ForceStopAction; +import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector; import org.junit.Before; import org.junit.Test; @@ -43,4 +44,10 @@ public class AnomalyUtilsTest { assertThat(mAnomalyUtils.getAnomalyAction(Anomaly.AnomalyType.WAKE_LOCK)).isInstanceOf( ForceStopAction.class); } + + @Test + public void testGetAnomalyDetector_typeWakeLock_returnWakeLockDetector() { + assertThat(mAnomalyUtils.getAnomalyDetector(Anomaly.AnomalyType.WAKE_LOCK)).isInstanceOf( + WakeLockAnomalyDetector.class); + } } -- 2.11.0