Address all API design review feedback.
See the latest design doc at go/art-services-apis.
Bug: 242990781
Test: atest ArtServiceTests
Ignore-AOSP-First: ART Services.
Change-Id: I5afb0142427e31dc1bc95206abea2c970a1981cf
diff --git a/libartservice/service/api/system-server-current.txt b/libartservice/service/api/system-server-current.txt
index cef4365..d22a8c3 100644
--- a/libartservice/service/api/system-server-current.txt
+++ b/libartservice/service/api/system-server-current.txt
@@ -51,15 +51,16 @@
}
public class OptimizationStatus {
- method @NonNull public java.util.List<com.android.server.art.model.OptimizationStatus.DexFileOptimizationStatus> getDexFileOptimizationStatuses();
+ method @NonNull public java.util.List<com.android.server.art.model.OptimizationStatus.DexContainerFileOptimizationStatus> getDexContainerFileOptimizationStatuses();
}
- public static class OptimizationStatus.DexFileOptimizationStatus {
+ public static class OptimizationStatus.DexContainerFileOptimizationStatus {
+ method @NonNull public String getAbi();
method @NonNull public String getCompilationReason();
method @NonNull public String getCompilerFilter();
- method @NonNull public String getDexFile();
- method @NonNull public String getInstructionSet();
+ method @NonNull public String getDexContainerFile();
method @NonNull public String getLocationDebugString();
+ method public boolean isPrimaryAbi();
}
public class OptimizeParams {
@@ -78,7 +79,6 @@
method @NonNull public com.android.server.art.model.OptimizeParams.Builder setFlags(int);
method @NonNull public com.android.server.art.model.OptimizeParams.Builder setFlags(int, int);
method @NonNull public com.android.server.art.model.OptimizeParams.Builder setPriorityClass(int);
- method @NonNull public com.android.server.art.model.OptimizeParams.Builder setReason(@NonNull String);
}
public class OptimizeResult {
@@ -92,17 +92,18 @@
field public static final int OPTIMIZE_SKIPPED = 10; // 0xa
}
- public static class OptimizeResult.DexFileOptimizeResult {
+ public static class OptimizeResult.DexContainerFileOptimizeResult {
+ method @NonNull public String getAbi();
method @NonNull public String getActualCompilerFilter();
method public long getDex2oatCpuTimeMillis();
method public long getDex2oatWallTimeMillis();
- method @NonNull public String getDexFile();
- method @NonNull public String getInstructionSet();
+ method @NonNull public String getDexContainerFile();
method public int getStatus();
+ method public boolean isPrimaryAbi();
}
public static class OptimizeResult.PackageOptimizeResult {
- method @NonNull public java.util.List<com.android.server.art.model.OptimizeResult.DexFileOptimizeResult> getDexFileOptimizeResults();
+ method @NonNull public java.util.List<com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult> getDexContainerFileOptimizeResults();
method @NonNull public String getPackageName();
method public int getStatus();
}
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index d4659ff..b67fb98 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -18,9 +18,10 @@
import static com.android.server.art.PrimaryDexUtils.DetailedPrimaryDexInfo;
import static com.android.server.art.PrimaryDexUtils.PrimaryDexInfo;
+import static com.android.server.art.Utils.Abi;
import static com.android.server.art.model.ArtFlags.DeleteFlags;
import static com.android.server.art.model.ArtFlags.GetStatusFlags;
-import static com.android.server.art.model.OptimizationStatus.DexFileOptimizationStatus;
+import static com.android.server.art.model.OptimizationStatus.DexContainerFileOptimizationStatus;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -142,10 +143,10 @@
if (!dexInfo.hasCode()) {
continue;
}
- for (String isa : Utils.getAllIsas(pkgState)) {
+ for (Abi abi : Utils.getAllAbis(pkgState)) {
freedBytes +=
mInjector.getArtd().deleteArtifacts(AidlUtils.buildArtifactsPath(
- dexInfo.dexPath(), isa, isInDalvikCache));
+ dexInfo.dexPath(), abi.isa(), isInDalvikCache));
}
}
}
@@ -193,7 +194,7 @@
AndroidPackageApi pkg = getPackageOrThrow(pkgState);
try {
- List<DexFileOptimizationStatus> statuses = new ArrayList<>();
+ List<DexContainerFileOptimizationStatus> statuses = new ArrayList<>();
if ((flags & ArtFlags.FLAG_FOR_PRIMARY_DEX) != 0) {
for (DetailedPrimaryDexInfo dexInfo :
@@ -201,17 +202,18 @@
if (!dexInfo.hasCode()) {
continue;
}
- for (String isa : Utils.getAllIsas(pkgState)) {
+ for (Abi abi : Utils.getAllAbis(pkgState)) {
try {
GetOptimizationStatusResult result =
- mInjector.getArtd().getOptimizationStatus(
- dexInfo.dexPath(), isa, dexInfo.classLoaderContext());
- statuses.add(new DexFileOptimizationStatus(dexInfo.dexPath(), isa,
- result.compilerFilter, result.compilationReason,
- result.locationDebugString));
+ mInjector.getArtd().getOptimizationStatus(dexInfo.dexPath(),
+ abi.isa(), dexInfo.classLoaderContext());
+ statuses.add(new DexContainerFileOptimizationStatus(dexInfo.dexPath(),
+ abi.isPrimaryAbi(), abi.name(), result.compilerFilter,
+ result.compilationReason, result.locationDebugString));
} catch (ServiceSpecificException e) {
- statuses.add(new DexFileOptimizationStatus(
- dexInfo.dexPath(), isa, "error", "error", e.getMessage()));
+ statuses.add(new DexContainerFileOptimizationStatus(dexInfo.dexPath(),
+ abi.isPrimaryAbi(), abi.name(), "error", "error",
+ e.getMessage()));
}
}
}
diff --git a/libartservice/service/java/com/android/server/art/ArtShellCommand.java b/libartservice/service/java/com/android/server/art/ArtShellCommand.java
index def1949..5f6d6d4 100644
--- a/libartservice/service/java/com/android/server/art/ArtShellCommand.java
+++ b/libartservice/service/java/com/android/server/art/ArtShellCommand.java
@@ -17,8 +17,8 @@
package com.android.server.art;
import static com.android.server.art.model.ArtFlags.OptimizeFlags;
-import static com.android.server.art.model.OptimizationStatus.DexFileOptimizationStatus;
-import static com.android.server.art.model.OptimizeResult.DexFileOptimizeResult;
+import static com.android.server.art.model.OptimizationStatus.DexContainerFileOptimizationStatus;
+import static com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult;
import static com.android.server.art.model.OptimizeResult.OptimizeStatus;
import static com.android.server.art.model.OptimizeResult.PackageOptimizeResult;
@@ -75,11 +75,12 @@
case "get-optimization-status": {
OptimizationStatus optimizationStatus = mArtManagerLocal.getOptimizationStatus(
snapshot, getNextArgRequired(), ArtFlags.defaultGetStatusFlags());
- for (DexFileOptimizationStatus status :
- optimizationStatus.getDexFileOptimizationStatuses()) {
- pw.printf("dexFile = %s, instructionSet = %s, compilerFilter = %s, "
- + "compilationReason = %s, locationDebugString = %s\n",
- status.getDexFile(), status.getInstructionSet(),
+ for (DexContainerFileOptimizationStatus status :
+ optimizationStatus.getDexContainerFileOptimizationStatuses()) {
+ pw.printf("dexContainerFile = %s, isPrimaryAbi = %b, abi = %s, "
+ + "compilerFilter = %s, compilationReason = %s, "
+ + "locationDebugString = %s\n",
+ status.getDexContainerFile(), status.isPrimaryAbi(), status.getAbi(),
status.getCompilerFilter(), status.getCompilationReason(),
status.getLocationDebugString());
}
@@ -124,16 +125,16 @@
pw.println(optimizeStatusToString(result.getFinalStatus()));
for (PackageOptimizeResult packageResult : result.getPackageOptimizeResults()) {
pw.printf("[%s]\n", packageResult.getPackageName());
- for (DexFileOptimizeResult dexFileResult :
- packageResult.getDexFileOptimizeResults()) {
- pw.printf("dexFile = %s, instructionSet = %s, compilerFilter = %s, "
- + "status = %s, dex2oatWallTimeMillis = %d, "
- + "dex2oatCpuTimeMillis = %d\n",
- dexFileResult.getDexFile(), dexFileResult.getInstructionSet(),
- dexFileResult.getActualCompilerFilter(),
- optimizeStatusToString(dexFileResult.getStatus()),
- dexFileResult.getDex2oatWallTimeMillis(),
- dexFileResult.getDex2oatCpuTimeMillis());
+ for (DexContainerFileOptimizeResult fileResult :
+ packageResult.getDexContainerFileOptimizeResults()) {
+ pw.printf("dexContainerFile = %s, isPrimaryAbi = %b, abi = %s, "
+ + "compilerFilter = %s, status = %s, "
+ + "dex2oatWallTimeMillis = %d, dex2oatCpuTimeMillis = %d\n",
+ fileResult.getDexContainerFile(), fileResult.isPrimaryAbi(),
+ fileResult.getAbi(), fileResult.getActualCompilerFilter(),
+ optimizeStatusToString(fileResult.getStatus()),
+ fileResult.getDex2oatWallTimeMillis(),
+ fileResult.getDex2oatCpuTimeMillis());
}
}
return 0;
diff --git a/libartservice/service/java/com/android/server/art/DexOptHelper.java b/libartservice/service/java/com/android/server/art/DexOptHelper.java
index de15dd4..e09bcf8 100644
--- a/libartservice/service/java/com/android/server/art/DexOptHelper.java
+++ b/libartservice/service/java/com/android/server/art/DexOptHelper.java
@@ -16,7 +16,7 @@
package com.android.server.art;
-import static com.android.server.art.model.OptimizeResult.DexFileOptimizeResult;
+import static com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult;
import static com.android.server.art.model.OptimizeResult.PackageOptimizeResult;
import android.annotation.NonNull;
@@ -77,7 +77,7 @@
@NonNull PackageState pkgState, @NonNull AndroidPackageApi pkg,
@NonNull OptimizeParams params, @NonNull CancellationSignal cancellationSignal)
throws RemoteException {
- List<DexFileOptimizeResult> results = new ArrayList<>();
+ List<DexContainerFileOptimizeResult> results = new ArrayList<>();
Supplier<OptimizeResult> createResult = ()
-> new OptimizeResult(params.getCompilerFilter(), params.getReason(),
List.of(new PackageOptimizeResult(pkgState.getPackageName(), results)));
diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
index 54a181a..f30fe0b 100644
--- a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
+++ b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
@@ -22,8 +22,9 @@
import static com.android.server.art.PrimaryDexUtils.DetailedPrimaryDexInfo;
import static com.android.server.art.ProfilePath.RefProfilePath;
import static com.android.server.art.ProfilePath.TmpRefProfilePath;
+import static com.android.server.art.Utils.Abi;
import static com.android.server.art.model.ArtFlags.OptimizeFlags;
-import static com.android.server.art.model.OptimizeResult.DexFileOptimizeResult;
+import static com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult;
import android.R;
import android.annotation.NonNull;
@@ -72,10 +73,10 @@
* ArtManagerLocal#optimizePackage(PackageDataSnapshot, String, OptimizeParams)}.
*/
@NonNull
- public List<DexFileOptimizeResult> dexopt(@NonNull PackageState pkgState,
+ public List<DexContainerFileOptimizeResult> dexopt(@NonNull PackageState pkgState,
@NonNull AndroidPackageApi pkg, @NonNull OptimizeParams params,
@NonNull CancellationSignal cancellationSignal) throws RemoteException {
- List<DexFileOptimizeResult> results = new ArrayList<>();
+ List<DexContainerFileOptimizeResult> results = new ArrayList<>();
int uid = pkg.getUid();
if (uid < 0) {
@@ -143,14 +144,14 @@
DexoptOptions dexoptOptions =
getDexoptOptions(pkgState, pkg, params, isProfileGuidedCompilerFilter);
- for (String isa : Utils.getAllIsas(pkgState)) {
+ for (Abi abi : Utils.getAllAbis(pkgState)) {
@OptimizeResult.OptimizeStatus int status = OptimizeResult.OPTIMIZE_SKIPPED;
long wallTimeMs = 0;
long cpuTimeMs = 0;
try {
DexoptTarget target = DexoptTarget.builder()
.setDexInfo(dexInfo)
- .setIsa(isa)
+ .setIsa(abi.isa())
.setIsInDalvikCache(isInDalvikCache)
.setCompilerFilter(compilerFilter)
.build();
@@ -199,13 +200,14 @@
Log.e(TAG,
String.format("Failed to dexopt [packageName = %s, dexPath = %s, "
+ "isa = %s, classLoaderContext = %s]",
- pkgState.getPackageName(), dexInfo.dexPath(), isa,
+ pkgState.getPackageName(), dexInfo.dexPath(), abi.isa(),
dexInfo.classLoaderContext()),
e);
status = OptimizeResult.OPTIMIZE_FAILED;
} finally {
- results.add(new DexFileOptimizeResult(dexInfo.dexPath(), isa,
- compilerFilter, status, wallTimeMs, cpuTimeMs));
+ results.add(new DexContainerFileOptimizeResult(dexInfo.dexPath(),
+ abi.isPrimaryAbi(), abi.name(), compilerFilter, status, wallTimeMs,
+ cpuTimeMs));
if (status != OptimizeResult.OPTIMIZE_SKIPPED
&& status != OptimizeResult.OPTIMIZE_PERFORMED) {
succeeded = false;
diff --git a/libartservice/service/java/com/android/server/art/Utils.java b/libartservice/service/java/com/android/server/art/Utils.java
index 8c1cfbe..134dc9f 100644
--- a/libartservice/service/java/com/android/server/art/Utils.java
+++ b/libartservice/service/java/com/android/server/art/Utils.java
@@ -26,9 +26,12 @@
import com.android.server.art.wrapper.PackageManagerLocal;
import com.android.server.art.wrapper.PackageState;
+import com.google.auto.value.AutoValue;
+
import dalvik.system.DexFile;
import dalvik.system.VMRuntime;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -58,17 +61,25 @@
}
@NonNull
- public static List<String> getAllIsas(@NonNull PackageState pkgState) {
+ public static List<Abi> getAllAbis(@NonNull PackageState pkgState) {
+ List<Abi> abis = new ArrayList<>();
String primaryCpuAbi = pkgState.getPrimaryCpuAbi();
- String secondaryCpuAbi = pkgState.getSecondaryCpuAbi();
if (primaryCpuAbi != null) {
- if (secondaryCpuAbi != null) {
- return List.of(VMRuntime.getInstructionSet(primaryCpuAbi),
- VMRuntime.getInstructionSet(secondaryCpuAbi));
- }
- return List.of(VMRuntime.getInstructionSet(primaryCpuAbi));
+ abis.add(Abi.create(primaryCpuAbi, VMRuntime.getInstructionSet(primaryCpuAbi),
+ true /* isPrimaryAbi */));
}
- return List.of();
+ String secondaryCpuAbi = pkgState.getSecondaryCpuAbi();
+ if (secondaryCpuAbi != null) {
+ abis.add(Abi.create(secondaryCpuAbi, VMRuntime.getInstructionSet(secondaryCpuAbi),
+ false /* isPrimaryAbi */));
+ }
+ // Primary and secondary ABIs are guaranteed to have different ISAs.
+ if (abis.size() == 2 && abis.get(0).isa().equals(abis.get(1).isa())) {
+ throw new IllegalStateException(
+ String.format("Duplicate ISA: primary ABI '%s', secondary ABI '%s'",
+ primaryCpuAbi, secondaryCpuAbi));
+ }
+ return abis;
}
public static boolean isInDalvikCache(@NonNull PackageState pkg) {
@@ -95,4 +106,20 @@
public static boolean implies(boolean cond1, boolean cond2) {
return cond1 ? cond2 : true;
}
+
+ @AutoValue
+ public abstract static class Abi {
+ static @NonNull Abi create(
+ @NonNull String name, @NonNull String isa, boolean isPrimaryAbi) {
+ return new AutoValue_Utils_Abi(name, isa, isPrimaryAbi);
+ }
+
+ // The ABI name. E.g., "arm64-v8a".
+ abstract @NonNull String name();
+
+ // The instruction set name. E.g., "arm64".
+ abstract @NonNull String isa();
+
+ abstract boolean isPrimaryAbi();
+ }
}
diff --git a/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java b/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java
index 724b0dd..f156e97 100644
--- a/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java
+++ b/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java
@@ -32,60 +32,79 @@
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
@Immutable
public class OptimizationStatus {
- private final @NonNull List<DexFileOptimizationStatus> mDexFileOptimizationStatuses;
+ private final
+ @NonNull List<DexContainerFileOptimizationStatus> mDexContainerFileOptimizationStatuses;
/** @hide */
- public OptimizationStatus(
- @NonNull List<DexFileOptimizationStatus> dexFileOptimizationStatuses) {
- mDexFileOptimizationStatuses = dexFileOptimizationStatuses;
+ public OptimizationStatus(@NonNull List<DexContainerFileOptimizationStatus>
+ dexContainerFileOptimizationStatuses) {
+ mDexContainerFileOptimizationStatuses = dexContainerFileOptimizationStatuses;
}
- /** The optimization status of each individual dex file. */
+ /**
+ * The statuses of the dex container file optimizations. Note that there can be
+ * multiple entries for the same dex container file, but for different ABIs.
+ */
@NonNull
- public List<DexFileOptimizationStatus> getDexFileOptimizationStatuses() {
- return mDexFileOptimizationStatuses;
+ public List<DexContainerFileOptimizationStatus> getDexContainerFileOptimizationStatuses() {
+ return mDexContainerFileOptimizationStatuses;
}
- /** Describes the optimization status of a dex file. */
+ /** Describes the optimization status of a dex container file. */
@Immutable
- public static class DexFileOptimizationStatus {
- private final @NonNull String mDexFile;
- private final @NonNull String mInstructionSet;
+ public static class DexContainerFileOptimizationStatus {
+ private final @NonNull String mDexContainerFile;
+ private final @NonNull boolean mIsPrimaryAbi;
+ private final @NonNull String mAbi;
private final @NonNull String mCompilerFilter;
private final @NonNull String mCompilationReason;
private final @NonNull String mLocationDebugString;
/** @hide */
- public DexFileOptimizationStatus(@NonNull String dexFile, @NonNull String instructionSet,
- @NonNull String compilerFilter, @NonNull String compilationReason,
- @NonNull String locationDebugString) {
- mDexFile = dexFile;
- mInstructionSet = instructionSet;
+ public DexContainerFileOptimizationStatus(@NonNull String dexContainerFile,
+ boolean isPrimaryAbi, @NonNull String abi, @NonNull String compilerFilter,
+ @NonNull String compilationReason, @NonNull String locationDebugString) {
+ mDexContainerFile = dexContainerFile;
+ mIsPrimaryAbi = isPrimaryAbi;
+ mAbi = abi;
mCompilerFilter = compilerFilter;
mCompilationReason = compilationReason;
mLocationDebugString = locationDebugString;
}
- /** The absolute path to the dex file. */
- public @NonNull String getDexFile() {
- return mDexFile;
- }
-
- /** The instruction set. */
- public @NonNull String getInstructionSet() {
- return mInstructionSet;
+ /** The absolute path to the dex container file. */
+ public @NonNull String getDexContainerFile() {
+ return mDexContainerFile;
}
/**
- * A string that describes the compiler filter.
+ * If true, the optimization is for the primary ABI of the package (the ABI that the
+ * application is launched with). Otherwise, the optimization is for an ABI that other
+ * applications might be launched with when using this application's code.
+ */
+ public boolean isPrimaryAbi() {
+ return mIsPrimaryAbi;
+ }
+
+ /**
+ * Returns the ABI that the optimization is for. Possible values are documented at
+ * https://developer.android.com/ndk/guides/abis#sa.
+ */
+ public @NonNull String getAbi() {
+ return mAbi;
+ }
+
+ /**
+ * A human-readable string that describes the compiler filter.
*
* Possible values are:
* <ul>
* <li>A valid value of the {@code --compiler-filer} option passed to {@code dex2oat}, if
- * the optimized artifacts are valid.
+ * the optimized artifacts are valid. See
+ * https://source.android.com/docs/core/dalvik/configure#compilation_options.
* <li>{@code "run-from-apk"}, if the optimized artifacts do not exist.
* <li>{@code "run-from-apk-fallback"}, if the optimized artifacts exist but are invalid
- * because the dex file has changed.
+ * because the dex container file has changed.
* <li>{@code "error"}, if an unexpected error occurs.
* </ul>
*/
diff --git a/libartservice/service/java/com/android/server/art/model/OptimizeParams.java b/libartservice/service/java/com/android/server/art/model/OptimizeParams.java
index fdfb6b8..e8d1554 100644
--- a/libartservice/service/java/com/android/server/art/model/OptimizeParams.java
+++ b/libartservice/service/java/com/android/server/art/model/OptimizeParams.java
@@ -38,7 +38,11 @@
*
* Uses default flags ({@link ArtFlags#defaultOptimizeFlags()}).
*
- * @param reason See {@link #setReason(String)}.
+ * @param reason Compilation reason. Can be a string defined in {@link ReasonMapping} or a
+ * custom string. If the value is a string defined in {@link ReasonMapping}, it
+ * determines the compiler filter and/or the priority class, if those values are not
+ * explicitly set. If the value is a custom string, the priority class and the
+ * compiler filter must be explicitly set.
*/
public Builder(@NonNull String reason) {
this(reason, ArtFlags.defaultOptimizeFlags());
@@ -48,7 +52,7 @@
* Same as above, but allows to specify flags.
*/
public Builder(@NonNull String reason, @OptimizeFlags int flags) {
- setReason(reason);
+ mParams.mReason = reason;
setFlags(flags);
}
@@ -94,21 +98,6 @@
}
/**
- * Compilation reason. Can be a string defined in {@link ReasonMapping} or a custom string.
- *
- * If the value is a string defined in {@link ReasonMapping}, it determines the compiler
- * filter and/or the priority class, if those values are not explicitly set.
- *
- * If the value is a custom string, the priority class and the compiler filter must be
- * explicitly set.
- */
- @NonNull
- public Builder setReason(@NonNull String value) {
- mParams.mReason = value;
- return this;
- }
-
- /**
* Returns the built object.
*
* @throws IllegalArgumentException if the built options would be invalid
diff --git a/libartservice/service/java/com/android/server/art/model/OptimizeResult.java b/libartservice/service/java/com/android/server/art/model/OptimizeResult.java
index 8a4449b..5ee5016 100644
--- a/libartservice/service/java/com/android/server/art/model/OptimizeResult.java
+++ b/libartservice/service/java/com/android/server/art/model/OptimizeResult.java
@@ -32,8 +32,8 @@
@Immutable
public class OptimizeResult {
// Possible values of {@link #OptimizeStatus}.
- // A larger number means a higher priority. If multiple dex files are processed, the final
- // status will be the one with the highest priority.
+ // A larger number means a higher priority. If multiple dex container files are processed, the
+ // final status will be the one with the highest priority.
public static final int OPTIMIZE_SKIPPED = 10;
public static final int OPTIMIZE_PERFORMED = 20;
public static final int OPTIMIZE_FAILED = 30;
@@ -68,7 +68,8 @@
* execution based on factors like whether the profile is available or whether the app is
* used by other apps.
*
- * @see DexFileOptimizeResult#getActualCompilerFilter.
+ * @see OptimizeParams.Builder#setCompilerFilter(String)
+ * @see DexContainerFileOptimizeResult#getActualCompilerFilter()
*/
public @NonNull String getRequestedCompilerFilter() {
return mRequestedCompilerFilter;
@@ -109,13 +110,14 @@
@Immutable
public static class PackageOptimizeResult {
private final @NonNull String mPackageName;
- private final @NonNull List<DexFileOptimizeResult> mDexFileOptimizeResults;
+ private final
+ @NonNull List<DexContainerFileOptimizeResult> mDexContainerFileOptimizeResults;
/** @hide */
public PackageOptimizeResult(@NonNull String packageName,
- @NonNull List<DexFileOptimizeResult> dexFileOptimizeResults) {
+ @NonNull List<DexContainerFileOptimizeResult> dexContainerFileOptimizeResults) {
mPackageName = packageName;
- mDexFileOptimizeResults = dexFileOptimizeResults;
+ mDexContainerFileOptimizeResults = dexContainerFileOptimizeResults;
}
/** The package name. */
@@ -123,59 +125,80 @@
return mPackageName;
}
- /** The result of each individual dex file. */
+ /**
+ * The results of optimizing dex container files. Note that there can be multiple entries
+ * for the same dex container file, but for different ABIs.
+ */
@NonNull
- public List<DexFileOptimizeResult> getDexFileOptimizeResults() {
- return mDexFileOptimizeResults;
+ public List<DexContainerFileOptimizeResult> getDexContainerFileOptimizeResults() {
+ return mDexContainerFileOptimizeResults;
}
/** The overall status of the package. */
public @OptimizeStatus int getStatus() {
- return mDexFileOptimizeResults.stream()
+ return mDexContainerFileOptimizeResults.stream()
.mapToInt(result -> result.getStatus())
.max()
.orElse(OPTIMIZE_SKIPPED);
}
}
- /** Describes the result of a dex file. */
+ /** Describes the result of optimizing a dex container file. */
@Immutable
- public static class DexFileOptimizeResult {
- private final @NonNull String mDexFile;
- private final @NonNull String mInstructionSet;
+ public static class DexContainerFileOptimizeResult {
+ private final @NonNull String mDexContainerFile;
+ private final boolean mIsPrimaryAbi;
+ private final @NonNull String mAbi;
private final @NonNull String mActualCompilerFilter;
private final @OptimizeStatus int mStatus;
private final long mDex2oatWallTimeMillis;
private final long mDex2oatCpuTimeMillis;
/** @hide */
- public DexFileOptimizeResult(@NonNull String dexFile, @NonNull String instructionSet,
- @NonNull String compilerFilter, @OptimizeStatus int status,
- long dex2oatWallTimeMillis, long dex2oatCpuTimeMillis) {
- mDexFile = dexFile;
- mInstructionSet = instructionSet;
+ public DexContainerFileOptimizeResult(@NonNull String dexContainerFile,
+ boolean isPrimaryAbi, @NonNull String abi, @NonNull String compilerFilter,
+ @OptimizeStatus int status, long dex2oatWallTimeMillis, long dex2oatCpuTimeMillis) {
+ mDexContainerFile = dexContainerFile;
+ mIsPrimaryAbi = isPrimaryAbi;
+ mAbi = abi;
mActualCompilerFilter = compilerFilter;
mStatus = status;
mDex2oatWallTimeMillis = dex2oatWallTimeMillis;
mDex2oatCpuTimeMillis = dex2oatCpuTimeMillis;
}
- /** The absolute path to the dex file. */
- public @NonNull String getDexFile() {
- return mDexFile;
+ /** The absolute path to the dex container file. */
+ public @NonNull String getDexContainerFile() {
+ return mDexContainerFile;
}
- /** The instruction set. */
- public @NonNull String getInstructionSet() {
- return mInstructionSet;
+ /**
+ * If true, the optimization is for the primary ABI of the package (the ABI that the
+ * application is launched with). Otherwise, the optimization is for an ABI that other
+ * applications might be launched with when using this application's code.
+ */
+ public boolean isPrimaryAbi() {
+ return mIsPrimaryAbi;
}
- /** The actual compiler filter. */
+ /**
+ * Returns the ABI that the optimization is for. Possible values are documented at
+ * https://developer.android.com/ndk/guides/abis#sa.
+ */
+ public @NonNull String getAbi() {
+ return mAbi;
+ }
+
+ /**
+ * The actual compiler filter.
+ *
+ * @see OptimizeParams.Builder#setCompilerFilter(String)
+ */
public @NonNull String getActualCompilerFilter() {
return mActualCompilerFilter;
}
- /** The status of optimizing this dex file. */
+ /** The status of optimizing this dex container file. */
public @OptimizeStatus int getStatus() {
return mStatus;
}
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index f534509..b10e31b 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -16,7 +16,7 @@
package com.android.server.art;
-import static com.android.server.art.model.OptimizationStatus.DexFileOptimizationStatus;
+import static com.android.server.art.model.OptimizationStatus.DexContainerFileOptimizationStatus;
import static com.google.common.truth.Truth.assertThat;
@@ -158,29 +158,34 @@
OptimizationStatus result =
mArtManagerLocal.getOptimizationStatus(mock(PackageDataSnapshot.class), PKG_NAME);
- List<DexFileOptimizationStatus> statuses = result.getDexFileOptimizationStatuses();
+ List<DexContainerFileOptimizationStatus> statuses =
+ result.getDexContainerFileOptimizationStatuses();
assertThat(statuses.size()).isEqualTo(4);
- assertThat(statuses.get(0).getDexFile()).isEqualTo("/data/app/foo/base.apk");
- assertThat(statuses.get(0).getInstructionSet()).isEqualTo("arm64");
+ assertThat(statuses.get(0).getDexContainerFile()).isEqualTo("/data/app/foo/base.apk");
+ assertThat(statuses.get(0).isPrimaryAbi()).isEqualTo(true);
+ assertThat(statuses.get(0).getAbi()).isEqualTo("arm64-v8a");
assertThat(statuses.get(0).getCompilerFilter()).isEqualTo("speed");
assertThat(statuses.get(0).getCompilationReason()).isEqualTo("compilation-reason-0");
assertThat(statuses.get(0).getLocationDebugString()).isEqualTo("location-debug-string-0");
- assertThat(statuses.get(1).getDexFile()).isEqualTo("/data/app/foo/base.apk");
- assertThat(statuses.get(1).getInstructionSet()).isEqualTo("arm");
+ assertThat(statuses.get(1).getDexContainerFile()).isEqualTo("/data/app/foo/base.apk");
+ assertThat(statuses.get(1).isPrimaryAbi()).isEqualTo(false);
+ assertThat(statuses.get(1).getAbi()).isEqualTo("armeabi-v7a");
assertThat(statuses.get(1).getCompilerFilter()).isEqualTo("speed-profile");
assertThat(statuses.get(1).getCompilationReason()).isEqualTo("compilation-reason-1");
assertThat(statuses.get(1).getLocationDebugString()).isEqualTo("location-debug-string-1");
- assertThat(statuses.get(2).getDexFile()).isEqualTo("/data/app/foo/split_0.apk");
- assertThat(statuses.get(2).getInstructionSet()).isEqualTo("arm64");
+ assertThat(statuses.get(2).getDexContainerFile()).isEqualTo("/data/app/foo/split_0.apk");
+ assertThat(statuses.get(2).isPrimaryAbi()).isEqualTo(true);
+ assertThat(statuses.get(2).getAbi()).isEqualTo("arm64-v8a");
assertThat(statuses.get(2).getCompilerFilter()).isEqualTo("verify");
assertThat(statuses.get(2).getCompilationReason()).isEqualTo("compilation-reason-2");
assertThat(statuses.get(2).getLocationDebugString()).isEqualTo("location-debug-string-2");
- assertThat(statuses.get(3).getDexFile()).isEqualTo("/data/app/foo/split_0.apk");
- assertThat(statuses.get(3).getInstructionSet()).isEqualTo("arm");
+ assertThat(statuses.get(3).getDexContainerFile()).isEqualTo("/data/app/foo/split_0.apk");
+ assertThat(statuses.get(3).isPrimaryAbi()).isEqualTo(false);
+ assertThat(statuses.get(3).getAbi()).isEqualTo("armeabi-v7a");
assertThat(statuses.get(3).getCompilerFilter()).isEqualTo("extract");
assertThat(statuses.get(3).getCompilationReason()).isEqualTo("compilation-reason-3");
assertThat(statuses.get(3).getLocationDebugString()).isEqualTo("location-debug-string-3");
@@ -208,10 +213,11 @@
OptimizationStatus result =
mArtManagerLocal.getOptimizationStatus(mock(PackageDataSnapshot.class), PKG_NAME);
- List<DexFileOptimizationStatus> statuses = result.getDexFileOptimizationStatuses();
+ List<DexContainerFileOptimizationStatus> statuses =
+ result.getDexContainerFileOptimizationStatuses();
assertThat(statuses.size()).isEqualTo(4);
- for (DexFileOptimizationStatus status : statuses) {
+ for (DexContainerFileOptimizationStatus status : statuses) {
assertThat(status.getCompilerFilter()).isEqualTo("error");
assertThat(status.getCompilationReason()).isEqualTo("error");
assertThat(status.getLocationDebugString()).isEqualTo("some error message");
diff --git a/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java b/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
index 5e2314e..095d828 100644
--- a/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
@@ -16,7 +16,7 @@
package com.android.server.art;
-import static com.android.server.art.model.OptimizeResult.DexFileOptimizeResult;
+import static com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult;
import static com.android.server.art.model.OptimizeResult.PackageOptimizeResult;
import static com.google.common.truth.Truth.assertThat;
@@ -77,13 +77,13 @@
private final OptimizeParams mParams =
new OptimizeParams.Builder("install").setCompilerFilter("speed-profile").build();
- private final List<DexFileOptimizeResult> mPrimaryResults =
- List.of(new DexFileOptimizeResult("/data/app/foo/base.apk", "arm64", "verify",
- OptimizeResult.OPTIMIZE_PERFORMED, 100 /* dex2oatWallTimeMillis */,
- 400 /* dex2oatCpuTimeMillis */),
- new DexFileOptimizeResult("/data/app/foo/base.apk", "arm", "verify",
- OptimizeResult.OPTIMIZE_FAILED, 100 /* dex2oatWallTimeMillis */,
- 400 /* dex2oatCpuTimeMillis */));
+ private final List<DexContainerFileOptimizeResult> mPrimaryResults = List.of(
+ new DexContainerFileOptimizeResult("/data/app/foo/base.apk", true /* isPrimaryAbi */,
+ "arm64-v8a", "verify", OptimizeResult.OPTIMIZE_PERFORMED,
+ 100 /* dex2oatWallTimeMillis */, 400 /* dex2oatCpuTimeMillis */),
+ new DexContainerFileOptimizeResult("/data/app/foo/base.apk", false /* isPrimaryAbi */,
+ "armeabi-v7a", "verify", OptimizeResult.OPTIMIZE_FAILED,
+ 100 /* dex2oatWallTimeMillis */, 400 /* dex2oatCpuTimeMillis */));
private DexOptHelper mDexOptHelper;
@@ -123,7 +123,7 @@
PackageOptimizeResult packageResult = result.getPackageOptimizeResults().get(0);
assertThat(packageResult.getPackageName()).isEqualTo(PKG_NAME);
- assertThat(packageResult.getDexFileOptimizeResults())
+ assertThat(packageResult.getDexContainerFileOptimizeResults())
.containsExactlyElementsIn(mPrimaryResults);
InOrder inOrder = inOrder(mPrimaryDexOptimizer, mWakeLock);
@@ -140,7 +140,8 @@
mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams, mCancellationSignal);
assertThat(result.getFinalStatus()).isEqualTo(OptimizeResult.OPTIMIZE_SKIPPED);
- assertThat(result.getPackageOptimizeResults().get(0).getDexFileOptimizeResults()).isEmpty();
+ assertThat(result.getPackageOptimizeResults().get(0).getDexContainerFileOptimizeResults())
+ .isEmpty();
}
@Test
@@ -151,7 +152,8 @@
mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams, mCancellationSignal);
assertThat(result.getFinalStatus()).isEqualTo(OptimizeResult.OPTIMIZE_SKIPPED);
- assertThat(result.getPackageOptimizeResults().get(0).getDexFileOptimizeResults()).isEmpty();
+ assertThat(result.getPackageOptimizeResults().get(0).getDexContainerFileOptimizeResults())
+ .isEmpty();
}
@Test
@@ -166,7 +168,7 @@
OptimizeResult result = mDexOptHelper.dexopt(
mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams, mCancellationSignal);
- assertThat(result.getPackageOptimizeResults().get(0).getDexFileOptimizeResults())
+ assertThat(result.getPackageOptimizeResults().get(0).getDexContainerFileOptimizeResults())
.containsExactlyElementsIn(mPrimaryResults);
}
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
index 0038456..000858c 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
@@ -20,7 +20,7 @@
import static com.android.server.art.AidlUtils.buildOutputArtifacts;
import static com.android.server.art.AidlUtils.buildPermissionSettings;
import static com.android.server.art.OutputArtifacts.PermissionSettings;
-import static com.android.server.art.model.OptimizeResult.DexFileOptimizeResult;
+import static com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult;
import static com.android.server.art.testing.TestingUtils.deepEq;
import static com.google.common.truth.Truth.assertThat;
@@ -257,18 +257,22 @@
assertThat(
mPrimaryDexOptimizer.dexopt(mPkgState, mPkg, mOptimizeParams, mCancellationSignal))
- .comparingElementsUsing(TestingUtils.<DexFileOptimizeResult>deepEquality())
+ .comparingElementsUsing(TestingUtils.<DexContainerFileOptimizeResult>deepEquality())
.containsExactly(
- new DexFileOptimizeResult("/data/app/foo/base.apk", "arm64",
+ new DexContainerFileOptimizeResult("/data/app/foo/base.apk",
+ true /* isPrimaryAbi */, "arm64-v8a",
mParams.mExpectedCompilerFilter, OptimizeResult.OPTIMIZE_PERFORMED,
100 /* dex2oatWallTimeMillis */, 400 /* dex2oatCpuTimeMillis */),
- new DexFileOptimizeResult("/data/app/foo/base.apk", "arm",
+ new DexContainerFileOptimizeResult("/data/app/foo/base.apk",
+ false /* isPrimaryAbi */, "armeabi-v7a",
mParams.mExpectedCompilerFilter, OptimizeResult.OPTIMIZE_FAILED,
0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */),
- new DexFileOptimizeResult("/data/app/foo/split_0.apk", "arm64",
+ new DexContainerFileOptimizeResult("/data/app/foo/split_0.apk",
+ true /* isPrimaryAbi */, "arm64-v8a",
mParams.mExpectedCompilerFilter, OptimizeResult.OPTIMIZE_SKIPPED,
0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */),
- new DexFileOptimizeResult("/data/app/foo/split_0.apk", "arm",
+ new DexContainerFileOptimizeResult("/data/app/foo/split_0.apk",
+ false /* isPrimaryAbi */, "armeabi-v7a",
mParams.mExpectedCompilerFilter, OptimizeResult.OPTIMIZE_PERFORMED,
200 /* dex2oatWallTimeMillis */, 200 /* dex2oatCpuTimeMillis */));
}
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
index 470fa6f..8eb0bfe 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
@@ -17,7 +17,7 @@
package com.android.server.art;
import static com.android.server.art.GetDexoptNeededResult.ArtifactsLocation;
-import static com.android.server.art.model.OptimizeResult.DexFileOptimizeResult;
+import static com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult;
import static com.android.server.art.testing.TestingUtils.deepEq;
import static com.google.common.truth.Truth.assertThat;
@@ -377,7 +377,7 @@
assertThat(
mPrimaryDexOptimizer.dexopt(mPkgState, mPkg, mOptimizeParams, mCancellationSignal)
.stream()
- .map(DexFileOptimizeResult::getStatus)
+ .map(DexContainerFileOptimizeResult::getStatus)
.collect(Collectors.toList()))
.containsExactly(OptimizeResult.OPTIMIZE_CANCELLED);
@@ -412,7 +412,7 @@
.when(artdCancellationSignal)
.cancel();
- Future<List<DexFileOptimizeResult>> results =
+ Future<List<DexContainerFileOptimizeResult>> results =
Executors.newSingleThreadExecutor().submit(() -> {
return mPrimaryDexOptimizer.dexopt(
mPkgState, mPkg, mOptimizeParams, mCancellationSignal);
@@ -424,7 +424,7 @@
assertThat(results.get()
.stream()
- .map(DexFileOptimizeResult::getStatus)
+ .map(DexContainerFileOptimizeResult::getStatus)
.collect(Collectors.toList()))
.containsExactly(OptimizeResult.OPTIMIZE_CANCELLED);