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

Commit c3fce7a0 authored by Jiakai Zhang's avatar Jiakai Zhang Committed by Cherrypicker Worker
Browse files

Clean up DexOptHelper.

1. Removed the check on "instant_app_dexopt_enabled": It was added by
   ag/2412782, with the goal being "enable/disable dexopt for instant
   apps remotely" via "gservices". "gservices" is a predecessor of P/H
   (go/android-gservices), and instant apps are being deprecated
   (go/aia-instantapps-deprecation-plan), so nobody cares about the
   switch now.
2. Removed the check on "recoverability_detection": The flag is always
   enabled since Android 15.
3. Removed the DexoptOptions parameter from shouldPerformDexopt and
   deferred the construction of DexoptOptions: shouldPerformDexopt no
   longer needs DexoptOptions since ag/27755957.
4. Renamed shouldPerformDexopt to shouldCallArtService and added
   comments to clarify its exact behavior.
5. Added shouldSkipDexopt: This is the new preferred way to skip dexopt.
6. Removed the out-of-date comments about the shouldPerformDexopt
   conditions. Those comments have been out of sync with the actual
   conditions for a long time. The actual conditions are
   self-explanatory enough, so we don't really need comments.
7. Removed the out-of-date comments about performing dexopt on the first
   time the instant app starts. The current code doesn't have such a
   behavior.

Bug: 377474232
Test: Presubmit
Flag: EXEMPT refactor
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:07ee801f663fe6f171f542abac39848b7791db59)
Merged-In: I502823bcd53e0c52536afa86e78ac36428286c2f
Change-Id: I502823bcd53e0c52536afa86e78ac36428286c2f
parent 043265b1
Loading
Loading
Loading
Loading
+82 −93
Original line number Diff line number Diff line
@@ -726,11 +726,9 @@ public final class DexOptHelper {
        }
    }

    /**
     * Returns DexoptOptions by the given InstallRequest.
     */
    static DexoptOptions getDexoptOptionsByInstallRequest(InstallRequest installRequest,
            DexManager dexManager) {
    /** Returns DexoptOptions by the given InstallRequest. */
    private static DexoptOptions getDexoptOptionsByInstallRequest(
            InstallRequest installRequest, DexManager dexManager) {
        final PackageSetting ps = installRequest.getScannedPackageSetting();
        final String packageName = ps.getPackageName();
        final boolean isBackupOrRestore =
@@ -748,33 +746,33 @@ public final class DexOptHelper {
        var options = new DexoptOptions(packageName, compilationReason, dexoptFlags);
        if (installRequest.getDexoptCompilerFilter() != null) {
            options = options.overrideCompilerFilter(installRequest.getDexoptCompilerFilter());
        } else if (pkg != null && pkg.isDebuggable()) {
        } else if (shouldSkipDexopt(installRequest)) {
            options = options.overrideCompilerFilter(DexoptParams.COMPILER_FILTER_NOOP);
        }
        return options;
    }

    /**
     * Perform dexopt if needed for the installation
     */
    static void performDexoptIfNeeded(InstallRequest installRequest, DexManager dexManager,
            Context context, PackageManagerTracedLock.RawLock installLock) {
        // Construct the DexoptOptions early to see if we should skip running dexopt.
        DexoptOptions dexoptOptions = getDexoptOptionsByInstallRequest(installRequest, dexManager);
        boolean performDexopt =
                DexOptHelper.shouldPerformDexopt(installRequest, dexoptOptions, context);

        if (performDexopt) {
            // dexopt can take long, and ArtService doesn't require installd, so we release
            // the lock here and re-acquire the lock after dexopt is finished.
    /** Perform dexopt if needed for the installation */
    static void performDexoptIfNeeded(
            InstallRequest installRequest,
            DexManager dexManager,
            PackageManagerTracedLock.RawLock installLock) {
        if (!shouldCallArtService(installRequest)) {
            return;
        }

        // dexopt can take long, and ArtService doesn't require installd, so we release the lock
        // here and re-acquire the lock after dexopt is finished.
        if (installLock != null) {
            installLock.unlock();
        }
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
            DexoptOptions dexoptOptions =
                    getDexoptOptionsByInstallRequest(installRequest, dexManager);
            // Don't fail application installs if the dexopt step fails.
                DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService(
                        installRequest, dexoptOptions);
            DexoptResult dexOptResult =
                    DexOptHelper.dexoptPackageUsingArtService(installRequest, dexoptOptions);
            installRequest.onDexoptFinished(dexOptResult);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -783,41 +781,39 @@ public final class DexOptHelper {
            }
        }
    }

    /** Same as above, but runs asynchronously. */
    static CompletableFuture<Void> performDexoptIfNeededAsync(
            InstallRequest installRequest, DexManager dexManager) {
        if (!shouldCallArtService(installRequest)) {
            return CompletableFuture.completedFuture(null);
        }

    /**
     * Same as above, but runs asynchronously.
     */
    static CompletableFuture<Void> performDexoptIfNeededAsync(InstallRequest installRequest,
            DexManager dexManager, Context context) {
        // Construct the DexoptOptions early to see if we should skip running dexopt.
        DexoptOptions dexoptOptions = getDexoptOptionsByInstallRequest(installRequest, dexManager);
        boolean performDexopt =
                DexOptHelper.shouldPerformDexopt(installRequest, dexoptOptions, context);

        if (performDexopt) {
            return CompletableFuture
                    .runAsync(() -> {
        return CompletableFuture.runAsync(
                        () -> {
                            try {
                                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
                                DexoptOptions dexoptOptions =
                                        getDexoptOptionsByInstallRequest(
                                                installRequest, dexManager);
                                // Don't fail application installs if the dexopt step fails.
                            // TODO(jiakaiz): Make this async in ART Service.
                            DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService(
                                // TODO(b/393076925): Make this async in ART Service.
                                DexoptResult dexOptResult =
                                        DexOptHelper.dexoptPackageUsingArtService(
                                                installRequest, dexoptOptions);
                                installRequest.onDexoptFinished(dexOptResult);
                            } finally {
                                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                            }
                    }, sDexoptExecutor)
                    .exceptionally((t) -> {
                        // This should never happen. A normal dexopt failure should result in a
                        // DexoptResult.DEXOPT_FAILED, not an exception.
                        },
                        sDexoptExecutor)
                .exceptionally(
                        (t) -> {
                            // This should never happen. A normal dexopt failure should result
                            // in a DexoptResult.DEXOPT_FAILED, not an exception.
                            Slog.wtf(TAG, "Dexopt encountered a fatal error", t);
                            return null;
                        });
        } else {
            return CompletableFuture.completedFuture(null);
        }
    }

    /**
@@ -852,43 +848,36 @@ public final class DexOptHelper {
        }
    }

    private static boolean shouldSkipDexopt(InstallRequest installRequest) {
        PackageSetting ps = installRequest.getScannedPackageSetting();
        AndroidPackage pkg = ps.getPkg();
        return pkg == null || pkg.isDebuggable();
    }

    /**
     * Returns whether to perform dexopt by the given InstallRequest.
     * Returns whether to call ART Service to perform dexopt for the given InstallRequest. Note that
     * ART Service may still skip dexopt, depending on the specified compiler filter, compilation
     * reason, and other conditions.
     */
    static boolean shouldPerformDexopt(InstallRequest installRequest, DexoptOptions dexoptOptions,
            Context context) {
        // We only need to dexopt if the package meets ALL of the following conditions:
        //   1) it is not an instant app or if it is then dexopt is enabled via gservices.
        //   2) it is not debuggable.
        //   3) it is not on Incremental File System.
        //
        // Note that we do not dexopt instant apps by default. dexopt can take some time to
        // complete, so we skip this step during installation. Instead, we'll take extra time
        // the first time the instant app starts. It's preferred to do it this way to provide
        // continuous progress to the user instead of mysteriously blocking somewhere in the
        // middle of running an instant app. The default behaviour can be overridden
        // via gservices.
        //
        // Furthermore, dexopt may be skipped, depending on the install scenario and current
        // state of the device.
    private static boolean shouldCallArtService(InstallRequest installRequest) {
        final boolean isApex = ((installRequest.getScanFlags() & SCAN_AS_APEX) != 0);
        // Historically, we did not dexopt instant apps,  and we have no plan to do so in the
        // future, so there is no need to call into ART Service.
        final boolean instantApp = ((installRequest.getScanFlags() & SCAN_AS_INSTANT_APP) != 0);
        final PackageSetting ps = installRequest.getScannedPackageSetting();
        final AndroidPackage pkg = ps.getPkg();
        final boolean onIncremental = isIncrementalPath(ps.getPathString());
        final boolean performDexOptForRollback = Flags.recoverabilityDetection()
                ? !(installRequest.isRollback()
                && installRequest.getInstallSource().mInitiatingPackageName.equals("android"))
                : true;

        // Don't skip the dexopt call if the compiler filter is "skip". Instead, call dexopt with
        // the "skip" filter so that ART Service gets notified and skips dexopt itself.
        return (!instantApp || Global.getInt(context.getContentResolver(),
                Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                && pkg != null
                && (!onIncremental)
                && !isApex
                && performDexOptForRollback;
        final boolean performDexOptForRollback =
                !(installRequest.isRollback()
                        && installRequest
                                .getInstallSource()
                                .mInitiatingPackageName
                                .equals("android"));

        // THINK TWICE when you add a new condition here. You probably want to add a condition to
        // `shouldSkipDexopt` instead. In that way, ART Service will be called with the "skip"
        // compiler filter and it will have the chance to decide whether to skip dexopt.
        return !instantApp && pkg != null && !onIncremental && !isApex && performDexOptForRollback;
    }

    private static class StagedApexObserver extends IStagedApexObserver.Stub {
+3 −3
Original line number Diff line number Diff line
@@ -1152,7 +1152,7 @@ final class InstallPackageHelper {
            }
            request.setKeepArtProfile(true);
            // TODO(b/388159696): Use performDexoptIfNeededAsync.
            DexOptHelper.performDexoptIfNeeded(request, mDexManager, mContext, null);
            DexOptHelper.performDexoptIfNeeded(request, mDexManager, null /* installLock */);
        }
    }

@@ -2790,8 +2790,8 @@ final class InstallPackageHelper {
                                    | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                }

                DexOptHelper.performDexoptIfNeeded(installRequest, mDexManager, mContext,
                        mPm.mInstallLock.getRawLock());
                DexOptHelper.performDexoptIfNeeded(
                        installRequest, mDexManager, mPm.mInstallLock.getRawLock());
            }
        }
        PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental(