Merge "Add log for anomaly." into oc-dr1-dev
am: 6666bf5605

Change-Id: I4903e3617b2fab64831b6e0ad8b5214ea5dd5317
diff --git a/src/com/android/settings/fuelgauge/anomaly/Anomaly.java b/src/com/android/settings/fuelgauge/anomaly/Anomaly.java
index dba964f..b070b26 100644
--- a/src/com/android/settings/fuelgauge/anomaly/Anomaly.java
+++ b/src/com/android/settings/fuelgauge/anomaly/Anomaly.java
@@ -68,6 +68,8 @@
     public final int uid;
     public final int targetSdkVersion;
     public final long wakelockTimeMs;
+    public final long bluetoothScanningTimeMs;
+    public final int wakeupAlarmCount;
     /**
      * {@code true} if background restriction is enabled
      *
@@ -88,6 +90,8 @@
         wakelockTimeMs = builder.mWakeLockTimeMs;
         targetSdkVersion = builder.mTargetSdkVersion;
         backgroundRestrictionEnabled = builder.mBgRestrictionEnabled;
+        bluetoothScanningTimeMs = builder.mBluetoothScanningTimeMs;
+        wakeupAlarmCount = builder.mWakeupAlarmCount;
     }
 
     private Anomaly(Parcel in) {
@@ -98,6 +102,8 @@
         wakelockTimeMs = in.readLong();
         targetSdkVersion = in.readInt();
         backgroundRestrictionEnabled = in.readBoolean();
+        wakeupAlarmCount = in.readInt();
+        bluetoothScanningTimeMs = in.readLong();
     }
 
     @Override
@@ -114,6 +120,8 @@
         dest.writeLong(wakelockTimeMs);
         dest.writeInt(targetSdkVersion);
         dest.writeBoolean(backgroundRestrictionEnabled);
+        dest.writeInt(wakeupAlarmCount);
+        dest.writeLong(bluetoothScanningTimeMs);
     }
 
     @Override
@@ -132,13 +140,36 @@
                 && TextUtils.equals(displayName, other.displayName)
                 && TextUtils.equals(packageName, other.packageName)
                 && targetSdkVersion == other.targetSdkVersion
-                && backgroundRestrictionEnabled == other.backgroundRestrictionEnabled;
+                && backgroundRestrictionEnabled == other.backgroundRestrictionEnabled
+                && wakeupAlarmCount == other.wakeupAlarmCount
+                && bluetoothScanningTimeMs == other.bluetoothScanningTimeMs;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(type, uid, displayName, packageName, wakelockTimeMs, targetSdkVersion,
-                backgroundRestrictionEnabled);
+                backgroundRestrictionEnabled, wakeupAlarmCount, bluetoothScanningTimeMs);
+    }
+
+    @Override
+    public String toString() {
+        return "type=" + toAnomalyTypeText(type) + " uid=" + uid + " package=" + packageName +
+                " displayName=" + displayName + " wakelockTimeMs=" + wakelockTimeMs +
+                " wakeupAlarmCount=" + wakeupAlarmCount + " bluetoothTimeMs="
+                + bluetoothScanningTimeMs;
+    }
+
+    private String toAnomalyTypeText(@AnomalyType int type) {
+        switch (type) {
+            case AnomalyType.WAKEUP_ALARM:
+                return "wakeupAlarm";
+            case AnomalyType.WAKE_LOCK:
+                return "wakelock";
+            case AnomalyType.BLUETOOTH_SCAN:
+                return "unoptimizedBluetoothScan";
+        }
+
+        return "";
     }
 
     public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@@ -160,6 +191,8 @@
         private String mPackageName;
         private long mWakeLockTimeMs;
         private boolean mBgRestrictionEnabled;
+        private int mWakeupAlarmCount;
+        private long mBluetoothScanningTimeMs;
 
         public Builder setType(@AnomalyType int type) {
             mType = type;
@@ -196,6 +229,16 @@
             return this;
         }
 
+        public Builder setWakeupAlarmCount(int wakeupAlarmCount) {
+            mWakeupAlarmCount = wakeupAlarmCount;
+            return this;
+        }
+
+        public Builder setBluetoothScanningTimeMs(long bluetoothScanningTimeMs) {
+            mBluetoothScanningTimeMs = bluetoothScanningTimeMs;
+            return this;
+        }
+
         public Anomaly build() {
             return new Anomaly(this);
         }
diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java
index 03d4d23..eb125ad 100644
--- a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java
+++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java
@@ -25,8 +25,11 @@
 import android.util.Log;
 
 import com.android.internal.os.BatteryStatsHelper;
+import com.android.internal.util.ArrayUtils;
 import com.android.settings.utils.AsyncLoader;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetector.java
index f66c61c..9fb4496 100644
--- a/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetector.java
+++ b/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetector.java
@@ -93,6 +93,7 @@
                         .setType(Anomaly.AnomalyType.BLUETOOTH_SCAN)
                         .setDisplayName(displayName)
                         .setPackageName(packageName)
+                        .setBluetoothScanningTimeMs(bluetoothTimeMs)
                         .build();
 
                 if (mAnomalyUtils.getAnomalyAction(anomaly).isActionActive(anomaly)) {
diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java
index 85f6862..c2bcd9a 100644
--- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java
+++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetector.java
@@ -97,6 +97,7 @@
                         .setType(Anomaly.AnomalyType.WAKE_LOCK)
                         .setDisplayName(displayName)
                         .setPackageName(packageName)
+                        .setWakeLockTimeMs(backgroundDurationMs)
                         .build();
 
                 if (mAnomalyUtils.getAnomalyAction(anomaly).isActionActive(anomaly)) {
diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java
index e0cc1c3..8823a17 100644
--- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java
+++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java
@@ -84,8 +84,9 @@
                     continue;
                 }
 
-                final int wakeups = getWakeupAlarmCountFromUid(uid);
-                if ((wakeups / totalRunningHours) > mWakeupAlarmThreshold) {
+                final int wakeupAlarmCount = (int) (getWakeupAlarmCountFromUid(uid)
+                        / totalRunningHours);
+                if (wakeupAlarmCount > mWakeupAlarmThreshold) {
                     final String packageName = mBatteryUtils.getPackageName(uid.getUid());
                     final CharSequence displayName = Utils.getApplicationLabel(mContext,
                             packageName);
@@ -100,6 +101,7 @@
                             .setBackgroundRestrictionEnabled(
                                     mBatteryUtils.isBackgroundRestrictionEnabled(targetSdkVersion,
                                             uid.getUid(), packageName))
+                            .setWakeupAlarmCount(wakeupAlarmCount)
                             .build();
 
                     if (mAnomalyUtils.getAnomalyAction(anomaly).isActionActive(anomaly)) {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyTest.java
index 759f0fd..13a5b31 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalyTest.java
@@ -23,6 +23,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.annotation.Config;
@@ -36,10 +37,14 @@
     private static long WAKE_LOCK_TIME_MS = 1500;
     private static String PACKAGE_NAME = "com.android.settings";
     private static String DISPLAY_NAME = "settings";
+    private static long BLUETOOTH_TIME_MS = 2555555;
+    private static int WAKEUP_ALARM_COUNT = 100;
 
-    @Test
-    public void testBuilder_buildCorrectly() {
-        Anomaly anomaly = new Anomaly.Builder()
+    private Anomaly mAnomaly;
+
+    @Before
+    public void setUp() {
+        mAnomaly = new Anomaly.Builder()
                 .setType(TYPE)
                 .setUid(UID)
                 .setWakeLockTimeMs(WAKE_LOCK_TIME_MS)
@@ -47,14 +52,28 @@
                 .setDisplayName(DISPLAY_NAME)
                 .setTargetSdkVersion(SDK_VERSION)
                 .setBackgroundRestrictionEnabled(true)
+                .setBluetoothScanningTimeMs(BLUETOOTH_TIME_MS)
+                .setWakeupAlarmCount(WAKEUP_ALARM_COUNT)
                 .build();
+    }
 
-        assertThat(anomaly.type).isEqualTo(TYPE);
-        assertThat(anomaly.uid).isEqualTo(UID);
-        assertThat(anomaly.wakelockTimeMs).isEqualTo(WAKE_LOCK_TIME_MS);
-        assertThat(anomaly.packageName).isEqualTo(PACKAGE_NAME);
-        assertThat(anomaly.displayName).isEqualTo(DISPLAY_NAME);
-        assertThat(anomaly.targetSdkVersion).isEqualTo(SDK_VERSION);
-        assertThat(anomaly.backgroundRestrictionEnabled).isTrue();
+    @Test
+    public void testBuilder_buildCorrectly() {
+        assertThat(mAnomaly.type).isEqualTo(TYPE);
+        assertThat(mAnomaly.uid).isEqualTo(UID);
+        assertThat(mAnomaly.wakelockTimeMs).isEqualTo(WAKE_LOCK_TIME_MS);
+        assertThat(mAnomaly.packageName).isEqualTo(PACKAGE_NAME);
+        assertThat(mAnomaly.displayName).isEqualTo(DISPLAY_NAME);
+        assertThat(mAnomaly.targetSdkVersion).isEqualTo(SDK_VERSION);
+        assertThat(mAnomaly.backgroundRestrictionEnabled).isTrue();
+        assertThat(mAnomaly.wakeupAlarmCount).isEqualTo(WAKEUP_ALARM_COUNT);
+        assertThat(mAnomaly.bluetoothScanningTimeMs).isEqualTo(BLUETOOTH_TIME_MS);
+    }
+
+    @Test
+    public void testToString() {
+        assertThat(mAnomaly.toString()).isEqualTo(
+                "type=wakelock uid=111 package=com.android.settings displayName=settings"
+                        + " wakelockTimeMs=1500 wakeupAlarmCount=100 bluetoothTimeMs=2555555");
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetectorTest.java
index d21687c..f8d02ff 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/BluetoothScanAnomalyDetectorTest.java
@@ -155,6 +155,7 @@
         return new Anomaly.Builder()
                 .setUid(uid)
                 .setType(Anomaly.AnomalyType.BLUETOOTH_SCAN)
+                .setBluetoothScanningTimeMs(ANOMALY_BLUETOOTH_SCANNING_TIME)
                 .build();
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java
index f53e8a0..d7682ea 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeLockAnomalyDetectorTest.java
@@ -99,6 +99,8 @@
     private WakeLockAnomalyDetector mWakelockAnomalyDetector;
     private Context mContext;
     private List<BatterySipper> mUsageList;
+    private Anomaly mAnomaly;
+    private Anomaly mTargetAnomaly;
 
     @Before
     public void setUp() throws Exception {
@@ -152,41 +154,40 @@
         mUsageList.add(mTargetSipper);
         mUsageList.add(mInactiveSipper);
         doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList();
+
+        mAnomaly = createWakeLockAnomaly(ANOMALY_UID);
+        mTargetAnomaly = createWakeLockAnomaly(TARGET_UID);
     }
 
     @Test
     public void testDetectAnomalies_containsAnomaly_detectIt() {
         doReturn(BatteryUtils.UID_NULL).when(mBatteryUtils).getPackageUid(nullable(String.class));
-        final Anomaly anomaly = new Anomaly.Builder()
-                .setUid(ANOMALY_UID)
-                .setType(Anomaly.AnomalyType.WAKE_LOCK)
-                .build();
-        final Anomaly targetAnomaly = new Anomaly.Builder()
-                .setUid(TARGET_UID)
-                .setType(Anomaly.AnomalyType.WAKE_LOCK)
-                .build();
 
         List<Anomaly> mAnomalies = mWakelockAnomalyDetector.detectAnomalies(mBatteryStatsHelper);
 
-        assertThat(mAnomalies).containsExactly(anomaly, targetAnomaly);
+        assertThat(mAnomalies).containsExactly(mAnomaly, mTargetAnomaly);
     }
 
     @Test
     public void testDetectAnomalies_containsTargetPackage_detectIt() {
         doReturn(TARGET_UID).when(mBatteryUtils).getPackageUid(TARGET_PACKAGE_NAME);
-        final Anomaly targetAnomaly = new Anomaly.Builder()
-                .setUid(TARGET_UID)
-                .setType(Anomaly.AnomalyType.WAKE_LOCK)
-                .build();
 
         List<Anomaly> mAnomalies = mWakelockAnomalyDetector.detectAnomalies(mBatteryStatsHelper,
                 TARGET_PACKAGE_NAME);
 
-        assertThat(mAnomalies).containsExactly(targetAnomaly);
+        assertThat(mAnomalies).containsExactly(mTargetAnomaly);
     }
 
     @Test
     public void testContainsThresholdFromPolicy() {
         assertThat(mWakelockAnomalyDetector.mWakeLockThresholdMs).isEqualTo(WAKELOCK_THRESHOLD_MS);
     }
+
+    private Anomaly createWakeLockAnomaly(int uid) {
+        return new Anomaly.Builder()
+                .setUid(uid)
+                .setType(Anomaly.AnomalyType.WAKE_LOCK)
+                .setWakeLockTimeMs(ANOMALY_WAKELOCK_TIME_MS)
+                .build();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java
index 27d8524..55be734 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java
@@ -69,6 +69,7 @@
             1 * DateUtils.HOUR_IN_MILLIS + 10 * DateUtils.MINUTE_IN_MILLIS;
     private static final int ANOMALY_WAKEUP_COUNT = 500;
     private static final int NORMAL_WAKEUP_COUNT = 61;
+    private static final int ANOMALY_WAKEUP_FREQUENCY = 428; // count per hour
     @Mock
     private BatteryStatsHelper mBatteryStatsHelper;
     @Mock
@@ -145,6 +146,7 @@
                 .setType(Anomaly.AnomalyType.WAKEUP_ALARM)
                 .setTargetSdkVersion(ANOMALY_SDK)
                 .setBackgroundRestrictionEnabled(ANOMALY_BACKGROUND_RESTRICTION_ON)
+                .setWakeupAlarmCount(ANOMALY_WAKEUP_FREQUENCY)
                 .build();
         mTargetAnomaly = new Anomaly.Builder()
                 .setUid(TARGET_UID)
@@ -152,6 +154,7 @@
                 .setType(Anomaly.AnomalyType.WAKEUP_ALARM)
                 .setTargetSdkVersion(TARGET_SDK)
                 .setBackgroundRestrictionEnabled(TARGET_BACKGROUND_RESTRICTION_ON)
+                .setWakeupAlarmCount(ANOMALY_WAKEUP_FREQUENCY)
                 .build();
 
         mWakeupAlarmAnomalyDetector = spy(