Home | History | Annotate | Download | only in anomaly
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.fuelgauge.anomaly;
     18 
     19 import android.content.Context;
     20 import android.net.Uri;
     21 import android.provider.Settings;
     22 import android.support.annotation.VisibleForTesting;
     23 import android.text.format.DateUtils;
     24 import android.util.KeyValueListParser;
     25 import android.util.Log;
     26 
     27 import java.util.Arrays;
     28 import java.util.Set;
     29 import java.util.stream.Collectors;
     30 
     31 /**
     32  * Class to store the policy for anomaly detection, which comes from
     33  * {@link android.provider.Settings.Global}
     34  */
     35 public class AnomalyDetectionPolicy {
     36     public static final String TAG = "AnomalyDetectionPolicy";
     37 
     38     @VisibleForTesting
     39     static final String KEY_ANOMALY_DETECTION_ENABLED = "anomaly_detection_enabled";
     40     @VisibleForTesting
     41     static final String KEY_WAKELOCK_DETECTION_ENABLED = "wakelock_enabled";
     42     @VisibleForTesting
     43     static final String KEY_WAKEUP_ALARM_DETECTION_ENABLED = "wakeup_alarm_enabled";
     44     @VisibleForTesting
     45     static final String KEY_BLUETOOTH_SCAN_DETECTION_ENABLED = "bluetooth_scan_enabled";
     46     @VisibleForTesting
     47     static final String KEY_WAKELOCK_THRESHOLD = "wakelock_threshold";
     48     @VisibleForTesting
     49     static final String KEY_WAKEUP_ALARM_THRESHOLD = "wakeup_alarm_threshold";
     50     @VisibleForTesting
     51     static final String KEY_WAKEUP_BLACKLISTED_TAGS = "wakeup_blacklisted_tags";
     52     @VisibleForTesting
     53     static final String KEY_BLUETOOTH_SCAN_THRESHOLD = "bluetooth_scan_threshold";
     54 
     55     /**
     56      * {@code true} if general anomaly detection is enabled
     57      *
     58      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
     59      * @see #KEY_ANOMALY_DETECTION_ENABLED
     60      */
     61     final boolean anomalyDetectionEnabled;
     62 
     63     /**
     64      * {@code true} if wakelock anomaly detection is enabled
     65      *
     66      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
     67      * @see #KEY_WAKELOCK_DETECTION_ENABLED
     68      */
     69     final boolean wakeLockDetectionEnabled;
     70 
     71     /**
     72      * {@code true} if wakeup alarm detection is enabled
     73      *
     74      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
     75      * @see #KEY_WAKEUP_ALARM_DETECTION_ENABLED
     76      */
     77     final boolean wakeupAlarmDetectionEnabled;
     78 
     79     /**
     80      * {@code true} if bluetooth scanning detection is enabled
     81      *
     82      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
     83      * @see #KEY_BLUETOOTH_SCAN_THRESHOLD
     84      */
     85     final boolean bluetoothScanDetectionEnabled;
     86 
     87     /**
     88      * Threshold for wakelock time in milli seconds
     89      *
     90      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
     91      * @see #KEY_WAKELOCK_THRESHOLD
     92      */
     93     public final long wakeLockThreshold;
     94 
     95     /**
     96      * Threshold for wakeup alarm count per hour
     97      *
     98      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
     99      * @see #KEY_WAKEUP_ALARM_THRESHOLD
    100      */
    101     public final long wakeupAlarmThreshold;
    102 
    103     /**
    104      * Array of blacklisted wakeups, by tag.
    105      *
    106      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
    107      * @see #KEY_WAKEUP_BLACKLISTED_TAGS
    108      */
    109     public final Set<String> wakeupBlacklistedTags;
    110 
    111     /**
    112      * Threshold for bluetooth unoptimized scanning time in milli seconds
    113      *
    114      * @see Settings.Global#ANOMALY_DETECTION_CONSTANTS
    115      * @see #KEY_BLUETOOTH_SCAN_THRESHOLD
    116      */
    117     public final long bluetoothScanThreshold;
    118 
    119     private final KeyValueListParser mParser;
    120 
    121     public AnomalyDetectionPolicy(Context context) {
    122         mParser = new KeyValueListParser(',');
    123         final String value = Settings.Global.getString(context.getContentResolver(),
    124                 Settings.Global.ANOMALY_DETECTION_CONSTANTS);
    125 
    126         try {
    127             mParser.setString(value);
    128         } catch (IllegalArgumentException e) {
    129             Log.e(TAG, "Bad anomaly detection constants");
    130         }
    131 
    132         anomalyDetectionEnabled =
    133                 mParser.getBoolean(KEY_ANOMALY_DETECTION_ENABLED, false);
    134         wakeLockDetectionEnabled =
    135                 mParser.getBoolean(KEY_WAKELOCK_DETECTION_ENABLED,false);
    136         wakeupAlarmDetectionEnabled =
    137                 mParser.getBoolean(KEY_WAKEUP_ALARM_DETECTION_ENABLED,false);
    138         bluetoothScanDetectionEnabled = mParser.getBoolean(
    139                 KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, false);
    140         wakeLockThreshold = mParser.getLong(KEY_WAKELOCK_THRESHOLD,
    141                 DateUtils.HOUR_IN_MILLIS);
    142         wakeupAlarmThreshold = mParser.getLong(KEY_WAKEUP_ALARM_THRESHOLD, 10);
    143         wakeupBlacklistedTags = parseStringSet(KEY_WAKEUP_BLACKLISTED_TAGS, null);
    144         bluetoothScanThreshold = mParser.getLong(KEY_BLUETOOTH_SCAN_THRESHOLD,
    145                 30 * DateUtils.MINUTE_IN_MILLIS);
    146     }
    147 
    148     public boolean isAnomalyDetectionEnabled() {
    149         return anomalyDetectionEnabled;
    150     }
    151 
    152     public boolean isAnomalyDetectorEnabled(@Anomaly.AnomalyType int type) {
    153         switch (type) {
    154             case Anomaly.AnomalyType.WAKE_LOCK:
    155                 return wakeLockDetectionEnabled;
    156             case Anomaly.AnomalyType.WAKEUP_ALARM:
    157                 return wakeupAlarmDetectionEnabled;
    158             case Anomaly.AnomalyType.BLUETOOTH_SCAN:
    159                 return bluetoothScanDetectionEnabled;
    160             default:
    161                 return false; // Disabled when no this type
    162         }
    163     }
    164 
    165     private Set<String> parseStringSet(final String key, final Set<String> defaultSet) {
    166         final String value = mParser.getString(key, null);
    167         if (value != null) {
    168             return Arrays.stream(value.split(":"))
    169                     .map(String::trim).map(Uri::decode).collect(Collectors.toSet());
    170         } else {
    171             return defaultSet;
    172         }
    173     }
    174 }
    175