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

Commit 06ae4cf5 authored by Martin Stjernholm's avatar Martin Stjernholm
Browse files

Add a checked exception to legacy dexopt code paths.

This exception helps us identify the code in PackageManager that will
eventually be replaced by ART Service. It's propagated to the point
where the code paths need to fork to call ArtManagerLocal instead.

This CL only adds TODO comments at those locations, unless supporting
ART Service is trivial.

This also fixes some cases where Exception is caught. It's an
antipattern because it matches both checked and unchecked exceptions,
so it hides unintended catching of checked exceptions. Instead catch
RuntimeException, along with a specific list of checked exceptions, if
any.

Test: Boot without dalvik.vm.useartservice=true
Test: m FrameworksMockingServicesTests
Bug: 251903639
Change-Id: I53758b8e4b135287e34b412ad1257e5f5fa58273
parent be9794ed
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -247,6 +247,19 @@ public class FunctionalUtils {
        }
        }
    }
    }


    /**
     * A {@link Supplier} that allows the caller to specify a custom checked {@link Exception} that
     * can be thrown by the implementer. This is usually used when proxying/wrapping calls between
     * different classes.
     *
     * @param <Output> Method return type
     * @param <ExceptionType> Checked exception type
     */
    @FunctionalInterface
    public interface ThrowingCheckedSupplier<Output, ExceptionType extends Exception> {
        Output get() throws ExceptionType;
    }

    /**
    /**
     * A {@link Consumer} that allows the caller to specify a custom checked {@link Exception} that
     * A {@link Consumer} that allows the caller to specify a custom checked {@link Exception} that
     * can be thrown by the implementer. This is usually used when proxying/wrapping calls between
     * can be thrown by the implementer. This is usually used when proxying/wrapping calls between
+44 −28
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.pm;


import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;


import static com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;


@@ -45,6 +46,7 @@ import android.util.TimingsTraceLog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Preconditions;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.AndroidPackage;
@@ -242,6 +244,7 @@ public class AppDataHelper {
                }
                }
            }
            }


            if (!useArtService()) { // ART Service handles this on demand instead.
                // Prepare the application profiles only for upgrades and
                // Prepare the application profiles only for upgrades and
                // first boot (so that we don't repeat the same operation at
                // first boot (so that we don't repeat the same operation at
                // each boot).
                // each boot).
@@ -267,8 +270,13 @@ public class AppDataHelper {
                // profiles.
                // profiles.
                if (mPm.isDeviceUpgrading() || mPm.isFirstBoot()
                if (mPm.isDeviceUpgrading() || mPm.isFirstBoot()
                        || (userId != UserHandle.USER_SYSTEM)) {
                        || (userId != UserHandle.USER_SYSTEM)) {
                    try {
                        mArtManagerService.prepareAppProfiles(pkg, userId,
                        mArtManagerService.prepareAppProfiles(pkg, userId,
                                /* updateReferenceProfileContent= */ false);
                                /* updateReferenceProfileContent= */ false);
                    } catch (LegacyDexoptDisabledException e2) {
                        throw new RuntimeException(e2);
                    }
                }
            }
            }


            if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {
            if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {
@@ -578,7 +586,12 @@ public class AppDataHelper {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return;
            return;
        }
        }
        // TODO(b/251903639): Call into ART Service.
        try {
            mArtManagerService.clearAppProfiles(pkg);
            mArtManagerService.clearAppProfiles(pkg);
        } catch (LegacyDexoptDisabledException e) {
            throw new RuntimeException(e);
        }
    }
    }


    public void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) {
    public void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) {
@@ -615,8 +628,11 @@ public class AppDataHelper {
    }
    }


    private void destroyAppProfilesLeafLIF(AndroidPackage pkg) {
    private void destroyAppProfilesLeafLIF(AndroidPackage pkg) {
        // TODO(b/251903639): Call into ART Service.
        try {
        try {
            mInstaller.destroyAppProfiles(pkg.getPackageName());
            mInstaller.destroyAppProfiles(pkg.getPackageName());
        } catch (LegacyDexoptDisabledException e) {
            throw new RuntimeException(e);
        } catch (Installer.InstallerException e) {
        } catch (Installer.InstallerException e) {
            Slog.w(TAG, String.valueOf(e));
            Slog.w(TAG, String.valueOf(e));
        }
        }
+85 −56
Original line number Original line Diff line number Diff line
@@ -55,9 +55,11 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.FunctionalUtils.ThrowingCheckedSupplier;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.LocalServices;
import com.android.server.PinnerService;
import com.android.server.PinnerService;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.PackageDexOptimizer.DexOptResult;
import com.android.server.pm.PackageDexOptimizer.DexOptResult;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.DexoptOptions;
@@ -71,7 +73,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;


/**
/**
 * Controls background dex optimization run as idle job or command line.
 * Controls background dex optimization run as idle job or command line.
@@ -202,7 +203,8 @@ public final class BackgroundDexOptService {
    }
    }


    /** Start scheduling job after boot completion */
    /** Start scheduling job after boot completion */
    public void systemReady() {
    public void systemReady() throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        if (mInjector.isBackgroundDexOptDisabled()) {
        if (mInjector.isBackgroundDexOptDisabled()) {
            return;
            return;
        }
        }
@@ -272,7 +274,8 @@ public final class BackgroundDexOptService {
     * @return true if dex optimization is complete. false if the task is cancelled or if there was
     * @return true if dex optimization is complete. false if the task is cancelled or if there was
     *         an error.
     *         an error.
     */
     */
    public boolean runBackgroundDexoptJob(@Nullable List<String> packageNames) {
    public boolean runBackgroundDexoptJob(@Nullable List<String> packageNames)
            throws LegacyDexoptDisabledException {
        enforceRootOrShell();
        enforceRootOrShell();
        long identity = Binder.clearCallingIdentity();
        long identity = Binder.clearCallingIdentity();
        try {
        try {
@@ -301,7 +304,8 @@ public final class BackgroundDexOptService {
     *
     *
     * <p>This is only for shell command and only root or shell user can use this.
     * <p>This is only for shell command and only root or shell user can use this.
     */
     */
    public void cancelBackgroundDexoptJob() {
    public void cancelBackgroundDexoptJob() throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        enforceRootOrShell();
        enforceRootOrShell();
        Binder.withCleanCallingIdentity(() -> cancelDexOptAndWaitForCompletion());
        Binder.withCleanCallingIdentity(() -> cancelDexOptAndWaitForCompletion());
    }
    }
@@ -315,7 +319,8 @@ public final class BackgroundDexOptService {
     *
     *
     * @param disable True if JobScheduler invocations should be disabled, false otherwise.
     * @param disable True if JobScheduler invocations should be disabled, false otherwise.
     */
     */
    public void setDisableJobSchedulerJobs(boolean disable) {
    public void setDisableJobSchedulerJobs(boolean disable) throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        enforceRootOrShell();
        enforceRootOrShell();
        synchronized (mLock) {
        synchronized (mLock) {
            mDisableJobSchedulerJobs = disable;
            mDisableJobSchedulerJobs = disable;
@@ -323,14 +328,18 @@ public final class BackgroundDexOptService {
    }
    }


    /** Adds listener for package update */
    /** Adds listener for package update */
    public void addPackagesUpdatedListener(PackagesUpdatedListener listener) {
    public void addPackagesUpdatedListener(PackagesUpdatedListener listener)
            throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        synchronized (mLock) {
        synchronized (mLock) {
            mPackagesUpdatedListeners.add(listener);
            mPackagesUpdatedListeners.add(listener);
        }
        }
    }
    }


    /** Removes package update listener */
    /** Removes package update listener */
    public void removePackagesUpdatedListener(PackagesUpdatedListener listener) {
    public void removePackagesUpdatedListener(PackagesUpdatedListener listener)
            throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        synchronized (mLock) {
        synchronized (mLock) {
            mPackagesUpdatedListeners.remove(listener);
            mPackagesUpdatedListeners.remove(listener);
        }
        }
@@ -340,7 +349,8 @@ public final class BackgroundDexOptService {
     * Notifies package change and removes the package from the failed package list so that
     * Notifies package change and removes the package from the failed package list so that
     * the package can run dexopt again.
     * the package can run dexopt again.
     */
     */
    public void notifyPackageChanged(String packageName) {
    public void notifyPackageChanged(String packageName) throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        // The idle maintenance job skips packages which previously failed to
        // The idle maintenance job skips packages which previously failed to
        // compile. The given package has changed and may successfully compile
        // compile. The given package has changed and may successfully compile
        // now. Remove it from the list of known failing packages.
        // now. Remove it from the list of known failing packages.
@@ -387,6 +397,7 @@ public final class BackgroundDexOptService {
                // Post boot job not finished yet. Run post boot job first.
                // Post boot job not finished yet. Run post boot job first.
                return false;
                return false;
            }
            }
            try {
                resetStatesForNewDexOptRunLocked(mInjector.createAndStartThread(
                resetStatesForNewDexOptRunLocked(mInjector.createAndStartThread(
                        "BackgroundDexOptService_" + (isPostBootUpdateJob ? "PostBoot" : "Idle"),
                        "BackgroundDexOptService_" + (isPostBootUpdateJob ? "PostBoot" : "Idle"),
                        () -> {
                        () -> {
@@ -397,6 +408,8 @@ public final class BackgroundDexOptService {
                            try {
                            try {
                                completed = runIdleOptimization(
                                completed = runIdleOptimization(
                                        pm, pkgs, params.getJobId() == JOB_POST_BOOT_UPDATE);
                                        pm, pkgs, params.getJobId() == JOB_POST_BOOT_UPDATE);
                            } catch (LegacyDexoptDisabledException e) {
                                Slog.wtf(TAG, e);
                            } finally { // Those cleanup should be done always.
                            } finally { // Those cleanup should be done always.
                                tr.traceEnd();
                                tr.traceEnd();
                                Slog.i(TAG,
                                Slog.i(TAG,
@@ -418,6 +431,9 @@ public final class BackgroundDexOptService {
                                markDexOptCompleted();
                                markDexOptCompleted();
                            }
                            }
                        }));
                        }));
            } catch (LegacyDexoptDisabledException e) {
                Slog.wtf(TAG, e);
            }
        }
        }
        return true;
        return true;
    }
    }
@@ -425,11 +441,16 @@ public final class BackgroundDexOptService {
    /** For BackgroundDexOptJobService to dispatch onStopJob event */
    /** For BackgroundDexOptJobService to dispatch onStopJob event */
    /* package */ boolean onStopJob(BackgroundDexOptJobService job, JobParameters params) {
    /* package */ boolean onStopJob(BackgroundDexOptJobService job, JobParameters params) {
        Slog.i(TAG, "onStopJob:" + params.getJobId());
        Slog.i(TAG, "onStopJob:" + params.getJobId());
        // This cannot block as it is in main thread, thus dispatch to a newly created thread and
        // This cannot block as it is in main thread, thus dispatch to a newly created thread
        // cancel it from there.
        // and cancel it from there. As this event does not happen often, creating a new thread
        // As this event does not happen often, creating a new thread is justified rather than
        // is justified rather than having one thread kept permanently.
        // having one thread kept permanently.
        mInjector.createAndStartThread("DexOptCancel", () -> {
        mInjector.createAndStartThread("DexOptCancel", this::cancelDexOptAndWaitForCompletion);
            try {
                cancelDexOptAndWaitForCompletion();
            } catch (LegacyDexoptDisabledException e) {
                Slog.wtf(TAG, e);
            }
        });
        // Always reschedule for cancellation.
        // Always reschedule for cancellation.
        return true;
        return true;
    }
    }
@@ -438,7 +459,7 @@ public final class BackgroundDexOptService {
     * Cancels pending dexopt and wait for completion of the cancellation. This can block the caller
     * Cancels pending dexopt and wait for completion of the cancellation. This can block the caller
     * until cancellation is done.
     * until cancellation is done.
     */
     */
    private void cancelDexOptAndWaitForCompletion() {
    private void cancelDexOptAndWaitForCompletion() throws LegacyDexoptDisabledException {
        synchronized (mLock) {
        synchronized (mLock) {
            if (mDexOptThread == null) {
            if (mDexOptThread == null) {
                return;
                return;
@@ -496,7 +517,8 @@ public final class BackgroundDexOptService {
    }
    }


    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private void resetStatesForNewDexOptRunLocked(Thread thread) {
    private void resetStatesForNewDexOptRunLocked(Thread thread)
            throws LegacyDexoptDisabledException {
        mDexOptThread = thread;
        mDexOptThread = thread;
        mLastCancelledPackages.clear();
        mLastCancelledPackages.clear();
        controlDexOptBlockingLocked(false);
        controlDexOptBlockingLocked(false);
@@ -510,7 +532,7 @@ public final class BackgroundDexOptService {
    }
    }


    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private void controlDexOptBlockingLocked(boolean block) {
    private void controlDexOptBlockingLocked(boolean block) throws LegacyDexoptDisabledException {
        PackageManagerService pm = mInjector.getPackageManagerService();
        PackageManagerService pm = mInjector.getPackageManagerService();
        mDexOptHelper.controlDexOptBlocking(block);
        mDexOptHelper.controlDexOptBlocking(block);
    }
    }
@@ -564,8 +586,8 @@ public final class BackgroundDexOptService {
     * Returns whether we've successfully run the job. Note that it will return true even if some
     * Returns whether we've successfully run the job. Note that it will return true even if some
     * packages may have failed compiling.
     * packages may have failed compiling.
     */
     */
    private boolean runIdleOptimization(
    private boolean runIdleOptimization(PackageManagerService pm, List<String> pkgs,
            PackageManagerService pm, List<String> pkgs, boolean isPostBootUpdate) {
            boolean isPostBootUpdate) throws LegacyDexoptDisabledException {
        synchronized (mLock) {
        synchronized (mLock) {
            mLastExecutionStatus = STATUS_UNSPECIFIED;
            mLastExecutionStatus = STATUS_UNSPECIFIED;
            mLastExecutionStartUptimeMs = SystemClock.uptimeMillis();
            mLastExecutionStartUptimeMs = SystemClock.uptimeMillis();
@@ -631,7 +653,8 @@ public final class BackgroundDexOptService {


    @Status
    @Status
    private int idleOptimizePackages(PackageManagerService pm, List<String> pkgs,
    private int idleOptimizePackages(PackageManagerService pm, List<String> pkgs,
            long lowStorageThreshold, boolean isPostBootUpdate) {
            long lowStorageThreshold, boolean isPostBootUpdate)
            throws LegacyDexoptDisabledException {
        ArraySet<String> updatedPackages = new ArraySet<>();
        ArraySet<String> updatedPackages = new ArraySet<>();


        try {
        try {
@@ -707,7 +730,8 @@ public final class BackgroundDexOptService {


    @Status
    @Status
    private int optimizePackages(List<String> pkgs, long lowStorageThreshold,
    private int optimizePackages(List<String> pkgs, long lowStorageThreshold,
            ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
            ArraySet<String> updatedPackages, boolean isPostBootUpdate)
            throws LegacyDexoptDisabledException {
        boolean supportSecondaryDex = mInjector.supportSecondaryDex();
        boolean supportSecondaryDex = mInjector.supportSecondaryDex();


        // Keep the error if there is any error from any package.
        // Keep the error if there is any error from any package.
@@ -760,7 +784,8 @@ public final class BackgroundDexOptService {
     */
     */
    @DexOptResult
    @DexOptResult
    private int downgradePackage(@NonNull Computer snapshot, PackageManagerService pm, String pkg,
    private int downgradePackage(@NonNull Computer snapshot, PackageManagerService pm, String pkg,
            boolean isForPrimaryDex, boolean isPostBootUpdate) {
            boolean isForPrimaryDex, boolean isPostBootUpdate)
            throws LegacyDexoptDisabledException {
        if (DEBUG) {
        if (DEBUG) {
            Slog.d(TAG, "Downgrading " + pkg);
            Slog.d(TAG, "Downgrading " + pkg);
        }
        }
@@ -808,7 +833,7 @@ public final class BackgroundDexOptService {
    }
    }


    @Status
    @Status
    private int reconcileSecondaryDexFiles() {
    private int reconcileSecondaryDexFiles() throws LegacyDexoptDisabledException {
        // TODO(calin): should we denylist packages for which we fail to reconcile?
        // TODO(calin): should we denylist packages for which we fail to reconcile?
        for (String p : mInjector.getDexManager().getAllPackagesWithSecondaryDexFiles()) {
        for (String p : mInjector.getDexManager().getAllPackagesWithSecondaryDexFiles()) {
            if (isCancelling()) {
            if (isCancelling()) {
@@ -829,7 +854,8 @@ public final class BackgroundDexOptService {
     * @return PackageDexOptimizer#DEX_OPT_*
     * @return PackageDexOptimizer#DEX_OPT_*
     */
     */
    @DexOptResult
    @DexOptResult
    private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) {
    private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate)
            throws LegacyDexoptDisabledException {
        int reason = isPostBootUpdate ? PackageManagerService.REASON_POST_BOOT
        int reason = isPostBootUpdate ? PackageManagerService.REASON_POST_BOOT
                                      : PackageManagerService.REASON_BACKGROUND_DEXOPT;
                                      : PackageManagerService.REASON_BACKGROUND_DEXOPT;
        String filter = getCompilerFilterForReason(reason);
        String filter = getCompilerFilterForReason(reason);
@@ -857,7 +883,8 @@ public final class BackgroundDexOptService {
    }
    }


    @DexOptResult
    @DexOptResult
    private int performDexOptPrimary(String pkg, int reason, String filter, int dexoptFlags) {
    private int performDexOptPrimary(String pkg, int reason, String filter, int dexoptFlags)
            throws LegacyDexoptDisabledException {
        DexoptOptions dexoptOptions =
        DexoptOptions dexoptOptions =
                new DexoptOptions(pkg, reason, filter, /*splitName=*/null, dexoptFlags);
                new DexoptOptions(pkg, reason, filter, /*splitName=*/null, dexoptFlags);
        return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/true,
        return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/true,
@@ -865,7 +892,8 @@ public final class BackgroundDexOptService {
    }
    }


    @DexOptResult
    @DexOptResult
    private int performDexOptSecondary(String pkg, int reason, String filter, int dexoptFlags) {
    private int performDexOptSecondary(String pkg, int reason, String filter, int dexoptFlags)
            throws LegacyDexoptDisabledException {
        DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason, filter, /*splitName=*/null,
        DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason, filter, /*splitName=*/null,
                dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX);
                dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX);
        return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/false,
        return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/false,
@@ -885,8 +913,9 @@ public final class BackgroundDexOptService {
     *  {@link PackageDexOptimizer#DEX_OPT_FAILED}
     *  {@link PackageDexOptimizer#DEX_OPT_FAILED}
     */
     */
    @DexOptResult
    @DexOptResult
    private int trackPerformDexOpt(
    private int trackPerformDexOpt(String pkg, boolean isForPrimaryDex,
            String pkg, boolean isForPrimaryDex, Supplier<Integer> performDexOptWrapper) {
            ThrowingCheckedSupplier<Integer, LegacyDexoptDisabledException> performDexOptWrapper)
            throws LegacyDexoptDisabledException {
        ArraySet<String> failedPackageNames;
        ArraySet<String> failedPackageNames;
        synchronized (mLock) {
        synchronized (mLock) {
            failedPackageNames =
            failedPackageNames =
+8 −2
Original line number Original line Diff line number Diff line
@@ -124,6 +124,7 @@ import com.android.internal.util.CollectionUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Preconditions;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageInfoUtils;
@@ -3009,8 +3010,13 @@ public class ComputerEngine implements Computer {
                    ipw.println("[" + pkgName + "]");
                    ipw.println("[" + pkgName + "]");
                    ipw.increaseIndent();
                    ipw.increaseIndent();


                    // TODO(b/251903639): Call into ART Service.
                    try {
                        mPackageDexOptimizer.dumpDexoptState(ipw, pkg, pkgSetting,
                        mPackageDexOptimizer.dumpDexoptState(ipw, pkg, pkgSetting,
                                mDexManager.getPackageUseInfoOrDefault(pkgName));
                                mDexManager.getPackageUseInfoOrDefault(pkgName));
                    } catch (LegacyDexoptDisabledException e) {
                        throw new RuntimeException(e);
                    }
                    ipw.decreaseIndent();
                    ipw.decreaseIndent();
                }
                }
                ipw.println("BgDexopt state:");
                ipw.println("BgDexopt state:");
+38 −15
Original line number Original line Diff line number Diff line
@@ -66,6 +66,8 @@ import com.android.server.art.DexUseManagerLocal;
import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.OptimizeParams;
import com.android.server.art.model.OptimizeParams;
import com.android.server.art.model.OptimizeResult;
import com.android.server.art.model.OptimizeResult;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.PackageDexOptimizer.DexOptResult;
import com.android.server.pm.PackageDexOptimizer.DexOptResult;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.DexoptOptions;
@@ -125,8 +127,9 @@ public final class DexOptHelper {
     * and {@code numberOfPackagesFailed}.
     * and {@code numberOfPackagesFailed}.
     */
     */
    public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates, boolean showDialog,
    public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates, boolean showDialog,
            final int compilationReason, boolean bootComplete) {
            final int compilationReason, boolean bootComplete)

            throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        int numberOfPackagesVisited = 0;
        int numberOfPackagesVisited = 0;
        int numberOfPackagesOptimized = 0;
        int numberOfPackagesOptimized = 0;
        int numberOfPackagesSkipped = 0;
        int numberOfPackagesSkipped = 0;
@@ -158,7 +161,7 @@ public final class DexOptHelper {
                            // even if things are already compiled.
                            // even if things are already compiled.
                            // useProfileForDexopt = true;
                            // useProfileForDexopt = true;
                        }
                        }
                    } catch (Exception e) {
                    } catch (InstallerException | RuntimeException e) {
                        Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ",
                        Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ",
                                e);
                                e);
                    }
                    }
@@ -193,7 +196,7 @@ public final class DexOptHelper {
                                } else {
                                } else {
                                    useProfileForDexopt = true;
                                    useProfileForDexopt = true;
                                }
                                }
                            } catch (Exception e) {
                            } catch (InstallerException | RuntimeException e) {
                                Log.e(TAG, "Failed to copy profile "
                                Log.e(TAG, "Failed to copy profile "
                                        + profileFile.getAbsolutePath() + " ", e);
                                        + profileFile.getAbsolutePath() + " ", e);
                            }
                            }
@@ -284,7 +287,8 @@ public final class DexOptHelper {
     * Checks if system UI package (typically "com.android.systemui") needs to be re-compiled, and
     * Checks if system UI package (typically "com.android.systemui") needs to be re-compiled, and
     * compiles it if needed.
     * compiles it if needed.
     */
     */
    private void checkAndDexOptSystemUi() {
    private void checkAndDexOptSystemUi() throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        Computer snapshot = mPm.snapshotComputer();
        Computer snapshot = mPm.snapshotComputer();
        String sysUiPackageName =
        String sysUiPackageName =
                mPm.mContext.getString(com.android.internal.R.string.config_systemUi);
                mPm.mContext.getString(com.android.internal.R.string.config_systemUi);
@@ -320,7 +324,7 @@ public final class DexOptHelper {
                            Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath());
                            Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath());
                        }
                        }
                    }
                    }
                } catch (Exception e) {
                } catch (InstallerException | RuntimeException e) {
                    Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath(), e);
                    Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath(), e);
                }
                }
            }
            }
@@ -341,7 +345,7 @@ public final class DexOptHelper {
    }
    }


    @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
    @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
    public void performPackageDexOptUpgradeIfNeeded() {
    public void performPackageDexOptUpgradeIfNeeded() throws LegacyDexoptDisabledException {
        PackageManagerServiceUtils.enforceSystemOrRoot(
        PackageManagerServiceUtils.enforceSystemOrRoot(
                "Only the system can request package update");
                "Only the system can request package update");


@@ -413,7 +417,12 @@ public final class DexOptHelper {
        }
        }


        if (options.isDexoptOnlySecondaryDex()) {
        if (options.isDexoptOnlySecondaryDex()) {
            // TODO(b/251903639): Call into ART Service.
            try {
                return mPm.getDexManager().dexoptSecondaryDex(options);
                return mPm.getDexManager().dexoptSecondaryDex(options);
            } catch (LegacyDexoptDisabledException e) {
                throw new RuntimeException(e);
            }
        } else {
        } else {
            int dexoptStatus = performDexOptWithStatus(options);
            int dexoptStatus = performDexOptWithStatus(options);
            return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
            return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
@@ -470,6 +479,8 @@ public final class DexOptHelper {
        final long callingId = Binder.clearCallingIdentity();
        final long callingId = Binder.clearCallingIdentity();
        try {
        try {
            return performDexOptInternalWithDependenciesLI(p, pkgSetting, options);
            return performDexOptInternalWithDependenciesLI(p, pkgSetting, options);
        } catch (LegacyDexoptDisabledException e) {
            throw new RuntimeException(e);
        } finally {
        } finally {
            Binder.restoreCallingIdentity(callingId);
            Binder.restoreCallingIdentity(callingId);
        }
        }
@@ -542,7 +553,8 @@ public final class DexOptHelper {


    @DexOptResult
    @DexOptResult
    private int performDexOptInternalWithDependenciesLI(
    private int performDexOptInternalWithDependenciesLI(
            AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) {
            AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options)
            throws LegacyDexoptDisabledException {
        // System server gets a special path.
        // System server gets a special path.
        if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) {
        if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) {
            return mPm.getDexManager().dexoptSystemServer(options);
            return mPm.getDexManager().dexoptSystemServer(options);
@@ -621,7 +633,11 @@ public final class DexOptHelper {
        if (artSrvRes.isPresent()) {
        if (artSrvRes.isPresent()) {
            res = artSrvRes.get();
            res = artSrvRes.get();
        } else {
        } else {
            try {
                res = performDexOptInternalWithDependenciesLI(pkg, packageState, options);
                res = performDexOptInternalWithDependenciesLI(pkg, packageState, options);
            } catch (LegacyDexoptDisabledException e) {
                throw new RuntimeException(e);
            }
        }
        }


        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -666,8 +682,8 @@ public final class DexOptHelper {
        return installerPkg.getUid() == Binder.getCallingUid();
        return installerPkg.getUid() == Binder.getCallingUid();
    }
    }


    public boolean performDexOptSecondary(String packageName, String compilerFilter,
    public boolean performDexOptSecondary(
            boolean force) {
            String packageName, String compilerFilter, boolean force) {
        int flags = DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX
        int flags = DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX
                | DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES
                | DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES
                | DexoptOptions.DEXOPT_BOOT_COMPLETE
                | DexoptOptions.DEXOPT_BOOT_COMPLETE
@@ -869,7 +885,7 @@ public final class DexOptHelper {
        }
        }
    }
    }


    /*package*/ void controlDexOptBlocking(boolean block) {
    /*package*/ void controlDexOptBlocking(boolean block) throws LegacyDexoptDisabledException {
        mPm.mPackageDexOptimizer.controlDexOptBlocking(block);
        mPm.mPackageDexOptimizer.controlDexOptBlocking(block);
    }
    }


@@ -928,11 +944,18 @@ public final class DexOptHelper {
        Slog.i(TAG, "Falling back to old PackageManager dexopt for " + packageName + ": " + reason);
        Slog.i(TAG, "Falling back to old PackageManager dexopt for " + packageName + ": " + reason);
    }
    }


    /**
     * Returns true if ART Service should be used for package optimization.
     */
    public static boolean useArtService() {
        return SystemProperties.getBoolean("dalvik.vm.useartservice", false);
    }

    /**
    /**
     * Returns {@link DexUseManagerLocal} if ART Service should be used for package optimization.
     * Returns {@link DexUseManagerLocal} if ART Service should be used for package optimization.
     */
     */
    public static @Nullable DexUseManagerLocal getDexUseManagerLocal() {
    public static @Nullable DexUseManagerLocal getDexUseManagerLocal() {
        if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) {
        if (!useArtService()) {
            return null;
            return null;
        }
        }
        try {
        try {
@@ -946,7 +969,7 @@ public final class DexOptHelper {
     * Returns {@link ArtManagerLocal} if ART Service should be used for package optimization.
     * Returns {@link ArtManagerLocal} if ART Service should be used for package optimization.
     */
     */
    private static @Nullable ArtManagerLocal getArtManagerLocal() {
    private static @Nullable ArtManagerLocal getArtManagerLocal() {
        if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) {
        if (!useArtService()) {
            return null;
            return null;
        }
        }
        try {
        try {
Loading