1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.applications; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.anyLong; 24 import static org.mockito.ArgumentMatchers.anyString; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.spy; 28 import static org.mockito.Mockito.when; 29 30 import android.app.usage.UsageStats; 31 import android.app.usage.UsageStatsManager; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.pm.ApplicationInfo; 35 import android.content.pm.ModuleInfo; 36 import android.content.pm.PackageManager; 37 import android.content.pm.ResolveInfo; 38 import android.os.PowerManager; 39 import android.os.UserHandle; 40 import android.os.UserManager; 41 42 import com.android.settingslib.applications.AppUtils; 43 import com.android.settingslib.applications.ApplicationsState; 44 import com.android.settingslib.applications.instantapps.InstantAppDataProvider; 45 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.Mock; 50 import org.mockito.MockitoAnnotations; 51 import org.robolectric.RobolectricTestRunner; 52 import org.robolectric.RuntimeEnvironment; 53 import org.robolectric.util.ReflectionHelpers; 54 55 import java.util.ArrayList; 56 import java.util.Arrays; 57 import java.util.List; 58 59 @RunWith(RobolectricTestRunner.class) 60 public class RecentAppStatsMixinTest { 61 62 private static final UserHandle NORMAL_USER = UserHandle.SYSTEM; 63 private static final UserHandle CLONE_USER = new UserHandle(2222); 64 private static final UserHandle WORK_USER = new UserHandle(3333); 65 66 @Mock 67 private UsageStatsManager mUsageStatsManager; 68 @Mock 69 private UsageStatsManager mWorkUsageStatsManager; 70 @Mock 71 private UserManager mUserManager; 72 @Mock 73 private ApplicationsState mAppState; 74 @Mock 75 private PackageManager mPackageManager; 76 @Mock 77 private ApplicationsState.AppEntry mAppEntry; 78 @Mock 79 private ApplicationInfo mApplicationInfo; 80 @Mock 81 private PowerManager mPowerManager; 82 @Mock 83 private UsageStatsManager mCloneUsageStatsManager; 84 @Mock 85 Context mMockContext; 86 87 private Context mContext; 88 89 private RecentAppStatsMixin mRecentAppStatsMixin; 90 91 @Before setUp()92 public void setUp() throws PackageManager.NameNotFoundException { 93 MockitoAnnotations.initMocks(this); 94 mContext = spy(RuntimeEnvironment.application); 95 when(mContext.getApplicationContext()).thenReturn(mContext); 96 ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mAppState); 97 doReturn(mUsageStatsManager).when(mContext).getSystemService(UsageStatsManager.class); 98 doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE); 99 doReturn(mPackageManager).when(mContext).getPackageManager(); 100 doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class); 101 when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{}); 102 103 doReturn(mMockContext).when(mContext).createContextAsUser(any(), anyInt()); 104 doReturn(mMockContext).when(mContext).createPackageContextAsUser(any(), anyInt(), any()); 105 when(mUserManager.getUserProfiles()) 106 .thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER))); 107 108 mRecentAppStatsMixin = new RecentAppStatsMixin(mContext, 3 /* maximumApps */); 109 } 110 111 @Test loadDisplayableRecentApps_oneValidRecentAppSet_shouldHaveOneRecentApp()112 public void loadDisplayableRecentApps_oneValidRecentAppSet_shouldHaveOneRecentApp() { 113 final List<UsageStats> stats = new ArrayList<>(); 114 final UsageStats stat1 = new UsageStats(); 115 stat1.mLastTimeUsed = System.currentTimeMillis(); 116 stat1.mPackageName = "pkg.class"; 117 stats.add(stat1); 118 // stat1 is valid app. 119 when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())) 120 .thenReturn(mAppEntry); 121 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 122 .thenReturn(new ResolveInfo()); 123 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 124 .thenReturn(stats); 125 mAppEntry.info = mApplicationInfo; 126 127 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 128 129 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1); 130 } 131 132 @Test loadDisplayableRecentApps_threeValidRecentAppsSet_shouldHaveThreeRecentApps()133 public void loadDisplayableRecentApps_threeValidRecentAppsSet_shouldHaveThreeRecentApps() { 134 final List<UsageStats> stats = new ArrayList<>(); 135 final UsageStats stat1 = new UsageStats(); 136 final UsageStats stat2 = new UsageStats(); 137 final UsageStats stat3 = new UsageStats(); 138 stat1.mLastTimeUsed = System.currentTimeMillis(); 139 stat1.mPackageName = "pkg.class"; 140 stats.add(stat1); 141 142 stat2.mLastTimeUsed = System.currentTimeMillis(); 143 stat2.mPackageName = "pkg.class2"; 144 stats.add(stat2); 145 146 stat3.mLastTimeUsed = System.currentTimeMillis(); 147 stat3.mPackageName = "pkg.class3"; 148 stats.add(stat3); 149 150 when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())) 151 .thenReturn(mAppEntry); 152 when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())) 153 .thenReturn(mAppEntry); 154 when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId())) 155 .thenReturn(mAppEntry); 156 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 157 .thenReturn(new ResolveInfo()); 158 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 159 .thenReturn(stats); 160 mAppEntry.info = mApplicationInfo; 161 162 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 163 164 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(3); 165 } 166 167 @Test loadDisplayableRecentApps_oneValidAndTwoInvalidSet_shouldHaveOneRecentApp()168 public void loadDisplayableRecentApps_oneValidAndTwoInvalidSet_shouldHaveOneRecentApp() { 169 final List<UsageStats> stats = new ArrayList<>(); 170 final UsageStats stat1 = new UsageStats(); 171 final UsageStats stat2 = new UsageStats(); 172 final UsageStats stat3 = new UsageStats(); 173 stat1.mLastTimeUsed = System.currentTimeMillis(); 174 stat1.mPackageName = "pkg.class"; 175 stats.add(stat1); 176 177 stat2.mLastTimeUsed = System.currentTimeMillis(); 178 stat2.mPackageName = "com.android.settings"; 179 stats.add(stat2); 180 181 stat3.mLastTimeUsed = System.currentTimeMillis(); 182 stat3.mPackageName = "pkg.class3"; 183 stats.add(stat3); 184 185 // stat1, stat2 are valid apps. stat3 is invalid. 186 when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())) 187 .thenReturn(mAppEntry); 188 when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())) 189 .thenReturn(mAppEntry); 190 when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId())) 191 .thenReturn(null); 192 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 193 .thenReturn(new ResolveInfo()); 194 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 195 .thenReturn(stats); 196 mAppEntry.info = mApplicationInfo; 197 198 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 199 200 // Only stat1. stat2 is skipped because of the package name, stat3 skipped because 201 // it's invalid app. 202 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1); 203 } 204 205 @Test loadDisplayableRecentApps_oneInstantAppSet_shouldHaveOneRecentApp()206 public void loadDisplayableRecentApps_oneInstantAppSet_shouldHaveOneRecentApp() { 207 final List<UsageStats> stats = new ArrayList<>(); 208 // Instant app. 209 final UsageStats stat = new UsageStats(); 210 stat.mLastTimeUsed = System.currentTimeMillis() + 200; 211 stat.mPackageName = "com.foo.barinstant"; 212 stats.add(stat); 213 214 ApplicationsState.AppEntry statEntry = mock(ApplicationsState.AppEntry.class); 215 statEntry.info = mApplicationInfo; 216 217 when(mAppState.getEntry(stat.mPackageName, UserHandle.myUserId())).thenReturn(statEntry); 218 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 219 .thenReturn(stats); 220 221 // Make sure stat is considered an instant app. 222 ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", 223 (InstantAppDataProvider) (ApplicationInfo info) -> info == statEntry.info); 224 225 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 226 227 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1); 228 } 229 230 @Test loadDisplayableRecentApps_withNullAppEntryOrInfo_shouldNotCrash()231 public void loadDisplayableRecentApps_withNullAppEntryOrInfo_shouldNotCrash() { 232 final List<UsageStats> stats = new ArrayList<>(); 233 final UsageStats stat1 = new UsageStats(); 234 final UsageStats stat2 = new UsageStats(); 235 stat1.mLastTimeUsed = System.currentTimeMillis(); 236 stat1.mPackageName = "pkg.class"; 237 stats.add(stat1); 238 239 stat2.mLastTimeUsed = System.currentTimeMillis(); 240 stat2.mPackageName = "pkg.class2"; 241 stats.add(stat2); 242 243 // app1 has AppEntry with null info, app2 has null AppEntry. 244 mAppEntry.info = null; 245 when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())) 246 .thenReturn(mAppEntry); 247 when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())) 248 .thenReturn(null); 249 250 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 251 .thenReturn(stats); 252 253 // We should not crash here. 254 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 255 } 256 257 @Test loadDisplayableRecentApps_hiddenSystemModuleSet_shouldNotHaveHiddenSystemModule()258 public void loadDisplayableRecentApps_hiddenSystemModuleSet_shouldNotHaveHiddenSystemModule() { 259 final List<UsageStats> stats = new ArrayList<>(); 260 // Regular app. 261 final UsageStats stat1 = new UsageStats(); 262 stat1.mLastTimeUsed = System.currentTimeMillis(); 263 stat1.mPackageName = "com.foo.bar"; 264 stats.add(stat1); 265 266 // Hidden system module. 267 final UsageStats stat2 = new UsageStats(); 268 stat2.mLastTimeUsed = System.currentTimeMillis() + 200; 269 stat2.mPackageName = "com.foo.hidden"; 270 stats.add(stat2); 271 272 ApplicationsState.AppEntry stat1Entry = mock(ApplicationsState.AppEntry.class); 273 ApplicationsState.AppEntry stat2Entry = mock(ApplicationsState.AppEntry.class); 274 stat1Entry.info = mApplicationInfo; 275 stat2Entry.info = mApplicationInfo; 276 277 when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())).thenReturn(stat1Entry); 278 when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())).thenReturn(stat2Entry); 279 280 final ModuleInfo moduleInfo1 = new ModuleInfo(); 281 moduleInfo1.setPackageName(stat1.mPackageName); 282 moduleInfo1.setHidden(false); 283 284 final ModuleInfo moduleInfo2 = new ModuleInfo(); 285 moduleInfo2.setPackageName(stat2.mPackageName); 286 moduleInfo2.setHidden(true); 287 288 ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null); 289 final List<ModuleInfo> modules = new ArrayList<>(); 290 modules.add(moduleInfo2); 291 when(mPackageManager.getInstalledModules(anyInt() /* flags */)) 292 .thenReturn(modules); 293 294 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 295 .thenReturn(new ResolveInfo()); 296 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 297 .thenReturn(stats); 298 299 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 300 301 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1); 302 } 303 304 @Test loadDisplayableRecentApps_powerSaverModeOn_shouldHaveEmptyList()305 public void loadDisplayableRecentApps_powerSaverModeOn_shouldHaveEmptyList() { 306 when(mPowerManager.isPowerSaveMode()).thenReturn(true); 307 308 final List<UsageStats> stats = new ArrayList<>(); 309 final UsageStats stat1 = new UsageStats(); 310 311 stat1.mLastTimeUsed = System.currentTimeMillis(); 312 stat1.mPackageName = "pkg.class"; 313 stats.add(stat1); 314 315 // stat1, stat2 are valid apps. stat3 is invalid. 316 when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())) 317 .thenReturn(mAppEntry); 318 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 319 .thenReturn(new ResolveInfo()); 320 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 321 .thenReturn(stats); 322 mAppEntry.info = mApplicationInfo; 323 324 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 325 326 assertThat(mRecentAppStatsMixin.mRecentApps).isEmpty(); 327 } 328 329 @Test loadDisplayableRecentApps_usePersonalAndWorkApps_shouldBeSortedByLastTimeUse()330 public void loadDisplayableRecentApps_usePersonalAndWorkApps_shouldBeSortedByLastTimeUse() { 331 final List<UsageStats> personalStats = new ArrayList<>(); 332 final UsageStats stats1 = new UsageStats(); 333 final UsageStats stats2 = new UsageStats(); 334 stats1.mLastTimeUsed = System.currentTimeMillis(); 335 stats1.mPackageName = "personal.pkg.class"; 336 personalStats.add(stats1); 337 338 stats2.mLastTimeUsed = System.currentTimeMillis() - 5000; 339 stats2.mPackageName = "personal.pkg.class2"; 340 personalStats.add(stats2); 341 342 final List<UsageStats> workStats = new ArrayList<>(); 343 final UsageStats stat3 = new UsageStats(); 344 stat3.mLastTimeUsed = System.currentTimeMillis() - 2000; 345 stat3.mPackageName = "work.pkg.class3"; 346 workStats.add(stat3); 347 348 when(mAppState.getEntry(anyString(), anyInt())) 349 .thenReturn(mAppEntry); 350 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 351 .thenReturn(new ResolveInfo()); 352 when(mUserManager.getUserProfiles()) 353 .thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER, WORK_USER))); 354 when(mMockContext.getSystemService(UsageStatsManager.class)) 355 .thenReturn(mWorkUsageStatsManager); 356 // personal app stats 357 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 358 .thenReturn(personalStats); 359 // work app stats 360 when(mWorkUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 361 .thenReturn(workStats); 362 mAppEntry.info = mApplicationInfo; 363 364 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 365 366 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(3); 367 assertThat(mRecentAppStatsMixin.mRecentApps.get(0).mUsageStats.mPackageName).isEqualTo( 368 "personal.pkg.class"); 369 assertThat(mRecentAppStatsMixin.mRecentApps.get(1).mUsageStats.mPackageName).isEqualTo( 370 "work.pkg.class3"); 371 assertThat(mRecentAppStatsMixin.mRecentApps.get(2).mUsageStats.mPackageName).isEqualTo( 372 "personal.pkg.class2"); 373 } 374 375 @Test loadDisplayableRecentApps_usePersonalAndWorkApps_shouldBeUniquePerProfile()376 public void loadDisplayableRecentApps_usePersonalAndWorkApps_shouldBeUniquePerProfile() 377 throws PackageManager.NameNotFoundException { 378 final String firstAppPackageName = "app1.pkg.class"; 379 final String secondAppPackageName = "app2.pkg.class"; 380 final List<UsageStats> personalStats = new ArrayList<>(); 381 final UsageStats personalStatsFirstApp = new UsageStats(); 382 final UsageStats personalStatsFirstAppOlderUse = new UsageStats(); 383 final UsageStats personalStatsSecondApp = new UsageStats(); 384 personalStatsFirstApp.mLastTimeUsed = System.currentTimeMillis(); 385 personalStatsFirstApp.mPackageName = firstAppPackageName; 386 personalStats.add(personalStatsFirstApp); 387 388 personalStatsFirstAppOlderUse.mLastTimeUsed = System.currentTimeMillis() - 5000; 389 personalStatsFirstAppOlderUse.mPackageName = firstAppPackageName; 390 personalStats.add(personalStatsFirstAppOlderUse); 391 392 personalStatsSecondApp.mLastTimeUsed = System.currentTimeMillis() - 2000; 393 personalStatsSecondApp.mPackageName = secondAppPackageName; 394 personalStats.add(personalStatsSecondApp); 395 396 final List<UsageStats> workStats = new ArrayList<>(); 397 final UsageStats workStatsSecondApp = new UsageStats(); 398 workStatsSecondApp.mLastTimeUsed = System.currentTimeMillis() - 1000; 399 workStatsSecondApp.mPackageName = secondAppPackageName; 400 workStats.add(workStatsSecondApp); 401 402 when(mAppState.getEntry(anyString(), anyInt())) 403 .thenReturn(mAppEntry); 404 when(mUserManager.getUserProfiles()) 405 .thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER, WORK_USER))); 406 when(mMockContext.getSystemService(UsageStatsManager.class)) 407 .thenReturn(mWorkUsageStatsManager); 408 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 409 .thenReturn(new ResolveInfo()); 410 // personal app stats 411 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 412 .thenReturn(personalStats); 413 // work app stats 414 when(mWorkUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 415 .thenReturn(workStats); 416 mAppEntry.info = mApplicationInfo; 417 418 mRecentAppStatsMixin.loadDisplayableRecentApps(3); 419 420 // The output should have the first app once since the duplicate use in the personal profile 421 // is filtered out, and the second app twice - once for each profile. 422 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(3); 423 assertThat(mRecentAppStatsMixin.mRecentApps.get(0).mUsageStats.mPackageName).isEqualTo( 424 firstAppPackageName); 425 assertThat(mRecentAppStatsMixin.mRecentApps.get(1).mUsageStats.mPackageName).isEqualTo( 426 secondAppPackageName); 427 assertThat(mRecentAppStatsMixin.mRecentApps.get(2).mUsageStats.mPackageName).isEqualTo( 428 secondAppPackageName); 429 } 430 431 @Test loadDisplayableRecentApps_multipleProfileApps_shouldBeSortedByLastTimeUse()432 public void loadDisplayableRecentApps_multipleProfileApps_shouldBeSortedByLastTimeUse() 433 throws PackageManager.NameNotFoundException { 434 final List<UsageStats> personalStats = new ArrayList<>(); 435 final UsageStats stats1 = new UsageStats(); 436 final UsageStats stats2 = new UsageStats(); 437 stats1.mLastTimeUsed = System.currentTimeMillis(); 438 stats1.mPackageName = "personal.pkg.class"; 439 personalStats.add(stats1); 440 441 stats2.mLastTimeUsed = System.currentTimeMillis() - 5000; 442 stats2.mPackageName = "personal.pkg.class2"; 443 personalStats.add(stats2); 444 445 final List<UsageStats> workStats = new ArrayList<>(); 446 final UsageStats stat3 = new UsageStats(); 447 stat3.mLastTimeUsed = System.currentTimeMillis() - 2000; 448 stat3.mPackageName = "work.pkg.class3"; 449 workStats.add(stat3); 450 451 final List<UsageStats> cloneStats = new ArrayList<>(); 452 final UsageStats stat4 = new UsageStats(); 453 stat4.mLastTimeUsed = System.currentTimeMillis() - 1000; 454 stat4.mPackageName = "clone.pkg.class4"; 455 cloneStats.add(stat4); 456 457 when(mAppState.getEntry(anyString(), anyInt())) 458 .thenReturn(mAppEntry); 459 when(mUserManager.getUserProfiles()) 460 .thenReturn(new ArrayList<>(Arrays.asList(NORMAL_USER, CLONE_USER, WORK_USER))); 461 when(mMockContext.getSystemService(UsageStatsManager.class)) 462 .thenReturn(mCloneUsageStatsManager, mWorkUsageStatsManager); 463 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 464 .thenReturn(new ResolveInfo()); 465 // personal app stats 466 when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 467 .thenReturn(personalStats); 468 // work app stats 469 when(mWorkUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 470 .thenReturn(workStats); 471 // clone app stats 472 when(mCloneUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) 473 .thenReturn(cloneStats); 474 475 mAppEntry.info = mApplicationInfo; 476 477 mRecentAppStatsMixin.loadDisplayableRecentApps(4); 478 479 assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(4); 480 assertThat(mRecentAppStatsMixin.mRecentApps.get(0).mUsageStats.mPackageName).isEqualTo( 481 "personal.pkg.class"); 482 assertThat(mRecentAppStatsMixin.mRecentApps.get(1).mUsageStats.mPackageName).isEqualTo( 483 "clone.pkg.class4"); 484 assertThat(mRecentAppStatsMixin.mRecentApps.get(2).mUsageStats.mPackageName).isEqualTo( 485 "work.pkg.class3"); 486 assertThat(mRecentAppStatsMixin.mRecentApps.get(3).mUsageStats.mPackageName).isEqualTo( 487 "personal.pkg.class2"); 488 } 489 } 490