diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7d68f8dd0d615..da45367767c40 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -24299,24 +24299,24 @@ public class PackageManagerService extends IPackageManager.Stub } enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, true /* checkShell */, "stop package"); - boolean shouldUnhibernate = false; // writer synchronized (mLock) { final PackageSetting ps = mSettings.getPackageLPr(packageName); - if (ps != null && ps.getStopped(userId) && !stopped) { - shouldUnhibernate = true; - } if (!shouldFilterApplicationLocked(ps, callingUid, userId) && mSettings.setPackageStoppedStateLPw(this, packageName, stopped, userId)) { scheduleWritePackageRestrictionsLocked(userId); } } - if (shouldUnhibernate) { + // If this would cause the app to leave force-stop, then also make sure to unhibernate the + // app if needed. + if (!stopped) { mHandler.post(() -> { AppHibernationManagerInternal ah = mInjector.getLocalService(AppHibernationManagerInternal.class); - ah.setHibernatingForUser(packageName, userId, false); - ah.setHibernatingGlobally(packageName, false); + if (ah != null && ah.isHibernatingForUser(packageName, userId)) { + ah.setHibernatingForUser(packageName, userId, false); + ah.setHibernatingGlobally(packageName, false); + } }); } } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt index fd97557480bbf..e053dc3fd32e1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt @@ -29,6 +29,7 @@ import com.android.server.apphibernation.AppHibernationManagerInternal import com.android.server.apphibernation.AppHibernationService import com.android.server.extendedtestutils.wheneverStatic import com.android.server.testutils.whenever +import org.junit.Assert import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before @@ -100,8 +101,11 @@ class PackageManagerServiceHibernationTests { rule.system().dataAppDirectory) val pm = createPackageManagerService() rule.system().validateFinalState() - val ps = pm.getPackageSetting(TEST_PACKAGE_NAME) - ps!!.setStopped(true, TEST_USER_ID) + + TestableLooper.get(this).processAllMessages() + + whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID)) + .thenReturn(true) pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID) @@ -111,6 +115,31 @@ class PackageManagerServiceHibernationTests { verify(appHibernationManager).setHibernatingGlobally(TEST_PACKAGE_NAME, false) } + @Test + fun testExitForceStop_nonExistingAppHibernationManager_doesNotThrowException() { + whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java)) + .thenReturn(null) + + rule.system().stageScanExistingPackage( + TEST_PACKAGE_NAME, + 1L, + rule.system().dataAppDirectory) + val pm = createPackageManagerService() + rule.system().validateFinalState() + + TestableLooper.get(this).processAllMessages() + + whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID)) + .thenReturn(true) + + try { + pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID) + TestableLooper.get(this).processAllMessages() + } catch (e: Exception) { + Assert.fail("Method throws exception when AppHibernationManager is not ready.\n$e") + } + } + @Test fun testGetOptimizablePackages_ExcludesGloballyHibernatingPackages() { rule.system().stageScanExistingPackage(