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.os.Parcel; 20 import android.os.Parcelable; 21 import android.support.annotation.IntDef; 22 import android.text.TextUtils; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 import java.util.Objects; 27 28 /** 29 * Data that represents an app has been detected as anomaly. It contains 30 * 31 * 1. Basic information of the app(i.e. uid, package name) 32 * 2. Type of anomaly 33 * 3. Data that has been detected as anomaly(i.e wakelock time) 34 */ 35 public class Anomaly implements Parcelable { 36 @Retention(RetentionPolicy.SOURCE) 37 @IntDef({AnomalyType.WAKE_LOCK, 38 AnomalyType.WAKEUP_ALARM, 39 AnomalyType.BLUETOOTH_SCAN}) 40 public @interface AnomalyType { 41 int WAKE_LOCK = 0; 42 int WAKEUP_ALARM = 1; 43 int BLUETOOTH_SCAN = 2; 44 } 45 46 @Retention(RetentionPolicy.SOURCE) 47 @IntDef({AnomalyActionType.FORCE_STOP, 48 AnomalyActionType.BACKGROUND_CHECK, 49 AnomalyActionType.LOCATION_CHECK, 50 AnomalyActionType.STOP_AND_BACKGROUND_CHECK}) 51 public @interface AnomalyActionType { 52 int FORCE_STOP = 0; 53 int BACKGROUND_CHECK = 1; 54 int LOCATION_CHECK = 2; 55 int STOP_AND_BACKGROUND_CHECK = 3; 56 } 57 58 @AnomalyType 59 public static final int[] ANOMALY_TYPE_LIST = { 60 AnomalyType.WAKE_LOCK, 61 AnomalyType.WAKEUP_ALARM, 62 AnomalyType.BLUETOOTH_SCAN}; 63 64 /** 65 * Type of this this anomaly 66 */ 67 public final int type; 68 public final int uid; 69 public final int targetSdkVersion; 70 public final long wakelockTimeMs; 71 public final long bluetoothScanningTimeMs; 72 public final int wakeupAlarmCount; 73 /** 74 * {@code true} if background restriction is enabled 75 * 76 * @see android.app.AppOpsManager.OP_RUN_IN_BACKGROUND 77 */ 78 public final boolean backgroundRestrictionEnabled; 79 /** 80 * Display name of this anomaly, usually it is the app name 81 */ 82 public final CharSequence displayName; 83 public final String packageName; 84 85 private Anomaly(Builder builder) { 86 type = builder.mType; 87 uid = builder.mUid; 88 displayName = builder.mDisplayName; 89 packageName = builder.mPackageName; 90 wakelockTimeMs = builder.mWakeLockTimeMs; 91 targetSdkVersion = builder.mTargetSdkVersion; 92 backgroundRestrictionEnabled = builder.mBgRestrictionEnabled; 93 bluetoothScanningTimeMs = builder.mBluetoothScanningTimeMs; 94 wakeupAlarmCount = builder.mWakeupAlarmCount; 95 } 96 97 private Anomaly(Parcel in) { 98 type = in.readInt(); 99 uid = in.readInt(); 100 displayName = in.readCharSequence(); 101 packageName = in.readString(); 102 wakelockTimeMs = in.readLong(); 103 targetSdkVersion = in.readInt(); 104 backgroundRestrictionEnabled = in.readBoolean(); 105 wakeupAlarmCount = in.readInt(); 106 bluetoothScanningTimeMs = in.readLong(); 107 } 108 109 @Override 110 public int describeContents() { 111 return 0; 112 } 113 114 @Override 115 public void writeToParcel(Parcel dest, int flags) { 116 dest.writeInt(type); 117 dest.writeInt(uid); 118 dest.writeCharSequence(displayName); 119 dest.writeString(packageName); 120 dest.writeLong(wakelockTimeMs); 121 dest.writeInt(targetSdkVersion); 122 dest.writeBoolean(backgroundRestrictionEnabled); 123 dest.writeInt(wakeupAlarmCount); 124 dest.writeLong(bluetoothScanningTimeMs); 125 } 126 127 @Override 128 public boolean equals(Object obj) { 129 if (this == obj) { 130 return true; 131 } 132 if (!(obj instanceof Anomaly)) { 133 return false; 134 } 135 136 Anomaly other = (Anomaly) obj; 137 return type == other.type 138 && uid == other.uid 139 && wakelockTimeMs == other.wakelockTimeMs 140 && TextUtils.equals(displayName, other.displayName) 141 && TextUtils.equals(packageName, other.packageName) 142 && targetSdkVersion == other.targetSdkVersion 143 && backgroundRestrictionEnabled == other.backgroundRestrictionEnabled 144 && wakeupAlarmCount == other.wakeupAlarmCount 145 && bluetoothScanningTimeMs == other.bluetoothScanningTimeMs; 146 } 147 148 @Override 149 public int hashCode() { 150 return Objects.hash(type, uid, displayName, packageName, wakelockTimeMs, targetSdkVersion, 151 backgroundRestrictionEnabled, wakeupAlarmCount, bluetoothScanningTimeMs); 152 } 153 154 @Override 155 public String toString() { 156 return "type=" + toAnomalyTypeText(type) + " uid=" + uid + " package=" + packageName + 157 " displayName=" + displayName + " wakelockTimeMs=" + wakelockTimeMs + 158 " wakeupAlarmCount=" + wakeupAlarmCount + " bluetoothTimeMs=" 159 + bluetoothScanningTimeMs; 160 } 161 162 private String toAnomalyTypeText(@AnomalyType int type) { 163 switch (type) { 164 case AnomalyType.WAKEUP_ALARM: 165 return "wakeupAlarm"; 166 case AnomalyType.WAKE_LOCK: 167 return "wakelock"; 168 case AnomalyType.BLUETOOTH_SCAN: 169 return "unoptimizedBluetoothScan"; 170 } 171 172 return ""; 173 } 174 175 public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 176 public Anomaly createFromParcel(Parcel in) { 177 return new Anomaly(in); 178 } 179 180 public Anomaly[] newArray(int size) { 181 return new Anomaly[size]; 182 } 183 }; 184 185 public static final class Builder { 186 @AnomalyType 187 private int mType; 188 private int mUid; 189 private int mTargetSdkVersion; 190 private CharSequence mDisplayName; 191 private String mPackageName; 192 private long mWakeLockTimeMs; 193 private boolean mBgRestrictionEnabled; 194 private int mWakeupAlarmCount; 195 private long mBluetoothScanningTimeMs; 196 197 public Builder setType(@AnomalyType int type) { 198 mType = type; 199 return this; 200 } 201 202 public Builder setUid(int uid) { 203 mUid = uid; 204 return this; 205 } 206 207 public Builder setDisplayName(CharSequence displayName) { 208 mDisplayName = displayName; 209 return this; 210 } 211 212 public Builder setPackageName(String packageName) { 213 mPackageName = packageName; 214 return this; 215 } 216 217 public Builder setWakeLockTimeMs(long wakeLockTimeMs) { 218 mWakeLockTimeMs = wakeLockTimeMs; 219 return this; 220 } 221 222 public Builder setTargetSdkVersion(int targetSdkVersion) { 223 mTargetSdkVersion = targetSdkVersion; 224 return this; 225 } 226 227 public Builder setBackgroundRestrictionEnabled(boolean bgRestrictionEnabled) { 228 mBgRestrictionEnabled = bgRestrictionEnabled; 229 return this; 230 } 231 232 public Builder setWakeupAlarmCount(int wakeupAlarmCount) { 233 mWakeupAlarmCount = wakeupAlarmCount; 234 return this; 235 } 236 237 public Builder setBluetoothScanningTimeMs(long bluetoothScanningTimeMs) { 238 mBluetoothScanningTimeMs = bluetoothScanningTimeMs; 239 return this; 240 } 241 242 public Anomaly build() { 243 return new Anomaly(this); 244 } 245 } 246 } 247