Merge "Add database to store anomaly data"
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 0000000..a13df25
--- /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 0000000..1daff36
--- /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<AppInfo>, 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 0000000..f87501f
--- /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<AppInfo> queryAllAnomaliesAfter(long timestampMs) {
+ final List<AppInfo> 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 8b74394..60aa6c8 100644
--- a/src/com/android/settings/fuelgauge/batterytip/HighUsageAdapter.java
+++ b/src/com/android/settings/fuelgauge/batterytip/HighUsageAdapter.java
@@ -39,7 +39,7 @@
private final Context mContext;
private final IconDrawableFactory mIconDrawableFactory;
private final PackageManager mPackageManager;
- private final List<HighUsageApp> mHighUsageAppList;
+ private final List<AppInfo> mHighUsageAppList;
public static class ViewHolder extends RecyclerView.ViewHolder {
public View view;
@@ -56,7 +56,7 @@
}
}
- public HighUsageAdapter(Context context, List<HighUsageApp> highUsageAppList) {
+ public HighUsageAdapter(Context context, List<AppInfo> highUsageAppList) {
mContext = context;
mHighUsageAppList = highUsageAppList;
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
@@ -72,7 +72,7 @@
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
- final HighUsageApp app = mHighUsageAppList.get(position);
+ final AppInfo app = mHighUsageAppList.get(position);
holder.appIcon.setImageDrawable(
Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager, app.packageName,
UserHandle.myUserId()));
diff --git a/src/com/android/settings/fuelgauge/batterytip/HighUsageApp.java b/src/com/android/settings/fuelgauge/batterytip/HighUsageApp.java
deleted file mode 100644
index f75ecf0..0000000
--- a/src/com/android/settings/fuelgauge/batterytip/HighUsageApp.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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;
-
-/**
- * Class representing app with high screen usage
- */
-public class HighUsageApp implements Comparable<HighUsageApp>, 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 237f430..3c69667 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 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 @@
public class HighUsageDetector implements BatteryTipDetector {
private BatteryTipPolicy mPolicy;
private BatteryStatsHelper mBatteryStatsHelper;
- private List<HighUsageApp> mHighUsageAppList;
+ private List<AppInfo> mHighUsageAppList;
private Context mContext;
@VisibleForTesting
BatteryUtils mBatteryUtils;
@@ -68,9 +66,10 @@
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 0316832..2aabf98 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 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 @@
private final long mScreenTimeMs;
@VisibleForTesting
- final List<HighUsageApp> mHighUsageAppList;
+ final List<AppInfo> mHighUsageAppList;
- public HighUsageTip(long screenTimeMs, List<HighUsageApp> appList) {
+ public HighUsageTip(long screenTimeMs, List<AppInfo> appList) {
super(TipType.HIGH_DEVICE_USAGE, appList.isEmpty() ? StateType.INVISIBLE : StateType.NEW,
true /* showDialog */);
mScreenTimeMs = screenTimeMs;
@@ -47,7 +47,7 @@
HighUsageTip(Parcel in) {
super(in);
mScreenTimeMs = in.readLong();
- mHighUsageAppList = in.createTypedArrayList(HighUsageApp.CREATOR);
+ mHighUsageAppList = in.createTypedArrayList(AppInfo.CREATOR);
}
@Override
@@ -82,7 +82,7 @@
return mScreenTimeMs;
}
- public List<HighUsageApp> getHighUsageAppList() {
+ public List<AppInfo> 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 0000000..ac8800e
--- /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<AppInfo> 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<AppInfo> 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<AppInfo> 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 0000000..16b45df
--- /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<AppInfo> 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 e2f8a26..0689778 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.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 @@
private Context mContext;
private HighUsageTip mBatteryTip;
- private List<HighUsageApp> mUsageAppList;
+ private List<AppInfo> 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 @@
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 11e740a..499a2f7 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 @@
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 static void clearDb(Context context) {
clearSearchDb(context);
clearSlicesDb(context);
+ clearAnomalyDb(context);
}
private static void clearSlicesDb(Context context) {
@@ -45,6 +47,21 @@
}
}
+ 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();