Add cache strategy for getUsageSource().
Cache usage source into SharedPreferences when phone is booting to avoid calling it too frequently. It should be safe because the usage source can only change on reboot. Bug: 293366011 Test: make RunSettingsRoboTests Change-Id: I35c07539d294737c5764b03b746cfb39f4ce008d
This commit is contained in:
@@ -22,8 +22,10 @@ import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Application;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
@@ -40,7 +42,6 @@ import org.robolectric.Shadows;
|
||||
import org.robolectric.shadows.ShadowAlarmManager;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -65,10 +66,12 @@ public final class BootBroadcastReceiverTest {
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, Clock.systemUTC().millis(), "com.android.systemui");
|
||||
mDao = database.batteryStateDao();
|
||||
clearSharedPreferences();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
clearSharedPreferences();
|
||||
mPeriodicJobManager.reset();
|
||||
}
|
||||
|
||||
@@ -82,8 +85,21 @@ public final class BootBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
public void onReceive_withBootCompletedIntent_refreshesJob() {
|
||||
final SharedPreferences sharedPreferences = DatabaseUtils.getSharedPreferences(mContext);
|
||||
sharedPreferences
|
||||
.edit()
|
||||
.putInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE,
|
||||
UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY)
|
||||
.apply();
|
||||
|
||||
mReceiver.onReceive(mContext, new Intent(Intent.ACTION_BOOT_COMPLETED));
|
||||
|
||||
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull();
|
||||
assertThat(
|
||||
DatabaseUtils
|
||||
.getSharedPreferences(mContext)
|
||||
.contains(DatabaseUtils.KEY_LAST_USAGE_SOURCE))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -133,15 +149,7 @@ public final class BootBroadcastReceiverTest {
|
||||
BootBroadcastReceiver.ACTION_PERIODIC_JOB_RECHECK);
|
||||
}
|
||||
|
||||
private void insertExpiredData(int shiftDay) {
|
||||
final long expiredTimeInMs =
|
||||
Clock.systemUTC().millis() - Duration.ofDays(shiftDay).toMillis();
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, expiredTimeInMs - 1, "com.android.systemui");
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, expiredTimeInMs, "com.android.systemui");
|
||||
// Ensures the testing environment is correct.
|
||||
assertThat(mDao.getAllAfter(0)).hasSize(3);
|
||||
private void clearSharedPreferences() {
|
||||
DatabaseUtils.getSharedPreferences(mContext).edit().clear().apply();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.usage.IUsageStatsManager;
|
||||
import android.app.usage.UsageEvents;
|
||||
import android.app.usage.UsageEvents.Event;
|
||||
import android.content.ContentValues;
|
||||
@@ -35,7 +34,6 @@ import android.database.MatrixCursor;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.LocaleList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
|
||||
@@ -62,14 +60,13 @@ public final class ConvertUtilsTest {
|
||||
@Mock
|
||||
private BatteryUsageStats mBatteryUsageStats;
|
||||
@Mock
|
||||
private IUsageStatsManager mUsageStatsManager;
|
||||
@Mock
|
||||
private BatteryEntry mMockBatteryEntry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
ConvertUtils.sUsageSource = ConvertUtils.EMPTY_USAGE_SOURCE;
|
||||
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
|
||||
}
|
||||
|
||||
@@ -302,7 +299,7 @@ public final class ConvertUtilsTest {
|
||||
|
||||
final long userId = 2;
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, mUsageStatsManager, event, userId);
|
||||
mContext, event, userId);
|
||||
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
||||
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.ACTIVITY_RESUMED);
|
||||
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
||||
@@ -322,8 +319,8 @@ public final class ConvertUtilsTest {
|
||||
when(mMockPackageManager.getPackageUidAsUser(any(), anyInt())).thenReturn(1001);
|
||||
|
||||
final long userId = 1;
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, mUsageStatsManager, event, userId);
|
||||
final AppUsageEvent appUsageEvent =
|
||||
ConvertUtils.convertToAppUsageEvent(mContext, event, userId);
|
||||
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
||||
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
|
||||
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
||||
@@ -338,8 +335,8 @@ public final class ConvertUtilsTest {
|
||||
final Event event = new Event();
|
||||
event.mPackage = null;
|
||||
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, mUsageStatsManager, event, /*userId=*/ 0);
|
||||
final AppUsageEvent appUsageEvent =
|
||||
ConvertUtils.convertToAppUsageEvent(mContext, event, /*userId=*/ 0);
|
||||
|
||||
assertThat(appUsageEvent).isNull();
|
||||
}
|
||||
@@ -354,8 +351,8 @@ public final class ConvertUtilsTest {
|
||||
.thenThrow(new PackageManager.NameNotFoundException());
|
||||
|
||||
final long userId = 1;
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, mUsageStatsManager, event, userId);
|
||||
final AppUsageEvent appUsageEvent =
|
||||
ConvertUtils.convertToAppUsageEvent(mContext, event, userId);
|
||||
|
||||
assertThat(appUsageEvent).isNull();
|
||||
}
|
||||
@@ -450,51 +447,47 @@ public final class ConvertUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_currentActivity_returnPackageName() throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_CURRENT_ACTIVITY);
|
||||
public void getEffectivePackageName_currentActivity_returnPackageName() {
|
||||
ConvertUtils.sUsageSource = USAGE_SOURCE_CURRENT_ACTIVITY;
|
||||
final String packageName = "com.android.settings1";
|
||||
final String taskRootPackageName = "com.android.settings2";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, taskRootPackageName))
|
||||
mContext, packageName, taskRootPackageName))
|
||||
.isEqualTo(packageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_usageSourceThrowException_returnPackageName()
|
||||
throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenThrow(new RemoteException());
|
||||
public void getEffectivePackageName_emptyUsageSource_returnPackageName() {
|
||||
final String packageName = "com.android.settings1";
|
||||
final String taskRootPackageName = "com.android.settings2";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, taskRootPackageName))
|
||||
mContext, packageName, taskRootPackageName))
|
||||
.isEqualTo(packageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_rootActivity_returnTaskRootPackageName()
|
||||
throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
public void getEffectivePackageName_rootActivity_returnTaskRootPackageName() {
|
||||
ConvertUtils.sUsageSource = USAGE_SOURCE_TASK_ROOT_ACTIVITY;
|
||||
final String packageName = "com.android.settings1";
|
||||
final String taskRootPackageName = "com.android.settings2";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, taskRootPackageName))
|
||||
mContext, packageName, taskRootPackageName))
|
||||
.isEqualTo(taskRootPackageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_nullOrEmptyTaskRoot_returnPackageName()
|
||||
throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
public void getEffectivePackageName_nullOrEmptyTaskRoot_returnPackageName() {
|
||||
ConvertUtils.sUsageSource = USAGE_SOURCE_TASK_ROOT_ACTIVITY;
|
||||
final String packageName = "com.android.settings1";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, /*taskRootPackageName=*/ null))
|
||||
mContext, packageName, /*taskRootPackageName=*/ null))
|
||||
.isEqualTo(packageName);
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, /*taskRootPackageName=*/ ""))
|
||||
mContext, packageName, /*taskRootPackageName=*/ ""))
|
||||
.isEqualTo(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public final class DataProcessManagerTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
DataProcessor.sUsageStatsManager = mUsageStatsManager;
|
||||
DatabaseUtils.sUsageStatsManager = mUsageStatsManager;
|
||||
doReturn(mContext).when(mContext).getApplicationContext();
|
||||
doReturn(mUserManager)
|
||||
.when(mContext)
|
||||
|
||||
@@ -93,7 +93,7 @@ public final class DataProcessorTest {
|
||||
mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
|
||||
|
||||
DataProcessor.sTestSystemAppsPackageNames = Set.of();
|
||||
DataProcessor.sUsageStatsManager = mUsageStatsManager;
|
||||
DatabaseUtils.sUsageStatsManager = mUsageStatsManager;
|
||||
doReturn(mIntent).when(mContext).registerReceiver(
|
||||
isA(BroadcastReceiver.class), isA(IntentFilter.class));
|
||||
doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
|
||||
@@ -249,7 +249,7 @@ public final class DataProcessorTest {
|
||||
|
||||
final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>> periodMap =
|
||||
DataProcessor.generateAppUsagePeriodMap(
|
||||
14400000L, hourlyBatteryLevelsPerDay, appUsageEventList, new ArrayList<>());
|
||||
mContext, hourlyBatteryLevelsPerDay, appUsageEventList, new ArrayList<>());
|
||||
|
||||
assertThat(periodMap).hasSize(3);
|
||||
// Day 1
|
||||
@@ -287,7 +287,8 @@ public final class DataProcessorTest {
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
|
||||
assertThat(DataProcessor.generateAppUsagePeriodMap(
|
||||
0L, hourlyBatteryLevelsPerDay, new ArrayList<>(), new ArrayList<>())).isNull();
|
||||
mContext, hourlyBatteryLevelsPerDay, new ArrayList<>(), new ArrayList<>()))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1644,7 +1645,7 @@ public final class DataProcessorTest {
|
||||
|
||||
final Map<Long, Map<String, List<AppUsagePeriod>>> appUsagePeriodMap =
|
||||
DataProcessor.buildAppUsagePeriodList(
|
||||
appUsageEvents, new ArrayList<>(), 0, 5);
|
||||
mContext, appUsageEvents, new ArrayList<>(), 0, 5);
|
||||
|
||||
assertThat(appUsagePeriodMap).hasSize(2);
|
||||
final Map<String, List<AppUsagePeriod>> userMap1 = appUsagePeriodMap.get(1L);
|
||||
@@ -1668,7 +1669,7 @@ public final class DataProcessorTest {
|
||||
@Test
|
||||
public void buildAppUsagePeriodList_emptyEventList_returnNull() {
|
||||
assertThat(DataProcessor.buildAppUsagePeriodList(
|
||||
new ArrayList<>(), new ArrayList<>(), 0, 1)).isNull();
|
||||
mContext, new ArrayList<>(), new ArrayList<>(), 0, 1)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1680,7 +1681,7 @@ public final class DataProcessorTest {
|
||||
AppUsageEventType.DEVICE_SHUTDOWN, /*timestamp=*/ 2));
|
||||
|
||||
assertThat(DataProcessor.buildAppUsagePeriodList(
|
||||
appUsageEvents, new ArrayList<>(), 0, 3)).isNull();
|
||||
mContext, appUsageEvents, new ArrayList<>(), 0, 3)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
|
||||
import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -23,15 +26,19 @@ import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.usage.IUsageStatsManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.MatrixCursor;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
@@ -67,6 +74,7 @@ public final class DatabaseUtilsTest {
|
||||
@Mock private BatteryEntry mMockBatteryEntry2;
|
||||
@Mock private BatteryEntry mMockBatteryEntry3;
|
||||
@Mock private Context mMockContext;
|
||||
@Mock private IUsageStatsManager mUsageStatsManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -77,6 +85,7 @@ public final class DatabaseUtilsTest {
|
||||
doReturn(mPackageManager).when(mMockContext).getPackageManager();
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
DatabaseUtils.getSharedPreferences(mContext).edit().clear().apply();
|
||||
DatabaseUtils.sUsageStatsManager = mUsageStatsManager;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -422,6 +431,71 @@ public final class DatabaseUtilsTest {
|
||||
assertThat(batteryHistMap).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeUsageSource_hasNoData() {
|
||||
DatabaseUtils.removeUsageSource(mContext);
|
||||
assertThat(
|
||||
DatabaseUtils
|
||||
.getSharedPreferences(mContext)
|
||||
.contains(DatabaseUtils.KEY_LAST_USAGE_SOURCE))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeUsageSource_hasData_deleteUsageSource() {
|
||||
final SharedPreferences sharedPreferences = DatabaseUtils.getSharedPreferences(mContext);
|
||||
sharedPreferences
|
||||
.edit()
|
||||
.putInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY)
|
||||
.apply();
|
||||
|
||||
DatabaseUtils.removeUsageSource(mContext);
|
||||
|
||||
assertThat(
|
||||
DatabaseUtils
|
||||
.getSharedPreferences(mContext)
|
||||
.contains(DatabaseUtils.KEY_LAST_USAGE_SOURCE))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUsageSource_hasData() {
|
||||
final SharedPreferences sharedPreferences = DatabaseUtils.getSharedPreferences(mContext);
|
||||
sharedPreferences
|
||||
.edit()
|
||||
.putInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY)
|
||||
.apply();
|
||||
|
||||
assertThat(DatabaseUtils.getUsageSource(mContext))
|
||||
.isEqualTo(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUsageSource_notHasData_writeLoadedData() throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
|
||||
assertThat(DatabaseUtils.getUsageSource(mContext))
|
||||
.isEqualTo(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
assertThat(
|
||||
DatabaseUtils
|
||||
.getSharedPreferences(mContext)
|
||||
.getInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_CURRENT_ACTIVITY))
|
||||
.isEqualTo(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUsageSource_throwException_writeDefaultData() throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenThrow(new RemoteException());
|
||||
|
||||
assertThat(DatabaseUtils.getUsageSource(mContext))
|
||||
.isEqualTo(USAGE_SOURCE_CURRENT_ACTIVITY);
|
||||
assertThat(
|
||||
DatabaseUtils
|
||||
.getSharedPreferences(mContext)
|
||||
.getInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_CURRENT_ACTIVITY))
|
||||
.isEqualTo(USAGE_SOURCE_CURRENT_ACTIVITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recordDateTime_writeDataIntoSharedPreferences() {
|
||||
final String preferenceKey = "test_preference_key";
|
||||
|
||||
Reference in New Issue
Block a user