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

Commit 04176c86 authored by Kevin Han's avatar Kevin Han Committed by Automerger Merge Worker
Browse files

Merge "Exempt hibernating apps from dex optimization" into sc-v2-dev am: 9a8937e9

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16278552

Change-Id: I92cb6ed335caa67489e08617b5ba46efbdf4eb2e
parents 31b94ebc 9a8937e9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -43,4 +43,9 @@ public abstract class AppHibernationManagerInternal {
     * @see AppHibernationService#setHibernatingGlobally
     */
    public abstract void setHibernatingGlobally(String packageName, boolean isHibernating);

    /**
     * @see AppHibernationService#isOatArtifactDeletionEnabled
     */
    public abstract boolean isOatArtifactDeletionEnabled();
}
+13 −0
Original line number Diff line number Diff line
@@ -199,6 +199,14 @@ public final class AppHibernationService extends SystemService {
        }
    }

    /**
     * Whether global hibernation should delete ART ahead-of-time compilation artifacts and prevent
     * package manager from re-optimizing the APK.
     */
    private boolean isOatArtifactDeletionEnabled() {
        return mOatArtifactDeletionEnabled;
    }

    /**
     * Whether a package is hibernating for a given user.
     *
@@ -742,6 +750,11 @@ public final class AppHibernationService extends SystemService {
        public boolean isHibernatingGlobally(String packageName) {
            return mService.isHibernatingGlobally(packageName);
        }

        @Override
        public boolean isOatArtifactDeletionEnabled() {
            return mService.isOatArtifactDeletionEnabled();
        }
    }

    private final AppHibernationServiceStub mServiceStub = new AppHibernationServiceStub(this);
+1 −1
Original line number Diff line number Diff line
@@ -381,7 +381,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
            }

            // Does the package have code? If not, there won't be any artifacts.
            if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
            if (!mPackageManagerService.mPackageDexOptimizer.canOptimizePackage(pkg)) {
                continue;
            }
            if (pkg.getPath() == null) {
+48 −5
Original line number Diff line number Diff line
@@ -63,7 +63,10 @@ import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.apphibernation.AppHibernationManagerInternal;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.ArtStatsLogUtils;
@@ -107,16 +110,24 @@ public class PackageDexOptimizer {
    private volatile boolean mSystemReady;

    private final ArtStatsLogger mArtStatsLogger = new ArtStatsLogger();
    private final Injector mInjector;


    private static final Random sRandom = new Random();

    PackageDexOptimizer(Installer installer, Object installLock, Context context,
            String wakeLockTag) {
        this.mInstaller = installer;
        this.mInstallLock = installLock;
        this(new Injector() {
            @Override
            public AppHibernationManagerInternal getAppHibernationManagerInternal() {
                return LocalServices.getService(AppHibernationManagerInternal.class);
            }

        PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        mDexoptWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag);
            @Override
            public PowerManager getPowerManager(Context context) {
                return context.getSystemService(PowerManager.class);
            }
        }, installer, installLock, context, wakeLockTag);
    }

    protected PackageDexOptimizer(PackageDexOptimizer from) {
@@ -124,9 +135,21 @@ public class PackageDexOptimizer {
        this.mInstallLock = from.mInstallLock;
        this.mDexoptWakeLock = from.mDexoptWakeLock;
        this.mSystemReady = from.mSystemReady;
        this.mInjector = from.mInjector;
    }

    static boolean canOptimizePackage(AndroidPackage pkg) {
    @VisibleForTesting
    PackageDexOptimizer(@NonNull Injector injector, Installer installer, Object installLock,
            Context context, String wakeLockTag) {
        this.mInstaller = installer;
        this.mInstallLock = installLock;

        PowerManager powerManager = injector.getPowerManager(context);
        mDexoptWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag);
        mInjector = injector;
    }

    boolean canOptimizePackage(AndroidPackage pkg) {
        // We do not dexopt a package with no code.
        // Note that the system package is marked as having no code, however we can
        // still optimize it via dexoptSystemServerPath.
@@ -134,6 +157,17 @@ public class PackageDexOptimizer {
            return false;
        }

        // We do not dexopt unused packages.
        // It's possible for this to be called before app hibernation service is ready due to
        // an OTA dexopt. In this case, we ignore the hibernation check here. This is fine since
        // a hibernating app should have no artifacts to copy in the first place.
        AppHibernationManagerInternal ahm = mInjector.getAppHibernationManagerInternal();
        if (ahm != null
                && ahm.isHibernatingGlobally(pkg.getPackageName())
                && ahm.isOatArtifactDeletionEnabled()) {
            return false;
        }

        return true;
    }

@@ -921,4 +955,13 @@ public class PackageDexOptimizer {
            return flags | DEXOPT_FORCE;
        }
    }

    /**
     * Injector for {@link PackageDexOptimizer} dependencies
     */
    interface Injector {
        AppHibernationManagerInternal getAppHibernationManagerInternal();

        PowerManager getPowerManager(Context context);
    }
}
+3 −9
Original line number Diff line number Diff line
@@ -369,7 +369,6 @@ 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;
@@ -1460,7 +1459,7 @@ public class PackageManagerService extends IPackageManager.Stub
    final ArtManagerService mArtManagerService;
    private final PackageDexOptimizer mPackageDexOptimizer;
    final PackageDexOptimizer mPackageDexOptimizer;
    // DexManager handles the usage of dex files (e.g. secondary files, whether or not a package
    // is used by other apps).
    private final DexManager mDexManager;
@@ -12750,7 +12749,7 @@ public class PackageManagerService extends IPackageManager.Stub
                }
            }
            if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
            if (!mPackageDexOptimizer.canOptimizePackage(pkg)) {
                if (DEBUG_DEXOPT) {
                    Log.i(TAG, "Skipping update of non-optimizable app " + pkg.getPackageName());
                }
@@ -13001,16 +13000,11 @@ public class PackageManagerService extends IPackageManager.Stub
        ArraySet<String> pkgs = new ArraySet<>();
        synchronized (mLock) {
            for (AndroidPackage p : mPackages.values()) {
                if (PackageDexOptimizer.canOptimizePackage(p)) {
                if (mPackageDexOptimizer.canOptimizePackage(p)) {
                    pkgs.add(p.getPackageName());
                }
            }
        }
        if (AppHibernationService.isAppHibernationEnabled()) {
            AppHibernationManagerInternal appHibernationManager =
                    mInjector.getLocalService(AppHibernationManagerInternal.class);
            pkgs.removeIf(pkgName -> appHibernationManager.isHibernatingGlobally(pkgName));
        }
        return pkgs;
    }
Loading