diff options
| -rw-r--r-- | services/core/java/com/android/server/pm/DexOptHelper.java | 175 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/InstallPackageHelper.java | 6 |
2 files changed, 85 insertions, 96 deletions
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index f011d283c8bb..24b3765a698a 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -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,76 +746,74 @@ 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); + installRequest.onDexoptFinished(dexOptResult); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (installLock != null) { - installLock.unlock(); - } - try { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); - // Don't fail application installs if the dexopt step fails. - DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService( - installRequest, dexoptOptions); - installRequest.onDexoptFinished(dexOptResult); - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - if (installLock != null) { - installLock.lock(); - } + installLock.lock(); } } } - /** - * 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(() -> { - try { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); - // Don't fail application installs if the dexopt step fails. - // TODO(jiakaiz): 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. - Slog.wtf(TAG, "Dexopt encountered a fatal error", t); - return null; - }); - } else { + /** Same as above, but runs asynchronously. */ + static CompletableFuture<Void> performDexoptIfNeededAsync( + InstallRequest installRequest, DexManager dexManager) { + if (!shouldCallArtService(installRequest)) { return CompletableFuture.completedFuture(null); } + + 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(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. + Slog.wtf(TAG, "Dexopt encountered a fatal error", t); + return 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 { diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index b03e8ca7a215..299dd19b3507 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -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( |