diff --git a/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java b/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java index 4d4b136a1cb..3344eb6329b 100644 --- a/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java +++ b/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java @@ -24,11 +24,18 @@ import com.android.settings.fuelgauge.anomaly.Anomaly; public interface AnomalyAction { /** * handle the action when user clicks positive button - * @param Anomaly about the app that we need to handle + * @param anomaly about the app that we need to handle * @param metricsKey key for the page that invokes the action * * @see com.android.internal.logging.nano.MetricsProto */ - void handlePositiveAction(Anomaly Anomaly, int metricsKey); + void handlePositiveAction(Anomaly anomaly, int metricsKey); + + /** + * Check whether the action is active for {@code anomaly} + * @param anomaly about the app that we need to handle + * @return {@code true} if action is active, otherwise return {@code false} + */ + boolean isActionActive(Anomaly anomaly); int getActionType(); } diff --git a/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java b/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java index 8c7e827bc83..16fd0dfec5b 100644 --- a/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java +++ b/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java @@ -45,6 +45,14 @@ public class BackgroundCheckAction implements AnomalyAction { AppOpsManager.MODE_IGNORED); } + @Override + public boolean isActionActive(Anomaly anomaly) { + final int mode = mAppOpsManager + .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, anomaly.uid, + anomaly.packageName); + return mode != AppOpsManager.MODE_IGNORED && mode != AppOpsManager.MODE_ERRORED; + } + @Override public int getActionType() { return Anomaly.AnomalyActionType.BACKGROUND_CHECK; diff --git a/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java b/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java index c124c9efcc4..557b2a9cf1e 100644 --- a/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java +++ b/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java @@ -18,6 +18,9 @@ package com.android.settings.fuelgauge.anomaly.action; import android.app.ActivityManager; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.util.Log; import android.util.Pair; import com.android.internal.logging.nano.MetricsProto; @@ -25,20 +28,25 @@ import com.android.settings.core.instrumentation.MetricsFeatureProvider; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.overlay.FeatureFactory; +import java.util.List; + /** * Force stop action for anomaly app, which means to stop the app which causes anomaly */ public class ForceStopAction implements AnomalyAction { + private static final String TAG = "ForceStopAction"; private Context mContext; private MetricsFeatureProvider mMetricsFeatureProvider; private ActivityManager mActivityManager; + private PackageManager mPackageManager; public ForceStopAction(Context context) { mContext = context; mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mActivityManager = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE); + mPackageManager = context.getPackageManager(); } @Override @@ -52,6 +60,18 @@ public class ForceStopAction implements AnomalyAction { mActivityManager.forceStopPackage(packageName); } + @Override + public boolean isActionActive(Anomaly anomaly) { + try { + ApplicationInfo info = mPackageManager.getApplicationInfo(anomaly.packageName, + PackageManager.GET_META_DATA); + return (info.flags & ApplicationInfo.FLAG_STOPPED) == 0; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Cannot find info for app: " + anomaly.packageName); + } + return false; + } + @Override public int getActionType() { return Anomaly.AnomalyActionType.FORCE_STOP; diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java index 8568d3720a5..74c43d00f6d 100644 --- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java +++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java @@ -17,14 +17,11 @@ package com.android.settings.fuelgauge.anomaly.checker; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.BatteryStats; import android.os.SystemClock; import android.support.annotation.VisibleForTesting; -import android.text.format.DateUtils; import android.util.ArrayMap; -import android.util.Log; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; @@ -32,6 +29,8 @@ import com.android.settings.Utils; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; +import com.android.settings.fuelgauge.anomaly.AnomalyUtils; +import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; import java.util.ArrayList; import java.util.List; @@ -47,6 +46,8 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { BatteryUtils mBatteryUtils; @VisibleForTesting long mWakeLockThresholdMs; + @VisibleForTesting + AnomalyAction mAnomalyAction; public WakeLockAnomalyDetector(Context context) { this(context, new AnomalyDetectionPolicy(context)); @@ -57,6 +58,8 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { mContext = context; mPackageManager = context.getPackageManager(); mBatteryUtils = BatteryUtils.getInstance(context); + mAnomalyAction = AnomalyUtils.getInstance(context).getAnomalyAction( + Anomaly.AnomalyType.WAKE_LOCK); mWakeLockThresholdMs = policy.wakeLockThreshold; } @@ -111,7 +114,10 @@ public class WakeLockAnomalyDetector implements AnomalyDetector { .setDisplayName(displayName) .setPackageName(packageName) .build(); - anomalies.add(anomaly); + + if (mAnomalyAction.isActionActive(anomaly)) { + anomalies.add(anomaly); + } } } diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java index 83b8d9a52c5..3502e73d70a 100644 --- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java +++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java @@ -17,9 +17,7 @@ package com.android.settings.fuelgauge.anomaly.checker; import android.content.Context; -import android.content.pm.PackageManager; import android.os.BatteryStats; -import android.os.SystemClock; import android.support.annotation.VisibleForTesting; import android.text.format.DateUtils; import android.util.ArrayMap; @@ -30,6 +28,8 @@ import com.android.settings.Utils; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; +import com.android.settings.fuelgauge.anomaly.AnomalyUtils; +import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; import java.util.ArrayList; import java.util.List; @@ -41,6 +41,8 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { private static final String TAG = "WakeupAlarmAnomalyDetector"; @VisibleForTesting BatteryUtils mBatteryUtils; + @VisibleForTesting + AnomalyAction mAnomalyAction; private long mWakeupAlarmThreshold; private Context mContext; @@ -52,6 +54,8 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { WakeupAlarmAnomalyDetector(Context context, AnomalyDetectionPolicy policy) { mContext = context; mBatteryUtils = BatteryUtils.getInstance(context); + mAnomalyAction = AnomalyUtils.getInstance(context).getAnomalyAction( + Anomaly.AnomalyType.WAKEUP_ALARM); mWakeupAlarmThreshold = policy.wakeupAlarmThreshold; } @@ -91,7 +95,10 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector { .setDisplayName(displayName) .setPackageName(packageName) .build(); - anomalies.add(anomaly); + + if (mAnomalyAction.isActionActive(anomaly)) { + anomalies.add(anomaly); + } } } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckActionTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckActionTest.java index 99f7c337e60..ae783ab4e49 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckActionTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckActionTest.java @@ -16,6 +16,8 @@ package com.android.settings.fuelgauge.anomaly.action; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; @@ -69,4 +71,20 @@ public class BackgroundCheckActionTest { verify(mAppOpsManagerr).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME, AppOpsManager.MODE_IGNORED); } + + @Test + public void testIsActionActive_modeAllowed_returnTrue() { + doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManagerr).checkOpNoThrow( + AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME); + + assertThat(mBackgroundCheckAction.isActionActive(mAnomaly)).isTrue(); + } + + @Test + public void testIsActionActive_modeIgnored_returnFalse() { + doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManagerr).checkOpNoThrow( + AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME); + + assertThat(mBackgroundCheckAction.isActionActive(mAnomaly)).isFalse(); + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/ForceStopActionTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/ForceStopActionTest.java index 7bb6a0493a8..89b1a161824 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/ForceStopActionTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/ForceStopActionTest.java @@ -16,11 +16,15 @@ package com.android.settings.fuelgauge.anomaly.action; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; @@ -44,15 +48,22 @@ public class ForceStopActionTest { private Context mContext; @Mock private ActivityManager mActivityManager; + @Mock + private ApplicationInfo mApplicationInfo; + @Mock + private PackageManager mPackageManager; private Anomaly mAnomaly; private ForceStopAction mForceStopAction; @Before - public void setUp() { + public void setUp() throws Exception { MockitoAnnotations.initMocks(this); FakeFeatureFactory.setupForTest(mContext); doReturn(mActivityManager).when(mContext).getSystemService(Context.ACTIVITY_SERVICE); + doReturn(mPackageManager).when(mContext).getPackageManager(); + doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(PACKAGE_NAME, + PackageManager.GET_META_DATA); mAnomaly = new Anomaly.Builder() .setPackageName(PACKAGE_NAME) @@ -66,4 +77,18 @@ public class ForceStopActionTest { verify(mActivityManager).forceStopPackage(PACKAGE_NAME); } + + @Test + public void testIsActionActive_appStopped_returnFalse() { + mApplicationInfo.flags = ApplicationInfo.FLAG_STOPPED; + + assertThat(mForceStopAction.isActionActive(mAnomaly)).isFalse(); + } + + @Test + public void testIsActionActive_appRunning_returnTrue() { + mApplicationInfo.flags = 0; + + assertThat(mForceStopAction.isActionActive(mAnomaly)).isTrue(); + } } 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 64e38401c8c..386e162aaaa 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 @@ -19,6 +19,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; import static org.mockito.Matchers.eq; @@ -39,6 +40,7 @@ import com.android.settings.TestConfig; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; +import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; import org.junit.Before; import org.junit.Test; @@ -96,6 +98,8 @@ public class WakeLockAnomalyDetectorTest { private ApplicationInfo mApplicationInfo; @Mock private AnomalyDetectionPolicy mPolicy; + @Mock + private AnomalyAction mAnomalyAction; private ArrayMap mAnomalyWakelocks; private ArrayMap mNormalWakelocks; @@ -115,6 +119,7 @@ public class WakeLockAnomalyDetectorTest { doReturn(mPackageManager).when(mContext).getPackageManager(); doReturn(mApplicationInfo).when(mPackageManager) .getApplicationInfo(nullable(String.class), anyInt()); + doReturn(true).when(mAnomalyAction).isActionActive(any()); mAnomalySipper.uidObj = mAnomalyUid; mAnomalyWakelocks = new ArrayMap<>(); @@ -145,6 +150,7 @@ public class WakeLockAnomalyDetectorTest { 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( 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 e6cdc4e3c03..21b2e548f51 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 @@ -38,6 +38,7 @@ import com.android.settings.TestConfig; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; +import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; import org.junit.Before; import org.junit.Test; @@ -85,6 +86,8 @@ public class WakeupAlarmAnomalyDetectorTest { private BatteryStats.Counter mCounter; @Mock private AnomalyDetectionPolicy mPolicy; + @Mock + private AnomalyAction mAnomalyAction; private WakeupAlarmAnomalyDetector mWakeupAlarmAnomalyDetector; private Context mContext; @@ -100,6 +103,7 @@ public class WakeupAlarmAnomalyDetectorTest { doReturn(false).when(mBatteryUtils).shouldHideSipper(any()); doReturn(RUNNING_TIME_MS).when(mBatteryUtils).calculateRunningTimeBasedOnStatsType(any(), anyInt()); + doReturn(true).when(mAnomalyAction).isActionActive(any()); mAnomalySipper.uidObj = mAnomalyUid; doReturn(ANOMALY_UID).when(mAnomalyUid).getUid(); @@ -116,6 +120,7 @@ public class WakeupAlarmAnomalyDetectorTest { mWakeupAlarmAnomalyDetector = spy(new WakeupAlarmAnomalyDetector(mContext, mPolicy)); mWakeupAlarmAnomalyDetector.mBatteryUtils = mBatteryUtils; + mWakeupAlarmAnomalyDetector.mAnomalyAction = mAnomalyAction; } @Test