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

Commit 95ebdd35 authored by Andrew Sapperstein's avatar Andrew Sapperstein Committed by android-build-merger
Browse files

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

am: 8bd54d45

Change-Id: If099f1d66dcb83817d5b6c3e22d4ca3e550d5e71
parents 47e2bad5 8bd54d45
Loading
Loading
Loading
Loading
+34 −6
Original line number Original line Diff line number Diff line
@@ -17,12 +17,17 @@
package com.android.settings.fuelgauge.anomaly;
package com.android.settings.fuelgauge.anomaly;


import android.content.Context;
import android.content.Context;
import android.net.Uri;
import android.provider.Settings;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.VisibleForTesting;
import android.text.format.DateUtils;
import android.text.format.DateUtils;
import android.util.KeyValueListParser;
import android.util.KeyValueListParser;
import android.util.Log;
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
 * Class to store the policy for anomaly detection, which comes from
 * {@link android.provider.Settings.Global}
 * {@link android.provider.Settings.Global}
@@ -43,6 +48,8 @@ public class AnomalyDetectionPolicy {
    @VisibleForTesting
    @VisibleForTesting
    static final String KEY_WAKEUP_ALARM_THRESHOLD = "wakeup_alarm_threshold";
    static final String KEY_WAKEUP_ALARM_THRESHOLD = "wakeup_alarm_threshold";
    @VisibleForTesting
    @VisibleForTesting
    static final String KEY_WAKEUP_BLACKLISTED_TAGS = "wakeup_blacklisted_tags";
    @VisibleForTesting
    static final String KEY_BLUETOOTH_SCAN_THRESHOLD = "bluetooth_scan_threshold";
    static final String KEY_BLUETOOTH_SCAN_THRESHOLD = "bluetooth_scan_threshold";


    /**
    /**
@@ -93,6 +100,14 @@ public class AnomalyDetectionPolicy {
     */
     */
    public final long wakeupAlarmThreshold;
    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
     * Threshold for bluetooth unoptimized scanning time in milli seconds
     *
     *
@@ -119,15 +134,18 @@ public class AnomalyDetectionPolicy {
            Log.e(TAG, "Bad anomaly detection constants");
            Log.e(TAG, "Bad anomaly detection constants");
        }
        }


        anomalyDetectionEnabled = mParserWrapper.getBoolean(KEY_ANOMALY_DETECTION_ENABLED, true);
        anomalyDetectionEnabled =
        wakeLockDetectionEnabled = mParserWrapper.getBoolean(KEY_WAKELOCK_DETECTION_ENABLED, true);
                mParserWrapper.getBoolean(KEY_ANOMALY_DETECTION_ENABLED, false);
        wakeupAlarmDetectionEnabled = mParserWrapper.getBoolean(KEY_WAKEUP_ALARM_DETECTION_ENABLED,
        wakeLockDetectionEnabled =
                false);
                mParserWrapper.getBoolean(KEY_WAKELOCK_DETECTION_ENABLED,false);
        wakeupAlarmDetectionEnabled =
                mParserWrapper.getBoolean(KEY_WAKEUP_ALARM_DETECTION_ENABLED,false);
        bluetoothScanDetectionEnabled = mParserWrapper.getBoolean(
        bluetoothScanDetectionEnabled = mParserWrapper.getBoolean(
                KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, true);
                KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, false);
        wakeLockThreshold = mParserWrapper.getLong(KEY_WAKELOCK_THRESHOLD,
        wakeLockThreshold = mParserWrapper.getLong(KEY_WAKELOCK_THRESHOLD,
                DateUtils.HOUR_IN_MILLIS);
                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,
        bluetoothScanThreshold = mParserWrapper.getLong(KEY_BLUETOOTH_SCAN_THRESHOLD,
                30 * DateUtils.MINUTE_IN_MILLIS);
                30 * DateUtils.MINUTE_IN_MILLIS);
    }
    }
@@ -148,4 +166,14 @@ public class AnomalyDetectionPolicy {
                return false; // Disabled when no this type
                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 Original line Diff line number Diff line
@@ -43,6 +43,14 @@ public interface KeyValueListParserWrapper {
     */
     */
    void setString(String str) throws IllegalArgumentException;
    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.
     * Get the value for key as a boolean.
     * @param key The key to lookup.
     * @param key The key to lookup.
+5 −0
Original line number Original line Diff line number Diff line
@@ -38,6 +38,11 @@ public class KeyValueListParserWrapperImpl implements KeyValueListParserWrapper
        mParser.setString(str);
        mParser.setString(str);
    }
    }


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

    @Override
    @Override
    public boolean getBoolean(String key, boolean defaultValue) {
    public boolean getBoolean(String key, boolean defaultValue) {
        return mParser.getBoolean(key, defaultValue);
        return mParser.getBoolean(key, defaultValue);
+10 −4
Original line number Original line 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.Anomaly;
import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy;
import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy;
import com.android.settings.fuelgauge.anomaly.AnomalyUtils;
import com.android.settings.fuelgauge.anomaly.AnomalyUtils;
import com.android.settings.fuelgauge.anomaly.action.AnomalyAction;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Set;


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


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


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

        }
        }


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


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


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


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


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


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


        assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled(
        assertThat(anomalyDetectionPolicy.isAnomalyDetectorEnabled(
@@ -103,18 +108,37 @@ public class AnomalyDetectionPolicyTest {
                Anomaly.AnomalyType.BLUETOOTH_SCAN)).isTrue();
                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() {
    private AnomalyDetectionPolicy createAnomalyPolicyWithConfig() {
        Settings.Global.putString(mContext.getContentResolver(),
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.ANOMALY_DETECTION_CONSTANTS, ANOMALY_DETECTION_CONSTANTS_VALUE);
                Settings.Global.ANOMALY_DETECTION_CONSTANTS, ANOMALY_DETECTION_CONSTANTS_VALUE);
        // Mock it to avoid noSuchMethodError
        // Mock it to avoid noSuchMethodError
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
                AnomalyDetectionPolicy.KEY_ANOMALY_DETECTION_ENABLED, true);
                AnomalyDetectionPolicy.KEY_ANOMALY_DETECTION_ENABLED, false);
        doReturn(false).when(mKeyValueListParserWrapper).getBoolean(
        doReturn(false).when(mKeyValueListParserWrapper).getBoolean(
                AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, true);
                AnomalyDetectionPolicy.KEY_WAKELOCK_DETECTION_ENABLED, false);
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
                AnomalyDetectionPolicy.KEY_WAKEUP_ALARM_DETECTION_ENABLED, false);
                AnomalyDetectionPolicy.KEY_WAKEUP_ALARM_DETECTION_ENABLED, false);
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
        doReturn(true).when(mKeyValueListParserWrapper).getBoolean(
                AnomalyDetectionPolicy.KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, true);
                AnomalyDetectionPolicy.KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, false);


        return new AnomalyDetectionPolicy(mContext, mKeyValueListParserWrapper);
        return new AnomalyDetectionPolicy(mContext, mKeyValueListParserWrapper);
    }
    }
Loading