OSDN Git Service

Merge "Change anomalyType to ArraySet in AppInfo" into pi-dev
authorLei Yu <jackqdyulei@google.com>
Fri, 9 Mar 2018 17:38:53 +0000 (17:38 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Fri, 9 Mar 2018 17:38:53 +0000 (17:38 +0000)
src/com/android/settings/fuelgauge/batterytip/AppInfo.java
src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java
tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java
tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java

index dc6ba25..9e8aba3 100644 (file)
@@ -20,9 +20,12 @@ import android.os.Parcel;
 import android.os.Parcelable;
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
+import android.util.ArraySet;
 
 import com.android.settings.fuelgauge.anomaly.Anomaly;
 
+import java.util.Objects;
+
 /**
  * Model class stores app info(e.g. package name, type..) that used in battery tip
  */
@@ -32,13 +35,13 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
      * Anomaly type of the app
      * @see Anomaly.AnomalyType
      */
-    public final int anomalyType;
+    public final ArraySet<Integer> anomalyTypes;
     public final long screenOnTimeMs;
     public final int uid;
 
     private AppInfo(AppInfo.Builder builder) {
         packageName = builder.mPackageName;
-        anomalyType = builder.mAnomalyType;
+        anomalyTypes = builder.mAnomalyTypes;
         screenOnTimeMs = builder.mScreenOnTimeMs;
         uid = builder.mUid;
     }
@@ -46,7 +49,7 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
     @VisibleForTesting
     AppInfo(Parcel in) {
         packageName = in.readString();
-        anomalyType = in.readInt();
+        anomalyTypes = (ArraySet<Integer>) in.readArraySet(null /* loader */);
         screenOnTimeMs = in.readLong();
         uid = in.readInt();
     }
@@ -64,14 +67,14 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(packageName);
-        dest.writeInt(anomalyType);
+        dest.writeArraySet(anomalyTypes);
         dest.writeLong(screenOnTimeMs);
         dest.writeInt(uid);
     }
 
     @Override
     public String toString() {
-        return "packageName=" + packageName + ",anomalyType=" + anomalyType + ",screenTime="
+        return "packageName=" + packageName + ",anomalyTypes=" + anomalyTypes + ",screenTime="
                 + screenOnTimeMs;
     }
 
@@ -85,7 +88,7 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
         }
 
         AppInfo other = (AppInfo) obj;
-        return anomalyType == other.anomalyType
+        return Objects.equals(anomalyTypes, other.anomalyTypes)
                 && uid == other.uid
                 && screenOnTimeMs == other.screenOnTimeMs
                 && TextUtils.equals(packageName, other.packageName);
@@ -102,13 +105,13 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
     };
 
     public static final class Builder {
-        private int mAnomalyType;
+        private ArraySet<Integer> mAnomalyTypes = new ArraySet<>();
         private String mPackageName;
         private long mScreenOnTimeMs;
         private int mUid;
 
-        public Builder setAnomalyType(int type) {
-            mAnomalyType = type;
+        public Builder addAnomalyType(int type) {
+            mAnomalyTypes.add(type);
             return this;
         }
 
index 798c8c6..58e9d03 100644 (file)
@@ -32,10 +32,12 @@ import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Database manager for battery data. Now it only contains anomaly data stored in {@link AppInfo}.
@@ -88,20 +90,30 @@ public class BatteryDatabaseManager {
         try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
             final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE, UID};
             final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC";
+            final Map<Integer, AppInfo.Builder> mAppInfoBuilders = new ArrayMap<>();
+            final String selection = TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ";
+            final String[] selectionArgs = new String[]{String.valueOf(timestampMsAfter),
+                    String.valueOf(state)};
 
-            try (Cursor cursor = db.query(TABLE_ANOMALY, projection,
-                    TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ",
-                    new String[]{String.valueOf(timestampMsAfter), String.valueOf(state)}, null,
-                    null, orderBy)) {
+            try (Cursor cursor = db.query(TABLE_ANOMALY, projection, selection, selectionArgs,
+                    null /* groupBy */, null /* having */, orderBy)) {
                 while (cursor.moveToNext()) {
-                    AppInfo appInfo = new AppInfo.Builder()
-                            .setPackageName(cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)))
-                            .setAnomalyType(cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)))
-                            .setUid(cursor.getInt(cursor.getColumnIndex(UID)))
-                            .build();
-                    appInfos.add(appInfo);
+                    final int uid = cursor.getInt(cursor.getColumnIndex(UID));
+                    if (!mAppInfoBuilders.containsKey(uid)) {
+                        final AppInfo.Builder builder = new AppInfo.Builder()
+                                .setUid(uid)
+                                .setPackageName(
+                                        cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)));
+                        mAppInfoBuilders.put(uid, builder);
+                    }
+                    mAppInfoBuilders.get(uid).addAnomalyType(
+                            cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)));
                 }
             }
+
+            for (Integer uid : mAppInfoBuilders.keySet()) {
+                appInfos.add(mAppInfoBuilders.get(uid).build());
+            }
         }
 
         return appInfos;
index 5c0147a..5ff5430 100644 (file)
@@ -16,8 +16,6 @@
 
 package com.android.settings.fuelgauge.batterytip;
 
-import android.app.Fragment;
-
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;
index 6360232..30999cb 100644 (file)
@@ -40,7 +40,6 @@ import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
 public class BatteryDatabaseManagerTest {
-
     private static String PACKAGE_NAME_NEW = "com.android.app1";
     private static int UID_NEW = 345;
     private static int TYPE_NEW = 1;
@@ -53,6 +52,9 @@ public class BatteryDatabaseManagerTest {
 
     private Context mContext;
     private BatteryDatabaseManager mBatteryDatabaseManager;
+    private AppInfo mNewAppInfo;
+    private AppInfo mOldAppInfo;
+    private AppInfo mCombinedAppInfo;
 
     @Before
     public void setUp() {
@@ -60,6 +62,23 @@ public class BatteryDatabaseManagerTest {
 
         mContext = RuntimeEnvironment.application;
         mBatteryDatabaseManager = spy(BatteryDatabaseManager.getInstance(mContext));
+
+        mNewAppInfo = new AppInfo.Builder()
+                .setUid(UID_NEW)
+                .setPackageName(PACKAGE_NAME_NEW)
+                .addAnomalyType(TYPE_NEW)
+                .build();
+        mOldAppInfo = new AppInfo.Builder()
+                .setUid(UID_OLD)
+                .setPackageName(PACKAGE_NAME_OLD)
+                .addAnomalyType(TYPE_OLD)
+                .build();
+        mCombinedAppInfo = new AppInfo.Builder()
+                .setUid(UID_NEW)
+                .setPackageName(PACKAGE_NAME_NEW)
+                .addAnomalyType(TYPE_NEW)
+                .addAnomalyType(TYPE_OLD)
+                .build();
     }
 
     @After
@@ -77,23 +96,19 @@ public class BatteryDatabaseManagerTest {
         // In database, it contains two record
         List<AppInfo> totalAppInfos = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
                 AnomalyDatabaseHelper.State.NEW);
-        assertThat(totalAppInfos).hasSize(2);
-        assertAppInfo(totalAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
-        assertAppInfo(totalAppInfos.get(1), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
+        assertThat(totalAppInfos).containsExactly(mNewAppInfo, mOldAppInfo);
 
         // Only one record shows up if we query by timestamp
         List<AppInfo> appInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
                 AnomalyDatabaseHelper.State.NEW);
-        assertThat(appInfos).hasSize(1);
-        assertAppInfo(appInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
+        assertThat(appInfos).containsExactly(mNewAppInfo);
 
         mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(ONE_DAY_BEFORE);
 
         // The obsolete record is removed from database
         List<AppInfo> appInfos1 = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
                 AnomalyDatabaseHelper.State.NEW);
-        assertThat(appInfos1).hasSize(1);
-        assertAppInfo(appInfos1.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
+        assertThat(appInfos1).containsExactly(mNewAppInfo);
     }
 
     @Test
@@ -113,19 +128,24 @@ public class BatteryDatabaseManagerTest {
         // The state of PACKAGE_NAME_NEW is still new
         List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
                 AnomalyDatabaseHelper.State.NEW);
-        assertThat(newAppInfos).hasSize(1);
-        assertAppInfo(newAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
+        assertThat(newAppInfos).containsExactly(mNewAppInfo);
 
         // The state of PACKAGE_NAME_OLD is changed to handled
         List<AppInfo> handledAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
                 AnomalyDatabaseHelper.State.HANDLED);
-        assertThat(handledAppInfos).hasSize(1);
-        assertAppInfo(handledAppInfos.get(0), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
+        assertThat(handledAppInfos).containsExactly(mOldAppInfo);
     }
 
-    private void assertAppInfo(final AppInfo appInfo, int uid, String packageName, int type) {
-        assertThat(appInfo.packageName).isEqualTo(packageName);
-        assertThat(appInfo.anomalyType).isEqualTo(type);
-        assertThat(appInfo.uid).isEqualTo(uid);
+    @Test
+    public void testQueryAnomalies_removeDuplicateByUid() {
+        mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
+                AnomalyDatabaseHelper.State.NEW, NOW);
+        mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_OLD,
+                AnomalyDatabaseHelper.State.NEW, NOW);
+
+        // Only contain one AppInfo with multiple types
+        List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
+                AnomalyDatabaseHelper.State.NEW);
+        assertThat(newAppInfos).containsExactly(mCombinedAppInfo);
     }
 }
index b140c4c..74e8fe6 100644 (file)
@@ -36,7 +36,8 @@ import java.util.List;
 public class AppInfoTest {
 
     private static final String PACKAGE_NAME = "com.android.app";
-    private static final int ANOMALY_TYPE = Anomaly.AnomalyType.WAKE_LOCK;
+    private static final int TYPE_WAKELOCK = Anomaly.AnomalyType.WAKE_LOCK;
+    private static final int TYPE_WAKEUP = Anomaly.AnomalyType.WAKEUP_ALARM;
     private static final long SCREEN_TIME_MS = DateUtils.HOUR_IN_MILLIS;
     private static final int UID = 3452;
 
@@ -46,7 +47,8 @@ public class AppInfoTest {
     public void setUp() {
         mAppInfo = new AppInfo.Builder()
                 .setPackageName(PACKAGE_NAME)
-                .setAnomalyType(ANOMALY_TYPE)
+                .addAnomalyType(TYPE_WAKELOCK)
+                .addAnomalyType(TYPE_WAKEUP)
                 .setScreenOnTimeMs(SCREEN_TIME_MS)
                 .setUid(UID)
                 .build();
@@ -61,7 +63,7 @@ public class AppInfoTest {
         final AppInfo appInfo = new AppInfo(parcel);
 
         assertThat(appInfo.packageName).isEqualTo(PACKAGE_NAME);
-        assertThat(appInfo.anomalyType).isEqualTo(ANOMALY_TYPE);
+        assertThat(appInfo.anomalyTypes).containsExactly(TYPE_WAKELOCK, TYPE_WAKEUP);
         assertThat(appInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
         assertThat(appInfo.uid).isEqualTo(UID);
     }
@@ -70,7 +72,7 @@ public class AppInfoTest {
     public void testCompareTo_hasCorrectOrder() {
         final AppInfo appInfo = new AppInfo.Builder()
                 .setPackageName(PACKAGE_NAME)
-                .setAnomalyType(ANOMALY_TYPE)
+                .addAnomalyType(TYPE_WAKELOCK)
                 .setScreenOnTimeMs(SCREEN_TIME_MS + 100)
                 .build();
 
@@ -85,7 +87,7 @@ public class AppInfoTest {
     @Test
     public void testBuilder() {
         assertThat(mAppInfo.packageName).isEqualTo(PACKAGE_NAME);
-        assertThat(mAppInfo.anomalyType).isEqualTo(ANOMALY_TYPE);
+        assertThat(mAppInfo.anomalyTypes).containsExactly(TYPE_WAKELOCK, TYPE_WAKEUP);
         assertThat(mAppInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
         assertThat(mAppInfo.uid).isEqualTo(UID);
     }
index af32dc5..85b1b02 100644 (file)
@@ -77,6 +77,7 @@ public class HighUsageTipTest {
     @Test
     public void toString_containsAppData() {
         assertThat(mBatteryTip.toString()).isEqualTo(
-                "type=2 state=0 { packageName=com.android.app,anomalyType=0,screenTime=1800000 }");
+                "type=2 state=0 { packageName=com.android.app,anomalyTypes={},screenTime=1800000 "
+                        + "}");
     }
 }
index 3298ea8..a2e91cb 100644 (file)
@@ -39,9 +39,10 @@ import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class RestrictAppTipTest {
-
     private static final String PACKAGE_NAME = "com.android.app";
     private static final String DISPLAY_NAME = "app";
+    private static final int ANOMALY_WAKEUP = 0;
+    private static final int ANOMALY_WAKELOCK = 1;
 
     private Context mContext;
     private RestrictAppTip mNewBatteryTip;
@@ -64,7 +65,11 @@ public class RestrictAppTipTest {
         doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager);
 
         mUsageAppList = new ArrayList<>();
-        mUsageAppList.add(new AppInfo.Builder().setPackageName(PACKAGE_NAME).build());
+        mUsageAppList.add(new AppInfo.Builder()
+                .setPackageName(PACKAGE_NAME)
+                .addAnomalyType(ANOMALY_WAKEUP)
+                .addAnomalyType(ANOMALY_WAKELOCK)
+                .build());
         mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
         mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
         mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, mUsageAppList);
@@ -125,6 +130,6 @@ public class RestrictAppTipTest {
     @Test
     public void toString_containsAppData() {
         assertThat(mNewBatteryTip.toString()).isEqualTo(
-                "type=1 state=0 { packageName=com.android.app,anomalyType=0,screenTime=0 }");
+                "type=1 state=0 { packageName=com.android.app,anomalyTypes={0, 1},screenTime=0 }");
     }
 }