summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/apphibernation/AppHibernationService.java18
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java15
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt32
-rw-r--r--services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java14
6 files changed, 78 insertions, 8 deletions
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index c2957780c9d7..a9eb2c110867 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1141,4 +1141,9 @@ public abstract class PackageManagerInternal {
*/
public abstract boolean isPackageFrozen(
@NonNull String packageName, int callingUid, int userId);
+
+ /**
+ * Deletes the OAT artifacts of a package.
+ */
+ public abstract void deleteOatArtifactsOfPackage(String packageName);
}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index ebe9d96ee1f6..5a99e0e77a6c 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -38,6 +38,7 @@ import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.Environment;
import android.os.RemoteException;
@@ -92,8 +93,10 @@ public final class AppHibernationService extends SystemService {
private final Object mLock = new Object();
private final Context mContext;
private final IPackageManager mIPackageManager;
+ private final PackageManagerInternal mPackageManagerInternal;
private final IActivityManager mIActivityManager;
private final UserManager mUserManager;
+
@GuardedBy("mLock")
private final SparseArray<Map<String, UserLevelState>> mUserStates = new SparseArray<>();
private final SparseArray<HibernationStateDiskStore<UserLevelState>> mUserDiskStores =
@@ -125,6 +128,7 @@ public final class AppHibernationService extends SystemService {
super(injector.getContext());
mContext = injector.getContext();
mIPackageManager = injector.getPackageManager();
+ mPackageManagerInternal = injector.getPackageManagerInternal();
mIActivityManager = injector.getActivityManager();
mUserManager = injector.getUserManager();
mGlobalLevelHibernationDiskStore = injector.getGlobalLevelDiskStore();
@@ -214,8 +218,9 @@ public final class AppHibernationService extends SystemService {
synchronized (mLock) {
GlobalLevelState state = mGlobalHibernationStates.get(packageName);
if (state == null) {
- throw new IllegalArgumentException(
- String.format("Package %s is not installed", packageName));
+ // This API can be legitimately called before installation finishes as part of
+ // dex optimization, so we just return false here.
+ return false;
}
return state.hibernated;
}
@@ -366,7 +371,7 @@ public final class AppHibernationService extends SystemService {
@GuardedBy("mLock")
private void hibernatePackageGlobally(@NonNull String packageName, GlobalLevelState state) {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackageGlobally");
- // TODO(175830194): Delete vdex/odex when DexManager API is built out
+ mPackageManagerInternal.deleteOatArtifactsOfPackage(packageName);
state.hibernated = true;
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
@@ -728,6 +733,8 @@ public final class AppHibernationService extends SystemService {
IPackageManager getPackageManager();
+ PackageManagerInternal getPackageManagerInternal();
+
IActivityManager getActivityManager();
UserManager getUserManager();
@@ -762,6 +769,11 @@ public final class AppHibernationService extends SystemService {
}
@Override
+ public PackageManagerInternal getPackageManagerInternal() {
+ return LocalServices.getService(PackageManagerInternal.class);
+ }
+
+ @Override
public IActivityManager getActivityManager() {
return ActivityManager.getService();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b27c0bd7034b..a8bdedf19cc7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -252,7 +252,6 @@ import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.parsing.component.ParsedProcess;
import android.content.pm.parsing.component.ParsedProvider;
import android.content.pm.parsing.component.ParsedService;
-import android.content.pm.parsing.component.ParsedUsesPermission;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.Resources;
@@ -371,6 +370,7 @@ 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.apphibernation.AppHibernationService;
import com.android.server.compat.CompatChange;
import com.android.server.compat.PlatformCompat;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -12304,9 +12304,15 @@ public class PackageManagerService extends IPackageManager.Stub
public ArraySet<String> getOptimizablePackages() {
ArraySet<String> pkgs = new ArraySet<>();
+ final boolean hibernationEnabled = AppHibernationService.isAppHibernationEnabled();
+ AppHibernationManagerInternal appHibernationManager =
+ mInjector.getLocalService(AppHibernationManagerInternal.class);
synchronized (mLock) {
for (AndroidPackage p : mPackages.values()) {
- if (PackageDexOptimizer.canOptimizePackage(p)) {
+ // Checking hibernation state is an inexpensive call.
+ boolean isHibernating = hibernationEnabled
+ && appHibernationManager.isHibernatingGlobally(p.getPackageName());
+ if (PackageDexOptimizer.canOptimizePackage(p) && !isHibernating) {
pkgs.add(p.getPackageName());
}
}
@@ -27329,6 +27335,11 @@ public class PackageManagerService extends IPackageManager.Stub
return PackageManagerService.this.getPackageStartability(
packageName, callingUid, userId) == PACKAGE_STARTABILITY_FROZEN;
}
+
+ @Override
+ public void deleteOatArtifactsOfPackage(String packageName) {
+ PackageManagerService.this.deleteOatArtifactsOfPackage(packageName);
+ }
}
@GuardedBy("mLock")
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 17c6b6fba861..db0c3aece023 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -36,6 +36,7 @@ import android.os.SystemProperties
import android.os.UserHandle
import android.os.UserManager
import android.os.incremental.IncrementalManager
+import android.provider.DeviceConfig
import android.util.ArrayMap
import android.util.DisplayMetrics
import android.util.EventLog
@@ -131,6 +132,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
.mockStatic(LockGuard::class.java)
.mockStatic(EventLog::class.java)
.mockStatic(LocalServices::class.java)
+ .mockStatic(DeviceConfig::class.java)
.apply(withSession)
session = apply.startMocking()
whenever(mocks.settings.insertPackageSettingLPw(
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 a0e208f662e3..46487ea27959 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
@@ -17,8 +17,13 @@
package com.android.server.pm
import android.os.Build
+import android.provider.DeviceConfig
+import android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION
import com.android.server.apphibernation.AppHibernationManagerInternal
+import com.android.server.extendedtestutils.wheneverStatic
import com.android.server.testutils.whenever
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -33,7 +38,10 @@ class PackageManagerServiceHibernationTests {
companion object {
val TEST_PACKAGE_NAME = "test.package"
+ val TEST_PACKAGE_2_NAME = "test.package2"
val TEST_USER_ID = 0
+
+ val KEY_APP_HIBERNATION_ENABLED = "app_hibernation_enabled"
}
@Rule
@@ -47,6 +55,8 @@ class PackageManagerServiceHibernationTests {
@Throws(Exception::class)
fun setup() {
MockitoAnnotations.initMocks(this)
+ wheneverStatic { DeviceConfig.getBoolean(
+ NAMESPACE_APP_HIBERNATION, KEY_APP_HIBERNATION_ENABLED, false) }.thenReturn(true)
rule.system().stageNominalSystemState()
whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java))
.thenReturn(appHibernationManager)
@@ -68,6 +78,28 @@ class PackageManagerServiceHibernationTests {
verify(appHibernationManager).setHibernatingGlobally(TEST_PACKAGE_NAME, false)
}
+ @Test
+ fun testGetOptimizablePackages_ExcludesGloballyHibernatingPackages() {
+ rule.system().stageScanExistingPackage(
+ TEST_PACKAGE_NAME,
+ 1L,
+ rule.system().dataAppDirectory,
+ withPackage = { it.apply { isHasCode = true } })
+ rule.system().stageScanExistingPackage(
+ TEST_PACKAGE_2_NAME,
+ 1L,
+ rule.system().dataAppDirectory,
+ withPackage = { it.apply { isHasCode = true } })
+ val pm = createPackageManagerService()
+ rule.system().validateFinalState()
+ whenever(appHibernationManager.isHibernatingGlobally(TEST_PACKAGE_2_NAME)).thenReturn(true)
+
+ val optimizablePkgs = pm.optimizablePackages
+
+ assertTrue(optimizablePkgs.contains(TEST_PACKAGE_NAME))
+ assertFalse(optimizablePkgs.contains(TEST_PACKAGE_2_NAME))
+ }
+
private fun createPackageManagerService(): PackageManagerService {
return PackageManagerService(rule.mocks().injector,
false /*coreOnly*/,
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index 2f0d71a2a579..0dbf3fe0cea3 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -28,6 +28,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.intThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.app.IActivityManager;
@@ -36,6 +37,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.net.Uri;
@@ -53,7 +55,6 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -82,6 +83,8 @@ public final class AppHibernationServiceTest {
@Mock
private IPackageManager mIPackageManager;
@Mock
+ private PackageManagerInternal mPackageManagerInternal;
+ @Mock
private IActivityManager mIActivityManager;
@Mock
private UserManager mUserManager;
@@ -255,6 +258,11 @@ public final class AppHibernationServiceTest {
}
@Override
+ public PackageManagerInternal getPackageManagerInternal() {
+ return mPackageManagerInternal;
+ }
+
+ @Override
public UserManager getUserManager() {
return mUserManager;
}
@@ -267,12 +275,12 @@ public final class AppHibernationServiceTest {
@Override
public HibernationStateDiskStore<GlobalLevelState> getGlobalLevelDiskStore() {
- return Mockito.mock(HibernationStateDiskStore.class);
+ return mock(HibernationStateDiskStore.class);
}
@Override
public HibernationStateDiskStore<UserLevelState> getUserLevelDiskStore(int userId) {
- return Mockito.mock(HibernationStateDiskStore.class);
+ return mock(HibernationStateDiskStore.class);
}
}
}