• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.os.Build;
21 import android.support.annotation.VisibleForTesting;
22 import android.util.Pair;
23 import android.util.SparseIntArray;
24 
25 import com.android.internal.logging.nano.MetricsProto;
26 import com.android.internal.os.BatteryStatsHelper;
27 import com.android.settings.fuelgauge.anomaly.action.AnomalyAction;
28 import com.android.settings.fuelgauge.anomaly.action.ForceStopAction;
29 import com.android.settings.fuelgauge.anomaly.action.LocationCheckAction;
30 import com.android.settings.fuelgauge.anomaly.action.StopAndBackgroundCheckAction;
31 import com.android.settings.fuelgauge.anomaly.checker.AnomalyDetector;
32 import com.android.settings.fuelgauge.anomaly.checker.BluetoothScanAnomalyDetector;
33 import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector;
34 import com.android.settings.fuelgauge.anomaly.checker.WakeupAlarmAnomalyDetector;
35 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
36 
37 import java.util.ArrayList;
38 import java.util.List;
39 
40 /**
41  * Utility class for anomaly detection
42  */
43 public class AnomalyUtils {
44     private Context mContext;
45     private static AnomalyUtils sInstance;
46 
47     private static final SparseIntArray mMetricArray;
48     static {
49         mMetricArray = new SparseIntArray();
mMetricArray.append(Anomaly.AnomalyType.WAKE_LOCK, MetricsProto.MetricsEvent.ANOMALY_TYPE_WAKELOCK)50         mMetricArray.append(Anomaly.AnomalyType.WAKE_LOCK,
51                 MetricsProto.MetricsEvent.ANOMALY_TYPE_WAKELOCK);
mMetricArray.append(Anomaly.AnomalyType.WAKEUP_ALARM, MetricsProto.MetricsEvent.ANOMALY_TYPE_WAKEUP_ALARM)52         mMetricArray.append(Anomaly.AnomalyType.WAKEUP_ALARM,
53                 MetricsProto.MetricsEvent.ANOMALY_TYPE_WAKEUP_ALARM);
mMetricArray.append(Anomaly.AnomalyType.BLUETOOTH_SCAN, MetricsProto.MetricsEvent.ANOMALY_TYPE_UNOPTIMIZED_BT)54         mMetricArray.append(Anomaly.AnomalyType.BLUETOOTH_SCAN,
55                 MetricsProto.MetricsEvent.ANOMALY_TYPE_UNOPTIMIZED_BT);
56     }
57 
58     @VisibleForTesting
AnomalyUtils(Context context)59     AnomalyUtils(Context context) {
60         mContext = context.getApplicationContext();
61     }
62 
getInstance(Context context)63     public static AnomalyUtils getInstance(Context context) {
64         if (sInstance == null) {
65             sInstance = new AnomalyUtils(context);
66         }
67         return sInstance;
68     }
69 
70     /**
71      * Return the corresponding {@link AnomalyAction} according to
72      * {@link com.android.settings.fuelgauge.anomaly.Anomaly}
73      *
74      * @return corresponding {@link AnomalyAction}, or null if cannot find it.
75      */
getAnomalyAction(Anomaly anomaly)76     public AnomalyAction getAnomalyAction(Anomaly anomaly) {
77         switch (anomaly.type) {
78             case Anomaly.AnomalyType.WAKE_LOCK:
79                 return new ForceStopAction(mContext);
80             case Anomaly.AnomalyType.WAKEUP_ALARM:
81                 if (anomaly.targetSdkVersion >= Build.VERSION_CODES.O
82                         || (anomaly.targetSdkVersion < Build.VERSION_CODES.O
83                                 && anomaly.backgroundRestrictionEnabled)) {
84                     return new ForceStopAction(mContext);
85                 } else {
86                     return new StopAndBackgroundCheckAction(mContext);
87                 }
88             case Anomaly.AnomalyType.BLUETOOTH_SCAN:
89                 return new LocationCheckAction(mContext);
90             default:
91                 return null;
92         }
93     }
94 
95     /**
96      * Return the corresponding {@link AnomalyDetector} according to
97      * {@link com.android.settings.fuelgauge.anomaly.Anomaly.AnomalyType}
98      *
99      * @return corresponding {@link AnomalyDetector}, or null if cannot find it.
100      */
getAnomalyDetector(@nomaly.AnomalyType int anomalyType)101     public AnomalyDetector getAnomalyDetector(@Anomaly.AnomalyType int anomalyType) {
102         switch (anomalyType) {
103             case Anomaly.AnomalyType.WAKE_LOCK:
104                 return new WakeLockAnomalyDetector(mContext);
105             case Anomaly.AnomalyType.WAKEUP_ALARM:
106                 return new WakeupAlarmAnomalyDetector(mContext);
107             case Anomaly.AnomalyType.BLUETOOTH_SCAN:
108                 return new BluetoothScanAnomalyDetector(mContext);
109             default:
110                 return null;
111         }
112     }
113 
114     /**
115      * Detect whether application with {@code targetPackageName} has anomaly. When
116      * {@code targetPackageName} is null, start detection among all the applications.
117      *
118      * @param batteryStatsHelper contains battery stats, used to detect anomaly
119      * @param policy             contains configuration about anomaly check
120      * @param targetPackageName  represents the app need to be detected
121      * @return the list of anomalies
122      */
detectAnomalies(BatteryStatsHelper batteryStatsHelper, AnomalyDetectionPolicy policy, String targetPackageName)123     public List<Anomaly> detectAnomalies(BatteryStatsHelper batteryStatsHelper,
124             AnomalyDetectionPolicy policy, String targetPackageName) {
125         final List<Anomaly> anomalies = new ArrayList<>();
126         for (@Anomaly.AnomalyType int type : Anomaly.ANOMALY_TYPE_LIST) {
127             if (policy.isAnomalyDetectorEnabled(type)) {
128                 anomalies.addAll(getAnomalyDetector(type).detectAnomalies(
129                         batteryStatsHelper, targetPackageName));
130             }
131         }
132 
133         return anomalies;
134     }
135 
136     /**
137      * Log the list of {@link Anomaly} using {@link MetricsFeatureProvider}, which contains
138      * anomaly type, package name, field_context, field_action_type
139      *
140      * @param provider  provider to do the logging
141      * @param anomalies contains the data to log
142      * @param contextId which page invoke this logging
143      * @see #logAnomaly(MetricsFeatureProvider, Anomaly, int)
144      */
logAnomalies(MetricsFeatureProvider provider, List<Anomaly> anomalies, int contextId)145     public void logAnomalies(MetricsFeatureProvider provider, List<Anomaly> anomalies,
146             int contextId) {
147         for (int i = 0, size = anomalies.size(); i < size; i++) {
148             logAnomaly(provider, anomalies.get(i), contextId);
149         }
150     }
151 
152     /**
153      * Log the {@link Anomaly} using {@link MetricsFeatureProvider}, which contains
154      * anomaly type, package name, field_context, field_action_type
155      *
156      * @param provider  provider to do the logging
157      * @param anomaly   contains the data to log
158      * @param contextId which page invoke this logging
159      * @see #logAnomalies(MetricsFeatureProvider, List, int)
160      */
logAnomaly(MetricsFeatureProvider provider, Anomaly anomaly, int contextId)161     public void logAnomaly(MetricsFeatureProvider provider, Anomaly anomaly, int contextId) {
162         provider.action(
163                 mContext,
164                 mMetricArray.get(anomaly.type, MetricsProto.MetricsEvent.VIEW_UNKNOWN),
165                 anomaly.packageName,
166                 Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, contextId),
167                 Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_ACTION_TYPE,
168                         getAnomalyAction(anomaly).getActionType()));
169     }
170 
171 }
172