From 963b7cca257bca828e98ce35be106e656c8e1538 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 16 Jan 2018 10:12:40 -0800 Subject: [PATCH] Add database to store anomaly data 1. Refactor HighUsageApp to AppInfo so it could be reused both in dialog and app restriction 2. Add BatteryDatabaseHelper to store the anomaly log Bug: 70570352 Test: RunSettingsRoboTests Change-Id: I900cd9746ff7f1e19bd6f3948463588b7cf72b85 --- .../batterytip/AnomalyDatabaseHelper.java | 114 ++++++++++++++++++ .../fuelgauge/batterytip/AppInfo.java | 101 ++++++++++++++++ .../batterytip/BatteryDatabaseManager.java | 93 ++++++++++++++ .../batterytip/HighUsageAdapter.java | 6 +- .../fuelgauge/batterytip/HighUsageApp.java | 64 ---------- .../detectors/HighUsageDetector.java | 13 +- .../batterytip/tips/HighUsageTip.java | 10 +- .../fuelgauge/BatteryDatabaseManagerTest.java | 98 +++++++++++++++ .../fuelgauge/batterytip/AppInfoTest.java | 90 ++++++++++++++ .../batterytip/tips/HighUsageTipTest.java | 11 +- .../settings/testutils/DatabaseTestUtils.java | 17 +++ 11 files changed, 534 insertions(+), 83 deletions(-) create mode 100644 src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java create mode 100644 src/com/android/settings/fuelgauge/batterytip/AppInfo.java create mode 100644 src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java delete mode 100644 src/com/android/settings/fuelgauge/batterytip/HighUsageApp.java create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java new file mode 100644 index 00000000000..a13df25eb55 --- /dev/null +++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.fuelgauge.batterytip; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import com.android.settings.fuelgauge.anomaly.Anomaly; + +/** + * Database controls the anomaly logging(e.g. packageName, anomalyType and time) + */ +public class AnomalyDatabaseHelper extends SQLiteOpenHelper { + private static final String TAG = "BatteryDatabaseHelper"; + + private static final String DATABASE_NAME = "battery_settings.db"; + private static final int DATABASE_VERSION = 1; + + public interface Tables { + String TABLE_ANOMALY = "anomaly"; + } + + public interface AnomalyColumns { + /** + * The package name of the anomaly app + */ + String PACKAGE_NAME = "package_name"; + /** + * The type of the anomaly app + * @see Anomaly.AnomalyType + */ + String ANOMALY_TYPE = "anomaly_type"; + /** + * The time when anomaly happens + */ + String TIME_STAMP_MS = "time_stamp_ms"; + } + + private static final String CREATE_ANOMALY_TABLE = + "CREATE TABLE " + Tables.TABLE_ANOMALY + + "(" + + AnomalyColumns.PACKAGE_NAME + + " TEXT, " + + AnomalyColumns.ANOMALY_TYPE + + " INTEGER, " + + AnomalyColumns.TIME_STAMP_MS + + " INTEGER)"; + + private static AnomalyDatabaseHelper sSingleton; + + public static synchronized AnomalyDatabaseHelper getInstance(Context context) { + if (sSingleton == null) { + sSingleton = new AnomalyDatabaseHelper(context.getApplicationContext()); + } + return sSingleton; + } + + private AnomalyDatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + bootstrapDB(db); + } + + private void bootstrapDB(SQLiteDatabase db) { + db.execSQL(CREATE_ANOMALY_TABLE); + Log.i(TAG, "Bootstrapped database"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion < DATABASE_VERSION) { + Log.w(TAG, "Detected schema version '" + oldVersion + "'. " + + "Index needs to be rebuilt for schema version '" + newVersion + "'."); + // We need to drop the tables and recreate them + reconstruct(db); + } + } + + @Override + public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.w(TAG, "Detected schema version '" + oldVersion + "'. " + + "Index needs to be rebuilt for schema version '" + newVersion + "'."); + // We need to drop the tables and recreate them + reconstruct(db); + } + + public void reconstruct(SQLiteDatabase db) { + dropTables(db); + bootstrapDB(db); + } + + private void dropTables(SQLiteDatabase db) { + db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ANOMALY); + } +} diff --git a/src/com/android/settings/fuelgauge/batterytip/AppInfo.java b/src/com/android/settings/fuelgauge/batterytip/AppInfo.java new file mode 100644 index 00000000000..1daff36ab17 --- /dev/null +++ b/src/com/android/settings/fuelgauge/batterytip/AppInfo.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.fuelgauge.batterytip; + +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.VisibleForTesting; + +import com.android.settings.fuelgauge.anomaly.Anomaly; + +/** + * Model class stores app info(e.g. package name, type..) that used in battery tip + */ +public class AppInfo implements Comparable, Parcelable { + public final String packageName; + /** + * Anomaly type of the app + * @see Anomaly.AnomalyType + */ + public final int anomalyType; + public final long screenOnTimeMs; + + private AppInfo(AppInfo.Builder builder) { + packageName = builder.mPackageName; + anomalyType = builder.mAnomalyType; + screenOnTimeMs = builder.mScreenOnTimeMs; + } + + @VisibleForTesting + AppInfo(Parcel in) { + packageName = in.readString(); + anomalyType = in.readInt(); + screenOnTimeMs = in.readLong(); + } + + @Override + public int compareTo(AppInfo o) { + return Long.compare(screenOnTimeMs, o.screenOnTimeMs); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(packageName); + dest.writeInt(anomalyType); + dest.writeLong(screenOnTimeMs); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public AppInfo createFromParcel(Parcel in) { + return new AppInfo(in); + } + + public AppInfo[] newArray(int size) { + return new AppInfo[size]; + } + }; + + public static final class Builder { + private int mAnomalyType; + private String mPackageName; + private long mScreenOnTimeMs; + + public Builder setAnomalyType(int type) { + mAnomalyType = type; + return this; + } + + public Builder setPackageName(String packageName) { + mPackageName = packageName; + return this; + } + + public Builder setScreenOnTimeMs(long screenOnTimeMs) { + mScreenOnTimeMs = screenOnTimeMs; + return this; + } + + public AppInfo build() { + return new AppInfo(this); + } + } +} \ No newline at end of file diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java new file mode 100644 index 00000000000..f87501ffba8 --- /dev/null +++ b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.fuelgauge.batterytip; + +import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns + .PACKAGE_NAME; +import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns + .ANOMALY_TYPE; +import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns + .TIME_STAMP_MS; +import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.Tables.TABLE_ANOMALY; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Database manager for battery data. Now it only contains anomaly data stored in {@link AppInfo}. + */ +public class BatteryDatabaseManager { + private final AnomalyDatabaseHelper mDatabaseHelper; + + public BatteryDatabaseManager(Context context) { + mDatabaseHelper = AnomalyDatabaseHelper.getInstance(context); + } + + /** + * Insert an anomaly log to database. + * + * @param packageName the package name of the app + * @param type the type of the anomaly + * @param timestampMs the time when it is happened + */ + public void insertAnomaly(String packageName, int type, long timestampMs) { + try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) { + ContentValues values = new ContentValues(); + values.put(PACKAGE_NAME, packageName); + values.put(ANOMALY_TYPE, type); + values.put(TIME_STAMP_MS, timestampMs); + + db.insert(TABLE_ANOMALY, null, values); + } + } + + /** + * Query all the anomalies that happened after {@code timestampMs}. + */ + public List queryAllAnomaliesAfter(long timestampMs) { + final List appInfos = new ArrayList<>(); + try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) { + final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE}; + final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC"; + + try (Cursor cursor = db.query(TABLE_ANOMALY, projection, TIME_STAMP_MS + " > ?", + new String[]{String.valueOf(timestampMs)}, null, null, orderBy)) { + while (cursor.moveToNext()) { + AppInfo appInfo = new AppInfo.Builder() + .setPackageName(cursor.getString(cursor.getColumnIndex(PACKAGE_NAME))) + .setAnomalyType(cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE))) + .build(); + appInfos.add(appInfo); + } + } + } + + return appInfos; + } + + public void deleteAllAnomaliesBeforeTimeStamp(long timestampMs) { + try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) { + db.delete(TABLE_ANOMALY, TIME_STAMP_MS + " < ?", + new String[]{String.valueOf(timestampMs)}); + } + } +} diff --git a/src/com/android/settings/fuelgauge/batterytip/HighUsageAdapter.java b/src/com/android/settings/fuelgauge/batterytip/HighUsageAdapter.java index 8b743946648..60aa6c8832a 100644 --- a/src/com/android/settings/fuelgauge/batterytip/HighUsageAdapter.java +++ b/src/com/android/settings/fuelgauge/batterytip/HighUsageAdapter.java @@ -39,7 +39,7 @@ public class HighUsageAdapter extends RecyclerView.Adapter mHighUsageAppList; + private final List mHighUsageAppList; public static class ViewHolder extends RecyclerView.ViewHolder { public View view; @@ -56,7 +56,7 @@ public class HighUsageAdapter extends RecyclerView.Adapter highUsageAppList) { + public HighUsageAdapter(Context context, List highUsageAppList) { mContext = context; mHighUsageAppList = highUsageAppList; mIconDrawableFactory = IconDrawableFactory.newInstance(context); @@ -72,7 +72,7 @@ public class HighUsageAdapter extends RecyclerView.Adapter, Parcelable { - public final String packageName; - public final long screenOnTimeMs; - - public HighUsageApp(String packageName, long screenOnTimeMs) { - this.packageName = packageName; - this.screenOnTimeMs = screenOnTimeMs; - } - - private HighUsageApp(Parcel in) { - packageName = in.readString(); - screenOnTimeMs = in.readLong(); - } - - @Override - public int compareTo(HighUsageApp o) { - return Long.compare(screenOnTimeMs, o.screenOnTimeMs); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(packageName); - dest.writeLong(screenOnTimeMs); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public HighUsageApp createFromParcel(Parcel in) { - return new HighUsageApp(in); - } - - public HighUsageApp[] newArray(int size) { - return new HighUsageApp[size]; - } - }; -} \ No newline at end of file diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java index 237f430c575..3c696671e95 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java @@ -23,13 +23,11 @@ import android.text.format.DateUtils; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; -import com.android.settings.Utils; import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy; -import com.android.settings.fuelgauge.batterytip.HighUsageApp; +import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; -import com.android.settings.fuelgauge.batterytip.tips.SummaryTip; import java.util.ArrayList; import java.util.Collections; @@ -42,7 +40,7 @@ import java.util.List; public class HighUsageDetector implements BatteryTipDetector { private BatteryTipPolicy mPolicy; private BatteryStatsHelper mBatteryStatsHelper; - private List mHighUsageAppList; + private List mHighUsageAppList; private Context mContext; @VisibleForTesting BatteryUtils mBatteryUtils; @@ -68,9 +66,10 @@ public class HighUsageDetector implements BatteryTipDetector { final long foregroundTimeMs = mBatteryUtils.getProcessTimeMs( BatteryUtils.StatusType.FOREGROUND, batterySipper.uidObj, BatteryStats.STATS_SINCE_CHARGED); - mHighUsageAppList.add(new HighUsageApp( - mBatteryUtils.getPackageName(batterySipper.getUid()), - foregroundTimeMs)); + mHighUsageAppList.add(new AppInfo.Builder() + .setPackageName(mBatteryUtils.getPackageName(batterySipper.getUid())) + .setScreenOnTimeMs(foregroundTimeMs) + .build()); } } diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java index 0316832f8d6..2aabf98610b 100644 --- a/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java +++ b/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java @@ -23,7 +23,7 @@ import android.support.annotation.VisibleForTesting; import com.android.settings.R; import com.android.settings.Utils; -import com.android.settings.fuelgauge.batterytip.HighUsageApp; +import com.android.settings.fuelgauge.batterytip.AppInfo; import java.util.List; @@ -34,9 +34,9 @@ public class HighUsageTip extends BatteryTip { private final long mScreenTimeMs; @VisibleForTesting - final List mHighUsageAppList; + final List mHighUsageAppList; - public HighUsageTip(long screenTimeMs, List appList) { + public HighUsageTip(long screenTimeMs, List appList) { super(TipType.HIGH_DEVICE_USAGE, appList.isEmpty() ? StateType.INVISIBLE : StateType.NEW, true /* showDialog */); mScreenTimeMs = screenTimeMs; @@ -47,7 +47,7 @@ public class HighUsageTip extends BatteryTip { HighUsageTip(Parcel in) { super(in); mScreenTimeMs = in.readLong(); - mHighUsageAppList = in.createTypedArrayList(HighUsageApp.CREATOR); + mHighUsageAppList = in.createTypedArrayList(AppInfo.CREATOR); } @Override @@ -82,7 +82,7 @@ public class HighUsageTip extends BatteryTip { return mScreenTimeMs; } - public List getHighUsageAppList() { + public List getHighUsageAppList() { return mHighUsageAppList; } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java new file mode 100644 index 00000000000..ac8800e5c7a --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.fuelgauge; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.text.format.DateUtils; + +import com.android.settings.TestConfig; +import com.android.settings.fuelgauge.batterytip.AppInfo; +import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager; +import com.android.settings.testutils.DatabaseTestUtils; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class BatteryDatabaseManagerTest { + private static String PACKAGE_NAME_NEW = "com.android.app1"; + private static int TYPE_NEW = 1; + private static String PACKAGE_NAME_OLD = "com.android.app2"; + private static int TYPE_OLD = 2; + private static long NOW = System.currentTimeMillis(); + private static long ONE_DAY_BEFORE = NOW - DateUtils.DAY_IN_MILLIS; + private static long TWO_DAYS_BEFORE = NOW - 2 * DateUtils.DAY_IN_MILLIS; + private Context mContext; + private BatteryDatabaseManager mBatteryDatabaseManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = RuntimeEnvironment.application; + mBatteryDatabaseManager = spy(new BatteryDatabaseManager(mContext)); + } + + @After + public void cleanUp() { + DatabaseTestUtils.clearDb(mContext); + } + + @Test + public void testAllFunctions() { + mBatteryDatabaseManager.insertAnomaly(PACKAGE_NAME_NEW, TYPE_NEW, NOW); + mBatteryDatabaseManager.insertAnomaly(PACKAGE_NAME_OLD, TYPE_OLD, TWO_DAYS_BEFORE); + + // In database, it contains two record + List totalAppInfos = mBatteryDatabaseManager.queryAllAnomaliesAfter(0); + assertThat(totalAppInfos).hasSize(2); + verifyAppInfo(totalAppInfos.get(0), PACKAGE_NAME_NEW, TYPE_NEW); + verifyAppInfo(totalAppInfos.get(1), PACKAGE_NAME_OLD, TYPE_OLD); + + // Only one record shows up if we query by timestamp + List appInfos = mBatteryDatabaseManager.queryAllAnomaliesAfter(ONE_DAY_BEFORE); + assertThat(appInfos).hasSize(1); + verifyAppInfo(appInfos.get(0), PACKAGE_NAME_NEW, TYPE_NEW); + + mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(ONE_DAY_BEFORE); + + // The obsolete record is removed from database + List appInfos1 = mBatteryDatabaseManager.queryAllAnomaliesAfter(0); + assertThat(appInfos1).hasSize(1); + verifyAppInfo(appInfos1.get(0), PACKAGE_NAME_NEW, TYPE_NEW); + + } + + private void verifyAppInfo(final AppInfo appInfo, String packageName, int type) { + assertThat(appInfo.packageName).isEqualTo(packageName); + assertThat(appInfo.anomalyType).isEqualTo(type); + } + +} diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java new file mode 100644 index 00000000000..16b45dff865 --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.fuelgauge.batterytip; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.Parcel; +import android.text.format.DateUtils; + +import com.android.settings.TestConfig; +import com.android.settings.fuelgauge.anomaly.Anomaly; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +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 long SCREEN_TIME_MS = DateUtils.HOUR_IN_MILLIS; + + private AppInfo mAppInfo; + + @Before + public void setUp() { + mAppInfo = new AppInfo.Builder() + .setPackageName(PACKAGE_NAME) + .setAnomalyType(ANOMALY_TYPE) + .setScreenOnTimeMs(SCREEN_TIME_MS) + .build(); + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + mAppInfo.writeToParcel(parcel, mAppInfo.describeContents()); + parcel.setDataPosition(0); + + final AppInfo appInfo = new AppInfo(parcel); + + assertThat(appInfo.packageName).isEqualTo(PACKAGE_NAME); + assertThat(appInfo.anomalyType).isEqualTo(ANOMALY_TYPE); + assertThat(appInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS); + } + + @Test + public void testCompareTo_hasCorrectOrder() { + final AppInfo appInfo = new AppInfo.Builder() + .setPackageName(PACKAGE_NAME) + .setAnomalyType(ANOMALY_TYPE) + .setScreenOnTimeMs(SCREEN_TIME_MS + 100) + .build(); + + List appInfos = new ArrayList<>(); + appInfos.add(appInfo); + appInfos.add(mAppInfo); + + Collections.sort(appInfos); + assertThat(appInfos.get(0).screenOnTimeMs).isLessThan(appInfos.get(1).screenOnTimeMs); + } + + @Test + public void testBuilder() { + assertThat(mAppInfo.packageName).isEqualTo(PACKAGE_NAME); + assertThat(mAppInfo.anomalyType).isEqualTo(ANOMALY_TYPE); + assertThat(mAppInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS); + } +} diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java index e2f8a26cc7e..068977884f2 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java @@ -22,7 +22,7 @@ import android.os.Parcel; import android.text.format.DateUtils; import com.android.settings.TestConfig; -import com.android.settings.fuelgauge.batterytip.HighUsageApp; +import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; @@ -42,14 +42,17 @@ public class HighUsageTipTest { private Context mContext; private HighUsageTip mBatteryTip; - private List mUsageAppList; + private List mUsageAppList; @Before public void setUp() { mContext = RuntimeEnvironment.application; mUsageAppList = new ArrayList<>(); - mUsageAppList.add(new HighUsageApp(PACKAGE_NAME, SCREEN_TIME)); + mUsageAppList.add(new AppInfo.Builder() + .setPackageName(PACKAGE_NAME) + .setScreenOnTimeMs(SCREEN_TIME) + .build()); mBatteryTip = new HighUsageTip(SCREEN_TIME, mUsageAppList); } @@ -67,7 +70,7 @@ public class HighUsageTipTest { assertThat(parcelTip.getState()).isEqualTo(BatteryTip.StateType.NEW); assertThat(parcelTip.getScreenTimeMs()).isEqualTo(SCREEN_TIME); assertThat(parcelTip.mHighUsageAppList.size()).isEqualTo(1); - final HighUsageApp app = parcelTip.mHighUsageAppList.get(0); + final AppInfo app = parcelTip.mHighUsageAppList.get(0); assertThat(app.packageName).isEqualTo(PACKAGE_NAME); assertThat(app.screenOnTimeMs).isEqualTo(SCREEN_TIME); } diff --git a/tests/robotests/src/com/android/settings/testutils/DatabaseTestUtils.java b/tests/robotests/src/com/android/settings/testutils/DatabaseTestUtils.java index 11e740ab0ae..499a2f78f34 100644 --- a/tests/robotests/src/com/android/settings/testutils/DatabaseTestUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/DatabaseTestUtils.java @@ -18,6 +18,7 @@ package com.android.settings.testutils; import android.content.Context; +import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper; import com.android.settings.search.IndexDatabaseHelper; import com.android.settings.slices.SlicesDatabaseHelper; @@ -28,6 +29,7 @@ public class DatabaseTestUtils { public static void clearDb(Context context) { clearSearchDb(context); clearSlicesDb(context); + clearAnomalyDb(context); } private static void clearSlicesDb(Context context) { @@ -45,6 +47,21 @@ public class DatabaseTestUtils { } } + private static void clearAnomalyDb(Context context) { + AnomalyDatabaseHelper helper = AnomalyDatabaseHelper.getInstance(context); + helper.close(); + + Field instance; + Class clazz = AnomalyDatabaseHelper.class; + try { + instance = clazz.getDeclaredField("sSingleton"); + instance.setAccessible(true); + instance.set(null, null); + } catch (Exception e) { + throw new RuntimeException(); + } + } + private static void clearSearchDb(Context context) { IndexDatabaseHelper helper = IndexDatabaseHelper.getInstance(context); helper.close();