Implement the app usage data loading from database function.

Bug: 260964903
Test: make RunSettingsRoboTests + manual
Change-Id: I459dbdebe53e6b7421642955f36976b3e7c95fcb
This commit is contained in:
Kuan Wang
2022-12-19 19:59:13 +08:00
parent 092d07fa60
commit 97924455ff
12 changed files with 581 additions and 50 deletions

View File

@@ -43,13 +43,18 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/** Tests for {@link BatteryUsageContentProvider}. */
@RunWith(RobolectricTestRunner.class)
public final class BatteryUsageContentProviderTest {
private static final Uri VALID_BATTERY_STATE_CONTENT_URI = DatabaseUtils.BATTERY_CONTENT_URI;
private static final long TIMESTAMP1 = System.currentTimeMillis();
private static final long TIMESTAMP2 = System.currentTimeMillis() + 2;
private static final long TIMESTAMP3 = System.currentTimeMillis() + 4;
private static final String PACKAGE_NAME1 = "com.android.settings1";
private static final String PACKAGE_NAME2 = "com.android.settings2";
private static final String PACKAGE_NAME3 = "com.android.settings3";
@@ -180,29 +185,49 @@ public final class BatteryUsageContentProviderTest {
BootBroadcastReceiver.ACTION_PERIODIC_JOB_RECHECK);
}
@Test
public void query_appUsageEvent_returnsExpectedResult() {
insertAppUsageEvent();
final List<Long> userIds1 = new ArrayList<>();
final long notExistingUserId = 3;
userIds1.add(USER_ID1);
userIds1.add(USER_ID2);
userIds1.add(notExistingUserId);
final Cursor cursor1 = getCursorOfAppUsage(userIds1, TIMESTAMP1);
assertThat(cursor1.getCount()).isEqualTo(3);
// Verifies the queried first battery state.
cursor1.moveToFirst();
assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME1);
// Verifies the queried second battery state.
cursor1.moveToNext();
assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME2);
// Verifies the queried third battery state.
cursor1.moveToNext();
assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
final List<Long> userIds2 = new ArrayList<>();
userIds2.add(USER_ID1);
final Cursor cursor2 = getCursorOfAppUsage(userIds2, TIMESTAMP3);
assertThat(cursor2.getCount()).isEqualTo(1);
// Verifies the queried first battery state.
cursor2.moveToFirst();
assertThat(cursor2.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
}
@Test
public void query_appUsageTimestamp_returnsExpectedResult() throws Exception {
mProvider.onCreate();
final long timestamp1 = System.currentTimeMillis();
final long timestamp2 = timestamp1 + 2;
final long timestamp3 = timestamp1 + 4;
// Inserts some valid testing data.
BatteryTestUtils.insertDataToAppUsageEventTable(
mContext, USER_ID1, timestamp1, PACKAGE_NAME1);
BatteryTestUtils.insertDataToAppUsageEventTable(
mContext, USER_ID2, timestamp2, PACKAGE_NAME2);
BatteryTestUtils.insertDataToAppUsageEventTable(
mContext, USER_ID1, timestamp3, PACKAGE_NAME3);
insertAppUsageEvent();
final Cursor cursor1 = getCursorOfLatestTimestamp(USER_ID1);
assertThat(cursor1.getCount()).isEqualTo(1);
cursor1.moveToFirst();
assertThat(cursor1.getLong(0)).isEqualTo(timestamp3);
assertThat(cursor1.getLong(0)).isEqualTo(TIMESTAMP3);
final Cursor cursor2 = getCursorOfLatestTimestamp(USER_ID2);
assertThat(cursor2.getCount()).isEqualTo(1);
cursor2.moveToFirst();
assertThat(cursor2.getLong(0)).isEqualTo(timestamp2);
assertThat(cursor2.getLong(0)).isEqualTo(TIMESTAMP2);
final long notExistingUserId = 3;
final Cursor cursor3 = getCursorOfLatestTimestamp(notExistingUserId);
@@ -383,6 +408,17 @@ public final class BatteryUsageContentProviderTest {
return cursor;
}
private void insertAppUsageEvent() {
mProvider.onCreate();
// Inserts some valid testing data.
BatteryTestUtils.insertDataToAppUsageEventTable(
mContext, USER_ID1, TIMESTAMP1, PACKAGE_NAME1);
BatteryTestUtils.insertDataToAppUsageEventTable(
mContext, USER_ID2, TIMESTAMP2, PACKAGE_NAME2);
BatteryTestUtils.insertDataToAppUsageEventTable(
mContext, USER_ID1, TIMESTAMP3, PACKAGE_NAME3);
}
private Cursor getCursorOfLatestTimestamp(final long userId) {
final Uri appUsageLatestTimestampQueryContentUri =
new Uri.Builder()
@@ -394,10 +430,28 @@ public final class BatteryUsageContentProviderTest {
.build();
return mProvider.query(
appUsageLatestTimestampQueryContentUri,
/*strings=*/ null,
/*s=*/ null,
/*strings1=*/ null,
/*s1=*/ null);
appUsageLatestTimestampQueryContentUri,
/*strings=*/ null,
/*s=*/ null,
/*strings1=*/ null,
/*s1=*/ null);
}
private Cursor getCursorOfAppUsage(final List<Long> userIds, final long queryTimestamp) {
final String queryUserIdString = userIds.stream()
.map(userId -> String.valueOf(userId))
.collect(Collectors.joining(","));
final Uri appUsageEventUri =
new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(DatabaseUtils.AUTHORITY)
.appendPath(DatabaseUtils.APP_USAGE_EVENT_TABLE)
.appendQueryParameter(
DatabaseUtils.QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
.appendQueryParameter(DatabaseUtils.QUERY_KEY_USERID, queryUserIdString)
.build();
return mProvider.query(
appUsageEventUri, /*strings=*/ null, /*s=*/ null, /*strings1=*/ null, /*s1=*/ null);
}
}

View File

@@ -27,6 +27,7 @@ import android.app.usage.UsageEvents.Event;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.MatrixCursor;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.LocaleList;
@@ -335,6 +336,68 @@ public final class ConvertUtilsTest {
assertThat(appUsageEvent).isNull();
}
@Test
public void convertToAppUsageEventFromCursor_returnExpectedResult() {
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
AppUsageEventEntity.KEY_USER_ID,
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP,
AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE,
AppUsageEventEntity.KEY_TASK_ROOT_PACKAGE_NAME,
AppUsageEventEntity.KEY_INSTANCE_ID});
cursor.addRow(
new Object[]{
101L,
1001L,
"com.android.settings1",
10001L,
AppUsageEventType.DEVICE_SHUTDOWN.getNumber(),
"com.android.settings2",
100001L});
cursor.moveToFirst();
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEventFromCursor(cursor);
assertThat(appUsageEvent.getUid()).isEqualTo(101L);
assertThat(appUsageEvent.getUserId()).isEqualTo(1001L);
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
assertThat(appUsageEvent.getTimestamp()).isEqualTo(10001L);
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
assertThat(appUsageEvent.getTaskRootPackageName()).isEqualTo("com.android.settings2");
assertThat(appUsageEvent.getInstanceId()).isEqualTo(100001L);
}
@Test
public void convertToAppUsageEventFromCursor_emptyInstanceIdAndRootName_returnExpectedResult() {
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
AppUsageEventEntity.KEY_USER_ID,
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP,
AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE});
cursor.addRow(
new Object[]{
101L,
1001L,
"com.android.settings1",
10001L,
AppUsageEventType.DEVICE_SHUTDOWN.getNumber()});
cursor.moveToFirst();
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEventFromCursor(cursor);
assertThat(appUsageEvent.getUid()).isEqualTo(101L);
assertThat(appUsageEvent.getUserId()).isEqualTo(1001L);
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
assertThat(appUsageEvent.getTimestamp()).isEqualTo(10001L);
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
assertThat(appUsageEvent.getTaskRootPackageName()).isEqualTo("");
assertThat(appUsageEvent.getInstanceId()).isEqualTo(0);
}
@Test
public void getLocale_nullContext_returnDefaultLocale() {
assertThat(ConvertUtils.getLocale(/*context=*/ null))

View File

@@ -27,10 +27,13 @@ import static org.mockito.Mockito.spy;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.content.Context;
import android.database.MatrixCursor;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.UserManager;
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,11 +68,31 @@ public final class DataProcessManagerTest {
mDataProcessManager = new DataProcessManager(
mContext, /*handler=*/ null, /*callbackFunction=*/ null,
/*hourlyBatteryLevelsPerDay=*/ null, /*batteryHistoryMap=*/ null);
/*hourlyBatteryLevelsPerDay=*/ new ArrayList<>(), /*batteryHistoryMap=*/ null);
}
@Test
public void start_loadExpectedCurrentAppUsageData() throws RemoteException {
public void start_loadEmptyDatabaseAppUsageData() {
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP});
DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
doReturn(true).when(mUserManager).isUserUnlocked(anyInt());
mDataProcessManager.start();
assertThat(mDataProcessManager.getIsCurrentAppUsageLoaded()).isTrue();
assertThat(mDataProcessManager.getIsDatabaseAppUsageLoaded()).isTrue();
assertThat(mDataProcessManager.getIsCurrentBatteryHistoryLoaded()).isTrue();
assertThat(mDataProcessManager.getShowScreenOnTime()).isTrue();
assertThat(mDataProcessManager.getAppUsageEventList()).isEmpty();
}
@Test
public void start_loadExpectedAppUsageData() throws RemoteException {
// Fake current usage data.
final UsageEvents.Event event1 =
getUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, /*timestamp=*/ 1);
final UsageEvents.Event event2 =
@@ -82,6 +105,22 @@ public final class DataProcessManagerTest {
.queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
doReturn(true).when(mUserManager).isUserUnlocked(anyInt());
// Fake database usage data.
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE,
AppUsageEventEntity.KEY_TIMESTAMP});
// Adds fake data into the cursor.
cursor.addRow(new Object[] {
AppUsageEventType.ACTIVITY_RESUMED.getNumber(), /*timestamp=*/ 3});
cursor.addRow(new Object[] {
AppUsageEventType.ACTIVITY_RESUMED.getNumber(), /*timestamp=*/ 4});
cursor.addRow(new Object[] {
AppUsageEventType.ACTIVITY_STOPPED.getNumber(), /*timestamp=*/ 5});
cursor.addRow(new Object[] {
AppUsageEventType.ACTIVITY_STOPPED.getNumber(), /*timestamp=*/ 6});
DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
mDataProcessManager.start();
assertThat(mDataProcessManager.getIsCurrentAppUsageLoaded()).isTrue();
@@ -89,11 +128,19 @@ public final class DataProcessManagerTest {
assertThat(mDataProcessManager.getIsCurrentBatteryHistoryLoaded()).isTrue();
assertThat(mDataProcessManager.getShowScreenOnTime()).isTrue();
final List<AppUsageEvent> appUsageEventList = mDataProcessManager.getAppUsageEventList();
assertThat(appUsageEventList.size()).isEqualTo(2);
assertThat(appUsageEventList.size()).isEqualTo(6);
assertAppUsageEvent(
appUsageEventList.get(0), AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1);
assertAppUsageEvent(
appUsageEventList.get(1), AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 2);
assertAppUsageEvent(
appUsageEventList.get(2), AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 3);
assertAppUsageEvent(
appUsageEventList.get(3), AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 4);
assertAppUsageEvent(
appUsageEventList.get(4), AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 5);
assertAppUsageEvent(
appUsageEventList.get(5), AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 6);
}
@Test
@@ -106,6 +153,14 @@ public final class DataProcessManagerTest {
.when(mUsageStatsManager)
.queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
doReturn(false).when(mUserManager).isUserUnlocked(anyInt());
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP});
// Adds fake data into the cursor.
cursor.addRow(new Object[] {101L, "app name1", 1001L});
DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
mDataProcessManager.start();
@@ -113,6 +168,42 @@ public final class DataProcessManagerTest {
assertThat(mDataProcessManager.getShowScreenOnTime()).isFalse();
}
@Test
public void getStartTimestampOfBatteryLevelData_returnExpectedResult() {
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
final List<Long> timestamps = new ArrayList<>();
timestamps.add(101L);
timestamps.add(1001L);
final List<Integer> levels = new ArrayList<>();
levels.add(1);
levels.add(2);
hourlyBatteryLevelsPerDay.add(null);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
final DataProcessManager dataProcessManager = new DataProcessManager(
mContext, /*handler=*/ null, /*callbackFunction=*/ null,
hourlyBatteryLevelsPerDay, /*batteryHistoryMap=*/ null);
assertThat(dataProcessManager.getStartTimestampOfBatteryLevelData()).isEqualTo(101);
}
@Test
public void getStartTimestampOfBatteryLevelData_emptyLevels_returnZero() {
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
hourlyBatteryLevelsPerDay.add(null);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
final DataProcessManager dataProcessManager = new DataProcessManager(
mContext, /*handler=*/ null, /*callbackFunction=*/ null,
hourlyBatteryLevelsPerDay, /*batteryHistoryMap=*/ null);
assertThat(dataProcessManager.getStartTimestampOfBatteryLevelData()).isEqualTo(0);
}
private UsageEvents getUsageEvents(final List<UsageEvents.Event> events) {
UsageEvents usageEvents = new UsageEvents(events, new String[] {"package"});
Parcel parcel = Parcel.obtain();

View File

@@ -213,7 +213,7 @@ public final class DataProcessorTest {
.when(mUsageStatsManager)
.queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId))
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0))
.isEqualTo(mUsageEvents1);
}
@@ -223,7 +223,7 @@ public final class DataProcessorTest {
// Test locked user.
doReturn(false).when(mUserManager).isUserUnlocked(userId);
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId)).isNull();
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0)).isNull();
}
@Test
@@ -233,7 +233,7 @@ public final class DataProcessorTest {
doReturn(null)
.when(mUsageStatsManager).queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId)).isNull();
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0)).isNull();
}
@Test public void generateAppUsageEventListFromUsageEvents_returnExpectedResult() {
@@ -647,6 +647,7 @@ public final class DataProcessorTest {
public void getBatteryUsageMap_emptyHistoryMap_returnNull() {
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));

View File

@@ -276,6 +276,62 @@ public final class DatabaseUtilsTest {
mContext, /*userId=*/ 0, earliestTimestamp2)).isEqualTo(earliestTimestamp2);
}
@Test
public void getAppUsageEventForUsers_emptyCursorContent_returnEmptyMap() {
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
AppUsageEventEntity.KEY_USER_ID,
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP,
AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE});
DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
assertThat(DatabaseUtils.getAppUsageEventForUsers(
mContext,
/*calendar=*/ null,
/*userIds=*/ new ArrayList<>(),
/*startTimestampOfLevelData=*/ 0)).isEmpty();
}
@Test
public void getAppUsageEventForUsers_nullCursor_returnEmptyMap() {
DatabaseUtils.sFakeAppUsageEventSupplier = () -> null;
assertThat(DatabaseUtils.getAppUsageEventForUsers(
mContext,
/*calendar=*/ null,
/*userIds=*/ new ArrayList<>(),
/*startTimestampOfLevelData=*/ 0)).isEmpty();
}
@Test
public void getAppUsageEventForUsers_returnExpectedMap() {
final Long timestamp1 = 1001L;
final Long timestamp2 = 1002L;
final MatrixCursor cursor = new MatrixCursor(
new String[]{
AppUsageEventEntity.KEY_UID,
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP});
// Adds fake data into the cursor.
cursor.addRow(new Object[] {101L, "app name1", timestamp1});
cursor.addRow(new Object[] {101L, "app name2", timestamp2});
cursor.addRow(new Object[] {101L, "app name3", timestamp2});
cursor.addRow(new Object[] {101L, "app name4", timestamp2});
DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
final List<AppUsageEvent> appUsageEventList = DatabaseUtils.getAppUsageEventForUsers(
mContext,
/*calendar=*/ null,
/*userIds=*/ new ArrayList<>(),
/*startTimestampOfLevelData=*/ 0);
assertThat(appUsageEventList.get(0).getPackageName()).isEqualTo("app name1");
assertThat(appUsageEventList.get(1).getPackageName()).isEqualTo("app name2");
assertThat(appUsageEventList.get(2).getPackageName()).isEqualTo("app name3");
assertThat(appUsageEventList.get(3).getPackageName()).isEqualTo("app name4");
}
@Test
public void getHistoryMapSinceLastFullCharge_emptyCursorContent_returnEmptyMap() {
final MatrixCursor cursor = new MatrixCursor(

View File

@@ -31,11 +31,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
/** Tests for {@link AppUsageEventDao}. */
@RunWith(RobolectricTestRunner.class)
public final class AppUsageEventDaoTest {
private static final int CURSOR_COLUMN_SIZE = 8;
private static final long TIMESTAMP1 = System.currentTimeMillis();
private static final long TIMESTAMP2 = System.currentTimeMillis() + 2;
private static final long TIMESTAMP3 = System.currentTimeMillis() + 4;
@@ -77,6 +79,36 @@ public final class AppUsageEventDaoTest {
assertAppUsageEvent(entities.get(1), TIMESTAMP2, PACKAGE_NAME2);
}
@Test
public void appUsageEventDao_getAllForUsersAfter() {
final List<Long> userIds1 = new ArrayList<>();
final long notExistingUserId = 3;
userIds1.add(USER_ID1);
userIds1.add(USER_ID2);
userIds1.add(notExistingUserId);
final Cursor cursor1 = mAppUsageEventDao.getAllForUsersAfter(userIds1, TIMESTAMP1);
assertThat(cursor1.getCount()).isEqualTo(3);
assertThat(cursor1.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
// Verifies the queried first battery state.
cursor1.moveToFirst();
assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME1);
// Verifies the queried second battery state.
cursor1.moveToNext();
assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME2);
// Verifies the queried third battery state.
cursor1.moveToNext();
assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
final List<Long> userIds2 = new ArrayList<>();
userIds2.add(USER_ID1);
final Cursor cursor2 = mAppUsageEventDao.getAllForUsersAfter(userIds2, TIMESTAMP3);
assertThat(cursor2.getCount()).isEqualTo(1);
assertThat(cursor2.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
// Verifies the queried first battery state.
cursor2.moveToFirst();
assertThat(cursor2.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
}
@Test
public void appUsageEventDao_getLatestTimestampOfUser() throws Exception {
final Cursor cursor1 = mAppUsageEventDao.getLatestTimestampOfUser(USER_ID1);