/*
 * 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 static android.os.Trace.TRACE_TAG_DALVIK;

import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
import static com.android.server.pm.ApexManager.ActiveApexInfo;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.REASON_BOOT_AFTER_MAINLINE_UPDATE;
import static com.android.server.pm.PackageManagerService.REASON_BOOT_AFTER_OTA;
import static com.android.server.pm.PackageManagerService.REASON_CMDLINE;
import static com.android.server.pm.PackageManagerService.REASON_FIRST_BOOT;
import static com.android.server.pm.PackageManagerService.STUB_SUFFIX;
import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefaultCompilerFilter;
import static com.android.server.pm.PackageManagerServiceUtils.REMOVE_IF_APEX_PKG;
import static com.android.server.pm.PackageManagerServiceUtils.REMOVE_IF_NULL_PKG;
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;

import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApexStagedEvent;
import android.content.pm.IPackageManagerNative;
import android.content.pm.IStagedApexObserver;
import android.content.pm.ResolveInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.dex.ArtManager;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices;
import com.android.server.PinnerService;
import com.android.server.art.ArtManagerLocal;
import com.android.server.art.DexUseManagerLocal;
import com.android.server.art.ReasonMapping;
import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
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.dex.DexManager;
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

/**
 * Helper class for dex optimization operations in PackageManagerService.
 */
public final class DexOptHelper {
    private static final long SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;

    private static boolean sArtManagerLocalIsInitialized = false;

    private final PackageManagerService mPm;

    // Start time for the boot dexopt in performPackageDexOptUpgradeIfNeeded when ART Service is
    // used, to make it available to the onDexoptDone callback.
    private volatile long mBootDexoptStartTime;

    DexOptHelper(PackageManagerService pm) {
        mPm = pm;
    }

    /*
     * Return the prebuilt profile path given a package base code path.
     */
    private static String getPrebuildProfilePath(AndroidPackage pkg) {
        return pkg.getBaseApkPath() + ".prof";
    }

    /**
     * Performs dexopt on the set of packages in {@code packages} and returns an int array
     * containing statistics about the invocation. The array consists of three elements,
     * which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped}
     * and {@code numberOfPackagesFailed}.
     */
    public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates,
            final int compilationReason, boolean bootComplete)
            throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();
        int numberOfPackagesVisited = 0;
        int numberOfPackagesOptimized = 0;
        int numberOfPackagesSkipped = 0;
        int numberOfPackagesFailed = 0;
        final int numberOfPackagesToDexopt = packageStates.size();

        for (var packageState : packageStates) {
            var pkg = packageState.getAndroidPackage();
            numberOfPackagesVisited++;

            boolean useProfileForDexopt = false;

            if ((mPm.isFirstBoot() || mPm.isDeviceUpgrading()) && packageState.isSystem()) {
                // Copy over initial preopt profiles since we won't get any JIT samples for methods
                // that are already compiled.
                File profileFile = new File(getPrebuildProfilePath(pkg));
                // Copy profile if it exists.
                if (profileFile.exists()) {
                    try {
                        // We could also do this lazily before calling dexopt in
                        // PackageDexOptimizer to prevent this happening on first boot. The issue
                        // is that we don't have a good way to say "do this only once".
                        if (!mPm.mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                pkg.getUid(), pkg.getPackageName(),
                                ArtManager.getProfileName(null))) {
                            Log.e(TAG, "Installer failed to copy system profile!");
                        } else {
                            // Disabled as this causes speed-profile compilation during first boot
                            // even if things are already compiled.
                            // useProfileForDexopt = true;
                        }
                    } catch (InstallerException | RuntimeException e) {
                        Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ",
                                e);
                    }
                } else {
                    PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(
                            pkg.getPackageName());
                    // Handle compressed APKs in this path. Only do this for stubs with profiles to
                    // minimize the number off apps being speed-profile compiled during first boot.
                    // The other paths will not change the filter.
                    if (disabledPs != null && disabledPs.getPkg().isStub()) {
                        // The package is the stub one, remove the stub suffix to get the normal
                        // package and APK names.
                        String systemProfilePath = getPrebuildProfilePath(disabledPs.getPkg())
                                .replace(STUB_SUFFIX, "");
                        profileFile = new File(systemProfilePath);
                        // If we have a profile for a compressed APK, copy it to the reference
                        // location.
                        // Note that copying the profile here will cause it to override the
                        // reference profile every OTA even though the existing reference profile
                        // may have more data. We can't copy during decompression since the
                        // directories are not set up at that point.
                        if (profileFile.exists()) {
                            try {
                                // We could also do this lazily before calling dexopt in
                                // PackageDexOptimizer to prevent this happening on first boot. The
                                // issue is that we don't have a good way to say "do this only
                                // once".
                                if (!mPm.mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                        pkg.getUid(), pkg.getPackageName(),
                                        ArtManager.getProfileName(null))) {
                                    Log.e(TAG, "Failed to copy system profile for stub package!");
                                } else {
                                    useProfileForDexopt = true;
                                }
                            } catch (InstallerException | RuntimeException e) {
                                Log.e(TAG, "Failed to copy profile "
                                        + profileFile.getAbsolutePath() + " ", e);
                            }
                        }
                    }
                }
            }

            if (!mPm.mPackageDexOptimizer.canOptimizePackage(pkg)) {
                if (DEBUG_DEXOPT) {
                    Log.i(TAG, "Skipping update of non-optimizable app " + pkg.getPackageName());
                }
                numberOfPackagesSkipped++;
                continue;
            }

            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Updating app " + numberOfPackagesVisited + " of "
                        + numberOfPackagesToDexopt + ": " + pkg.getPackageName());
            }

            int pkgCompilationReason = compilationReason;
            if (useProfileForDexopt) {
                // Use background dexopt mode to try and use the profile. Note that this does not
                // guarantee usage of the profile.
                pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
            }

            int dexoptFlags = bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0;

            String filter = getCompilerFilterForReason(pkgCompilationReason);
            if (isProfileGuidedCompilerFilter(filter)) {
                // DEXOPT_CHECK_FOR_PROFILES_UPDATES used to be false to avoid merging profiles
                // during boot which might interfere with background compilation (b/28612421).
                // However those problems were related to the verify-profile compiler filter which
                // doesn't exist any more, so enable it again.
                dexoptFlags |= DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES;
            }

            if (compilationReason == REASON_FIRST_BOOT) {
                // TODO: This doesn't cover the upgrade case, we should check for this too.
                dexoptFlags |= DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE;
            }
            int primaryDexOptStatus = performDexOptTraced(
                    new DexoptOptions(pkg.getPackageName(), pkgCompilationReason, filter,
                            /*splitName*/ null, dexoptFlags));

            switch (primaryDexOptStatus) {
                case PackageDexOptimizer.DEX_OPT_PERFORMED:
                    numberOfPackagesOptimized++;
                    break;
                case PackageDexOptimizer.DEX_OPT_SKIPPED:
                    numberOfPackagesSkipped++;
                    break;
                case PackageDexOptimizer.DEX_OPT_CANCELLED:
                    // ignore this case
                    break;
                case PackageDexOptimizer.DEX_OPT_FAILED:
                    numberOfPackagesFailed++;
                    break;
                default:
                    Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStatus);
                    break;
            }
        }

        return new int[]{numberOfPackagesOptimized, numberOfPackagesSkipped,
                numberOfPackagesFailed};
    }

    /**
     * Checks if system UI package (typically "com.android.systemui") needs to be re-compiled, and
     * compiles it if needed.
     */
    private void checkAndDexOptSystemUi(int reason) throws LegacyDexoptDisabledException {
        Computer snapshot = mPm.snapshotComputer();
        String sysUiPackageName =
                mPm.mContext.getString(com.android.internal.R.string.config_systemUi);
        AndroidPackage pkg = snapshot.getPackage(sysUiPackageName);
        if (pkg == null) {
            Log.w(TAG, "System UI package " + sysUiPackageName + " is not found for dexopting");
            return;
        }

        String defaultCompilerFilter = getCompilerFilterForReason(reason);
        String targetCompilerFilter =
                SystemProperties.get("dalvik.vm.systemuicompilerfilter", defaultCompilerFilter);
        String compilerFilter;

        if (isProfileGuidedCompilerFilter(targetCompilerFilter)) {
            compilerFilter = "verify";
            File profileFile = new File(getPrebuildProfilePath(pkg));

            // Copy the profile to the reference profile path if it exists. Installd can only use a
            // profile at the reference profile path for dexopt.
            if (profileFile.exists()) {
                try {
                    synchronized (mPm.mInstallLock) {
                        if (mPm.mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                    pkg.getUid(), pkg.getPackageName(),
                                    ArtManager.getProfileName(null))) {
                            compilerFilter = targetCompilerFilter;
                        } else {
                            Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath());
                        }
                    }
                } catch (InstallerException | RuntimeException e) {
                    Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath(), e);
                }
            }
        } else {
            compilerFilter = targetCompilerFilter;
        }

        performDexoptPackage(sysUiPackageName, reason, compilerFilter);
    }

    private void dexoptLauncher(int reason) throws LegacyDexoptDisabledException {
        Computer snapshot = mPm.snapshotComputer();
        RoleManager roleManager = mPm.mContext.getSystemService(RoleManager.class);
        for (var packageName : roleManager.getRoleHolders(RoleManager.ROLE_HOME)) {
            AndroidPackage pkg = snapshot.getPackage(packageName);
            if (pkg == null) {
                Log.w(TAG, "Launcher package " + packageName + " is not found for dexopting");
            } else {
                performDexoptPackage(packageName, reason, "speed-profile");
            }
        }
    }

    private void performDexoptPackage(@NonNull String packageName, int reason,
            @NonNull String compilerFilter) throws LegacyDexoptDisabledException {
        Installer.checkLegacyDexoptDisabled();

        // DEXOPT_CHECK_FOR_PROFILES_UPDATES is set to replicate behaviour that will be
        // unconditionally enabled for profile guided filters when ART Service is called instead of
        // the legacy PackageDexOptimizer implementation.
        int dexoptFlags = isProfileGuidedCompilerFilter(compilerFilter)
                ? DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES
                : 0;

        performDexOptTraced(new DexoptOptions(
                packageName, reason, compilerFilter, null /* splitName */, dexoptFlags));
    }

    /**
     * Called during startup to do any boot time dexopting. This can occasionally be time consuming
     * (30+ seconds) and the function will block until it is complete.
     */
    public void performPackageDexOptUpgradeIfNeeded() {
        PackageManagerServiceUtils.enforceSystemOrRoot(
                "Only the system can request package update");

        int reason;
        if (mPm.isFirstBoot()) {
            reason = REASON_FIRST_BOOT; // First boot or factory reset.
        } else if (mPm.isDeviceUpgrading()) {
            reason = REASON_BOOT_AFTER_OTA;
        } else if (hasBcpApexesChanged()) {
            reason = REASON_BOOT_AFTER_MAINLINE_UPDATE;
        } else {
            return;
        }

        Log.i(TAG,
                "Starting boot dexopt for reason "
                        + DexoptOptions.convertToArtServiceDexoptReason(reason));

        final long startTime = System.nanoTime();

        if (useArtService()) {
            mBootDexoptStartTime = startTime;
            getArtManagerLocal().onBoot(DexoptOptions.convertToArtServiceDexoptReason(reason),
                    null /* progressCallbackExecutor */, null /* progressCallback */);
        } else {
            try {
                // System UI and the launcher are important to user experience, so we check them
                // after a mainline update or OTA. They may need to be re-compiled in these cases.
                checkAndDexOptSystemUi(reason);
                dexoptLauncher(reason);

                if (reason != REASON_BOOT_AFTER_OTA && reason != REASON_FIRST_BOOT) {
                    return;
                }

                final Computer snapshot = mPm.snapshotComputer();

                // TODO(b/251903639): Align this with how ART Service selects packages for boot
                // compilation.
                List<PackageStateInternal> pkgSettings =
                        getPackagesForDexopt(snapshot.getPackageStates().values(), mPm);

                final int[] stats =
                        performDexOptUpgrade(pkgSettings, reason, false /* bootComplete */);
                reportBootDexopt(startTime, stats[0], stats[1], stats[2]);
            } catch (LegacyDexoptDisabledException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void reportBootDexopt(long startTime, int numDexopted, int numSkipped, int numFailed) {
        final int elapsedTimeSeconds =
                (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);

        final Computer newSnapshot = mPm.snapshotComputer();

        MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_dexopted", numDexopted);
        MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_skipped", numSkipped);
        MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_failed", numFailed);
        // TODO(b/251903639): getOptimizablePackages calls PackageDexOptimizer.canOptimizePackage
        // which duplicates logic in ART Service (com.android.server.art.Utils.canDexoptPackage).
        MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_total",
                getOptimizablePackages(newSnapshot).size());
        MetricsLogger.histogram(mPm.mContext, "opt_dialog_time_s", elapsedTimeSeconds);
    }

    public List<String> getOptimizablePackages(@NonNull Computer snapshot) {
        ArrayList<String> pkgs = new ArrayList<>();
        mPm.forEachPackageState(snapshot, packageState -> {
            final AndroidPackage pkg = packageState.getPkg();
            if (pkg != null && mPm.mPackageDexOptimizer.canOptimizePackage(pkg)) {
                pkgs.add(packageState.getPackageName());
            }
        });
        return pkgs;
    }

    /*package*/ boolean performDexOpt(DexoptOptions options) {
        final Computer snapshot = mPm.snapshotComputer();
        if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) {
            return false;
        } else if (snapshot.isInstantApp(options.getPackageName(), UserHandle.getCallingUserId())) {
            return false;
        }
        var pkg = snapshot.getPackage(options.getPackageName());
        if (pkg != null && pkg.isApex()) {
            // skip APEX
            return true;
        }

        @DexOptResult int dexoptStatus;
        if (options.isDexoptOnlySecondaryDex()) {
            if (useArtService()) {
                dexoptStatus = performDexOptWithArtService(options, 0 /* extraFlags */);
            } else {
                try {
                    return mPm.getDexManager().dexoptSecondaryDex(options);
                } catch (LegacyDexoptDisabledException e) {
                    throw new RuntimeException(e);
                }
            }
        } else {
            dexoptStatus = performDexOptWithStatus(options);
        }
        return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
    }

    /**
     * Perform dexopt on the given package and return one of following result:
     * {@link PackageDexOptimizer#DEX_OPT_SKIPPED}
     * {@link PackageDexOptimizer#DEX_OPT_PERFORMED}
     * {@link PackageDexOptimizer#DEX_OPT_CANCELLED}
     * {@link PackageDexOptimizer#DEX_OPT_FAILED}
     */
    @DexOptResult
    /* package */ int performDexOptWithStatus(DexoptOptions options) {
        return performDexOptTraced(options);
    }

    @DexOptResult
    private int performDexOptTraced(DexoptOptions options) {
        Trace.traceBegin(TRACE_TAG_DALVIK, "dexopt");
        try {
            return performDexOptInternal(options);
        } finally {
            Trace.traceEnd(TRACE_TAG_DALVIK);
        }
    }

    // Run dexopt on a given package. Returns true if dexopt did not fail, i.e.
    // if the package can now be considered up to date for the given filter.
    @DexOptResult
    private int performDexOptInternal(DexoptOptions options) {
        if (useArtService()) {
            return performDexOptWithArtService(options, ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES);
        }

        AndroidPackage p;
        PackageSetting pkgSetting;
        synchronized (mPm.mLock) {
            p = mPm.mPackages.get(options.getPackageName());
            pkgSetting = mPm.mSettings.getPackageLPr(options.getPackageName());
            if (p == null || pkgSetting == null) {
                // Package could not be found. Report failure.
                return PackageDexOptimizer.DEX_OPT_FAILED;
            }
            if (p.isApex()) {
                // APEX needs no dexopt
                return PackageDexOptimizer.DEX_OPT_SKIPPED;
            }
            mPm.getPackageUsage().maybeWriteAsync(mPm.mSettings.getPackagesLocked());
            mPm.mCompilerStats.maybeWriteAsync();
        }
        final long callingId = Binder.clearCallingIdentity();
        try {
            return performDexOptInternalWithDependenciesLI(p, pkgSetting, options);
        } catch (LegacyDexoptDisabledException e) {
            throw new RuntimeException(e);
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
    }

    /**
     * Performs dexopt on the given package using ART Service. May only be called when ART Service
     * is enabled, i.e. when {@link useArtService} returns true.
     */
    @DexOptResult
    private int performDexOptWithArtService(DexoptOptions options,
            /*@DexoptFlags*/ int extraFlags) {
        try (PackageManagerLocal.FilteredSnapshot snapshot =
                        getPackageManagerLocal().withFilteredSnapshot()) {
            PackageState ops = snapshot.getPackageState(options.getPackageName());
            if (ops == null) {
                return PackageDexOptimizer.DEX_OPT_FAILED;
            }
            AndroidPackage oap = ops.getAndroidPackage();
            if (oap == null) {
                return PackageDexOptimizer.DEX_OPT_FAILED;
            }
            DexoptParams params = options.convertToDexoptParams(extraFlags);
            DexoptResult result =
                    getArtManagerLocal().dexoptPackage(snapshot, options.getPackageName(), params);
            return convertToDexOptResult(result);
        }
    }

    @DexOptResult
    private int performDexOptInternalWithDependenciesLI(
            AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options)
            throws LegacyDexoptDisabledException {
        if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) {
            // This needs to be done in odrefresh in early boot, for security reasons.
            throw new IllegalArgumentException("Cannot dexopt the system server");
        }

        // Select the dex optimizer based on the force parameter.
        // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
        //       allocate an object here.
        PackageDexOptimizer pdo = options.isForce()
                ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPm.mPackageDexOptimizer)
                : mPm.mPackageDexOptimizer;

        // Dexopt all dependencies first. Note: we ignore the return value and march on
        // on errors.
        // Note that we are going to call performDexOpt on those libraries as many times as
        // they are referenced in packages. When we do a batch of performDexOpt (for example
        // at boot, or background job), the passed 'targetCompilerFilter' stays the same,
        // and the first package that uses the library will dexopt it. The
        // others will see that the compiled code for the library is up to date.
        Collection<SharedLibraryInfo> deps = SharedLibraryUtils.findSharedLibraries(pkgSetting);
        final String[] instructionSets = getAppDexInstructionSets(
                pkgSetting.getPrimaryCpuAbi(),
                pkgSetting.getSecondaryCpuAbi());
        if (!deps.isEmpty()) {
            DexoptOptions libraryOptions = new DexoptOptions(options.getPackageName(),
                    options.getCompilationReason(), options.getCompilerFilter(),
                    options.getSplitName(),
                    options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY);
            for (SharedLibraryInfo info : deps) {
                Computer snapshot = mPm.snapshotComputer();
                AndroidPackage depPackage = snapshot.getPackage(info.getPackageName());
                PackageStateInternal depPackageStateInternal =
                        snapshot.getPackageStateInternal(info.getPackageName());
                if (depPackage != null && depPackageStateInternal != null) {
                    // TODO: Analyze and investigate if we (should) profile libraries.
                    pdo.performDexOpt(depPackage, depPackageStateInternal, instructionSets,
                            mPm.getOrCreateCompilerPackageStats(depPackage),
                            mPm.getDexManager().getPackageUseInfoOrDefault(
                                    depPackage.getPackageName()), libraryOptions);
                } else {
                    // TODO(ngeoffray): Support dexopting system shared libraries.
                }
            }
        }

        return pdo.performDexOpt(p, pkgSetting, instructionSets,
                mPm.getOrCreateCompilerPackageStats(p),
                mPm.getDexManager().getPackageUseInfoOrDefault(p.getPackageName()), options);
    }

    /** @deprecated For legacy shell command only. */
    @Deprecated
    public void forceDexOpt(@NonNull Computer snapshot, String packageName)
            throws LegacyDexoptDisabledException {
        PackageManagerServiceUtils.enforceSystemOrRoot("forceDexOpt");

        final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
        final AndroidPackage pkg = packageState == null ? null : packageState.getPkg();
        if (packageState == null || pkg == null) {
            throw new IllegalArgumentException("Unknown package: " + packageName);
        }
        if (pkg.isApex()) {
            throw new IllegalArgumentException("Can't dexopt APEX package: " + packageName);
        }

        Trace.traceBegin(TRACE_TAG_DALVIK, "dexopt");

        // Whoever is calling forceDexOpt wants a compiled package.
        // Don't use profiles since that may cause compilation to be skipped.
        DexoptOptions options = new DexoptOptions(packageName, REASON_CMDLINE,
                getDefaultCompilerFilter(), null /* splitName */,
                DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE);

        @DexOptResult int res = performDexOptInternalWithDependenciesLI(pkg, packageState, options);

        Trace.traceEnd(TRACE_TAG_DALVIK);
        if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
            throw new IllegalStateException("Failed to dexopt: " + res);
        }
    }

    public boolean performDexOptMode(@NonNull Computer snapshot, String packageName,
            String targetCompilerFilter, boolean force, boolean bootComplete, String splitName) {
        if (!PackageManagerServiceUtils.isSystemOrRootOrShell()
                && !isCallerInstallerForPackage(snapshot, packageName)) {
            throw new SecurityException("performDexOptMode");
        }

        int flags = (force ? DexoptOptions.DEXOPT_FORCE : 0)
                | (bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0);

        if (isProfileGuidedCompilerFilter(targetCompilerFilter)) {
            // Set this flag whenever the filter is profile guided, to align with ART Service
            // behavior.
            flags |= DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES;
        }

        return performDexOpt(new DexoptOptions(packageName, REASON_CMDLINE,
                targetCompilerFilter, splitName, flags));
    }

    private boolean isCallerInstallerForPackage(@NonNull Computer snapshot, String packageName) {
        final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
        if (packageState == null) {
            return false;
        }
        final InstallSource installSource = packageState.getInstallSource();

        final PackageStateInternal installerPackageState =
                snapshot.getPackageStateInternal(installSource.mInstallerPackageName);
        if (installerPackageState == null) {
            return false;
        }
        final AndroidPackage installerPkg = installerPackageState.getPkg();
        return installerPkg.getUid() == Binder.getCallingUid();
    }

    public boolean performDexOptSecondary(
            String packageName, String compilerFilter, boolean force) {
        int flags = DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX
                | DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES
                | DexoptOptions.DEXOPT_BOOT_COMPLETE
                | (force ? DexoptOptions.DEXOPT_FORCE : 0);
        return performDexOpt(new DexoptOptions(packageName, REASON_CMDLINE,
                compilerFilter, null /* splitName */, flags));
    }

    // Sort apps by importance for dexopt ordering. Important apps are given
    // more priority in case the device runs out of space.
    public static List<PackageStateInternal> getPackagesForDexopt(
            Collection<? extends PackageStateInternal> packages,
            PackageManagerService packageManagerService) {
        return getPackagesForDexopt(packages, packageManagerService, DEBUG_DEXOPT);
    }

    public static List<PackageStateInternal> getPackagesForDexopt(
            Collection<? extends PackageStateInternal> pkgSettings,
            PackageManagerService packageManagerService,
            boolean debug) {
        List<PackageStateInternal> result = new ArrayList<>();
        ArrayList<PackageStateInternal> remainingPkgSettings = new ArrayList<>(pkgSettings);

        // First, remove all settings without available packages
        remainingPkgSettings.removeIf(REMOVE_IF_NULL_PKG);
        remainingPkgSettings.removeIf(REMOVE_IF_APEX_PKG);

        ArrayList<PackageStateInternal> sortTemp = new ArrayList<>(remainingPkgSettings.size());

        final Computer snapshot = packageManagerService.snapshotComputer();

        // Give priority to core apps.
        applyPackageFilter(snapshot, pkgSetting -> pkgSetting.getPkg().isCoreApp(), result,
                remainingPkgSettings, sortTemp, packageManagerService);

        // Give priority to system apps that listen for pre boot complete.
        Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
        final ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
        applyPackageFilter(snapshot, pkgSetting -> pkgNames.contains(pkgSetting.getPackageName()), result,
                remainingPkgSettings, sortTemp, packageManagerService);

        // Give priority to apps used by other apps.
        DexManager dexManager = packageManagerService.getDexManager();
        applyPackageFilter(snapshot, pkgSetting ->
                        dexManager.getPackageUseInfoOrDefault(pkgSetting.getPackageName())
                                .isAnyCodePathUsedByOtherApps(),
                result, remainingPkgSettings, sortTemp, packageManagerService);

        // Filter out packages that aren't recently used, add all remaining apps.
        // TODO: add a property to control this?
        Predicate<PackageStateInternal> remainingPredicate;
        if (!remainingPkgSettings.isEmpty()
                && packageManagerService.isHistoricalPackageUsageAvailable()) {
            if (debug) {
                Log.i(TAG, "Looking at historical package use");
            }
            // Get the package that was used last.
            PackageStateInternal lastUsed = Collections.max(remainingPkgSettings,
                    Comparator.comparingLong(
                            pkgSetting -> pkgSetting.getTransientState()
                                    .getLatestForegroundPackageUseTimeInMills()));
            if (debug) {
                Log.i(TAG, "Taking package " + lastUsed.getPackageName()
                        + " as reference in time use");
            }
            long estimatedPreviousSystemUseTime = lastUsed.getTransientState()
                    .getLatestForegroundPackageUseTimeInMills();
            // Be defensive if for some reason package usage has bogus data.
            if (estimatedPreviousSystemUseTime != 0) {
                final long cutoffTime = estimatedPreviousSystemUseTime - SEVEN_DAYS_IN_MILLISECONDS;
                remainingPredicate = pkgSetting -> pkgSetting.getTransientState()
                        .getLatestForegroundPackageUseTimeInMills() >= cutoffTime;
            } else {
                // No meaningful historical info. Take all.
                remainingPredicate = pkgSetting -> true;
            }
            sortPackagesByUsageDate(remainingPkgSettings, packageManagerService);
        } else {
            // No historical info. Take all.
            remainingPredicate = pkgSetting -> true;
        }
        applyPackageFilter(snapshot, remainingPredicate, result, remainingPkgSettings, sortTemp,
                packageManagerService);

        // Make sure the system server isn't in the result, because it can never be dexopted here.
        result.removeIf(pkgSetting -> PLATFORM_PACKAGE_NAME.equals(pkgSetting.getPackageName()));

        if (debug) {
            Log.i(TAG, "Packages to be dexopted: " + packagesToString(result));
            Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgSettings));
        }

        return result;
    }

    // Apply the given {@code filter} to all packages in {@code packages}. If tested positive, the
    // package will be removed from {@code packages} and added to {@code result} with its
    // dependencies. If usage data is available, the positive packages will be sorted by usage
    // data (with {@code sortTemp} as temporary storage).
    private static void applyPackageFilter(@NonNull Computer snapshot,
            Predicate<PackageStateInternal> filter,
            Collection<PackageStateInternal> result,
            Collection<PackageStateInternal> packages,
            @NonNull List<PackageStateInternal> sortTemp,
            PackageManagerService packageManagerService) {
        for (PackageStateInternal pkgSetting : packages) {
            if (filter.test(pkgSetting)) {
                sortTemp.add(pkgSetting);
            }
        }

        sortPackagesByUsageDate(sortTemp, packageManagerService);
        packages.removeAll(sortTemp);

        for (PackageStateInternal pkgSetting : sortTemp) {
            result.add(pkgSetting);

            List<PackageStateInternal> deps = snapshot.findSharedNonSystemLibraries(pkgSetting);
            if (!deps.isEmpty()) {
                deps.removeAll(result);
                result.addAll(deps);
                packages.removeAll(deps);
            }
        }

        sortTemp.clear();
    }

    // Sort a list of apps by their last usage, most recently used apps first. The order of
    // packages without usage data is undefined (but they will be sorted after the packages
    // that do have usage data).
    private static void sortPackagesByUsageDate(List<PackageStateInternal> pkgSettings,
            PackageManagerService packageManagerService) {
        if (!packageManagerService.isHistoricalPackageUsageAvailable()) {
            return;
        }

        Collections.sort(pkgSettings, (pkgSetting1, pkgSetting2) ->
                Long.compare(
                        pkgSetting2.getTransientState().getLatestForegroundPackageUseTimeInMills(),
                        pkgSetting1.getTransientState().getLatestForegroundPackageUseTimeInMills())
        );
    }

    private static ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
        List<ResolveInfo> ris = null;
        try {
            ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId)
                    .getList();
        } catch (RemoteException e) {
        }
        ArraySet<String> pkgNames = new ArraySet<String>();
        if (ris != null) {
            for (ResolveInfo ri : ris) {
                pkgNames.add(ri.activityInfo.packageName);
            }
        }
        return pkgNames;
    }

    public static String packagesToString(List<PackageStateInternal> pkgSettings) {
        StringBuilder sb = new StringBuilder();
        for (int index = 0; index < pkgSettings.size(); index++) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(pkgSettings.get(index).getPackageName());
        }
        return sb.toString();
    }

     /**
     * Requests that files preopted on a secondary system partition be copied to the data partition
     * if possible.  Note that the actual copying of the files is accomplished by init for security
     * reasons. This simply requests that the copy takes place and awaits confirmation of its
     * completion. See platform/system/extras/cppreopt/ for the implementation of the actual copy.
     */
    public static void requestCopyPreoptedFiles() {
        final int WAIT_TIME_MS = 100;
        final String CP_PREOPT_PROPERTY = "sys.cppreopt";
        if (SystemProperties.getInt("ro.cp_system_other_odex", 0) == 1) {
            SystemProperties.set(CP_PREOPT_PROPERTY, "requested");
            // We will wait for up to 100 seconds.
            final long timeStart = SystemClock.uptimeMillis();
            final long timeEnd = timeStart + 100 * 1000;
            long timeNow = timeStart;
            while (!SystemProperties.get(CP_PREOPT_PROPERTY).equals("finished")) {
                try {
                    Thread.sleep(WAIT_TIME_MS);
                } catch (InterruptedException e) {
                    // Do nothing
                }
                timeNow = SystemClock.uptimeMillis();
                if (timeNow > timeEnd) {
                    SystemProperties.set(CP_PREOPT_PROPERTY, "timed-out");
                    Slog.wtf(TAG, "cppreopt did not finish!");
                    break;
                }
            }

            Slog.i(TAG, "cppreopts took " + (timeNow - timeStart) + " ms");
        }
    }

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

    /**
     * Dumps the dexopt state for the given package, or all packages if it is null.
     */
    public static void dumpDexoptState(
            @NonNull IndentingPrintWriter ipw, @Nullable String packageName) {
        try (PackageManagerLocal.FilteredSnapshot snapshot =
                        getPackageManagerLocal().withFilteredSnapshot()) {
            if (packageName != null) {
                try {
                    DexOptHelper.getArtManagerLocal().dumpPackage(ipw, snapshot, packageName);
                } catch (IllegalArgumentException e) {
                    // Package isn't found, but that should only happen due to race.
                    ipw.println(e);
                }
            } else {
                DexOptHelper.getArtManagerLocal().dump(ipw, snapshot);
            }
        }
    }

    /**
     * Returns the module names of the APEXes that contribute to bootclasspath.
     */
    private static List<String> getBcpApexes() {
        String bcp = System.getenv("BOOTCLASSPATH");
        if (TextUtils.isEmpty(bcp)) {
            Log.e(TAG, "Unable to get BOOTCLASSPATH");
            return List.of();
        }

        ArrayList<String> bcpApexes = new ArrayList<>();
        for (String pathStr : bcp.split(":")) {
            Path path = Paths.get(pathStr);
            // Check if the path is in the format of `/apex/<apex-module-name>/...` and extract the
            // apex module name from the path.
            if (path.getNameCount() >= 2 && path.getName(0).toString().equals("apex")) {
                bcpApexes.add(path.getName(1).toString());
            }
        }

        return bcpApexes;
    }

    /**
     * Returns true of any of the APEXes that contribute to bootclasspath has changed during this
     * boot.
     */
    private static boolean hasBcpApexesChanged() {
        Set<String> bcpApexes = new HashSet<>(getBcpApexes());
        ApexManager apexManager = ApexManager.getInstance();
        for (ActiveApexInfo apexInfo : apexManager.getActiveApexInfos()) {
            if (bcpApexes.contains(apexInfo.apexModuleName) && apexInfo.activeApexChanged) {
                return true;
            }
        }
        return false;
    }

    /**
     * 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.
     */
    public static @Nullable DexUseManagerLocal getDexUseManagerLocal() {
        if (!useArtService()) {
            return null;
        }
        try {
            return LocalManagerRegistry.getManagerOrThrow(DexUseManagerLocal.class);
        } catch (ManagerNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    private class DexoptDoneHandler implements ArtManagerLocal.DexoptDoneCallback {
        /**
         * Called after every package dexopt operation done by {@link ArtManagerLocal} (when ART
         * Service is in use).
         */
        @Override
        public void onDexoptDone(@NonNull DexoptResult result) {
            switch (result.getReason()) {
                case ReasonMapping.REASON_FIRST_BOOT:
                case ReasonMapping.REASON_BOOT_AFTER_OTA:
                case ReasonMapping.REASON_BOOT_AFTER_MAINLINE_UPDATE:
                    int numDexopted = 0;
                    int numSkipped = 0;
                    int numFailed = 0;
                    for (DexoptResult.PackageDexoptResult pkgRes :
                            result.getPackageDexoptResults()) {
                        switch (pkgRes.getStatus()) {
                            case DexoptResult.DEXOPT_PERFORMED:
                                numDexopted += 1;
                                break;
                            case DexoptResult.DEXOPT_SKIPPED:
                                numSkipped += 1;
                                break;
                            case DexoptResult.DEXOPT_FAILED:
                                numFailed += 1;
                                break;
                        }
                    }

                    reportBootDexopt(mBootDexoptStartTime, numDexopted, numSkipped, numFailed);
                    break;
            }

            for (DexoptResult.PackageDexoptResult pkgRes : result.getPackageDexoptResults()) {
                CompilerStats.PackageStats stats =
                        mPm.getOrCreateCompilerPackageStats(pkgRes.getPackageName());
                for (DexoptResult.DexContainerFileDexoptResult dexRes :
                        pkgRes.getDexContainerFileDexoptResults()) {
                    stats.setCompileTime(
                            dexRes.getDexContainerFile(), dexRes.getDex2oatWallTimeMillis());
                }
            }

            synchronized (mPm.mLock) {
                mPm.getPackageUsage().maybeWriteAsync(mPm.mSettings.getPackagesLocked());
                mPm.mCompilerStats.maybeWriteAsync();
            }

            if (result.getReason().equals(ReasonMapping.REASON_INACTIVE)) {
                for (DexoptResult.PackageDexoptResult pkgRes : result.getPackageDexoptResults()) {
                    if (pkgRes.getStatus() == DexoptResult.DEXOPT_PERFORMED) {
                        long pkgSizeBytes = 0;
                        long pkgSizeBeforeBytes = 0;
                        for (DexoptResult.DexContainerFileDexoptResult dexRes :
                                pkgRes.getDexContainerFileDexoptResults()) {
                            long dexContainerSize = new File(dexRes.getDexContainerFile()).length();
                            pkgSizeBytes += dexRes.getSizeBytes() + dexContainerSize;
                            pkgSizeBeforeBytes += dexRes.getSizeBeforeBytes() + dexContainerSize;
                        }
                        FrameworkStatsLog.write(FrameworkStatsLog.APP_DOWNGRADED,
                                pkgRes.getPackageName(), pkgSizeBeforeBytes, pkgSizeBytes,
                                false /* aggressive */);
                    }
                }
            }

            var updatedPackages = new ArraySet<String>();
            for (DexoptResult.PackageDexoptResult pkgRes : result.getPackageDexoptResults()) {
                if (pkgRes.hasUpdatedArtifacts()) {
                    updatedPackages.add(pkgRes.getPackageName());
                }
            }
            if (!updatedPackages.isEmpty()) {
                LocalServices.getService(PinnerService.class)
                        .update(updatedPackages, false /* force */);
            }
        }
    }

    /**
     * Initializes {@link ArtManagerLocal} before {@link getArtManagerLocal} is called.
     */
    public static void initializeArtManagerLocal(
            @NonNull Context systemContext, @NonNull PackageManagerService pm) {
        if (!useArtService()) {
            return;
        }

        ArtManagerLocal artManager = new ArtManagerLocal(systemContext);
        artManager.addDexoptDoneCallback(false /* onlyIncludeUpdates */, Runnable::run,
                pm.getDexOptHelper().new DexoptDoneHandler());
        LocalManagerRegistry.addManager(ArtManagerLocal.class, artManager);
        sArtManagerLocalIsInitialized = true;

        // Schedule the background job when boot is complete. This decouples us from when
        // JobSchedulerService is initialized.
        systemContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                context.unregisterReceiver(this);
                artManager.scheduleBackgroundDexoptJob();
            }
        }, new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED));

        StagedApexObserver.registerForStagedApexUpdates(artManager);
    }

    /**
     * Returns true if an {@link ArtManagerLocal} instance has been created.
     *
     * Avoid this function if at all possible, because it may hide initialization order problems.
     */
    public static boolean artManagerLocalIsInitialized() {
        return sArtManagerLocalIsInitialized;
    }

    /**
     * Returns the registered {@link ArtManagerLocal} instance, or else throws an unchecked error.
     */
    public static @NonNull ArtManagerLocal getArtManagerLocal() {
        try {
            return LocalManagerRegistry.getManagerOrThrow(ArtManagerLocal.class);
        } catch (ManagerNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Converts an ART Service {@link DexoptResult} to {@link DexOptResult}.
     *
     * For interfacing {@link ArtManagerLocal} with legacy dex optimization code in PackageManager.
     */
    @DexOptResult
    private static int convertToDexOptResult(DexoptResult result) {
        /*@DexoptResultStatus*/ int status = result.getFinalStatus();
        switch (status) {
            case DexoptResult.DEXOPT_SKIPPED:
                return PackageDexOptimizer.DEX_OPT_SKIPPED;
            case DexoptResult.DEXOPT_FAILED:
                return PackageDexOptimizer.DEX_OPT_FAILED;
            case DexoptResult.DEXOPT_PERFORMED:
                return PackageDexOptimizer.DEX_OPT_PERFORMED;
            case DexoptResult.DEXOPT_CANCELLED:
                return PackageDexOptimizer.DEX_OPT_CANCELLED;
            default:
                throw new IllegalArgumentException("DexoptResult for "
                        + result.getPackageDexoptResults().get(0).getPackageName()
                        + " has unsupported status " + status);
        }
    }

    private static class StagedApexObserver extends IStagedApexObserver.Stub {
        private final @NonNull ArtManagerLocal mArtManager;

        static void registerForStagedApexUpdates(@NonNull ArtManagerLocal artManager) {
            IPackageManagerNative packageNative = IPackageManagerNative.Stub.asInterface(
                    ServiceManager.getService("package_native"));
            if (packageNative == null) {
                Log.e(TAG, "No IPackageManagerNative");
                return;
            }

            try {
                packageNative.registerStagedApexObserver(new StagedApexObserver(artManager));
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to register staged apex observer", e);
            }
        }

        private StagedApexObserver(@NonNull ArtManagerLocal artManager) {
            mArtManager = artManager;
        }

        @Override
        public void onApexStaged(@NonNull ApexStagedEvent event) {
            mArtManager.onApexStaged(event.stagedApexModuleNames);
        }
    }
}
