summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/DexOptHelper.java175
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java6
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(