Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import static android.app.usage.UsageStatsManager.INTERVAL_DAILY;
      4 import static android.app.usage.UsageStatsManager.INTERVAL_WEEKLY;
      5 import static android.content.Context.USAGE_STATS_SERVICE;
      6 import static android.os.Build.VERSION_CODES.LOLLIPOP;
      7 import static com.google.common.truth.Truth.assertThat;
      8 import static java.util.concurrent.TimeUnit.HOURS;
      9 import static org.robolectric.Shadows.shadowOf;
     10 
     11 import android.app.Application;
     12 import android.app.PendingIntent;
     13 import android.app.usage.UsageEvents;
     14 import android.app.usage.UsageEvents.Event;
     15 import android.app.usage.UsageStats;
     16 import android.app.usage.UsageStatsManager;
     17 import android.content.Intent;
     18 import android.os.Build;
     19 import androidx.test.core.app.ApplicationProvider;
     20 import androidx.test.ext.junit.runners.AndroidJUnit4;
     21 import com.google.common.collect.ImmutableList;
     22 import java.util.Collections;
     23 import java.util.List;
     24 import java.util.Map;
     25 import java.util.concurrent.TimeUnit;
     26 import org.junit.Before;
     27 import org.junit.Test;
     28 import org.junit.runner.RunWith;
     29 import org.robolectric.annotation.Config;
     30 import org.robolectric.shadows.ShadowUsageStatsManager.AppUsageObserver;
     31 import org.robolectric.shadows.ShadowUsageStatsManager.UsageStatsBuilder;
     32 
     33 /** Test for {@link ShadowUsageStatsManager}. */
     34 @RunWith(AndroidJUnit4.class)
     35 @Config(minSdk = LOLLIPOP)
     36 public class ShadowUsageStatsManagerTest {
     37 
     38   private static final String TEST_PACKAGE_NAME1 = "com.company1.pkg1";
     39   private static final String TEST_PACKAGE_NAME2 = "com.company2.pkg2";
     40   private static final String TEST_ACTIVITY_NAME = "com.company2.pkg2.Activity";
     41 
     42   private UsageStatsManager usageStatsManager;
     43   private Application context;
     44 
     45   @Before
     46   public void setUp() throws Exception {
     47     usageStatsManager =
     48         (UsageStatsManager)
     49             ApplicationProvider.getApplicationContext().getSystemService(USAGE_STATS_SERVICE);
     50     context = ApplicationProvider.getApplicationContext();
     51   }
     52 
     53   @Test
     54   public void testQueryEvents_emptyEvents() throws Exception {
     55     UsageEvents events = usageStatsManager.queryEvents(1000L, 2000L);
     56     Event event = new Event();
     57 
     58     assertThat(events.hasNextEvent()).isFalse();
     59     assertThat(events.getNextEvent(event)).isFalse();
     60   }
     61 
     62   @Test
     63   public void testQueryEvents_appendEventData_shouldCombineWithPreviousData() throws Exception {
     64     shadowOf(usageStatsManager).addEvent(TEST_PACKAGE_NAME1, 500L, Event.MOVE_TO_FOREGROUND);
     65     shadowOf(usageStatsManager).addEvent(TEST_PACKAGE_NAME1, 1000L, Event.MOVE_TO_BACKGROUND);
     66     shadowOf(usageStatsManager)
     67         .addEvent(
     68             ShadowUsageStatsManager.EventBuilder.buildEvent()
     69                 .setTimeStamp(1500L)
     70                 .setPackage(TEST_PACKAGE_NAME2)
     71                 .setClass(TEST_ACTIVITY_NAME)
     72                 .setEventType(Event.MOVE_TO_FOREGROUND)
     73                 .build());
     74     shadowOf(usageStatsManager).addEvent(TEST_PACKAGE_NAME2, 2000L, Event.MOVE_TO_BACKGROUND);
     75     shadowOf(usageStatsManager)
     76         .addEvent(
     77             ShadowUsageStatsManager.EventBuilder.buildEvent()
     78                 .setTimeStamp(2500L)
     79                 .setPackage(TEST_PACKAGE_NAME1)
     80                 .setEventType(Event.MOVE_TO_FOREGROUND)
     81                 .setClass(TEST_ACTIVITY_NAME)
     82                 .build());
     83 
     84     UsageEvents events = usageStatsManager.queryEvents(1000L, 2000L);
     85     Event event = new Event();
     86 
     87     assertThat(events.hasNextEvent()).isTrue();
     88     assertThat(events.getNextEvent(event)).isTrue();
     89     assertThat(event.getPackageName()).isEqualTo(TEST_PACKAGE_NAME1);
     90     assertThat(event.getTimeStamp()).isEqualTo(1000L);
     91     assertThat(event.getEventType()).isEqualTo(Event.MOVE_TO_BACKGROUND);
     92 
     93     assertThat(events.hasNextEvent()).isTrue();
     94     assertThat(events.getNextEvent(event)).isTrue();
     95     assertThat(event.getPackageName()).isEqualTo(TEST_PACKAGE_NAME2);
     96     assertThat(event.getTimeStamp()).isEqualTo(1500L);
     97     assertThat(event.getEventType()).isEqualTo(Event.MOVE_TO_FOREGROUND);
     98     assertThat(event.getClassName()).isEqualTo(TEST_ACTIVITY_NAME);
     99 
    100     assertThat(events.hasNextEvent()).isFalse();
    101     assertThat(events.getNextEvent(event)).isFalse();
    102   }
    103 
    104   @Test
    105   public void testQueryEvents_appendEventData_simulateTimeChange_shouldAddOffsetToPreviousData()
    106       throws Exception {
    107     shadowOf(usageStatsManager).addEvent(TEST_PACKAGE_NAME1, 500L, Event.MOVE_TO_FOREGROUND);
    108     shadowOf(usageStatsManager).addEvent(TEST_PACKAGE_NAME1, 1000L, Event.MOVE_TO_BACKGROUND);
    109     shadowOf(usageStatsManager)
    110         .addEvent(
    111             ShadowUsageStatsManager.EventBuilder.buildEvent()
    112                 .setTimeStamp(1500L)
    113                 .setPackage(TEST_PACKAGE_NAME2)
    114                 .setClass(TEST_ACTIVITY_NAME)
    115                 .setEventType(Event.MOVE_TO_FOREGROUND)
    116                 .build());
    117     shadowOf(usageStatsManager).addEvent(TEST_PACKAGE_NAME2, 2000L, Event.MOVE_TO_BACKGROUND);
    118     shadowOf(usageStatsManager)
    119         .addEvent(
    120             ShadowUsageStatsManager.EventBuilder.buildEvent()
    121                 .setTimeStamp(2500L)
    122                 .setPackage(TEST_PACKAGE_NAME1)
    123                 .setEventType(Event.MOVE_TO_FOREGROUND)
    124                 .setClass(TEST_ACTIVITY_NAME)
    125                 .build());
    126     shadowOf(usageStatsManager).simulateTimeChange(10000L);
    127 
    128     UsageEvents events = usageStatsManager.queryEvents(11000L, 12000L);
    129     Event event = new Event();
    130 
    131     assertThat(events.hasNextEvent()).isTrue();
    132     assertThat(events.getNextEvent(event)).isTrue();
    133     assertThat(event.getPackageName()).isEqualTo(TEST_PACKAGE_NAME1);
    134     assertThat(event.getTimeStamp()).isEqualTo(11000L);
    135     assertThat(event.getEventType()).isEqualTo(Event.MOVE_TO_BACKGROUND);
    136 
    137     assertThat(events.hasNextEvent()).isTrue();
    138     assertThat(events.getNextEvent(event)).isTrue();
    139     assertThat(event.getPackageName()).isEqualTo(TEST_PACKAGE_NAME2);
    140     assertThat(event.getTimeStamp()).isEqualTo(11500L);
    141     assertThat(event.getEventType()).isEqualTo(Event.MOVE_TO_FOREGROUND);
    142     assertThat(event.getClassName()).isEqualTo(TEST_ACTIVITY_NAME);
    143 
    144     assertThat(events.hasNextEvent()).isFalse();
    145     assertThat(events.getNextEvent(event)).isFalse();
    146   }
    147 
    148   @Test
    149   @Config(minSdk = Build.VERSION_CODES.P)
    150   public void testGetAppStandbyBucket_withPackageName() throws Exception {
    151     assertThat(shadowOf(usageStatsManager).getAppStandbyBuckets()).isEmpty();
    152 
    153     shadowOf(usageStatsManager).setAppStandbyBucket("app1", UsageStatsManager.STANDBY_BUCKET_RARE);
    154     assertThat(shadowOf(usageStatsManager).getAppStandbyBucket("app1"))
    155         .isEqualTo(UsageStatsManager.STANDBY_BUCKET_RARE);
    156     assertThat(shadowOf(usageStatsManager).getAppStandbyBuckets().keySet()).containsExactly("app1");
    157     assertThat(shadowOf(usageStatsManager).getAppStandbyBuckets().get("app1"))
    158         .isEqualTo(UsageStatsManager.STANDBY_BUCKET_RARE);
    159 
    160     assertThat(shadowOf(usageStatsManager).getAppStandbyBucket("app_unset"))
    161         .isEqualTo(UsageStatsManager.STANDBY_BUCKET_ACTIVE);
    162   }
    163 
    164   @Test
    165   @Config(minSdk = Build.VERSION_CODES.P)
    166   public void testSetAppStandbyBuckets() throws Exception {
    167     assertThat(shadowOf(usageStatsManager).getAppStandbyBuckets()).isEmpty();
    168     assertThat(shadowOf(usageStatsManager).getAppStandbyBucket("app1"))
    169         .isEqualTo(UsageStatsManager.STANDBY_BUCKET_ACTIVE);
    170 
    171     Map<String, Integer> appBuckets =
    172         Collections.singletonMap("app1", UsageStatsManager.STANDBY_BUCKET_RARE);
    173     shadowOf(usageStatsManager).setAppStandbyBuckets(appBuckets);
    174 
    175     assertThat(shadowOf(usageStatsManager).getAppStandbyBuckets()).isEqualTo(appBuckets);
    176     assertThat(shadowOf(usageStatsManager).getAppStandbyBucket("app1"))
    177         .isEqualTo(UsageStatsManager.STANDBY_BUCKET_RARE);
    178   }
    179 
    180   @Test
    181   @Config(minSdk = Build.VERSION_CODES.P)
    182   public void testGetAppStandbyBucket_currentApp() throws Exception {
    183     shadowOf(usageStatsManager).setCurrentAppStandbyBucket(UsageStatsManager.STANDBY_BUCKET_RARE);
    184     assertThat(shadowOf(usageStatsManager).getAppStandbyBucket())
    185         .isEqualTo(UsageStatsManager.STANDBY_BUCKET_RARE);
    186     ShadowUsageStatsManager.reset();
    187     assertThat(shadowOf(usageStatsManager).getAppStandbyBucket())
    188         .isEqualTo(UsageStatsManager.STANDBY_BUCKET_ACTIVE);
    189   }
    190 
    191   @Test
    192   @Config(minSdk = Build.VERSION_CODES.P)
    193   public void testRegisterAppUsageObserver_uniqueObserverIds_shouldAddBothObservers() {
    194     PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION1"), 0);
    195     usageStatsManager.registerAppUsageObserver(
    196         12, new String[] {"com.package1", "com.package2"}, 123L, TimeUnit.MINUTES, pendingIntent1);
    197     PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION2"), 0);
    198     usageStatsManager.registerAppUsageObserver(
    199         24, new String[] {"com.package3"}, 456L, TimeUnit.SECONDS, pendingIntent2);
    200 
    201     assertThat(shadowOf(usageStatsManager).getRegisteredAppUsageObservers())
    202         .containsExactly(
    203             new AppUsageObserver(
    204                 12,
    205                 ImmutableList.of("com.package1", "com.package2"),
    206                 123L,
    207                 TimeUnit.MINUTES,
    208                 pendingIntent1),
    209             new AppUsageObserver(
    210                 24, ImmutableList.of("com.package3"), 456L, TimeUnit.SECONDS, pendingIntent2));
    211   }
    212 
    213   @Test
    214   @Config(minSdk = Build.VERSION_CODES.P)
    215   public void testRegisterAppUsageObserver_duplicateObserverIds_shouldOverrideExistingObserver() {
    216     PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION1"), 0);
    217     usageStatsManager.registerAppUsageObserver(
    218         12, new String[] {"com.package1", "com.package2"}, 123L, TimeUnit.MINUTES, pendingIntent1);
    219     PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION2"), 0);
    220     usageStatsManager.registerAppUsageObserver(
    221         12, new String[] {"com.package3"}, 456L, TimeUnit.SECONDS, pendingIntent2);
    222 
    223     assertThat(shadowOf(usageStatsManager).getRegisteredAppUsageObservers())
    224         .containsExactly(
    225             new AppUsageObserver(
    226                 12, ImmutableList.of("com.package3"), 456L, TimeUnit.SECONDS, pendingIntent2));
    227   }
    228 
    229   @Test
    230   @Config(minSdk = Build.VERSION_CODES.P)
    231   public void testUnregisterAppUsageObserver_existingObserverId_shouldRemoveObserver() {
    232     PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION1"), 0);
    233     usageStatsManager.registerAppUsageObserver(
    234         12, new String[] {"com.package1", "com.package2"}, 123L, TimeUnit.MINUTES, pendingIntent1);
    235     PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION2"), 0);
    236     usageStatsManager.registerAppUsageObserver(
    237         24, new String[] {"com.package3"}, 456L, TimeUnit.SECONDS, pendingIntent2);
    238 
    239     usageStatsManager.unregisterAppUsageObserver(12);
    240 
    241     assertThat(shadowOf(usageStatsManager).getRegisteredAppUsageObservers())
    242         .containsExactly(
    243             new AppUsageObserver(
    244                 24, ImmutableList.of("com.package3"), 456L, TimeUnit.SECONDS, pendingIntent2));
    245   }
    246 
    247   @Test
    248   @Config(minSdk = Build.VERSION_CODES.P)
    249   public void testUnregisterAppUsageObserver_nonExistentObserverId_shouldBeNoOp() {
    250     PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION1"), 0);
    251     usageStatsManager.registerAppUsageObserver(
    252         12, new String[] {"com.package1", "com.package2"}, 123L, TimeUnit.MINUTES, pendingIntent1);
    253     PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION2"), 0);
    254     usageStatsManager.registerAppUsageObserver(
    255         24, new String[] {"com.package3"}, 456L, TimeUnit.SECONDS, pendingIntent2);
    256 
    257     usageStatsManager.unregisterAppUsageObserver(36);
    258 
    259     assertThat(shadowOf(usageStatsManager).getRegisteredAppUsageObservers())
    260         .containsExactly(
    261             new AppUsageObserver(
    262                 12,
    263                 ImmutableList.of("com.package1", "com.package2"),
    264                 123L,
    265                 TimeUnit.MINUTES,
    266                 pendingIntent1),
    267             new AppUsageObserver(
    268                 24, ImmutableList.of("com.package3"), 456L, TimeUnit.SECONDS, pendingIntent2));
    269   }
    270 
    271   @Test
    272   @Config(minSdk = Build.VERSION_CODES.P)
    273   public void testTriggerRegisteredAppUsageObserver_shouldSendIntentAndRemoveObserver() {
    274     PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION1"), 0);
    275     usageStatsManager.registerAppUsageObserver(
    276         12, new String[] {"com.package1", "com.package2"}, 123L, TimeUnit.MINUTES, pendingIntent1);
    277     PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, new Intent("ACTION2"), 0);
    278     usageStatsManager.registerAppUsageObserver(
    279         24, new String[] {"com.package3"}, 456L, TimeUnit.SECONDS, pendingIntent2);
    280 
    281     shadowOf(usageStatsManager).triggerRegisteredAppUsageObserver(24, 500000L);
    282 
    283     List<Intent> broadcastIntents = shadowOf(context).getBroadcastIntents();
    284     assertThat(broadcastIntents).hasSize(1);
    285     Intent broadcastIntent = broadcastIntents.get(0);
    286     assertThat(broadcastIntent.getAction()).isEqualTo("ACTION2");
    287     assertThat(broadcastIntent.getIntExtra(UsageStatsManager.EXTRA_OBSERVER_ID, 0)).isEqualTo(24);
    288     assertThat(broadcastIntent.getLongExtra(UsageStatsManager.EXTRA_TIME_LIMIT, 0))
    289         .isEqualTo(456000L);
    290     assertThat(broadcastIntent.getLongExtra(UsageStatsManager.EXTRA_TIME_USED, 0))
    291         .isEqualTo(500000L);
    292     assertThat(shadowOf(usageStatsManager).getRegisteredAppUsageObservers())
    293         .containsExactly(
    294             new AppUsageObserver(
    295                 12,
    296                 ImmutableList.of("com.package1", "com.package2"),
    297                 123L,
    298                 TimeUnit.MINUTES,
    299                 pendingIntent1));
    300   }
    301 
    302   @Test
    303   public void queryUsageStats_noStatsAdded() {
    304     List<UsageStats> results = usageStatsManager.queryUsageStats(INTERVAL_WEEKLY, 0, 3000);
    305     assertThat(results).isEmpty();
    306   }
    307 
    308   @Test
    309   public void queryUsageStats() {
    310     UsageStats usageStats1 = newUsageStats(TEST_PACKAGE_NAME1, 0, 1000);
    311     UsageStats usageStats2 = newUsageStats(TEST_PACKAGE_NAME1, 1001, 2000);
    312     UsageStats usageStats3 = newUsageStats(TEST_PACKAGE_NAME1, 2001, 3000);
    313     UsageStats usageStats4 = newUsageStats(TEST_PACKAGE_NAME1, 3001, 4000);
    314     shadowOf(usageStatsManager).addUsageStats(INTERVAL_WEEKLY, usageStats1);
    315     shadowOf(usageStatsManager).addUsageStats(INTERVAL_WEEKLY, usageStats2);
    316     shadowOf(usageStatsManager).addUsageStats(INTERVAL_WEEKLY, usageStats3);
    317     shadowOf(usageStatsManager).addUsageStats(INTERVAL_WEEKLY, usageStats4);
    318     // Query fully covers usageStats 2 and 3, and partially overlaps with 4.
    319     List<UsageStats> results = usageStatsManager.queryUsageStats(INTERVAL_WEEKLY, 1001, 3500);
    320     assertThat(results).containsExactly(usageStats2, usageStats3, usageStats4);
    321   }
    322 
    323   @Test
    324   public void queryUsageStats_multipleIntervalTypes() {
    325     // Weekly data.
    326     UsageStats usageStats1 = newUsageStats(TEST_PACKAGE_NAME1, 1000, 2000);
    327     UsageStats usageStats2 = newUsageStats(TEST_PACKAGE_NAME1, 2001, 3000);
    328     shadowOf(usageStatsManager).addUsageStats(INTERVAL_WEEKLY, usageStats1);
    329     shadowOf(usageStatsManager).addUsageStats(INTERVAL_WEEKLY, usageStats2);
    330 
    331     // Daily data.
    332     UsageStats usageStats3 = newUsageStats(TEST_PACKAGE_NAME1, 2001, 3000);
    333     shadowOf(usageStatsManager).addUsageStats(INTERVAL_DAILY, usageStats3);
    334 
    335     List<UsageStats> results = usageStatsManager.queryUsageStats(INTERVAL_WEEKLY, 0, 3000);
    336     assertThat(results).containsExactly(usageStats1, usageStats2);
    337     results = usageStatsManager.queryUsageStats(INTERVAL_DAILY, 0, 3000);
    338     assertThat(results).containsExactly(usageStats3);
    339   }
    340 
    341   private UsageStats newUsageStats(String packageName, long firstTimeStamp, long lastTimeStamp) {
    342     return UsageStatsBuilder.newBuilder()
    343         .setPackageName(packageName)
    344         .setFirstTimeStamp(firstTimeStamp)
    345         .setLastTimeStamp(lastTimeStamp)
    346         .build();
    347   }
    348 
    349   @Test
    350   public void usageStatsBuilder_noFieldsSet() {
    351     UsageStats usage =
    352         UsageStatsBuilder.newBuilder()
    353             // Don't set any fields; the object should still build.
    354             .build();
    355     assertThat(usage.getPackageName()).isNull();
    356     assertThat(usage.getFirstTimeStamp()).isEqualTo(0);
    357     assertThat(usage.getLastTimeStamp()).isEqualTo(0);
    358     assertThat(usage.getLastTimeUsed()).isEqualTo(0);
    359     assertThat(usage.getTotalTimeInForeground()).isEqualTo(0);
    360   }
    361 
    362   @Test
    363   public void usageStatsBuilder() {
    364     long firstTimestamp = 1_500_000_000_000L;
    365     long lastTimestamp = firstTimestamp + 10000;
    366     long lastTimeUsed = firstTimestamp + 100;
    367     long totalTimeInForeground = HOURS.toMillis(10);
    368 
    369     UsageStats usage =
    370         UsageStatsBuilder.newBuilder()
    371             // Set all fields
    372             .setPackageName(TEST_PACKAGE_NAME1)
    373             .setFirstTimeStamp(firstTimestamp)
    374             .setLastTimeStamp(lastTimestamp)
    375             .setLastTimeUsed(lastTimeUsed)
    376             .setTotalTimeInForeground(totalTimeInForeground)
    377             .build();
    378     assertThat(usage.getPackageName()).isEqualTo(TEST_PACKAGE_NAME1);
    379     assertThat(usage.getFirstTimeStamp()).isEqualTo(firstTimestamp);
    380     assertThat(usage.getLastTimeStamp()).isEqualTo(lastTimestamp);
    381     assertThat(usage.getLastTimeUsed()).isEqualTo(lastTimeUsed);
    382     assertThat(usage.getTotalTimeInForeground()).isEqualTo(totalTimeInForeground);
    383   }
    384 }
    385