diff --git a/src/com/android/settings/fuelgauge/anomaly/Anomaly.java b/src/com/android/settings/fuelgauge/anomaly/Anomaly.java index 90fc852daf3..37b52fcdb54 100644 --- a/src/com/android/settings/fuelgauge/anomaly/Anomaly.java +++ b/src/com/android/settings/fuelgauge/anomaly/Anomaly.java @@ -42,9 +42,11 @@ public class Anomaly implements Parcelable { } @Retention(RetentionPolicy.SOURCE) - @IntDef({AnomalyActionType.FORCE_STOP}) + @IntDef({AnomalyActionType.FORCE_STOP, + AnomalyActionType.BACKGROUND_CHECK}) public @interface AnomalyActionType { int FORCE_STOP = 0; + int BACKGROUND_CHECK = 1; } @AnomalyType diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyDialogFragment.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyDialogFragment.java index e05eace63d4..ef15d51aba1 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyDialogFragment.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyDialogFragment.java @@ -87,7 +87,7 @@ public class AnomalyDialogFragment extends InstrumentedDialogFragment implements final AnomalyAction anomalyAction = mAnomalyUtils.getAnomalyAction(mAnomaly.type); final int metricsKey = getArguments().getInt(ARG_METRICS_KEY); - anomalyAction.handlePositiveAction(mAnomaly.packageName, metricsKey); + anomalyAction.handlePositiveAction(mAnomaly, metricsKey); lsn.onAnomalyHandled(mAnomaly); } diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java index e55d485bbd3..d2268992eb1 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyUtils.java @@ -20,9 +20,11 @@ import android.content.Context; import android.support.annotation.VisibleForTesting; import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; +import com.android.settings.fuelgauge.anomaly.action.BackgroundCheckAction; import com.android.settings.fuelgauge.anomaly.action.ForceStopAction; import com.android.settings.fuelgauge.anomaly.checker.AnomalyDetector; import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector; +import com.android.settings.fuelgauge.anomaly.checker.WakeupAlarmAnomalyDetector; /** * Utility class for anomaly detection @@ -53,6 +55,8 @@ public class AnomalyUtils { switch (anomalyType) { case Anomaly.AnomalyType.WAKE_LOCK: return new ForceStopAction(mContext); + case Anomaly.AnomalyType.WAKEUP_ALARM: + return new BackgroundCheckAction(mContext); default: return null; } @@ -68,6 +72,8 @@ public class AnomalyUtils { switch (anomalyType) { case Anomaly.AnomalyType.WAKE_LOCK: return new WakeLockAnomalyDetector(mContext); + case Anomaly.AnomalyType.WAKEUP_ALARM: + return new WakeupAlarmAnomalyDetector(mContext); default: return null; } diff --git a/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java b/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java index 6b8ff678ace..4d4b136a1cb 100644 --- a/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java +++ b/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java @@ -16,17 +16,19 @@ package com.android.settings.fuelgauge.anomaly.action; +import com.android.settings.fuelgauge.anomaly.Anomaly; + /** * Interface for anomaly action, which is triggered if we need to handle the anomaly */ public interface AnomalyAction { /** * handle the action when user clicks positive button - * @param packageName 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(String packageName, int metricsKey); + void handlePositiveAction(Anomaly Anomaly, int metricsKey); int getActionType(); } diff --git a/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java b/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java new file mode 100644 index 00000000000..8c7e827bc83 --- /dev/null +++ b/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java @@ -0,0 +1,52 @@ +/* + * 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.action; + +import android.app.AppOpsManager; +import android.content.Context; + +import com.android.settings.core.instrumentation.MetricsFeatureProvider; +import com.android.settings.fuelgauge.anomaly.Anomaly; +import com.android.settings.overlay.FeatureFactory; + +/** + * Background check action for anomaly app, which means to stop app running in the background + */ +public class BackgroundCheckAction implements AnomalyAction { + + private Context mContext; + private MetricsFeatureProvider mMetricsFeatureProvider; + private AppOpsManager mAppOpsManager; + + public BackgroundCheckAction(Context context) { + mContext = context; + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); + mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + } + + @Override + public void handlePositiveAction(Anomaly anomaly, int metricsKey) { + // TODO(b/37681923): add metric log here if possible + mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, anomaly.uid, anomaly.packageName, + AppOpsManager.MODE_IGNORED); + } + + @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 40f6839eaa7..c124c9efcc4 100644 --- a/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java +++ b/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java @@ -42,7 +42,8 @@ public class ForceStopAction implements AnomalyAction { } @Override - public void handlePositiveAction(String packageName, int metricsKey) { + public void handlePositiveAction(Anomaly anomaly, int metricsKey) { + final String packageName = anomaly.packageName; // force stop the package mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_FORCE_STOP, packageName, 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 d8652e51a05..c246eee186b 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyUtilsTest.java @@ -20,9 +20,11 @@ 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.BackgroundCheckAction; import com.android.settings.fuelgauge.anomaly.action.ForceStopAction; import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector; import com.android.settings.testutils.shadow.ShadowKeyValueListParserWrapperImpl; +import com.android.settings.fuelgauge.anomaly.checker.WakeupAlarmAnomalyDetector; import org.junit.Before; import org.junit.Test; @@ -47,9 +49,21 @@ public class AnomalyUtilsTest { ForceStopAction.class); } + @Test + public void testGetAnomalyAction_typeWakeUpAlarm_returnBackgroundCheck() { + assertThat(mAnomalyUtils.getAnomalyAction(Anomaly.AnomalyType.WAKEUP_ALARM)).isInstanceOf( + BackgroundCheckAction.class); + } + @Test public void testGetAnomalyDetector_typeWakeLock_returnWakeLockDetector() { assertThat(mAnomalyUtils.getAnomalyDetector(Anomaly.AnomalyType.WAKE_LOCK)).isInstanceOf( WakeLockAnomalyDetector.class); } + + @Test + public void testGetAnomalyDetector_typeWakeUpAlarm_returnWakeUpAlarmDetector() { + assertThat(mAnomalyUtils.getAnomalyDetector(Anomaly.AnomalyType.WAKEUP_ALARM)).isInstanceOf( + WakeupAlarmAnomalyDetector.class); + } } 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 new file mode 100644 index 00000000000..83d2e987c58 --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckActionTest.java @@ -0,0 +1,73 @@ +/* + * 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.action; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; + +import android.app.ActivityManager; +import android.app.AppOpsManager; +import android.content.Context; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.fuelgauge.anomaly.Anomaly; +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; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class BackgroundCheckActionTest { + private static final String PACKAGE_NAME = "com.android.app"; + private static final int UID = 111; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private AppOpsManager mAppOpsManagerr; + private Anomaly mAnomaly; + private BackgroundCheckAction mBackgroundCheckAction; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + FakeFeatureFactory.setupForTest(mContext); + doReturn(mAppOpsManagerr).when(mContext).getSystemService(Context.APP_OPS_SERVICE); + + mAnomaly = new Anomaly.Builder() + .setUid(UID) + .setPackageName(PACKAGE_NAME) + .build(); + mBackgroundCheckAction = new BackgroundCheckAction(mContext); + } + + @Test + public void testHandlePositiveAction_forceStopPackage() { + mBackgroundCheckAction.handlePositiveAction(mAnomaly, 0 /* metricskey */); + + verify(mAppOpsManagerr).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID, PACKAGE_NAME, + AppOpsManager.MODE_IGNORED); + } +} 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 e4bcb1d4379..87c946a742f 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 @@ -24,6 +24,7 @@ import android.content.Context; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; @@ -43,6 +44,7 @@ public class ForceStopActionTest { private Context mContext; @Mock private ActivityManager mActivityManager; + private Anomaly mAnomaly; private ForceStopAction mForceStopAction; @Before @@ -52,12 +54,15 @@ public class ForceStopActionTest { FakeFeatureFactory.setupForTest(mContext); doReturn(mActivityManager).when(mContext).getSystemService(Context.ACTIVITY_SERVICE); + mAnomaly = new Anomaly.Builder() + .setPackageName(PACKAGE_NAME) + .build(); mForceStopAction = new ForceStopAction(mContext); } @Test public void testHandlePositiveAction_forceStopPackage() { - mForceStopAction.handlePositiveAction(PACKAGE_NAME, 0 /* metricskey */); + mForceStopAction.handlePositiveAction(mAnomaly, 0 /* metricskey */); verify(mActivityManager).forceStopPackage(PACKAGE_NAME); }