Merge "Change anomalyType to ArraySet in AppInfo" into pi-dev

This commit is contained in:
Lei Yu
2018-03-09 17:38:53 +00:00
committed by Android (Google) Code Review
7 changed files with 87 additions and 46 deletions

View File

@@ -20,9 +20,12 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArraySet;
import com.android.settings.fuelgauge.anomaly.Anomaly; 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 * 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 * Anomaly type of the app
* @see Anomaly.AnomalyType * @see Anomaly.AnomalyType
*/ */
public final int anomalyType; public final ArraySet<Integer> anomalyTypes;
public final long screenOnTimeMs; public final long screenOnTimeMs;
public final int uid; public final int uid;
private AppInfo(AppInfo.Builder builder) { private AppInfo(AppInfo.Builder builder) {
packageName = builder.mPackageName; packageName = builder.mPackageName;
anomalyType = builder.mAnomalyType; anomalyTypes = builder.mAnomalyTypes;
screenOnTimeMs = builder.mScreenOnTimeMs; screenOnTimeMs = builder.mScreenOnTimeMs;
uid = builder.mUid; uid = builder.mUid;
} }
@@ -46,7 +49,7 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
@VisibleForTesting @VisibleForTesting
AppInfo(Parcel in) { AppInfo(Parcel in) {
packageName = in.readString(); packageName = in.readString();
anomalyType = in.readInt(); anomalyTypes = (ArraySet<Integer>) in.readArraySet(null /* loader */);
screenOnTimeMs = in.readLong(); screenOnTimeMs = in.readLong();
uid = in.readInt(); uid = in.readInt();
} }
@@ -64,14 +67,14 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(packageName); dest.writeString(packageName);
dest.writeInt(anomalyType); dest.writeArraySet(anomalyTypes);
dest.writeLong(screenOnTimeMs); dest.writeLong(screenOnTimeMs);
dest.writeInt(uid); dest.writeInt(uid);
} }
@Override @Override
public String toString() { public String toString() {
return "packageName=" + packageName + ",anomalyType=" + anomalyType + ",screenTime=" return "packageName=" + packageName + ",anomalyTypes=" + anomalyTypes + ",screenTime="
+ screenOnTimeMs; + screenOnTimeMs;
} }
@@ -85,7 +88,7 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
} }
AppInfo other = (AppInfo) obj; AppInfo other = (AppInfo) obj;
return anomalyType == other.anomalyType return Objects.equals(anomalyTypes, other.anomalyTypes)
&& uid == other.uid && uid == other.uid
&& screenOnTimeMs == other.screenOnTimeMs && screenOnTimeMs == other.screenOnTimeMs
&& TextUtils.equals(packageName, other.packageName); && TextUtils.equals(packageName, other.packageName);
@@ -102,13 +105,13 @@ public class AppInfo implements Comparable<AppInfo>, Parcelable {
}; };
public static final class Builder { public static final class Builder {
private int mAnomalyType; private ArraySet<Integer> mAnomalyTypes = new ArraySet<>();
private String mPackageName; private String mPackageName;
private long mScreenOnTimeMs; private long mScreenOnTimeMs;
private int mUid; private int mUid;
public Builder setAnomalyType(int type) { public Builder addAnomalyType(int type) {
mAnomalyType = type; mAnomalyTypes.add(type);
return this; return this;
} }

View File

@@ -32,10 +32,12 @@ import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Database manager for battery data. Now it only contains anomaly data stored in {@link AppInfo}. * Database manager for battery data. Now it only contains anomaly data stored in {@link AppInfo}.
@@ -88,19 +90,29 @@ public class BatteryDatabaseManager {
try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) { try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE, UID}; final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE, UID};
final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC"; 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, try (Cursor cursor = db.query(TABLE_ANOMALY, projection, selection, selectionArgs,
TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ", null /* groupBy */, null /* having */, orderBy)) {
new String[]{String.valueOf(timestampMsAfter), String.valueOf(state)}, null,
null, orderBy)) {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
AppInfo appInfo = new AppInfo.Builder() final int uid = cursor.getInt(cursor.getColumnIndex(UID));
.setPackageName(cursor.getString(cursor.getColumnIndex(PACKAGE_NAME))) if (!mAppInfoBuilders.containsKey(uid)) {
.setAnomalyType(cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE))) final AppInfo.Builder builder = new AppInfo.Builder()
.setUid(cursor.getInt(cursor.getColumnIndex(UID))) .setUid(uid)
.build(); .setPackageName(
appInfos.add(appInfo); 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());
} }
} }

View File

@@ -16,8 +16,6 @@
package com.android.settings.fuelgauge.batterytip; package com.android.settings.fuelgauge.batterytip;
import android.app.Fragment;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction; import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;

View File

@@ -40,7 +40,6 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class BatteryDatabaseManagerTest { public class BatteryDatabaseManagerTest {
private static String PACKAGE_NAME_NEW = "com.android.app1"; private static String PACKAGE_NAME_NEW = "com.android.app1";
private static int UID_NEW = 345; private static int UID_NEW = 345;
private static int TYPE_NEW = 1; private static int TYPE_NEW = 1;
@@ -53,6 +52,9 @@ public class BatteryDatabaseManagerTest {
private Context mContext; private Context mContext;
private BatteryDatabaseManager mBatteryDatabaseManager; private BatteryDatabaseManager mBatteryDatabaseManager;
private AppInfo mNewAppInfo;
private AppInfo mOldAppInfo;
private AppInfo mCombinedAppInfo;
@Before @Before
public void setUp() { public void setUp() {
@@ -60,6 +62,23 @@ public class BatteryDatabaseManagerTest {
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
mBatteryDatabaseManager = spy(BatteryDatabaseManager.getInstance(mContext)); 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 @After
@@ -77,23 +96,19 @@ public class BatteryDatabaseManagerTest {
// In database, it contains two record // In database, it contains two record
List<AppInfo> totalAppInfos = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */, List<AppInfo> totalAppInfos = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
AnomalyDatabaseHelper.State.NEW); AnomalyDatabaseHelper.State.NEW);
assertThat(totalAppInfos).hasSize(2); assertThat(totalAppInfos).containsExactly(mNewAppInfo, mOldAppInfo);
assertAppInfo(totalAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
assertAppInfo(totalAppInfos.get(1), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
// Only one record shows up if we query by timestamp // Only one record shows up if we query by timestamp
List<AppInfo> appInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE, List<AppInfo> appInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.NEW); AnomalyDatabaseHelper.State.NEW);
assertThat(appInfos).hasSize(1); assertThat(appInfos).containsExactly(mNewAppInfo);
assertAppInfo(appInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(ONE_DAY_BEFORE); mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(ONE_DAY_BEFORE);
// The obsolete record is removed from database // The obsolete record is removed from database
List<AppInfo> appInfos1 = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */, List<AppInfo> appInfos1 = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
AnomalyDatabaseHelper.State.NEW); AnomalyDatabaseHelper.State.NEW);
assertThat(appInfos1).hasSize(1); assertThat(appInfos1).containsExactly(mNewAppInfo);
assertAppInfo(appInfos1.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
} }
@Test @Test
@@ -113,19 +128,24 @@ public class BatteryDatabaseManagerTest {
// The state of PACKAGE_NAME_NEW is still new // The state of PACKAGE_NAME_NEW is still new
List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE, List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.NEW); AnomalyDatabaseHelper.State.NEW);
assertThat(newAppInfos).hasSize(1); assertThat(newAppInfos).containsExactly(mNewAppInfo);
assertAppInfo(newAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
// The state of PACKAGE_NAME_OLD is changed to handled // The state of PACKAGE_NAME_OLD is changed to handled
List<AppInfo> handledAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE, List<AppInfo> handledAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.HANDLED); AnomalyDatabaseHelper.State.HANDLED);
assertThat(handledAppInfos).hasSize(1); assertThat(handledAppInfos).containsExactly(mOldAppInfo);
assertAppInfo(handledAppInfos.get(0), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
} }
private void assertAppInfo(final AppInfo appInfo, int uid, String packageName, int type) { @Test
assertThat(appInfo.packageName).isEqualTo(packageName); public void testQueryAnomalies_removeDuplicateByUid() {
assertThat(appInfo.anomalyType).isEqualTo(type); mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
assertThat(appInfo.uid).isEqualTo(uid); 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);
} }
} }

View File

@@ -36,7 +36,8 @@ import java.util.List;
public class AppInfoTest { public class AppInfoTest {
private static final String PACKAGE_NAME = "com.android.app"; 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 long SCREEN_TIME_MS = DateUtils.HOUR_IN_MILLIS;
private static final int UID = 3452; private static final int UID = 3452;
@@ -46,7 +47,8 @@ public class AppInfoTest {
public void setUp() { public void setUp() {
mAppInfo = new AppInfo.Builder() mAppInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME) .setPackageName(PACKAGE_NAME)
.setAnomalyType(ANOMALY_TYPE) .addAnomalyType(TYPE_WAKELOCK)
.addAnomalyType(TYPE_WAKEUP)
.setScreenOnTimeMs(SCREEN_TIME_MS) .setScreenOnTimeMs(SCREEN_TIME_MS)
.setUid(UID) .setUid(UID)
.build(); .build();
@@ -61,7 +63,7 @@ public class AppInfoTest {
final AppInfo appInfo = new AppInfo(parcel); final AppInfo appInfo = new AppInfo(parcel);
assertThat(appInfo.packageName).isEqualTo(PACKAGE_NAME); 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.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
assertThat(appInfo.uid).isEqualTo(UID); assertThat(appInfo.uid).isEqualTo(UID);
} }
@@ -70,7 +72,7 @@ public class AppInfoTest {
public void testCompareTo_hasCorrectOrder() { public void testCompareTo_hasCorrectOrder() {
final AppInfo appInfo = new AppInfo.Builder() final AppInfo appInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME) .setPackageName(PACKAGE_NAME)
.setAnomalyType(ANOMALY_TYPE) .addAnomalyType(TYPE_WAKELOCK)
.setScreenOnTimeMs(SCREEN_TIME_MS + 100) .setScreenOnTimeMs(SCREEN_TIME_MS + 100)
.build(); .build();
@@ -85,7 +87,7 @@ public class AppInfoTest {
@Test @Test
public void testBuilder() { public void testBuilder() {
assertThat(mAppInfo.packageName).isEqualTo(PACKAGE_NAME); 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.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
assertThat(mAppInfo.uid).isEqualTo(UID); assertThat(mAppInfo.uid).isEqualTo(UID);
} }

View File

@@ -77,6 +77,7 @@ public class HighUsageTipTest {
@Test @Test
public void toString_containsAppData() { public void toString_containsAppData() {
assertThat(mBatteryTip.toString()).isEqualTo( 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 "
+ "}");
} }
} }

View File

@@ -39,9 +39,10 @@ import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
public class RestrictAppTipTest { public class RestrictAppTipTest {
private static final String PACKAGE_NAME = "com.android.app"; private static final String PACKAGE_NAME = "com.android.app";
private static final String DISPLAY_NAME = "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 Context mContext;
private RestrictAppTip mNewBatteryTip; private RestrictAppTip mNewBatteryTip;
@@ -64,7 +65,11 @@ public class RestrictAppTipTest {
doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager); doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager);
mUsageAppList = new ArrayList<>(); 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); mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList); mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, mUsageAppList); mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, mUsageAppList);
@@ -125,6 +130,6 @@ public class RestrictAppTipTest {
@Test @Test
public void toString_containsAppData() { public void toString_containsAppData() {
assertThat(mNewBatteryTip.toString()).isEqualTo( 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 }");
} }
} }