Report bad external profile errors during compilation.
Bug: 278080573
Test: atest ArtServiceTests
Change-Id: I770ac90016d9ead4eb02e557b5aa9070bcd67a5c
Merged-In: I770ac90016d9ead4eb02e557b5aa9070bcd67a5c
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index 2734c96..4a3c28f 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -23,6 +23,7 @@
import static com.android.server.art.ReasonMapping.BatchDexoptReason;
import static com.android.server.art.ReasonMapping.BootReason;
import static com.android.server.art.Utils.Abi;
+import static com.android.server.art.Utils.InitProfileResult;
import static com.android.server.art.model.ArtFlags.GetStatusFlags;
import static com.android.server.art.model.ArtFlags.ScheduleStatus;
import static com.android.server.art.model.Config.Callback;
@@ -738,12 +739,18 @@
List<ProfilePath> profiles = new ArrayList<>();
- Pair<ProfilePath, Boolean> pair = Utils.getOrInitReferenceProfile(mInjector.getArtd(),
+ InitProfileResult result = Utils.getOrInitReferenceProfile(mInjector.getArtd(),
dexInfo.dexPath(), PrimaryDexUtils.buildRefProfilePath(pkgState, dexInfo),
PrimaryDexUtils.getExternalProfiles(dexInfo),
PrimaryDexUtils.buildOutputProfile(pkgState, dexInfo, Process.SYSTEM_UID,
Process.SYSTEM_UID, false /* isPublic */));
- ProfilePath refProfile = pair != null ? pair.first : null;
+ if (!result.externalProfileErrors().isEmpty()) {
+ Log.e(TAG,
+ "Error occurred when initializing from external profiles: "
+ + result.externalProfileErrors());
+ }
+
+ ProfilePath refProfile = result.profile();
if (refProfile != null) {
profiles.add(refProfile);
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index 72fd22e..e822d31 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -20,6 +20,7 @@
import static com.android.server.art.OutputArtifacts.PermissionSettings;
import static com.android.server.art.ProfilePath.TmpProfilePath;
import static com.android.server.art.Utils.Abi;
+import static com.android.server.art.Utils.InitProfileResult;
import static com.android.server.art.model.ArtFlags.DexoptFlags;
import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult;
@@ -104,6 +105,7 @@
for (DexInfoType dexInfo : getDexInfoList()) {
ProfilePath profile = null;
boolean succeeded = true;
+ List<String> externalProfileErrors = List.of();
try {
if (!isDexoptable(dexInfo)) {
continue;
@@ -120,13 +122,15 @@
boolean profileMerged = false;
if (DexFile.isProfileGuidedCompilerFilter(compilerFilter)) {
if (needsToBeShared) {
- profile = initReferenceProfile(dexInfo);
+ InitProfileResult result = initReferenceProfile(dexInfo);
+ profile = result.profile();
+ isOtherReadable = result.isOtherReadable();
+ externalProfileErrors = result.externalProfileErrors();
} else {
- Pair<ProfilePath, Boolean> pair = getOrInitReferenceProfile(dexInfo);
- if (pair != null) {
- profile = pair.first;
- isOtherReadable = pair.second;
- }
+ InitProfileResult result = getOrInitReferenceProfile(dexInfo);
+ profile = result.profile();
+ isOtherReadable = result.isOtherReadable();
+ externalProfileErrors = result.externalProfileErrors();
ProfilePath mergedProfile = mergeProfiles(dexInfo, profile);
if (mergedProfile != null) {
if (profile != null && profile.getTag() == ProfilePath.tmpProfilePath) {
@@ -241,9 +245,13 @@
e);
status = DexoptResult.DEXOPT_FAILED;
} finally {
+ if (!externalProfileErrors.isEmpty()) {
+ extraStatus |= DexoptResult.EXTRA_BAD_EXTERNAL_PROFILE;
+ }
var result = DexContainerFileDexoptResult.create(dexInfo.dexPath(),
abi.isPrimaryAbi(), abi.name(), compilerFilter, status, wallTimeMs,
- cpuTimeMs, sizeBytes, sizeBeforeBytes, extraStatus);
+ cpuTimeMs, sizeBytes, sizeBeforeBytes, extraStatus,
+ externalProfileErrors);
Log.i(TAG,
String.format("Dexopt result: [packageName = %s] %s",
mPkgState.getPackageName(), result));
@@ -344,7 +352,7 @@
/** @see Utils#getOrInitReferenceProfile */
@Nullable
- private Pair<ProfilePath, Boolean> getOrInitReferenceProfile(@NonNull DexInfoType dexInfo)
+ private InitProfileResult getOrInitReferenceProfile(@NonNull DexInfoType dexInfo)
throws RemoteException {
return Utils.getOrInitReferenceProfile(mInjector.getArtd(), dexInfo.dexPath(),
buildRefProfilePath(dexInfo), getExternalProfiles(dexInfo),
@@ -352,7 +360,8 @@
}
@Nullable
- private ProfilePath initReferenceProfile(@NonNull DexInfoType dexInfo) throws RemoteException {
+ private InitProfileResult initReferenceProfile(@NonNull DexInfoType dexInfo)
+ throws RemoteException {
return Utils.initReferenceProfile(mInjector.getArtd(), dexInfo.dexPath(),
getExternalProfiles(dexInfo), buildOutputProfile(dexInfo, true /* isPublic */));
}
diff --git a/libartservice/service/java/com/android/server/art/Utils.java b/libartservice/service/java/com/android/server/art/Utils.java
index 273d8dd..252074a 100644
--- a/libartservice/service/java/com/android/server/art/Utils.java
+++ b/libartservice/service/java/com/android/server/art/Utils.java
@@ -57,6 +57,7 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
@@ -366,13 +367,9 @@
* @param externalProfiles a list of external profiles to initialize the reference profile from,
* in the order of preference
* @param initOutput the final location to initialize the reference profile to
- *
- * @return a pair where the first element is the found or initialized profile, and the second
- * element is true if the profile is readable by others. Returns null if there is no
- * reference profile or external profile to use
*/
- @Nullable
- public static Pair<ProfilePath, Boolean> getOrInitReferenceProfile(@NonNull IArtd artd,
+ @NonNull
+ public static InitProfileResult getOrInitReferenceProfile(@NonNull IArtd artd,
@NonNull String dexPath, @NonNull ProfilePath refProfile,
@NonNull List<ProfilePath> externalProfiles, @NonNull OutputProfile initOutput)
throws RemoteException {
@@ -380,7 +377,8 @@
if (artd.isProfileUsable(refProfile, dexPath)) {
boolean isOtherReadable =
artd.getProfileVisibility(refProfile) == FileVisibility.OTHER_READABLE;
- return Pair.create(refProfile, isOtherReadable);
+ return InitProfileResult.create(
+ refProfile, isOtherReadable, List.of() /* externalProfileErrors */);
}
} catch (ServiceSpecificException e) {
Log.e(TAG,
@@ -389,22 +387,21 @@
e);
}
- ProfilePath initializedProfile =
- initReferenceProfile(artd, dexPath, externalProfiles, initOutput);
- return initializedProfile != null ? Pair.create(initializedProfile, true) : null;
+ return initReferenceProfile(artd, dexPath, externalProfiles, initOutput);
}
/**
* Similar to above, but never uses an existing profile.
*
- * Unlike the one above, this method doesn't return a boolean flag to indicate if the profile is
- * readable by others. The profile returned by this method is initialized form an external
- * profile, meaning it has no user data, so it's always readable by others.
+ * The {@link InitProfileResult#isOtherReadable} field is always set to true. The profile
+ * returned by this method is initialized from an external profile, meaning it has no user data,
+ * so it's always readable by others.
*/
@Nullable
- public static ProfilePath initReferenceProfile(@NonNull IArtd artd, @NonNull String dexPath,
- @NonNull List<ProfilePath> externalProfiles, @NonNull OutputProfile output)
- throws RemoteException {
+ public static InitProfileResult initReferenceProfile(@NonNull IArtd artd,
+ @NonNull String dexPath, @NonNull List<ProfilePath> externalProfiles,
+ @NonNull OutputProfile output) throws RemoteException {
+ List<String> externalProfileErrors = new ArrayList<>();
for (ProfilePath profile : externalProfiles) {
try {
// If the profile path is a PrebuiltProfilePath, and the APK is really a prebuilt
@@ -412,18 +409,22 @@
// build time and is correctly set in the profile header. However, the APK can also
// be an installed one, in which case partners may place a profile file next to the
// APK at install time. Rewriting the profile in the latter case is necessary.
- // TODO(b/278080573): Make use of the detailed result.
CopyAndRewriteProfileResult result =
artd.copyAndRewriteProfile(profile, output, dexPath);
if (result.status == CopyAndRewriteProfileResult.Status.SUCCESS) {
- return ProfilePath.tmpProfilePath(output.profilePath);
+ return InitProfileResult.create(ProfilePath.tmpProfilePath(output.profilePath),
+ true /* isOtherReadable */, externalProfileErrors);
+ }
+ if (result.status == CopyAndRewriteProfileResult.Status.BAD_PROFILE) {
+ externalProfileErrors.add(result.errorMsg);
}
} catch (ServiceSpecificException e) {
Log.e(TAG, "Failed to initialize profile from " + AidlUtils.toString(profile), e);
}
}
- return null;
+ return InitProfileResult.create(
+ null /* profile */, true /* isOtherReadable */, externalProfileErrors);
}
public static void logArtdException(@NonNull RemoteException e) {
@@ -490,4 +491,31 @@
super.close();
}
}
+
+ /** The result of {@link #getOrInitReferenceProfile} and {@link #initReferenceProfile}. */
+ @AutoValue
+ @SuppressWarnings("AutoValueImmutableFields") // Can't use ImmutableList because it's in Guava.
+ public abstract static class InitProfileResult {
+ static @NonNull InitProfileResult create(@Nullable ProfilePath profile,
+ boolean isOtherReadable, @NonNull List<String> externalProfileErrors) {
+ return new AutoValue_Utils_InitProfileResult(
+ profile, isOtherReadable, Collections.unmodifiableList(externalProfileErrors));
+ }
+
+ /**
+ * The found or initialized profile, or null if there is no reference profile or external
+ * profile to use.
+ */
+ abstract @Nullable ProfilePath profile();
+
+ /**
+ * Whether the profile is readable by others.
+ *
+ * If {@link #profile} returns null, this field is always true.
+ */
+ abstract boolean isOtherReadable();
+
+ /** Errors encountered when initializing from external profiles. */
+ abstract @NonNull List<String> externalProfileErrors();
+ }
}
diff --git a/libartservice/service/java/com/android/server/art/model/DexoptResult.java b/libartservice/service/java/com/android/server/art/model/DexoptResult.java
index b678a77..55298af 100644
--- a/libartservice/service/java/com/android/server/art/model/DexoptResult.java
+++ b/libartservice/service/java/com/android/server/art/model/DexoptResult.java
@@ -23,12 +23,14 @@
import android.annotation.SystemApi;
import com.android.internal.annotations.Immutable;
+import com.android.internal.annotations.VisibleForTesting;
import com.google.auto.value.AutoValue;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/** @hide */
@@ -65,12 +67,15 @@
public static final int EXTRA_SKIPPED_STORAGE_LOW = 1 << 0;
/** @hide */
public static final int EXTRA_SKIPPED_NO_DEX_CODE = 1 << 1;
+ /** @hide */
+ public static final int EXTRA_BAD_EXTERNAL_PROFILE = 1 << 2;
/** @hide */
// clang-format off
@IntDef(flag = true, prefix = {"EXTRA_"}, value = {
EXTRA_SKIPPED_STORAGE_LOW,
EXTRA_SKIPPED_NO_DEX_CODE,
+ EXTRA_BAD_EXTERNAL_PROFILE,
})
// clang-format on
@Retention(RetentionPolicy.SOURCE)
@@ -152,6 +157,9 @@
if ((extraStatus & DexoptResult.EXTRA_SKIPPED_NO_DEX_CODE) != 0) {
strs.add("EXTRA_SKIPPED_NO_DEX_CODE");
}
+ if ((extraStatus & DexoptResult.EXTRA_BAD_EXTERNAL_PROFILE) != 0) {
+ strs.add("EXTRA_BAD_EXTERNAL_PROFILE");
+ }
return String.join(", ", strs);
}
@@ -213,6 +221,7 @@
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
@Immutable
@AutoValue
+ @SuppressWarnings("AutoValueImmutableFields") // Can't use ImmutableList because it's in Guava.
public static abstract class DexContainerFileDexoptResult {
/** @hide */
protected DexContainerFileDexoptResult() {}
@@ -222,10 +231,23 @@
boolean isPrimaryAbi, @NonNull String abi, @NonNull String compilerFilter,
@DexoptResultStatus int status, long dex2oatWallTimeMillis,
long dex2oatCpuTimeMillis, long sizeBytes, long sizeBeforeBytes,
- @DexoptResultExtraStatus int extraStatus) {
+ @DexoptResultExtraStatus int extraStatus,
+ @NonNull List<String> externalProfileErrors) {
return new AutoValue_DexoptResult_DexContainerFileDexoptResult(dexContainerFile,
isPrimaryAbi, abi, compilerFilter, status, dex2oatWallTimeMillis,
- dex2oatCpuTimeMillis, sizeBytes, sizeBeforeBytes, extraStatus);
+ dex2oatCpuTimeMillis, sizeBytes, sizeBeforeBytes, extraStatus,
+ Collections.unmodifiableList(externalProfileErrors));
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public static @NonNull DexContainerFileDexoptResult create(@NonNull String dexContainerFile,
+ boolean isPrimaryAbi, @NonNull String abi, @NonNull String compilerFilter,
+ @DexoptResultStatus int status) {
+ return create(dexContainerFile, isPrimaryAbi, abi, compilerFilter, status,
+ 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */, 0 /* sizeBytes */,
+ 0 /* sizeBeforeBytes */, 0 /* extraStatus */,
+ List.of() /* externalProfileErrors */);
}
/** The absolute path to the dex container file. */
@@ -282,6 +304,9 @@
/** @hide */
public abstract @DexoptResultExtraStatus int getExtraStatus();
+ /** @hide */
+ public abstract @NonNull List<String> getExternalProfileErrors();
+
@Override
@NonNull
public String toString() {
diff --git a/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java b/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
index 21d89e6..97bdb4f 100644
--- a/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
@@ -819,14 +819,10 @@
private List<DexContainerFileDexoptResult> createResults(
String dexPath, @DexoptResultStatus int status1, @DexoptResultStatus int status2) {
- return List.of(DexContainerFileDexoptResult.create(dexPath, true /* isPrimaryAbi */,
- "arm64-v8a", "verify", status1, 100 /* dex2oatWallTimeMillis */,
- 400 /* dex2oatCpuTimeMillis */, 0 /* sizeBytes */,
- 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
- DexContainerFileDexoptResult.create(dexPath, false /* isPrimaryAbi */,
- "armeabi-v7a", "verify", status2, 100 /* dex2oatWallTimeMillis */,
- 400 /* dex2oatCpuTimeMillis */, 0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
- 0 /* extraStatus */));
+ return List.of(DexContainerFileDexoptResult.create(
+ dexPath, true /* isPrimaryAbi */, "arm64-v8a", "verify", status1),
+ DexContainerFileDexoptResult.create(
+ dexPath, false /* isPrimaryAbi */, "armeabi-v7a", "verify", status2));
}
private void checkPackageResult(DexoptResult result, int index, String packageName,
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index fe95847..a9f0cd1 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -280,23 +280,19 @@
mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_PERFORMED,
100 /* dex2oatWallTimeMillis */, 400 /* dex2oatCpuTimeMillis */,
30000 /* sizeBytes */, 32000 /* sizeBeforeBytes */,
- 0 /* extraStatus */),
+ 0 /* extraStatus */, List.of() /* externalProfileErrors */),
DexContainerFileDexoptResult.create("/data/app/foo/base.apk",
false /* isPrimaryAbi */, "armeabi-v7a",
- mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_FAILED,
- 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
- 0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
+ mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_FAILED),
DexContainerFileDexoptResult.create("/data/app/foo/split_0.apk",
true /* isPrimaryAbi */, "arm64-v8a",
- mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_SKIPPED,
- 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
- 0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
+ mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_SKIPPED),
DexContainerFileDexoptResult.create("/data/app/foo/split_0.apk",
false /* isPrimaryAbi */, "armeabi-v7a",
mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_PERFORMED,
200 /* dex2oatWallTimeMillis */, 200 /* dex2oatCpuTimeMillis */,
- 10000 /* sizeBytes */, 0 /* sizeBeforeBytes */,
- 0 /* extraStatus */));
+ 10000 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */,
+ List.of() /* externalProfileErrors */));
// Verify that there are no more calls than the ones above.
verify(mArtd, times(3))
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
index 1525192..aa5203d 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
@@ -177,7 +177,8 @@
.dexopt(any(), eq(mSplit0DexPath), eq("arm"), any(), any(), any(), isNull(), any(),
anyInt(), any(), any());
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
}
@Test
@@ -186,7 +187,8 @@
.when(mArtd.getDmFileVisibility(deepEq(mDmFile)))
.thenReturn(FileVisibility.OTHER_READABLE);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
verify(mArtd, times(2))
.dexopt(any(), eq(mDexPath), any(), any(), any(), any(), any(), deepEq(mDmFile),
@@ -211,7 +213,8 @@
makeProfileUsable(mPrebuiltProfile);
makeProfileUsable(mDmProfile);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
verify(mArtd).getDexoptNeeded(
eq(mDexPath), eq("arm64"), any(), eq("speed-profile"), eq(mDefaultDexoptTrigger));
@@ -247,7 +250,8 @@
makeProfileUsable(mPrebuiltProfile);
makeProfileUsable(mDmProfile);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
checkDexoptWithProfile(verify(mArtd), mDexPath, "arm64", mRefProfile,
true /* isOtherReadable */, true /* generateAppImage */);
@@ -264,7 +268,8 @@
makeProfileUsable(mPrebuiltProfile);
makeProfileUsable(mDmProfile);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
InOrder inOrder = inOrder(mArtd);
@@ -295,7 +300,8 @@
when(mArtd.getProfileVisibility(deepEq(mRefProfile)))
.thenReturn(FileVisibility.OTHER_READABLE);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
InOrder inOrder = inOrder(mArtd);
@@ -339,7 +345,8 @@
when(mArtd.getProfileVisibility(deepEq(mRefProfile)))
.thenReturn(FileVisibility.OTHER_READABLE);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
// It should still use "speed-profile", but with the existing reference profile only.
verify(mArtd).getDexoptNeeded(
@@ -362,7 +369,8 @@
makeProfileNotUsable(mPrebuiltProfile);
makeProfileUsable(mDmProfile);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
verify(mArtd).copyAndRewriteProfile(
deepEq(mDmProfile), deepEq(mPublicOutputProfile), eq(mDexPath));
@@ -379,6 +387,30 @@
}
@Test
+ public void testDexoptExternalProfileErrors() throws Exception {
+ makeProfileNotUsable(mRefProfile);
+
+ // Having no profile should not be reported.
+ makeProfileNotUsable(mPrebuiltProfile);
+
+ // Having a bad profile should be reported.
+ lenient()
+ .when(mArtd.copyAndRewriteProfile(deepEq(mDmProfile), any(), any()))
+ .thenReturn(TestingUtils.createCopyAndRewriteProfileBadProfile("error_msg"));
+
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+
+ assertThat(results.get(0).getStatus()).isEqualTo(DexoptResult.DEXOPT_PERFORMED);
+ assertThat(results.get(0).getExtraStatus() & DexoptResult.EXTRA_BAD_EXTERNAL_PROFILE)
+ .isNotEqualTo(0);
+ assertThat(results.get(0).getExternalProfileErrors()).containsExactly("error_msg");
+ assertThat(results.get(1).getStatus()).isEqualTo(DexoptResult.DEXOPT_PERFORMED);
+ assertThat(results.get(1).getExtraStatus() & DexoptResult.EXTRA_BAD_EXTERNAL_PROFILE)
+ .isNotEqualTo(0);
+ assertThat(results.get(1).getExternalProfileErrors()).containsExactly("error_msg");
+ }
+
+ @Test
public void testDexoptDeletesProfileOnFailure() throws Exception {
makeProfileNotUsable(mRefProfile);
makeProfileNotUsable(mPrebuiltProfile);
@@ -413,7 +445,8 @@
argThat(artifactsPath -> artifactsPath.dexPath == mDexPath)))
.thenReturn(FileVisibility.NOT_OTHER_READABLE);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
verify(mArtd).copyAndRewriteProfile(
deepEq(mDmProfile), deepEq(mPublicOutputProfile), eq(mDexPath));
@@ -453,7 +486,8 @@
argThat(artifactsPath -> artifactsPath.dexPath == mDexPath)))
.thenReturn(FileVisibility.OTHER_READABLE);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
// It should use the default dexopt trigger.
verify(mArtd).getDexoptNeeded(
@@ -468,7 +502,8 @@
when(mArtd.getProfileVisibility(deepEq(mSplit0RefProfile)))
.thenReturn(FileVisibility.NOT_OTHER_READABLE);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
verify(mArtd).getDexoptNeeded(eq(mSplit0DexPath), eq("arm64"), any(), eq("speed-profile"),
eq(mDefaultDexoptTrigger));
@@ -566,7 +601,8 @@
mPrimaryDexopter =
new PrimaryDexopter(mInjector, mPkgState, mPkg, mDexoptParams, mCancellationSignal);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
verify(mArtd, times(2))
.dexopt(any(), eq(mDexPath), any(), any(), any(), any(), any(), any(), anyInt(),
@@ -587,7 +623,8 @@
mPrimaryDexopter =
new PrimaryDexopter(mInjector, mPkgState, mPkg, mDexoptParams, mCancellationSignal);
- mPrimaryDexopter.dexopt();
+ List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
+ verifyStatusAllOk(results);
verify(mArtd, never())
.dexopt(any(), eq(mDexPath), any(), any(), any(), any(), any(), any(), anyInt(),
@@ -703,4 +740,12 @@
.when(mArtd.copyAndRewriteProfile(deepEq(profile), any(), any()))
.thenReturn(TestingUtils.createCopyAndRewriteProfileNoProfile());
}
+
+ private void verifyStatusAllOk(List<DexContainerFileDexoptResult> results) {
+ for (DexContainerFileDexoptResult result : results) {
+ assertThat(result.getStatus()).isEqualTo(DexoptResult.DEXOPT_PERFORMED);
+ assertThat(result.getExtraStatus()).isEqualTo(0);
+ assertThat(result.getExternalProfileErrors()).isEmpty();
+ }
+ }
}
diff --git a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
index 35e256a..85d2983 100644
--- a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
@@ -165,21 +165,13 @@
.comparingElementsUsing(TestingUtils.<DexContainerFileDexoptResult>deepEquality())
.containsExactly(
DexContainerFileDexoptResult.create(DEX_1, true /* isPrimaryAbi */,
- "arm64-v8a", "speed-profile", DexoptResult.DEXOPT_PERFORMED,
- 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
- 0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
+ "arm64-v8a", "speed-profile", DexoptResult.DEXOPT_PERFORMED),
DexContainerFileDexoptResult.create(DEX_2, true /* isPrimaryAbi */,
- "arm64-v8a", "speed", DexoptResult.DEXOPT_PERFORMED,
- 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
- 0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
+ "arm64-v8a", "speed", DexoptResult.DEXOPT_PERFORMED),
DexContainerFileDexoptResult.create(DEX_2, false /* isPrimaryAbi */,
- "armeabi-v7a", "speed", DexoptResult.DEXOPT_PERFORMED,
- 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
- 0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
+ "armeabi-v7a", "speed", DexoptResult.DEXOPT_PERFORMED),
DexContainerFileDexoptResult.create(DEX_3, true /* isPrimaryAbi */,
- "arm64-v8a", "verify", DexoptResult.DEXOPT_PERFORMED,
- 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
- 0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */));
+ "arm64-v8a", "verify", DexoptResult.DEXOPT_PERFORMED));
// It should use profile for dex 1.