Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8bd54d45 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update wakeup anomaly to exclude blacklisted wakeups." into oc-mr1-dev

parents 85d5d627 f59cbb14
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -17,12 +17,17 @@
package com.android.settings.fuelgauge.anomaly;

import android.content.Context;
import android.net.Uri;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.text.format.DateUtils;
import android.util.KeyValueListParser;
import android.util.Log;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Class to store the policy for anomaly detection, which comes from
 * {@link android.provider.Settings.Global}
@@ -43,6 +48,8 @@ public class AnomalyDetectionPolicy {
    @VisibleForTesting
    static final String KEY_WAKEUP_ALARM_THRESHOLD = "wakeup_alarm_threshold";
    @VisibleForTesting
    static final String KEY_WAKEUP_BLACKLISTED_TAGS = "wakeup_blacklisted_tags";
    @VisibleForTesting
    static final String KEY_BLUETOOTH_SCAN_THRESHOLD = "bluetooth_scan_threshold";

    /**
@@ -93,6 +100,14 @@ public class AnomalyDetectionPolicy {
     */
    public final long wakeupAlarmThreshold;

    /**
     * Array of blacklisted wakeups, by tag.
     *
     * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
     * @see #KEY_WAKEUP_BLACKLISTED_TAGS
     */
    public final Set<String> wakeupBlacklistedTags;

    /**
     * Threshold for bluetooth unoptimized scanning time in milli seconds
     *
@@ -119,15 +134,18 @@ public class AnomalyDetectionPolicy {
            Log.e(TAG, "Bad anomaly detection constants");
        }

        anomalyDetectionEnabled = mParserWrapper.getBoolean(KEY_ANOMALY_DETECTION_ENABLED, true);
        wakeLockDetectionEnabled = mParserWrapper.getBoolean(KEY_WAKELOCK_DETECTION_ENABLED, true);
        wakeupAlarmDetectionEnabled = mParserWrapper.getBoolean(KEY_WAKEUP_ALARM_DETECTION_ENABLED,
                false);
        anomalyDetectionEnabled =
                mParserWrapper.getBoolean(KEY_ANOMALY_DETECTION_ENABLED, false);
        wakeLockDetectionEnabled =
                mParserWrapper.getBoolean(KEY_WAKELOCK_DETECTION_ENABLED,false);
        wakeupAlarmDetectionEnabled =
                mParserWrapper.getBoolean(KEY_WAKEUP_ALARM_DETECTION_ENABLED,false);
        bluetoothScanDetectionEnabled = mParserWrapper.getBoolean(
                KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, true);
                KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, false);
        wakeLockThreshold = mParserWrapper.getLong(KEY_WAKELOCK_THRESHOLD,
                DateUtils.HOUR_IN_MILLIS);
        wakeupAlarmThreshold = mParserWrapper.getLong(KEY_WAKEUP_ALARM_THRESHOLD, 60);
        wakeupAlarmThreshold = mParserWrapper.getLong(KEY_WAKEUP_ALARM_THRESHOLD, 10);
        wakeupBlacklistedTags = parseStringSet(KEY_WAKEUP_BLACKLISTED_TAGS, null);
        bluetoothScanThreshold = mParserWrapper.getLong(KEY_BLUETOOTH_SCAN_THRESHOLD,
                30 * DateUtils.MINUTE_IN_MILLIS);
    }
@@ -148,4 +166,14 @@ public class AnomalyDetectionPolicy {
                return false; // Disabled when no this type
        }
    }

    private Set<String> parseStringSet(final String key, final Set<String> defaultSet) {
        final String value = mParserWrapper.getString(key, null);
        if (value != null) {
            return Arrays.stream(value.split(":"))
                    .map(String::trim).map(Uri::decode).collect(Collectors.toSet());
        } else {
            return defaultSet;
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -43,6 +43,14 @@ public interface KeyValueListParserWrapper {
     */
    void setString(String str) throws IllegalArgumentException;

    /**
     * Get the value for key as a string.
     * @param key The key to lookup.
     * @param defaultValue The value to return if the key was not found.
     * @return the string value associated with the key.
     */
    String getString(String key, String defaultValue);

    /**
     * Get the value for key as a boolean.
     * @param key The key to lookup.
+5 −0
Original line number Diff line number Diff line
@@ -38,6 +38,11 @@ public class KeyValueListParserWrapperImpl implements KeyValueListParserWrapper
        mParser.setString(str);
    }

    @Override
    public String getString(String key, String defaultValue) {
        return mParser.getString(key, defaultValue);
    }

    @Override
    public boolean getBoolean(String key, boolean defaultValue) {
        return mParser.getBoolean(key, defaultValue);
+10 −4
Original line number Diff line number Diff line
@@ -29,10 +29,11 @@ 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;
import java.util.Map;
import java.util.Set;

/**
 * Check whether apps has too many wakeup alarms
@@ -42,6 +43,7 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector {
    @VisibleForTesting
    BatteryUtils mBatteryUtils;
    private long mWakeupAlarmThreshold;
    private Set<String> mWakeupBlacklistedTags;
    private Context mContext;
    private AnomalyUtils mAnomalyUtils;

@@ -56,6 +58,7 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector {
        mBatteryUtils = BatteryUtils.getInstance(context);
        mAnomalyUtils = anomalyUtils;
        mWakeupAlarmThreshold = policy.wakeupAlarmThreshold;
        mWakeupBlacklistedTags = policy.wakeupBlacklistedTags;
    }

    @Override
@@ -123,11 +126,14 @@ public class WakeupAlarmAnomalyDetector implements AnomalyDetector {
            final BatteryStats.Uid.Pkg ps = packageStats.valueAt(ipkg);
            final ArrayMap<String, ? extends BatteryStats.Counter> alarms =
                    ps.getWakeupAlarmStats();
            for (int iwa = alarms.size() - 1; iwa >= 0; iwa--) {
                int count = alarms.valueAt(iwa).getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
            for (Map.Entry<String, ? extends BatteryStats.Counter> alarm : alarms.entrySet()) {
                if (mWakeupBlacklistedTags != null
                        && mWakeupBlacklistedTags.contains(alarm.getKey())) {
                    continue;
                }
                int count = alarm.getValue().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
                wakeups += count;
            }

        }

        return wakeups;
+35 −11
Original line number Diff line number Diff line
@@ -40,11 +40,13 @@ import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AnomalyDetectionPolicyTest {
    private static final String ANOMALY_DETECTION_CONSTANTS_VALUE = "anomaly_detection_enabled=true"
    private static final String ANOMALY_DETECTION_CONSTANTS_VALUE =
            "anomaly_detection_enabled=true"
            + ",wakelock_enabled=false"
            + ",wakelock_threshold=3000"
            + ",wakeup_alarm_enabled=true"
            + ",wakeup_alarm_threshold=100"
            + ",wakeup_blacklisted_tags=tag1:tag2:with%2Ccomma:with%3Acolon"
            + ",bluetooth_scan_enabled=true"
            + ",bluetooth_scan_threshold=2000";
    private Context mContext;
@@ -58,7 +60,7 @@ public class AnomalyDetectionPolicyTest {
    }

    @Test
    public void testInit_containsDataFromSettings() {
    public void testInit_usesConfigValues() {
        AnomalyDetectionPolicy anomalyDetectionPolicy = createAnomalyPolicyWithConfig();

        assertThat(anomalyDetectionPolicy.anomalyDetectionEnabled).isTrue();
@@ -66,12 +68,14 @@ public class AnomalyDetectionPolicyTest {
        assertThat(anomalyDetectionPolicy.wakeLockThreshold).isEqualTo(3000);
        assertThat(anomalyDetectionPolicy.wakeupAlarmDetectionEnabled).isTrue();
        assertThat(anomalyDetectionPolicy.wakeupAlarmThreshold).isEqualTo(100);
        assertThat(anomalyDetectionPolicy.wakeupBlacklistedTags)
                .containsExactly("tag1", "tag2", "with,comma", "with:colon");
        assertThat(anomalyDetectionPolicy.bluetoothScanDetectionEnabled).isTrue();
        assertThat(anomalyDetectionPolicy.bluetoothScanThreshold).isEqualTo(2000);
    }

    @Test
    public void testInit_containsDefaultData() {
    public void testInit_defaultValues() {
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.ANOMALY_DETECTION_CONSTANTS, "");
        // Mock it to avoid noSuchMethodError
@@ -81,18 +85,19 @@ public class AnomalyDetectionPolicyTest {
        AnomalyDetectionPolicy anomalyDetectionPolicy = new AnomalyDetectionPolicy(mContext,
                mKeyValueListParserWrapper);

        assertThat(anomalyDetectionPolicy.anomalyDetectionEnabled).isTrue();
        assertThat(anomalyDetectionPolicy.wakeLockDetectionEnabled).isTrue();
        assertThat(anomalyDetectionPolicy.anomalyDetectionEnabled).isFalse();
        assertThat(anomalyDetectionPolicy.wakeLockDetectionEnabled).isFalse();
        assertThat(anomalyDetectionPolicy.wakeLockThreshold).isEqualTo(DateUtils.HOUR_IN_MILLIS);
        assertThat(anomalyDetectionPolicy.wakeupAlarmDetectionEnabled).isFalse();
        assertThat(anomalyDetectionPolicy.wakeupAlarmThreshold).isEqualTo(60);
        assertThat(anomalyDetectionPolicy.bluetoothScanDetectionEnabled).isTrue();
        assertThat(anomalyDetectionPolicy.wakeupAlarmThreshold).isEqualTo(10);
        assertThat(anomalyDetectionPolicy.wakeupBlacklistedTags).isNull();
        assertThat(anomalyDetectionPolicy.bluetoothScanDetectionEnabled).isFalse();
        assertThat(anomalyDetectionPolicy.bluetoothScanThreshold).isEqualTo(
                30 * DateUtils.MINUTE_IN_MILLIS);
    }

    @Test
    public void testIsAnomalyDetectorEnabled() {
    public void testIsAnomalyDetectorEnabled_usesConfigValues() {
        AnomalyDetectionPolicy anomalyDetectionPolicy = createAnomalyPolicyWithConfig();

        assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled(
@@ -103,18 +108,37 @@ public class AnomalyDetectionPolicyTest {
                Anomaly.AnomalyType.BLUETOOTH_SCAN)).isTrue();
    }

    @Test
    public void testIsAnomalyDetectorEnabled_usesDefaultValues() {
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.ANOMALY_DETECTION_CONSTANTS, "");
        // Mock it to avoid noSuchMethodError
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(anyString(), eq(true));
        doReturn(false).when(mKeyValueListParserWrapper).getBoolean(anyString(), eq(false));

        AnomalyDetectionPolicy anomalyDetectionPolicy = new AnomalyDetectionPolicy(mContext,
                mKeyValueListParserWrapper);

        assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled(
                Anomaly.AnomalyType.WAKE_LOCK)).isFalse();
        assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled(
                Anomaly.AnomalyType.WAKEUP_ALARM)).isFalse();
        assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled(
                Anomaly.AnomalyType.BLUETOOTH_SCAN)).isFalse();
    }

    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);
                AnomalyDetectionPolicy.KEY_ANOMALY_DETECTION_ENABLED, false);
        doReturn(false).when(mKeyValueListParserWrapper).getBoolean(
                AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, true);
                AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, false);
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
                AnomalyDetectionPolicy.KEY_WAKEUP_ALARM_DETECTION_ENABLED, false);
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
                AnomalyDetectionPolicy.KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, true);
                AnomalyDetectionPolicy.KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, false);

        return new AnomalyDetectionPolicy(mContext, mKeyValueListParserWrapper);
    }
Loading