Always pass --dm-fd to dex2oat and change reason to "install-dm".
Bug: 255944781
Test: atest ArtServiceTests
Test: m test-art-host-gtest-art_artd_tests
Ignore-AOSP-First: ART Services.
Change-Id: Ibb8ffd6da39186cb571dbd9e59847bc2161ebd15
diff --git a/libartservice/service/java/com/android/server/art/DexOptimizer.java b/libartservice/service/java/com/android/server/art/DexOptimizer.java
index 8cfe8ad..356d74b 100644
--- a/libartservice/service/java/com/android/server/art/DexOptimizer.java
+++ b/libartservice/service/java/com/android/server/art/DexOptimizer.java
@@ -148,13 +148,13 @@
long wallTimeMs = 0;
long cpuTimeMs = 0;
try {
- DexoptTarget target = DexoptTarget.builder()
+ var target = DexoptTarget.<DexInfoType>builder()
.setDexInfo(dexInfo)
.setIsa(abi.isa())
.setIsInDalvikCache(isInDalvikCache())
.setCompilerFilter(compilerFilter)
.build();
- GetDexoptNeededOptions options =
+ var options =
GetDexoptNeededOptions.builder()
.setProfileMerged(profileMerged)
.setFlags(mParams.getFlags())
@@ -346,7 +346,7 @@
}
@NonNull
- GetDexoptNeededResult getDexoptNeeded(@NonNull DexoptTarget target,
+ GetDexoptNeededResult getDexoptNeeded(@NonNull DexoptTarget<DexInfoType> target,
@NonNull GetDexoptNeededOptions options) throws RemoteException {
int dexoptTrigger = getDexoptTrigger(target, options);
@@ -362,8 +362,8 @@
return result;
}
- int getDexoptTrigger(@NonNull DexoptTarget target, @NonNull GetDexoptNeededOptions options)
- throws RemoteException {
+ int getDexoptTrigger(@NonNull DexoptTarget<DexInfoType> target,
+ @NonNull GetDexoptNeededOptions options) throws RemoteException {
if ((options.flags() & ArtFlags.FLAG_FORCE) != 0) {
return DexoptTrigger.COMPILER_FILTER_IS_BETTER | DexoptTrigger.COMPILER_FILTER_IS_SAME
| DexoptTrigger.COMPILER_FILTER_IS_WORSE
@@ -396,8 +396,8 @@
return dexoptTrigger;
}
- private DexoptResult dexoptFile(@NonNull DexoptTarget target, @Nullable ProfilePath profile,
- @NonNull GetDexoptNeededResult getDexoptNeededResult,
+ private DexoptResult dexoptFile(@NonNull DexoptTarget<DexInfoType> target,
+ @Nullable ProfilePath profile, @NonNull GetDexoptNeededResult getDexoptNeededResult,
@NonNull PermissionSettings permissionSettings, @PriorityClass int priorityClass,
@NonNull DexoptOptions dexoptOptions, IArtdCancellationSignal artdCancellationSignal)
throws RemoteException {
@@ -407,9 +407,25 @@
VdexPath inputVdex =
getInputVdex(getDexoptNeededResult, target.dexInfo().dexPath(), target.isa());
+ DexMetadataPath dmFile = getDmFile(target.dexInfo());
+ if (dmFile != null
+ && ReasonMapping.REASONS_FOR_INSTALL.contains(dexoptOptions.compilationReason)) {
+ // If the DM file is passed to dex2oat, then add the "-dm" suffix to the reason (e.g.,
+ // "install-dm").
+ // Note that this only applies to reasons for app install because the goal is to give
+ // Play a signal that a DM file is downloaded at install time. We actually pass the DM
+ // file regardless of the compilation reason, but we don't append a suffix when the
+ // compilation reason is not a reason for app install.
+ // Also note that the "-dm" suffix does NOT imply anything in the DM file being used by
+ // dex2oat. dex2oat may ignore some contents of the DM file when appropriate. The
+ // compilation reason can still be "install-dm" even if dex2oat left all contents of the
+ // DM file unused or an empty DM file is passed to dex2oat.
+ dexoptOptions.compilationReason = dexoptOptions.compilationReason + "-dm";
+ }
+
return mInjector.getArtd().dexopt(outputArtifacts, target.dexInfo().dexPath(), target.isa(),
target.dexInfo().classLoaderContext(), target.compilerFilter(), profile, inputVdex,
- priorityClass, dexoptOptions, artdCancellationSignal);
+ dmFile, priorityClass, dexoptOptions, artdCancellationSignal);
}
@Nullable
@@ -426,7 +442,8 @@
return VdexPath.artifactsPath(
AidlUtils.buildArtifactsPath(dexPath, isa, false /* isInDalvikCache */));
case ArtifactsLocation.DM:
- return VdexPath.dexMetadataPath(AidlUtils.buildDexMetadataPath(dexPath));
+ // The DM file is passed to dex2oat as a separate flag whenever it exists.
+ return null;
default:
// This should never happen as the value is got from artd.
throw new IllegalStateException(
@@ -434,6 +451,22 @@
}
}
+ @Nullable
+ private DexMetadataPath getDmFile(@NonNull DexInfoType dexInfo) throws RemoteException {
+ DexMetadataPath path = buildDmPath(dexInfo);
+ if (path == null) {
+ return null;
+ }
+ try {
+ if (mInjector.getArtd().getDmFileVisibility(path) != FileVisibility.NOT_FOUND) {
+ return path;
+ }
+ } catch (ServiceSpecificException e) {
+ Log.e(TAG, "Failed to check DM file for " + dexInfo.dexPath(), e);
+ }
+ return null;
+ }
+
private boolean commitProfileChanges(@NonNull TmpProfilePath profile) throws RemoteException {
try {
mInjector.getArtd().commitTmpProfile(profile);
@@ -525,24 +558,30 @@
/** Returns the paths to the current profiles of the given dex file. */
@NonNull protected abstract List<ProfilePath> getCurProfiles(@NonNull DexInfoType dexInfo);
+ /**
+ * Returns the path to the DM file that should be passed to dex2oat, or null if no DM file
+ * should be passed.
+ */
+ @Nullable protected abstract DexMetadataPath buildDmPath(@NonNull DexInfoType dexInfo);
+
@AutoValue
- abstract static class DexoptTarget {
- abstract @NonNull DetailedDexInfo dexInfo();
+ abstract static class DexoptTarget<DexInfoType extends DetailedDexInfo> {
+ abstract @NonNull DexInfoType dexInfo();
abstract @NonNull String isa();
abstract boolean isInDalvikCache();
abstract @NonNull String compilerFilter();
- static Builder builder() {
- return new AutoValue_DexOptimizer_DexoptTarget.Builder();
+ static <DexInfoType extends DetailedDexInfo> Builder<DexInfoType> builder() {
+ return new AutoValue_DexOptimizer_DexoptTarget.Builder<DexInfoType>();
}
@AutoValue.Builder
- abstract static class Builder {
- abstract Builder setDexInfo(@NonNull DetailedDexInfo value);
+ abstract static class Builder<DexInfoType extends DetailedDexInfo> {
+ abstract Builder setDexInfo(@NonNull DexInfoType value);
abstract Builder setIsa(@NonNull String value);
abstract Builder setIsInDalvikCache(boolean value);
abstract Builder setCompilerFilter(@NonNull String value);
- abstract DexoptTarget build();
+ abstract DexoptTarget<DexInfoType> build();
}
}