Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb8c8105 authored by Kevin Han's avatar Kevin Han Committed by Android (Google) Code Review
Browse files

Merge "Delete vdex/odex when package is globally hibernating" into sc-dev

parents d0980160 71edf551
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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);
}
+15 −3
Original line number Diff line number Diff line
@@ -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();
@@ -761,6 +768,11 @@ public final class AppHibernationService extends SystemService {
            return IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
        }

        @Override
        public PackageManagerInternal getPackageManagerInternal() {
            return LocalServices.getService(PackageManagerInternal.class);
        }

        @Override
        public IActivityManager getActivityManager() {
            return ActivityManager.getService();
+13 −2
Original line number Diff line number Diff line
@@ -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")
+2 −0
Original line number Diff line number Diff line
@@ -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(
+32 −0
Original line number Diff line number Diff line
@@ -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*/,
Loading