Unhibernate when an app is no longer force-stopped.
To ensure we don't end up in scenarios where an app is hibernated but not force-stopped, we unhibernate at both the user and package level when an app is no longer force-stopped. Bug: 175829330 Test: adb shell cmd app_hibernation set-state com.google.android.deskclock true Launch the app adb shell cmd app_hibernation get-state com.google.android.deskclock Change-Id: I0a0b1747b129a64f63f08b6d0c51954a77c3c73d
This commit is contained in:
@@ -314,17 +314,8 @@ public final class AppHibernationService extends SystemService {
|
||||
private void unhibernatePackageForUser(@NonNull String packageName, int userId,
|
||||
UserLevelState pkgState) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mIPackageManager.setPackageStoppedState(packageName, false, userId);
|
||||
pkgState.hibernated = false;
|
||||
} catch (RemoteException e) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to unhibernate due to manager not being available", e);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
}
|
||||
pkgState.hibernated = false;
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -367,6 +367,7 @@ import com.android.server.ServiceThread;
|
||||
import com.android.server.SystemConfig;
|
||||
import com.android.server.SystemServerInitThreadPool;
|
||||
import com.android.server.Watchdog;
|
||||
import com.android.server.apphibernation.AppHibernationManagerInternal;
|
||||
import com.android.server.compat.CompatChange;
|
||||
import com.android.server.compat.PlatformCompat;
|
||||
import com.android.server.net.NetworkPolicyManagerInternal;
|
||||
@@ -23400,15 +23401,25 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
|
||||
enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
|
||||
true /* checkShell */, "stop package");
|
||||
boolean shouldUnhibernate = false;
|
||||
// writer
|
||||
synchronized (mLock) {
|
||||
final PackageSetting ps = mSettings.getPackageLPr(packageName);
|
||||
if (ps.getStopped(userId) && !stopped) {
|
||||
shouldUnhibernate = true;
|
||||
}
|
||||
if (!shouldFilterApplicationLocked(ps, callingUid, userId)
|
||||
&& mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
|
||||
allowedByPermission, callingUid, userId)) {
|
||||
scheduleWritePackageRestrictionsLocked(userId);
|
||||
}
|
||||
}
|
||||
if (shouldUnhibernate) {
|
||||
AppHibernationManagerInternal ah =
|
||||
mInjector.getLocalService(AppHibernationManagerInternal.class);
|
||||
ah.setHibernatingForUser(packageName, userId, false);
|
||||
ah.setHibernatingGlobally(packageName, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -287,6 +287,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
|
||||
whenever(mocks.settings.internalVersion).thenReturn(DEFAULT_VERSION_INFO)
|
||||
whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService)
|
||||
whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService)
|
||||
whenever(mocks.settings.snapshot()).thenReturn(mocks.settings)
|
||||
whenever(mocks.packageAbiHelper.derivePackageAbi(
|
||||
any(AndroidPackage::class.java), anyBoolean(), nullable(), any(File::class.java))) {
|
||||
android.util.Pair(PackageAbiHelper.Abis("", ""),
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.server.pm
|
||||
|
||||
import android.os.Build
|
||||
import com.android.server.apphibernation.AppHibernationManagerInternal
|
||||
import com.android.server.testutils.whenever
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@RunWith(JUnit4::class)
|
||||
class PackageManagerServiceHibernationTests {
|
||||
|
||||
companion object {
|
||||
val TEST_PACKAGE_NAME = "test.package"
|
||||
val TEST_USER_ID = 0
|
||||
}
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val rule = MockSystemRule()
|
||||
|
||||
@Mock
|
||||
lateinit var appHibernationManager: AppHibernationManagerInternal
|
||||
|
||||
@Before
|
||||
@Throws(Exception::class)
|
||||
fun setup() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
rule.system().stageNominalSystemState()
|
||||
whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java))
|
||||
.thenReturn(appHibernationManager)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExitForceStopExitsHibernation() {
|
||||
rule.system().stageScanExistingPackage(
|
||||
TEST_PACKAGE_NAME,
|
||||
1L,
|
||||
rule.system().dataAppDirectory)
|
||||
val pm = createPackageManagerService()
|
||||
rule.system().validateFinalState()
|
||||
val ps = pm.getPackageSetting(TEST_PACKAGE_NAME)
|
||||
ps!!.setStopped(true, TEST_USER_ID)
|
||||
|
||||
pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID)
|
||||
verify(appHibernationManager).setHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID, false)
|
||||
verify(appHibernationManager).setHibernatingGlobally(TEST_PACKAGE_NAME, false)
|
||||
}
|
||||
|
||||
private fun createPackageManagerService(): PackageManagerService {
|
||||
return PackageManagerService(rule.mocks().injector,
|
||||
false /*coreOnly*/,
|
||||
false /*factoryTest*/,
|
||||
MockSystem.DEFAULT_VERSION_INFO.fingerprint,
|
||||
false /*isEngBuild*/,
|
||||
false /*isUserDebugBuild*/,
|
||||
Build.VERSION_CODES.CUR_DEVELOPMENT,
|
||||
Build.VERSION.INCREMENTAL)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user