1 /* 2 * Copyright (C) 2021 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.server.apphibernation; 18 19 import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED; 20 import static android.app.usage.UsageEvents.Event.APP_COMPONENT_USED; 21 import static android.app.usage.UsageEvents.Event.USER_INTERACTION; 22 import static android.content.pm.PackageManager.MATCH_ANY_USER; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertFalse; 26 import static org.junit.Assert.assertNotNull; 27 import static org.junit.Assert.assertTrue; 28 import static org.mockito.AdditionalAnswers.returnsArgAt; 29 import static org.mockito.ArgumentMatchers.any; 30 import static org.mockito.ArgumentMatchers.anyBoolean; 31 import static org.mockito.ArgumentMatchers.anyInt; 32 import static org.mockito.ArgumentMatchers.anyLong; 33 import static org.mockito.ArgumentMatchers.anyString; 34 import static org.mockito.ArgumentMatchers.eq; 35 import static org.mockito.ArgumentMatchers.longThat; 36 import static org.mockito.Mockito.doAnswer; 37 import static org.mockito.Mockito.doReturn; 38 import static org.mockito.Mockito.mock; 39 import static org.mockito.Mockito.times; 40 import static org.mockito.Mockito.verify; 41 42 import android.app.IActivityManager; 43 import android.app.usage.StorageStats; 44 import android.app.usage.StorageStatsManager; 45 import android.app.usage.UsageEvents.Event; 46 import android.app.usage.UsageStatsManagerInternal; 47 import android.app.usage.UsageStatsManagerInternal.UsageEventListener; 48 import android.apphibernation.HibernationStats; 49 import android.content.BroadcastReceiver; 50 import android.content.Context; 51 import android.content.Intent; 52 import android.content.pm.ApplicationInfo; 53 import android.content.pm.IPackageManager; 54 import android.content.pm.PackageInfo; 55 import android.content.pm.PackageManager; 56 import android.content.pm.PackageManagerInternal; 57 import android.content.pm.ParceledListSlice; 58 import android.content.pm.UserInfo; 59 import android.net.Uri; 60 import android.os.RemoteException; 61 import android.os.UserManager; 62 import android.platform.test.annotations.Presubmit; 63 64 import androidx.test.filters.SmallTest; 65 66 import com.android.server.LocalServices; 67 import com.android.server.SystemService; 68 69 import org.junit.Before; 70 import org.junit.Test; 71 import org.mockito.ArgumentCaptor; 72 import org.mockito.Captor; 73 import org.mockito.Mock; 74 import org.mockito.MockitoAnnotations; 75 76 import java.io.IOException; 77 import java.util.ArrayList; 78 import java.util.List; 79 import java.util.Map; 80 import java.util.Set; 81 import java.util.UUID; 82 import java.util.concurrent.Executor; 83 84 /** 85 * Tests for {@link com.android.server.apphibernation.AppHibernationService} 86 */ 87 @SmallTest 88 @Presubmit 89 public final class AppHibernationServiceTest { 90 private static final String PACKAGE_SCHEME = "package"; 91 private static final String PACKAGE_NAME_1 = "package1"; 92 private static final String PACKAGE_NAME_2 = "package2"; 93 private static final String PACKAGE_NAME_3 = "package3"; 94 private static final int USER_ID_1 = 1; 95 private static final int USER_ID_2 = 2; 96 97 private final List<UserInfo> mUserInfos = new ArrayList<>(); 98 99 private AppHibernationService mAppHibernationService; 100 private BroadcastReceiver mBroadcastReceiver; 101 private UsageEventListener mUsageEventListener; 102 103 @Mock 104 private Context mContext; 105 @Mock 106 private IPackageManager mIPackageManager; 107 @Mock 108 private PackageManagerInternal mPackageManagerInternal; 109 @Mock 110 private IActivityManager mIActivityManager; 111 @Mock 112 private UserManager mUserManager; 113 @Mock 114 private StorageStatsManager mStorageStatsManager; 115 @Mock 116 private HibernationStateDiskStore<UserLevelState> mUserLevelDiskStore; 117 @Mock 118 private UsageStatsManagerInternal mUsageStatsManagerInternal; 119 @Mock 120 private HibernationStateDiskStore<UserLevelState> mHibernationStateDiskStore; 121 @Captor 122 private ArgumentCaptor<BroadcastReceiver> mReceiverCaptor; 123 @Captor 124 private ArgumentCaptor<UsageEventListener> mUsageEventListenerCaptor; 125 126 @Before setUp()127 public void setUp() throws RemoteException, PackageManager.NameNotFoundException, IOException { 128 // Share class loader to allow access to package-private classes 129 System.setProperty("dexmaker.share_classloader", "true"); 130 MockitoAnnotations.initMocks(this); 131 doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt()); 132 133 LocalServices.removeServiceForTest(AppHibernationManagerInternal.class); 134 mAppHibernationService = new AppHibernationService(new MockInjector(mContext)); 135 136 verify(mContext).registerReceiver(mReceiverCaptor.capture(), any()); 137 mBroadcastReceiver = mReceiverCaptor.getValue(); 138 verify(mUsageStatsManagerInternal).registerListener(mUsageEventListenerCaptor.capture()); 139 mUsageEventListener = mUsageEventListenerCaptor.getValue(); 140 141 doReturn(mUserInfos).when(mUserManager).getUsers(); 142 doReturn(true).when(mPackageManagerInternal).canQueryPackage(anyInt(), any()); 143 doAnswer(returnsArgAt(2)).when(mIActivityManager).handleIncomingUser(anyInt(), anyInt(), 144 anyInt(), anyBoolean(), anyBoolean(), any(), any()); 145 146 List<PackageInfo> packages = new ArrayList<>(); 147 packages.add(makePackageInfo(PACKAGE_NAME_1)); 148 packages.add(makePackageInfo(PACKAGE_NAME_2)); 149 packages.add(makePackageInfo(PACKAGE_NAME_3)); 150 doReturn(new ParceledListSlice<>(packages)).when(mIPackageManager).getInstalledPackages( 151 longThat(arg -> (arg & MATCH_ANY_USER) != 0), anyInt()); 152 doReturn(mock(ApplicationInfo.class)).when(mIPackageManager).getApplicationInfo( 153 any(), anyLong(), anyInt()); 154 StorageStats storageStats = new StorageStats(); 155 doReturn(storageStats).when(mStorageStatsManager).queryStatsForPackage( 156 (UUID) any(), anyString(), any()); 157 mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 158 159 UserInfo userInfo = addUser(USER_ID_1); 160 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_1); 161 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); 162 163 mAppHibernationService.sIsServiceEnabled = true; 164 } 165 166 @Test testSetHibernatingForUser_packageIsHibernating()167 public void testSetHibernatingForUser_packageIsHibernating() throws Exception { 168 // WHEN we hibernate a package for a user 169 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); 170 171 // THEN the package is marked hibernating for the user 172 assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1)); 173 verify(mIActivityManager).forceStopPackage(PACKAGE_NAME_1, USER_ID_1); 174 verify(mIPackageManager).deleteApplicationCacheFilesAsUser( 175 eq(PACKAGE_NAME_1), eq(USER_ID_1), any()); 176 } 177 178 @Test testSetHibernatingForUser_newPackageAdded_packageIsHibernating()179 public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating() { 180 // WHEN a new package is added and it is hibernated 181 Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, 182 Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */)); 183 intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_1); 184 mBroadcastReceiver.onReceive(mContext, intent); 185 186 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_1, true); 187 188 // THEN the new package is hibernated 189 assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_2, USER_ID_1)); 190 } 191 192 @Test testSetHibernatingForUser_newUserUnlocked_packageIsHibernating()193 public void testSetHibernatingForUser_newUserUnlocked_packageIsHibernating() 194 throws RemoteException { 195 // WHEN a new user is added and a package from the user is hibernated 196 UserInfo user2 = addUser(USER_ID_2); 197 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); 198 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(user2)); 199 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); 200 201 // THEN the new user's package is hibernated 202 assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_2)); 203 } 204 205 @Test testIsHibernatingForUser_packageReplaced_stillReturnsHibernating()206 public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating() { 207 // GIVEN a package is currently hibernated 208 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); 209 210 // WHEN the package is removed but marked as replacing 211 Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED, 212 Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */)); 213 intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_1); 214 intent.putExtra(Intent.EXTRA_REPLACING, true); 215 mBroadcastReceiver.onReceive(mContext, intent); 216 217 // THEN the package is still hibernating 218 assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1)); 219 } 220 221 @Test testSetHibernatingGlobally_packageIsHibernatingGlobally()222 public void testSetHibernatingGlobally_packageIsHibernatingGlobally() throws RemoteException { 223 // WHEN we hibernate a package 224 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); 225 226 // THEN the package is marked hibernating for the user 227 assertTrue(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); 228 verify(mPackageManagerInternal).deleteOatArtifactsOfPackage(PACKAGE_NAME_1); 229 } 230 231 @Test testGetHibernatingPackagesForUser_returnsCorrectPackages()232 public void testGetHibernatingPackagesForUser_returnsCorrectPackages() throws RemoteException { 233 // GIVEN an unlocked user with all packages installed 234 UserInfo userInfo = 235 addUser(USER_ID_2, new String[]{PACKAGE_NAME_1, PACKAGE_NAME_2, PACKAGE_NAME_3}); 236 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); 237 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); 238 239 // WHEN packages are hibernated for the user 240 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); 241 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_2, true); 242 243 // THEN the hibernating packages returned matches 244 List<String> hibernatingPackages = 245 mAppHibernationService.getHibernatingPackagesForUser(USER_ID_2); 246 assertEquals(2, hibernatingPackages.size()); 247 assertTrue(hibernatingPackages.contains(PACKAGE_NAME_1)); 248 assertTrue(hibernatingPackages.contains(PACKAGE_NAME_2)); 249 } 250 251 @Test testGetHibernatingPackagesForUser_doesNotReturnPackagesThatArentVisible()252 public void testGetHibernatingPackagesForUser_doesNotReturnPackagesThatArentVisible() 253 throws RemoteException { 254 // GIVEN an unlocked user with all packages installed but only some are visible to the 255 // caller 256 UserInfo userInfo = 257 addUser(USER_ID_2, new String[]{PACKAGE_NAME_1, PACKAGE_NAME_2, PACKAGE_NAME_3}); 258 doReturn(false).when(mPackageManagerInternal).canQueryPackage(anyInt(), eq(PACKAGE_NAME_2)); 259 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); 260 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); 261 262 // WHEN packages are hibernated for the user 263 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); 264 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_2, true); 265 266 // THEN the hibernating packages returned does not contain the package that was not visible 267 List<String> hibernatingPackages = 268 mAppHibernationService.getHibernatingPackagesForUser(USER_ID_2); 269 assertEquals(1, hibernatingPackages.size()); 270 assertTrue(hibernatingPackages.contains(PACKAGE_NAME_1)); 271 assertFalse(hibernatingPackages.contains(PACKAGE_NAME_2)); 272 } 273 274 @Test testUserLevelStatesInitializedFromDisk()275 public void testUserLevelStatesInitializedFromDisk() throws RemoteException { 276 // GIVEN states stored on disk that match with package manager's force-stop states 277 List<UserLevelState> diskStates = new ArrayList<>(); 278 diskStates.add(makeUserLevelState(PACKAGE_NAME_1, false /* hibernated */)); 279 diskStates.add(makeUserLevelState(PACKAGE_NAME_2, true /* hibernated */)); 280 doReturn(diskStates).when(mUserLevelDiskStore).readHibernationStates(); 281 282 List<PackageInfo> packageInfos = new ArrayList<>(); 283 packageInfos.add(makePackageInfo(PACKAGE_NAME_1)); 284 PackageInfo stoppedPkg = makePackageInfo(PACKAGE_NAME_2); 285 stoppedPkg.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED; 286 packageInfos.add(stoppedPkg); 287 288 // WHEN a user is unlocked and the states are initialized 289 UserInfo user2 = addUser(USER_ID_2, packageInfos); 290 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); 291 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(user2)); 292 293 // THEN the hibernation states are initialized to the disk states 294 assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_2)); 295 assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_2, USER_ID_2)); 296 } 297 298 @Test testNonForceStoppedAppsNotHibernatedOnUnlock()299 public void testNonForceStoppedAppsNotHibernatedOnUnlock() throws RemoteException { 300 // GIVEN a package that is hibernated on disk but not force-stopped 301 List<UserLevelState> diskStates = new ArrayList<>(); 302 diskStates.add(makeUserLevelState(PACKAGE_NAME_1, true /* hibernated */)); 303 doReturn(diskStates).when(mUserLevelDiskStore).readHibernationStates(); 304 305 // WHEN a user is unlocked and the states are initialized 306 UserInfo user2 = addUser(USER_ID_2, new String[]{PACKAGE_NAME_1}); 307 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); 308 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(user2)); 309 310 // THEN the app is not hibernating for the user 311 assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_2)); 312 } 313 314 @Test testUnhibernatedPackageForUserUnhibernatesPackageGloballyOnUnlock()315 public void testUnhibernatedPackageForUserUnhibernatesPackageGloballyOnUnlock() 316 throws RemoteException { 317 // GIVEN a package that is globally hibernating 318 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); 319 320 // WHEN a user is unlocked and the package is not hibernating for the user 321 UserInfo user2 = addUser(USER_ID_2); 322 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); 323 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(user2)); 324 325 // THEN the package is no longer globally hibernating 326 assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); 327 } 328 329 @Test testUnhibernatingPackageForUserSendsBootCompleteBroadcast()330 public void testUnhibernatingPackageForUserSendsBootCompleteBroadcast() 331 throws RemoteException { 332 // GIVEN a hibernating package for a user 333 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); 334 335 // WHEN we unhibernate the package 336 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, false); 337 338 // THEN we send the boot complete broadcasts 339 ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); 340 verify(mIActivityManager, times(2)).broadcastIntentWithFeature(any(), any(), 341 intentArgumentCaptor.capture(), any(), any(), anyInt(), any(), any(), any(), any(), 342 any(), anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1)); 343 List<Intent> capturedIntents = intentArgumentCaptor.getAllValues(); 344 assertEquals(capturedIntents.get(0).getAction(), Intent.ACTION_LOCKED_BOOT_COMPLETED); 345 assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED); 346 } 347 348 @Test testHibernatingPackageIsUnhibernatedForUserWhenUserInteracted()349 public void testHibernatingPackageIsUnhibernatedForUserWhenUserInteracted() { 350 // GIVEN a package that is currently hibernated for a user 351 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); 352 353 // WHEN the package is interacted with by user 354 generateUsageEvent(USER_INTERACTION); 355 356 // THEN the package is not hibernating anymore 357 assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1)); 358 } 359 360 @Test testHibernatingPackageIsUnhibernatedForUserWhenActivityResumed()361 public void testHibernatingPackageIsUnhibernatedForUserWhenActivityResumed() { 362 // GIVEN a package that is currently hibernated for a user 363 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); 364 365 // WHEN the package has activity resumed 366 generateUsageEvent(ACTIVITY_RESUMED); 367 368 // THEN the package is not hibernating anymore 369 assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1)); 370 } 371 372 @Test testHibernatingPackageIsUnhibernatedForUserWhenComponentUsed()373 public void testHibernatingPackageIsUnhibernatedForUserWhenComponentUsed() { 374 // GIVEN a package that is currently hibernated for a user 375 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); 376 377 // WHEN a package component is used 378 generateUsageEvent(APP_COMPONENT_USED); 379 380 // THEN the package is not hibernating anymore 381 assertFalse(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1)); 382 } 383 384 @Test testHibernatingPackageIsUnhibernatedGloballyWhenUserInteracted()385 public void testHibernatingPackageIsUnhibernatedGloballyWhenUserInteracted() { 386 // GIVEN a package that is currently hibernated globally 387 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); 388 389 // WHEN the user interacts with the package 390 generateUsageEvent(USER_INTERACTION); 391 392 // THEN the package is not hibernating globally anymore 393 assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); 394 } 395 396 @Test testHibernatingPackageIsUnhibernatedGloballyWhenActivityResumed()397 public void testHibernatingPackageIsUnhibernatedGloballyWhenActivityResumed() { 398 // GIVEN a package that is currently hibernated globally 399 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); 400 401 // WHEN activity in package resumed 402 generateUsageEvent(ACTIVITY_RESUMED); 403 404 // THEN the package is not hibernating globally anymore 405 assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); 406 } 407 408 @Test testHibernatingPackageIsUnhibernatedGloballyWhenComponentUsed()409 public void testHibernatingPackageIsUnhibernatedGloballyWhenComponentUsed() { 410 // GIVEN a package that is currently hibernated globally 411 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); 412 413 // WHEN a package component is used 414 generateUsageEvent(APP_COMPONENT_USED); 415 416 // THEN the package is not hibernating globally anymore 417 assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1)); 418 } 419 420 @Test testGetHibernationStatsForUser_getsStatsForPackage()421 public void testGetHibernationStatsForUser_getsStatsForPackage() 422 throws PackageManager.NameNotFoundException, IOException, RemoteException { 423 // GIVEN a package is hibernating globally and for a user with some storage saved 424 final long cacheSavings = 1000; 425 StorageStats storageStats = new StorageStats(); 426 storageStats.cacheBytes = cacheSavings; 427 doReturn(storageStats).when(mStorageStatsManager).queryStatsForPackage( 428 (UUID) any(), eq(PACKAGE_NAME_1), any()); 429 final long oatDeletionSavings = 2000; 430 doReturn(oatDeletionSavings).when(mPackageManagerInternal).deleteOatArtifactsOfPackage( 431 PACKAGE_NAME_1); 432 433 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); 434 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true); 435 436 // WHEN we ask for the hibernation stats for the package 437 Map<String, HibernationStats> statsMap = 438 mAppHibernationService.getHibernationStatsForUser( 439 Set.of(PACKAGE_NAME_1), USER_ID_1); 440 441 // THEN the stats exist for the package and add up to the OAT deletion and cache deletion 442 // savings 443 HibernationStats stats = statsMap.get(PACKAGE_NAME_1); 444 assertNotNull(stats); 445 assertEquals(cacheSavings + oatDeletionSavings, stats.getDiskBytesSaved()); 446 } 447 448 @Test testGetHibernationStatsForUser_noExceptionThrownWhenPackageDoesntExist()449 public void testGetHibernationStatsForUser_noExceptionThrownWhenPackageDoesntExist() { 450 // WHEN we ask for the hibernation stats for a package that doesn't exist 451 Map<String, HibernationStats> stats = 452 mAppHibernationService.getHibernationStatsForUser( 453 Set.of(PACKAGE_NAME_1), USER_ID_1); 454 455 // THEN no exception is thrown and empty stats are returned 456 assertNotNull(stats); 457 } 458 459 @Test testGetHibernationStatsForUser_returnsAllIfNoPackagesSpecified()460 public void testGetHibernationStatsForUser_returnsAllIfNoPackagesSpecified() 461 throws RemoteException { 462 // GIVEN an unlocked user with all packages installed and they're all hibernating 463 UserInfo userInfo = 464 addUser(USER_ID_2, new String[]{PACKAGE_NAME_1, PACKAGE_NAME_2, PACKAGE_NAME_3}); 465 doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_2); 466 mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo)); 467 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true); 468 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true); 469 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_2, true); 470 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_2, true); 471 mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_3, true); 472 mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_3, USER_ID_2, true); 473 474 // WHEN we ask for the hibernation stats with no package specified 475 Map<String, HibernationStats> stats = 476 mAppHibernationService.getHibernationStatsForUser( 477 null /* packageNames */, USER_ID_2); 478 479 // THEN all the package stats are returned 480 assertTrue(stats.containsKey(PACKAGE_NAME_1)); 481 assertTrue(stats.containsKey(PACKAGE_NAME_2)); 482 assertTrue(stats.containsKey(PACKAGE_NAME_3)); 483 } 484 485 /** 486 * Mock a usage event occurring. 487 * 488 * @param usageEventId id of a usage event 489 */ generateUsageEvent(int usageEventId)490 private void generateUsageEvent(int usageEventId) { 491 Event event = new Event(usageEventId, 0 /* timestamp */); 492 event.mPackage = PACKAGE_NAME_1; 493 mUsageEventListener.onUsageEvent(USER_ID_1, event); 494 } 495 496 /** 497 * Add a mock user with one package. 498 */ addUser(int userId)499 private UserInfo addUser(int userId) throws RemoteException { 500 return addUser(userId, new String[]{PACKAGE_NAME_1}); 501 } 502 503 /** 504 * Add a mock user with the packages specified. 505 */ addUser(int userId, String[] packageNames)506 private UserInfo addUser(int userId, String[] packageNames) throws RemoteException { 507 List<PackageInfo> userPackages = new ArrayList<>(); 508 for (String pkgName : packageNames) { 509 userPackages.add(makePackageInfo(pkgName)); 510 } 511 return addUser(userId, userPackages); 512 } 513 514 /** 515 * Add a mock user with the package infos specified. 516 */ addUser(int userId, List<PackageInfo> userPackages)517 private UserInfo addUser(int userId, List<PackageInfo> userPackages) throws RemoteException { 518 UserInfo userInfo = new UserInfo(userId, "user_" + userId, 0 /* flags */); 519 mUserInfos.add(userInfo); 520 doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager) 521 .getInstalledPackages(longThat(arg -> (arg & MATCH_ANY_USER) == 0), eq(userId)); 522 return userInfo; 523 } 524 makePackageInfo(String packageName)525 private static PackageInfo makePackageInfo(String packageName) { 526 PackageInfo pkg = new PackageInfo(); 527 pkg.packageName = packageName; 528 pkg.applicationInfo = new ApplicationInfo(); 529 return pkg; 530 } 531 makeUserLevelState(String packageName, boolean hibernated)532 private static UserLevelState makeUserLevelState(String packageName, boolean hibernated) { 533 UserLevelState state = new UserLevelState(); 534 state.packageName = packageName; 535 state.hibernated = hibernated; 536 return state; 537 } 538 539 private class MockInjector implements AppHibernationService.Injector { 540 private final Context mContext; 541 MockInjector(Context context)542 MockInjector(Context context) { 543 mContext = context; 544 } 545 546 @Override getActivityManager()547 public IActivityManager getActivityManager() { 548 return mIActivityManager; 549 } 550 551 @Override getContext()552 public Context getContext() { 553 return mContext; 554 } 555 556 @Override getPackageManager()557 public IPackageManager getPackageManager() { 558 return mIPackageManager; 559 } 560 561 @Override getPackageManagerInternal()562 public PackageManagerInternal getPackageManagerInternal() { 563 return mPackageManagerInternal; 564 } 565 566 @Override getUserManager()567 public UserManager getUserManager() { 568 return mUserManager; 569 } 570 571 @Override getStorageStatsManager()572 public StorageStatsManager getStorageStatsManager() { 573 return mStorageStatsManager; 574 } 575 576 @Override getUsageStatsManagerInternal()577 public UsageStatsManagerInternal getUsageStatsManagerInternal() { 578 return mUsageStatsManagerInternal; 579 } 580 581 @Override getBackgroundExecutor()582 public Executor getBackgroundExecutor() { 583 // Just execute immediately in tests. 584 return r -> r.run(); 585 } 586 587 @Override getGlobalLevelDiskStore()588 public HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore() { 589 return mock(HibernationStateDiskStore.class); 590 } 591 592 @Override getUserLevelDiskStore(int userId)593 public HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId) { 594 return mUserLevelDiskStore; 595 } 596 597 @Override isOatArtifactDeletionEnabled()598 public boolean isOatArtifactDeletionEnabled() { 599 return true; 600 } 601 } 602 } 603