ModuleInfo#isHidden is used for getting hidden module status from ModuleMetadata package (Mainline). It was set to hide Mainline modules' Apk to show in the Settings UI and this has caused the issue as it disallowed the user to toggle permissions where it was needed. Thus, we decided to deprecate the usage of ModuleInfo#isHidden (see go/aml-hidden-modules-permissions). Bug: 379056868 Test: unittest Test: check behavior before/after enable flags Flag: android.content.pm.remove_hidden_module_usage Change-Id: I670c95350e3c21db9f74f37b675aba1b23c67a61
550 lines
24 KiB
Java
550 lines
24 KiB
Java
/*
|
|
* Copyright (C) 2019 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.applications;
|
|
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.anyInt;
|
|
import static org.mockito.ArgumentMatchers.anyLong;
|
|
import static org.mockito.ArgumentMatchers.anyString;
|
|
import static org.mockito.Mockito.doReturn;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.spy;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
import android.app.usage.UsageStats;
|
|
import android.app.usage.UsageStatsManager;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.pm.ApplicationInfo;
|
|
import android.content.pm.ModuleInfo;
|
|
import android.content.pm.PackageManager;
|
|
import android.content.pm.ResolveInfo;
|
|
import android.os.PowerManager;
|
|
import android.os.UserHandle;
|
|
import android.os.UserManager;
|
|
import android.platform.test.annotations.DisableFlags;
|
|
import android.platform.test.annotations.EnableFlags;
|
|
import android.platform.test.flag.junit.SetFlagsRule;
|
|
|
|
import com.android.settingslib.applications.AppUtils;
|
|
import com.android.settingslib.applications.ApplicationsState;
|
|
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
|
|
|
|
import org.junit.Before;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.mockito.Mock;
|
|
import org.mockito.MockitoAnnotations;
|
|
import org.robolectric.RobolectricTestRunner;
|
|
import org.robolectric.RuntimeEnvironment;
|
|
import org.robolectric.util.ReflectionHelpers;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
@RunWith(RobolectricTestRunner.class)
|
|
public class RecentAppStatsMixinTest {
|
|
|
|
private static final UserHandle NORMAL_USER = UserHandle.SYSTEM;
|
|
private static final UserHandle CLONE_USER = new UserHandle(2222);
|
|
private static final UserHandle WORK_USER = new UserHandle(3333);
|
|
|
|
@Mock
|
|
private UsageStatsManager mUsageStatsManager;
|
|
@Mock
|
|
private UsageStatsManager mWorkUsageStatsManager;
|
|
@Mock
|
|
private UserManager mUserManager;
|
|
@Mock
|
|
private ApplicationsState mAppState;
|
|
@Mock
|
|
private PackageManager mPackageManager;
|
|
@Mock
|
|
private ApplicationsState.AppEntry mAppEntry;
|
|
@Mock
|
|
private ApplicationInfo mApplicationInfo;
|
|
@Mock
|
|
private PowerManager mPowerManager;
|
|
@Mock
|
|
private UsageStatsManager mCloneUsageStatsManager;
|
|
@Mock
|
|
Context mMockContext;
|
|
|
|
private Context mContext;
|
|
|
|
private RecentAppStatsMixin mRecentAppStatsMixin;
|
|
|
|
@Rule
|
|
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
|
|
|
@Before
|
|
public void setUp() throws PackageManager.NameNotFoundException {
|
|
MockitoAnnotations.initMocks(this);
|
|
mContext = spy(RuntimeEnvironment.application);
|
|
when(mContext.getApplicationContext()).thenReturn(mContext);
|
|
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mAppState);
|
|
doReturn(mUsageStatsManager).when(mContext).getSystemService(UsageStatsManager.class);
|
|
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
|
|
doReturn(mPackageManager).when(mContext).getPackageManager();
|
|
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
|
|
when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
|
|
|
|
doReturn(mMockContext).when(mContext).createContextAsUser(any(), anyInt());
|
|
doReturn(mMockContext).when(mContext).createPackageContextAsUser(any(), anyInt(), any());
|
|
when(mUserManager.getUserProfiles())
|
|
.thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER)));
|
|
|
|
mRecentAppStatsMixin = new RecentAppStatsMixin(mContext, 3 /* maximumApps */);
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_oneValidRecentAppSet_shouldHaveOneRecentApp() {
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
final UsageStats stat1 = new UsageStats();
|
|
stat1.mLastTimeUsed = System.currentTimeMillis();
|
|
stat1.mPackageName = "pkg.class";
|
|
stats.add(stat1);
|
|
// stat1 is valid app.
|
|
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
mAppEntry.info = mApplicationInfo;
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_threeValidRecentAppsSet_shouldHaveThreeRecentApps() {
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
final UsageStats stat1 = new UsageStats();
|
|
final UsageStats stat2 = new UsageStats();
|
|
final UsageStats stat3 = new UsageStats();
|
|
stat1.mLastTimeUsed = System.currentTimeMillis();
|
|
stat1.mPackageName = "pkg.class";
|
|
stats.add(stat1);
|
|
|
|
stat2.mLastTimeUsed = System.currentTimeMillis();
|
|
stat2.mPackageName = "pkg.class2";
|
|
stats.add(stat2);
|
|
|
|
stat3.mLastTimeUsed = System.currentTimeMillis();
|
|
stat3.mPackageName = "pkg.class3";
|
|
stats.add(stat3);
|
|
|
|
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
mAppEntry.info = mApplicationInfo;
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(3);
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_oneValidAndTwoInvalidSet_shouldHaveOneRecentApp() {
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
final UsageStats stat1 = new UsageStats();
|
|
final UsageStats stat2 = new UsageStats();
|
|
final UsageStats stat3 = new UsageStats();
|
|
stat1.mLastTimeUsed = System.currentTimeMillis();
|
|
stat1.mPackageName = "pkg.class";
|
|
stats.add(stat1);
|
|
|
|
stat2.mLastTimeUsed = System.currentTimeMillis();
|
|
stat2.mPackageName = "com.android.settings";
|
|
stats.add(stat2);
|
|
|
|
stat3.mLastTimeUsed = System.currentTimeMillis();
|
|
stat3.mPackageName = "pkg.class3";
|
|
stats.add(stat3);
|
|
|
|
// stat1, stat2 are valid apps. stat3 is invalid.
|
|
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(null);
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
mAppEntry.info = mApplicationInfo;
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
// Only stat1. stat2 is skipped because of the package name, stat3 skipped because
|
|
// it's invalid app.
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_oneInstantAppSet_shouldHaveOneRecentApp() {
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
// Instant app.
|
|
final UsageStats stat = new UsageStats();
|
|
stat.mLastTimeUsed = System.currentTimeMillis() + 200;
|
|
stat.mPackageName = "com.foo.barinstant";
|
|
stats.add(stat);
|
|
|
|
ApplicationsState.AppEntry statEntry = mock(ApplicationsState.AppEntry.class);
|
|
statEntry.info = mApplicationInfo;
|
|
|
|
when(mAppState.getEntry(stat.mPackageName, UserHandle.myUserId())).thenReturn(statEntry);
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
|
|
// Make sure stat is considered an instant app.
|
|
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
|
|
(InstantAppDataProvider) (ApplicationInfo info) -> info == statEntry.info);
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_withNullAppEntryOrInfo_shouldNotCrash() {
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
final UsageStats stat1 = new UsageStats();
|
|
final UsageStats stat2 = new UsageStats();
|
|
stat1.mLastTimeUsed = System.currentTimeMillis();
|
|
stat1.mPackageName = "pkg.class";
|
|
stats.add(stat1);
|
|
|
|
stat2.mLastTimeUsed = System.currentTimeMillis();
|
|
stat2.mPackageName = "pkg.class2";
|
|
stats.add(stat2);
|
|
|
|
// app1 has AppEntry with null info, app2 has null AppEntry.
|
|
mAppEntry.info = null;
|
|
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(null);
|
|
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
|
|
// We should not crash here.
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
}
|
|
|
|
@Test
|
|
@EnableFlags({android.content.pm.Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE})
|
|
public void loadDisplayableRecentApps_twoSystemModulesSet_shouldHaveTwoSystemModules() {
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
|
|
// System modules.
|
|
final UsageStats stat1 = new UsageStats();
|
|
stat1.mLastTimeUsed = System.currentTimeMillis();
|
|
stat1.mPackageName = "com.foo.module1";
|
|
stats.add(stat1);
|
|
|
|
final UsageStats stat2 = new UsageStats();
|
|
stat2.mLastTimeUsed = System.currentTimeMillis() + 200;
|
|
stat2.mPackageName = "com.foo.module2";
|
|
stats.add(stat2);
|
|
|
|
ApplicationsState.AppEntry stat1Entry = mock(ApplicationsState.AppEntry.class);
|
|
ApplicationsState.AppEntry stat2Entry = mock(ApplicationsState.AppEntry.class);
|
|
stat1Entry.info = mApplicationInfo;
|
|
stat2Entry.info = mApplicationInfo;
|
|
|
|
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())).thenReturn(stat1Entry);
|
|
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())).thenReturn(stat2Entry);
|
|
|
|
// Hidden status set to false and true, but they should not cause the difference in
|
|
// the behavior.
|
|
final ModuleInfo moduleInfo1 = new ModuleInfo();
|
|
moduleInfo1.setPackageName(stat1.mPackageName);
|
|
moduleInfo1.setHidden(false);
|
|
|
|
final ModuleInfo moduleInfo2 = new ModuleInfo();
|
|
moduleInfo2.setPackageName(stat2.mPackageName);
|
|
moduleInfo2.setHidden(true);
|
|
|
|
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null);
|
|
final List<ModuleInfo> modules = new ArrayList<>();
|
|
modules.add(moduleInfo1);
|
|
modules.add(moduleInfo2);
|
|
when(mPackageManager.getInstalledModules(anyInt() /* flags */))
|
|
.thenReturn(modules);
|
|
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(2);
|
|
}
|
|
|
|
// TODO(b/382016780): to be removed after flag cleanup.
|
|
@Test
|
|
@DisableFlags({android.content.pm.Flags.FLAG_REMOVE_HIDDEN_MODULE_USAGE})
|
|
public void loadDisplayableRecentApps_hiddenSystemModuleSet_shouldNotHaveHiddenSystemModule() {
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
// Regular app.
|
|
final UsageStats stat1 = new UsageStats();
|
|
stat1.mLastTimeUsed = System.currentTimeMillis();
|
|
stat1.mPackageName = "com.foo.bar";
|
|
stats.add(stat1);
|
|
|
|
// Hidden system module.
|
|
final UsageStats stat2 = new UsageStats();
|
|
stat2.mLastTimeUsed = System.currentTimeMillis() + 200;
|
|
stat2.mPackageName = "com.foo.hidden";
|
|
stats.add(stat2);
|
|
|
|
ApplicationsState.AppEntry stat1Entry = mock(ApplicationsState.AppEntry.class);
|
|
ApplicationsState.AppEntry stat2Entry = mock(ApplicationsState.AppEntry.class);
|
|
stat1Entry.info = mApplicationInfo;
|
|
stat2Entry.info = mApplicationInfo;
|
|
|
|
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())).thenReturn(stat1Entry);
|
|
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())).thenReturn(stat2Entry);
|
|
|
|
final ModuleInfo moduleInfo1 = new ModuleInfo();
|
|
moduleInfo1.setPackageName(stat1.mPackageName);
|
|
moduleInfo1.setHidden(false);
|
|
|
|
final ModuleInfo moduleInfo2 = new ModuleInfo();
|
|
moduleInfo2.setPackageName(stat2.mPackageName);
|
|
moduleInfo2.setHidden(true);
|
|
|
|
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null);
|
|
final List<ModuleInfo> modules = new ArrayList<>();
|
|
modules.add(moduleInfo2);
|
|
when(mPackageManager.getInstalledModules(anyInt() /* flags */))
|
|
.thenReturn(modules);
|
|
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_powerSaverModeOn_shouldHaveEmptyList() {
|
|
when(mPowerManager.isPowerSaveMode()).thenReturn(true);
|
|
|
|
final List<UsageStats> stats = new ArrayList<>();
|
|
final UsageStats stat1 = new UsageStats();
|
|
|
|
stat1.mLastTimeUsed = System.currentTimeMillis();
|
|
stat1.mPackageName = "pkg.class";
|
|
stats.add(stat1);
|
|
|
|
// stat1, stat2 are valid apps. stat3 is invalid.
|
|
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
|
|
.thenReturn(mAppEntry);
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(stats);
|
|
mAppEntry.info = mApplicationInfo;
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps).isEmpty();
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_usePersonalAndWorkApps_shouldBeSortedByLastTimeUse() {
|
|
final List<UsageStats> personalStats = new ArrayList<>();
|
|
final UsageStats stats1 = new UsageStats();
|
|
final UsageStats stats2 = new UsageStats();
|
|
stats1.mLastTimeUsed = System.currentTimeMillis();
|
|
stats1.mPackageName = "personal.pkg.class";
|
|
personalStats.add(stats1);
|
|
|
|
stats2.mLastTimeUsed = System.currentTimeMillis() - 5000;
|
|
stats2.mPackageName = "personal.pkg.class2";
|
|
personalStats.add(stats2);
|
|
|
|
final List<UsageStats> workStats = new ArrayList<>();
|
|
final UsageStats stat3 = new UsageStats();
|
|
stat3.mLastTimeUsed = System.currentTimeMillis() - 2000;
|
|
stat3.mPackageName = "work.pkg.class3";
|
|
workStats.add(stat3);
|
|
|
|
when(mAppState.getEntry(anyString(), anyInt()))
|
|
.thenReturn(mAppEntry);
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
when(mUserManager.getUserProfiles())
|
|
.thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER, WORK_USER)));
|
|
when(mMockContext.getSystemService(UsageStatsManager.class))
|
|
.thenReturn(mWorkUsageStatsManager);
|
|
// personal app stats
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(personalStats);
|
|
// work app stats
|
|
when(mWorkUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(workStats);
|
|
mAppEntry.info = mApplicationInfo;
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(3);
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(0).mUsageStats.mPackageName).isEqualTo(
|
|
"personal.pkg.class");
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(1).mUsageStats.mPackageName).isEqualTo(
|
|
"work.pkg.class3");
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(2).mUsageStats.mPackageName).isEqualTo(
|
|
"personal.pkg.class2");
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_usePersonalAndWorkApps_shouldBeUniquePerProfile()
|
|
throws PackageManager.NameNotFoundException {
|
|
final String firstAppPackageName = "app1.pkg.class";
|
|
final String secondAppPackageName = "app2.pkg.class";
|
|
final List<UsageStats> personalStats = new ArrayList<>();
|
|
final UsageStats personalStatsFirstApp = new UsageStats();
|
|
final UsageStats personalStatsFirstAppOlderUse = new UsageStats();
|
|
final UsageStats personalStatsSecondApp = new UsageStats();
|
|
personalStatsFirstApp.mLastTimeUsed = System.currentTimeMillis();
|
|
personalStatsFirstApp.mPackageName = firstAppPackageName;
|
|
personalStats.add(personalStatsFirstApp);
|
|
|
|
personalStatsFirstAppOlderUse.mLastTimeUsed = System.currentTimeMillis() - 5000;
|
|
personalStatsFirstAppOlderUse.mPackageName = firstAppPackageName;
|
|
personalStats.add(personalStatsFirstAppOlderUse);
|
|
|
|
personalStatsSecondApp.mLastTimeUsed = System.currentTimeMillis() - 2000;
|
|
personalStatsSecondApp.mPackageName = secondAppPackageName;
|
|
personalStats.add(personalStatsSecondApp);
|
|
|
|
final List<UsageStats> workStats = new ArrayList<>();
|
|
final UsageStats workStatsSecondApp = new UsageStats();
|
|
workStatsSecondApp.mLastTimeUsed = System.currentTimeMillis() - 1000;
|
|
workStatsSecondApp.mPackageName = secondAppPackageName;
|
|
workStats.add(workStatsSecondApp);
|
|
|
|
when(mAppState.getEntry(anyString(), anyInt()))
|
|
.thenReturn(mAppEntry);
|
|
when(mUserManager.getUserProfiles())
|
|
.thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER, WORK_USER)));
|
|
when(mMockContext.getSystemService(UsageStatsManager.class))
|
|
.thenReturn(mWorkUsageStatsManager);
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
// personal app stats
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(personalStats);
|
|
// work app stats
|
|
when(mWorkUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(workStats);
|
|
mAppEntry.info = mApplicationInfo;
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(3);
|
|
|
|
// The output should have the first app once since the duplicate use in the personal profile
|
|
// is filtered out, and the second app twice - once for each profile.
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(3);
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(0).mUsageStats.mPackageName).isEqualTo(
|
|
firstAppPackageName);
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(1).mUsageStats.mPackageName).isEqualTo(
|
|
secondAppPackageName);
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(2).mUsageStats.mPackageName).isEqualTo(
|
|
secondAppPackageName);
|
|
}
|
|
|
|
@Test
|
|
public void loadDisplayableRecentApps_multipleProfileApps_shouldBeSortedByLastTimeUse()
|
|
throws PackageManager.NameNotFoundException {
|
|
final List<UsageStats> personalStats = new ArrayList<>();
|
|
final UsageStats stats1 = new UsageStats();
|
|
final UsageStats stats2 = new UsageStats();
|
|
stats1.mLastTimeUsed = System.currentTimeMillis();
|
|
stats1.mPackageName = "personal.pkg.class";
|
|
personalStats.add(stats1);
|
|
|
|
stats2.mLastTimeUsed = System.currentTimeMillis() - 5000;
|
|
stats2.mPackageName = "personal.pkg.class2";
|
|
personalStats.add(stats2);
|
|
|
|
final List<UsageStats> workStats = new ArrayList<>();
|
|
final UsageStats stat3 = new UsageStats();
|
|
stat3.mLastTimeUsed = System.currentTimeMillis() - 2000;
|
|
stat3.mPackageName = "work.pkg.class3";
|
|
workStats.add(stat3);
|
|
|
|
final List<UsageStats> cloneStats = new ArrayList<>();
|
|
final UsageStats stat4 = new UsageStats();
|
|
stat4.mLastTimeUsed = System.currentTimeMillis() - 1000;
|
|
stat4.mPackageName = "clone.pkg.class4";
|
|
cloneStats.add(stat4);
|
|
|
|
when(mAppState.getEntry(anyString(), anyInt()))
|
|
.thenReturn(mAppEntry);
|
|
when(mUserManager.getUserProfiles())
|
|
.thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER, CLONE_USER, WORK_USER)));
|
|
when(mMockContext.getSystemService(UsageStatsManager.class))
|
|
.thenReturn(mCloneUsageStatsManager, mWorkUsageStatsManager);
|
|
when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt()))
|
|
.thenReturn(new ResolveInfo());
|
|
// personal app stats
|
|
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(personalStats);
|
|
// work app stats
|
|
when(mWorkUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(workStats);
|
|
// clone app stats
|
|
when(mCloneUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
|
|
.thenReturn(cloneStats);
|
|
|
|
mAppEntry.info = mApplicationInfo;
|
|
|
|
mRecentAppStatsMixin.loadDisplayableRecentApps(4);
|
|
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(4);
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(0).mUsageStats.mPackageName).isEqualTo(
|
|
"personal.pkg.class");
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(1).mUsageStats.mPackageName).isEqualTo(
|
|
"clone.pkg.class4");
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(2).mUsageStats.mPackageName).isEqualTo(
|
|
"work.pkg.class3");
|
|
assertThat(mRecentAppStatsMixin.mRecentApps.get(3).mUsageStats.mPackageName).isEqualTo(
|
|
"personal.pkg.class2");
|
|
}
|
|
}
|