Loading services/core/java/com/android/server/pm/DexOptHelper.java +159 −8 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 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; Loading @@ -34,6 +35,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.REMOVE_IF_NULL_PK import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.ActivityManager; import android.app.AppGlobals; Loading @@ -56,9 +58,16 @@ import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.server.LocalManagerRegistry; import com.android.server.art.ArtManagerLocal; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.OptimizeParams; import com.android.server.art.model.OptimizeResult; 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 dalvik.system.DexFile; Loading @@ -72,11 +81,15 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; final class DexOptHelper { /** * 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 final PackageManagerService mPm; Loading Loading @@ -405,11 +418,12 @@ final class DexOptHelper { * {@link PackageDexOptimizer#DEX_OPT_CANCELLED} * {@link PackageDexOptimizer#DEX_OPT_FAILED} */ @PackageDexOptimizer.DexOptResult @DexOptResult /* package */ int performDexOptWithStatus(DexoptOptions options) { return performDexOptTraced(options); } @DexOptResult private int performDexOptTraced(DexoptOptions options) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); try { Loading @@ -421,7 +435,13 @@ final class DexOptHelper { // 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) { Optional<Integer> artSrvRes = performDexOptWithArtService(options); if (artSrvRes.isPresent()) { return artSrvRes.get(); } AndroidPackage p; PackageSetting pkgSetting; synchronized (mPm.mLock) { Loading @@ -446,8 +466,74 @@ final class DexOptHelper { } } private int performDexOptInternalWithDependenciesLI(AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) { /** * Performs dexopt on the given package using ART Service. * * @return a {@link DexOptResult}, or empty if the request isn't supported so that it is * necessary to fall back to the legacy code paths. */ private Optional<Integer> performDexOptWithArtService(DexoptOptions options) { ArtManagerLocal artManager = getArtManagerLocal(); if (artManager == null) { return Optional.empty(); } try (PackageManagerLocal.FilteredSnapshot snapshot = getPackageManagerLocal().withFilteredSnapshot()) { PackageState ops = snapshot.getPackageState(options.getPackageName()); if (ops == null) { return Optional.of(PackageDexOptimizer.DEX_OPT_FAILED); } AndroidPackage oap = ops.getAndroidPackage(); if (oap == null) { return Optional.of(PackageDexOptimizer.DEX_OPT_FAILED); } if (oap.isApex()) { return Optional.of(PackageDexOptimizer.DEX_OPT_SKIPPED); } // TODO(b/245301593): Delete the conditional when ART Service supports // FLAG_SHOULD_INCLUDE_DEPENDENCIES and we can just set it unconditionally. /*@OptimizeFlags*/ int extraFlags = ops.getUsesLibraries().isEmpty() ? 0 : ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES; OptimizeParams params = options.convertToOptimizeParams(extraFlags); if (params == null) { return Optional.empty(); } // TODO(b/251903639): Either remove controlDexOptBlocking, or don't ignore it here. OptimizeResult result; try { result = artManager.optimizePackage(snapshot, options.getPackageName(), params); } catch (UnsupportedOperationException e) { reportArtManagerFallback(options.getPackageName(), e.toString()); return Optional.empty(); } // TODO(b/251903639): Move this to ArtManagerLocal.addOptimizePackageDoneCallback when // it is implemented. for (OptimizeResult.PackageOptimizeResult pkgRes : result.getPackageOptimizeResults()) { PackageState ps = snapshot.getPackageState(pkgRes.getPackageName()); AndroidPackage ap = ps != null ? ps.getAndroidPackage() : null; if (ap != null) { CompilerStats.PackageStats stats = mPm.getOrCreateCompilerPackageStats(ap); for (OptimizeResult.DexContainerFileOptimizeResult dexRes : pkgRes.getDexContainerFileOptimizeResults()) { stats.setCompileTime( dexRes.getDexContainerFile(), dexRes.getDex2oatWallTimeMillis()); } } } return Optional.of(convertToDexOptResult(result)); } } @DexOptResult private int performDexOptInternalWithDependenciesLI( AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) { // System server gets a special path. if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) { return mPm.getDexManager().dexoptSystemServer(options); Loading Loading @@ -514,10 +600,20 @@ final class DexOptHelper { // Whoever is calling forceDexOpt wants a compiled package. // Don't use profiles since that may cause compilation to be skipped. final int res = performDexOptInternalWithDependenciesLI(pkg, packageState, new DexoptOptions(packageName, REASON_CMDLINE, DexoptOptions options = new DexoptOptions(packageName, REASON_CMDLINE, getDefaultCompilerFilter(), null /* splitName */, DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE)); DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE); // performDexOptWithArtService ignores the snapshot and takes its own, so it can race with // the package checks above, but at worst the effect is only a bit less friendly error // below. Optional<Integer> artSrvRes = performDexOptWithArtService(options); int res; if (artSrvRes.isPresent()) { res = artSrvRes.get(); } else { res = performDexOptInternalWithDependenciesLI(pkg, packageState, options); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) { Loading Loading @@ -800,4 +896,59 @@ final class DexOptHelper { } return false; } private @NonNull PackageManagerLocal getPackageManagerLocal() { try { return LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal.class); } catch (ManagerNotFoundException e) { throw new RuntimeException(e); } } /** * Called whenever we need to fall back from ART Service to the legacy dexopt code. */ public static void reportArtManagerFallback(String packageName, String reason) { // STOPSHIP(b/251903639): Minimize these calls to avoid platform getting shipped with code // paths that will always bypass ART Service. Slog.i(TAG, "Falling back to old PackageManager dexopt for " + packageName + ": " + reason); } /** * Returns {@link ArtManagerLocal} if one is found and should be used for package optimization. */ private @Nullable ArtManagerLocal getArtManagerLocal() { if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { return null; } try { return LocalManagerRegistry.getManagerOrThrow(ArtManagerLocal.class); } catch (ManagerNotFoundException e) { throw new RuntimeException(e); } } /** * Converts an ART Service {@link OptimizeResult} to {@link DexOptResult}. * * For interfacing {@link ArtManagerLocal} with legacy dex optimization code in PackageManager. */ @DexOptResult private static int convertToDexOptResult(OptimizeResult result) { /*@OptimizeStatus*/ int status = result.getFinalStatus(); switch (status) { case OptimizeResult.OPTIMIZE_SKIPPED: return PackageDexOptimizer.DEX_OPT_SKIPPED; case OptimizeResult.OPTIMIZE_FAILED: return PackageDexOptimizer.DEX_OPT_FAILED; case OptimizeResult.OPTIMIZE_PERFORMED: return PackageDexOptimizer.DEX_OPT_PERFORMED; case OptimizeResult.OPTIMIZE_CANCELLED: return PackageDexOptimizer.DEX_OPT_CANCELLED; default: throw new IllegalArgumentException("OptimizeResult for " + result.getPackageOptimizeResults().get(0).getPackageName() + " has unsupported status " + status); } } } services/core/java/com/android/server/pm/dex/DexoptOptions.java +139 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,16 @@ package com.android.server.pm.dex; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; import android.annotation.Nullable; import com.android.server.art.ReasonMapping; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.OptimizeParams; import com.android.server.pm.DexOptHelper; import com.android.server.pm.PackageManagerService; import dalvik.system.DexFile; /** * Options used for dexopt invocations. */ Loading Loading @@ -189,4 +199,133 @@ public final class DexoptOptions { mSplitName, mFlags); } /** * Returns an {@link OptimizeParams} instance corresponding to this object, for use with * {@link com.android.server.art.ArtManagerLocal}. * * @param extraFlags extra {@link ArtFlags#OptimizeFlags} to set in the returned * {@code OptimizeParams} beyond those converted from this object * @return null if the settings cannot be accurately represented, and hence the old * PackageManager/installd code paths need to be used. */ public @Nullable OptimizeParams convertToOptimizeParams(/*@OptimizeFlags*/ int extraFlags) { if (mSplitName != null) { DexOptHelper.reportArtManagerFallback( mPackageName, "Request to optimize only split " + mSplitName); return null; } /*@OptimizeFlags*/ int flags = extraFlags; if ((mFlags & DEXOPT_CHECK_FOR_PROFILES_UPDATES) == 0 && DexFile.isProfileGuidedCompilerFilter(mCompilerFilter)) { // ART Service doesn't support bypassing this, so not setting this flag is not // supported. DexOptHelper.reportArtManagerFallback(mPackageName, "DEXOPT_CHECK_FOR_PROFILES_UPDATES not set with profile compiler filter"); return null; } if ((mFlags & DEXOPT_FORCE) != 0) { flags |= ArtFlags.FLAG_FORCE; } if ((mFlags & DEXOPT_ONLY_SECONDARY_DEX) != 0) { flags |= ArtFlags.FLAG_FOR_SECONDARY_DEX; } else { flags |= ArtFlags.FLAG_FOR_PRIMARY_DEX; } if ((mFlags & DEXOPT_DOWNGRADE) != 0) { flags |= ArtFlags.FLAG_SHOULD_DOWNGRADE; } if ((mFlags & DEXOPT_INSTALL_WITH_DEX_METADATA_FILE) == 0) { // ART Service cannot be instructed to ignore a DM file if present, so not setting this // flag is not supported. DexOptHelper.reportArtManagerFallback( mPackageName, "DEXOPT_INSTALL_WITH_DEX_METADATA_FILE not set"); return null; } /*@PriorityClassApi*/ int priority; // Replicates logic in RunDex2Oat::PrepareCompilerRuntimeAndPerfConfigFlags in installd. if ((mFlags & DEXOPT_BOOT_COMPLETE) != 0) { if ((mFlags & DEXOPT_FOR_RESTORE) != 0) { priority = ArtFlags.PRIORITY_INTERACTIVE_FAST; } else { // TODO(b/251903639): Repurpose DEXOPT_IDLE_BACKGROUND_JOB to choose new // dalvik.vm.background-dex2oat-* properties. priority = ArtFlags.PRIORITY_INTERACTIVE; } } else { priority = ArtFlags.PRIORITY_BOOT; } // The following flags in mFlags are ignored: // // - DEXOPT_AS_SHARED_LIBRARY: It's implicit with ART Service since it always looks at // <uses-library> rather than actual dependencies. // // We don't require it to be set either. It's safe when switching between old and new // code paths since the only effect is that some packages may be unnecessarily compiled // without user profiles. // // - DEXOPT_IDLE_BACKGROUND_JOB: Its only effect is to allow the debug variant dex2oatd to // be used, but ART Service never uses that (cf. Artd::GetDex2Oat in artd.cc). String reason; switch (mCompilationReason) { case PackageManagerService.REASON_FIRST_BOOT: reason = ReasonMapping.REASON_FIRST_BOOT; break; case PackageManagerService.REASON_BOOT_AFTER_OTA: reason = ReasonMapping.REASON_BOOT_AFTER_OTA; break; case PackageManagerService.REASON_POST_BOOT: // This reason will go away with the legacy dexopt code. DexOptHelper.reportArtManagerFallback( mPackageName, "Unsupported compilation reason REASON_POST_BOOT"); return null; case PackageManagerService.REASON_INSTALL: reason = ReasonMapping.REASON_INSTALL; break; case PackageManagerService.REASON_INSTALL_FAST: reason = ReasonMapping.REASON_INSTALL_FAST; break; case PackageManagerService.REASON_INSTALL_BULK: reason = ReasonMapping.REASON_INSTALL_BULK; break; case PackageManagerService.REASON_INSTALL_BULK_SECONDARY: reason = ReasonMapping.REASON_INSTALL_BULK_SECONDARY; break; case PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED: reason = ReasonMapping.REASON_INSTALL_BULK_DOWNGRADED; break; case PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED: reason = ReasonMapping.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; break; case PackageManagerService.REASON_BACKGROUND_DEXOPT: reason = ReasonMapping.REASON_BG_DEXOPT; break; case PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE: reason = ReasonMapping.REASON_INACTIVE; break; case PackageManagerService.REASON_CMDLINE: reason = ReasonMapping.REASON_CMDLINE; break; case PackageManagerService.REASON_SHARED: case PackageManagerService.REASON_AB_OTA: // REASON_SHARED shouldn't go into this code path - it's only used at lower levels // in PackageDexOptimizer. // TODO(b/251921228): OTA isn't supported, so REASON_AB_OTA shouldn't come this way // either. throw new UnsupportedOperationException( "ART Service unsupported compilation reason " + mCompilationReason); default: throw new IllegalArgumentException( "Invalid compilation reason " + mCompilationReason); } return new OptimizeParams.Builder(reason, flags) .setCompilerFilter(mCompilerFilter) .setPriorityClass(priority) .build(); } } Loading
services/core/java/com/android/server/pm/DexOptHelper.java +159 −8 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 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; Loading @@ -34,6 +35,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.REMOVE_IF_NULL_PK import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.ActivityManager; import android.app.AppGlobals; Loading @@ -56,9 +58,16 @@ import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.server.LocalManagerRegistry; import com.android.server.art.ArtManagerLocal; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.OptimizeParams; import com.android.server.art.model.OptimizeResult; 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 dalvik.system.DexFile; Loading @@ -72,11 +81,15 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; final class DexOptHelper { /** * 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 final PackageManagerService mPm; Loading Loading @@ -405,11 +418,12 @@ final class DexOptHelper { * {@link PackageDexOptimizer#DEX_OPT_CANCELLED} * {@link PackageDexOptimizer#DEX_OPT_FAILED} */ @PackageDexOptimizer.DexOptResult @DexOptResult /* package */ int performDexOptWithStatus(DexoptOptions options) { return performDexOptTraced(options); } @DexOptResult private int performDexOptTraced(DexoptOptions options) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); try { Loading @@ -421,7 +435,13 @@ final class DexOptHelper { // 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) { Optional<Integer> artSrvRes = performDexOptWithArtService(options); if (artSrvRes.isPresent()) { return artSrvRes.get(); } AndroidPackage p; PackageSetting pkgSetting; synchronized (mPm.mLock) { Loading @@ -446,8 +466,74 @@ final class DexOptHelper { } } private int performDexOptInternalWithDependenciesLI(AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) { /** * Performs dexopt on the given package using ART Service. * * @return a {@link DexOptResult}, or empty if the request isn't supported so that it is * necessary to fall back to the legacy code paths. */ private Optional<Integer> performDexOptWithArtService(DexoptOptions options) { ArtManagerLocal artManager = getArtManagerLocal(); if (artManager == null) { return Optional.empty(); } try (PackageManagerLocal.FilteredSnapshot snapshot = getPackageManagerLocal().withFilteredSnapshot()) { PackageState ops = snapshot.getPackageState(options.getPackageName()); if (ops == null) { return Optional.of(PackageDexOptimizer.DEX_OPT_FAILED); } AndroidPackage oap = ops.getAndroidPackage(); if (oap == null) { return Optional.of(PackageDexOptimizer.DEX_OPT_FAILED); } if (oap.isApex()) { return Optional.of(PackageDexOptimizer.DEX_OPT_SKIPPED); } // TODO(b/245301593): Delete the conditional when ART Service supports // FLAG_SHOULD_INCLUDE_DEPENDENCIES and we can just set it unconditionally. /*@OptimizeFlags*/ int extraFlags = ops.getUsesLibraries().isEmpty() ? 0 : ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES; OptimizeParams params = options.convertToOptimizeParams(extraFlags); if (params == null) { return Optional.empty(); } // TODO(b/251903639): Either remove controlDexOptBlocking, or don't ignore it here. OptimizeResult result; try { result = artManager.optimizePackage(snapshot, options.getPackageName(), params); } catch (UnsupportedOperationException e) { reportArtManagerFallback(options.getPackageName(), e.toString()); return Optional.empty(); } // TODO(b/251903639): Move this to ArtManagerLocal.addOptimizePackageDoneCallback when // it is implemented. for (OptimizeResult.PackageOptimizeResult pkgRes : result.getPackageOptimizeResults()) { PackageState ps = snapshot.getPackageState(pkgRes.getPackageName()); AndroidPackage ap = ps != null ? ps.getAndroidPackage() : null; if (ap != null) { CompilerStats.PackageStats stats = mPm.getOrCreateCompilerPackageStats(ap); for (OptimizeResult.DexContainerFileOptimizeResult dexRes : pkgRes.getDexContainerFileOptimizeResults()) { stats.setCompileTime( dexRes.getDexContainerFile(), dexRes.getDex2oatWallTimeMillis()); } } } return Optional.of(convertToDexOptResult(result)); } } @DexOptResult private int performDexOptInternalWithDependenciesLI( AndroidPackage p, @NonNull PackageStateInternal pkgSetting, DexoptOptions options) { // System server gets a special path. if (PLATFORM_PACKAGE_NAME.equals(p.getPackageName())) { return mPm.getDexManager().dexoptSystemServer(options); Loading Loading @@ -514,10 +600,20 @@ final class DexOptHelper { // Whoever is calling forceDexOpt wants a compiled package. // Don't use profiles since that may cause compilation to be skipped. final int res = performDexOptInternalWithDependenciesLI(pkg, packageState, new DexoptOptions(packageName, REASON_CMDLINE, DexoptOptions options = new DexoptOptions(packageName, REASON_CMDLINE, getDefaultCompilerFilter(), null /* splitName */, DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE)); DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE); // performDexOptWithArtService ignores the snapshot and takes its own, so it can race with // the package checks above, but at worst the effect is only a bit less friendly error // below. Optional<Integer> artSrvRes = performDexOptWithArtService(options); int res; if (artSrvRes.isPresent()) { res = artSrvRes.get(); } else { res = performDexOptInternalWithDependenciesLI(pkg, packageState, options); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) { Loading Loading @@ -800,4 +896,59 @@ final class DexOptHelper { } return false; } private @NonNull PackageManagerLocal getPackageManagerLocal() { try { return LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal.class); } catch (ManagerNotFoundException e) { throw new RuntimeException(e); } } /** * Called whenever we need to fall back from ART Service to the legacy dexopt code. */ public static void reportArtManagerFallback(String packageName, String reason) { // STOPSHIP(b/251903639): Minimize these calls to avoid platform getting shipped with code // paths that will always bypass ART Service. Slog.i(TAG, "Falling back to old PackageManager dexopt for " + packageName + ": " + reason); } /** * Returns {@link ArtManagerLocal} if one is found and should be used for package optimization. */ private @Nullable ArtManagerLocal getArtManagerLocal() { if (!"true".equals(SystemProperties.get("dalvik.vm.useartservice", ""))) { return null; } try { return LocalManagerRegistry.getManagerOrThrow(ArtManagerLocal.class); } catch (ManagerNotFoundException e) { throw new RuntimeException(e); } } /** * Converts an ART Service {@link OptimizeResult} to {@link DexOptResult}. * * For interfacing {@link ArtManagerLocal} with legacy dex optimization code in PackageManager. */ @DexOptResult private static int convertToDexOptResult(OptimizeResult result) { /*@OptimizeStatus*/ int status = result.getFinalStatus(); switch (status) { case OptimizeResult.OPTIMIZE_SKIPPED: return PackageDexOptimizer.DEX_OPT_SKIPPED; case OptimizeResult.OPTIMIZE_FAILED: return PackageDexOptimizer.DEX_OPT_FAILED; case OptimizeResult.OPTIMIZE_PERFORMED: return PackageDexOptimizer.DEX_OPT_PERFORMED; case OptimizeResult.OPTIMIZE_CANCELLED: return PackageDexOptimizer.DEX_OPT_CANCELLED; default: throw new IllegalArgumentException("OptimizeResult for " + result.getPackageOptimizeResults().get(0).getPackageName() + " has unsupported status " + status); } } }
services/core/java/com/android/server/pm/dex/DexoptOptions.java +139 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,16 @@ package com.android.server.pm.dex; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; import android.annotation.Nullable; import com.android.server.art.ReasonMapping; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.OptimizeParams; import com.android.server.pm.DexOptHelper; import com.android.server.pm.PackageManagerService; import dalvik.system.DexFile; /** * Options used for dexopt invocations. */ Loading Loading @@ -189,4 +199,133 @@ public final class DexoptOptions { mSplitName, mFlags); } /** * Returns an {@link OptimizeParams} instance corresponding to this object, for use with * {@link com.android.server.art.ArtManagerLocal}. * * @param extraFlags extra {@link ArtFlags#OptimizeFlags} to set in the returned * {@code OptimizeParams} beyond those converted from this object * @return null if the settings cannot be accurately represented, and hence the old * PackageManager/installd code paths need to be used. */ public @Nullable OptimizeParams convertToOptimizeParams(/*@OptimizeFlags*/ int extraFlags) { if (mSplitName != null) { DexOptHelper.reportArtManagerFallback( mPackageName, "Request to optimize only split " + mSplitName); return null; } /*@OptimizeFlags*/ int flags = extraFlags; if ((mFlags & DEXOPT_CHECK_FOR_PROFILES_UPDATES) == 0 && DexFile.isProfileGuidedCompilerFilter(mCompilerFilter)) { // ART Service doesn't support bypassing this, so not setting this flag is not // supported. DexOptHelper.reportArtManagerFallback(mPackageName, "DEXOPT_CHECK_FOR_PROFILES_UPDATES not set with profile compiler filter"); return null; } if ((mFlags & DEXOPT_FORCE) != 0) { flags |= ArtFlags.FLAG_FORCE; } if ((mFlags & DEXOPT_ONLY_SECONDARY_DEX) != 0) { flags |= ArtFlags.FLAG_FOR_SECONDARY_DEX; } else { flags |= ArtFlags.FLAG_FOR_PRIMARY_DEX; } if ((mFlags & DEXOPT_DOWNGRADE) != 0) { flags |= ArtFlags.FLAG_SHOULD_DOWNGRADE; } if ((mFlags & DEXOPT_INSTALL_WITH_DEX_METADATA_FILE) == 0) { // ART Service cannot be instructed to ignore a DM file if present, so not setting this // flag is not supported. DexOptHelper.reportArtManagerFallback( mPackageName, "DEXOPT_INSTALL_WITH_DEX_METADATA_FILE not set"); return null; } /*@PriorityClassApi*/ int priority; // Replicates logic in RunDex2Oat::PrepareCompilerRuntimeAndPerfConfigFlags in installd. if ((mFlags & DEXOPT_BOOT_COMPLETE) != 0) { if ((mFlags & DEXOPT_FOR_RESTORE) != 0) { priority = ArtFlags.PRIORITY_INTERACTIVE_FAST; } else { // TODO(b/251903639): Repurpose DEXOPT_IDLE_BACKGROUND_JOB to choose new // dalvik.vm.background-dex2oat-* properties. priority = ArtFlags.PRIORITY_INTERACTIVE; } } else { priority = ArtFlags.PRIORITY_BOOT; } // The following flags in mFlags are ignored: // // - DEXOPT_AS_SHARED_LIBRARY: It's implicit with ART Service since it always looks at // <uses-library> rather than actual dependencies. // // We don't require it to be set either. It's safe when switching between old and new // code paths since the only effect is that some packages may be unnecessarily compiled // without user profiles. // // - DEXOPT_IDLE_BACKGROUND_JOB: Its only effect is to allow the debug variant dex2oatd to // be used, but ART Service never uses that (cf. Artd::GetDex2Oat in artd.cc). String reason; switch (mCompilationReason) { case PackageManagerService.REASON_FIRST_BOOT: reason = ReasonMapping.REASON_FIRST_BOOT; break; case PackageManagerService.REASON_BOOT_AFTER_OTA: reason = ReasonMapping.REASON_BOOT_AFTER_OTA; break; case PackageManagerService.REASON_POST_BOOT: // This reason will go away with the legacy dexopt code. DexOptHelper.reportArtManagerFallback( mPackageName, "Unsupported compilation reason REASON_POST_BOOT"); return null; case PackageManagerService.REASON_INSTALL: reason = ReasonMapping.REASON_INSTALL; break; case PackageManagerService.REASON_INSTALL_FAST: reason = ReasonMapping.REASON_INSTALL_FAST; break; case PackageManagerService.REASON_INSTALL_BULK: reason = ReasonMapping.REASON_INSTALL_BULK; break; case PackageManagerService.REASON_INSTALL_BULK_SECONDARY: reason = ReasonMapping.REASON_INSTALL_BULK_SECONDARY; break; case PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED: reason = ReasonMapping.REASON_INSTALL_BULK_DOWNGRADED; break; case PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED: reason = ReasonMapping.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; break; case PackageManagerService.REASON_BACKGROUND_DEXOPT: reason = ReasonMapping.REASON_BG_DEXOPT; break; case PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE: reason = ReasonMapping.REASON_INACTIVE; break; case PackageManagerService.REASON_CMDLINE: reason = ReasonMapping.REASON_CMDLINE; break; case PackageManagerService.REASON_SHARED: case PackageManagerService.REASON_AB_OTA: // REASON_SHARED shouldn't go into this code path - it's only used at lower levels // in PackageDexOptimizer. // TODO(b/251921228): OTA isn't supported, so REASON_AB_OTA shouldn't come this way // either. throw new UnsupportedOperationException( "ART Service unsupported compilation reason " + mCompilationReason); default: throw new IllegalArgumentException( "Invalid compilation reason " + mCompilationReason); } return new OptimizeParams.Builder(reason, flags) .setCompilerFilter(mCompilerFilter) .setPriorityClass(priority) .build(); } }