Expose `optimizePackage` and fix API lint errors.

Changes:
1. Rename `OptimizeOptions` to `OptimizeParams` (enforced by
   https://cs.android.com/android/platform/superproject/+/master:tools/metalava/src/main/java/com/android/tools/metalava/ApiLint.kt;l=2405;drc=26ec88f1d22ddd33c30aec46b1a5a50339e3c159)
2. Change the backing type of `PriorityClass` from `byte` to `int`.
3. Duplicate the keys of `PriorityClass` as `PriorityClassApi` to be
   exposed as API.
4. Use a bit field `OptimizeParams.mFlags` instead of booleans and
   change flag handling.

Bug: 229268202
Test: m update-api
Ignore-AOSP-First: ART Services
Change-Id: I12e497c46ec68f347b76b34920ba2f7405263aa9
diff --git a/artd/binder/com/android/server/art/PriorityClass.aidl b/artd/binder/com/android/server/art/PriorityClass.aidl
index 38adfc7..abea3f3 100644
--- a/artd/binder/com/android/server/art/PriorityClass.aidl
+++ b/artd/binder/com/android/server/art/PriorityClass.aidl
@@ -17,22 +17,14 @@
 package com.android.server.art;
 
 /**
- * Indicates the priority of an operation. The value affects the resource usage and the process
- * priority. A higher value may result in faster execution but may consume more resources and
- * compete for resources with other processes.
+ * Keep in sync with {@link ArtFlags.PriorityClassApi}.
  *
  * @hide
  */
+@Backing(type="int")
 enum PriorityClass {
-    /** Indicates that the operation blocks boot. */
     BOOT = 100,
-    /**
-     * Indicates that a human is waiting on the result and the operation is more latency sensitive
-     * than usual.
-     */
     INTERACTIVE_FAST = 80,
-    /** Indicates that a human is waiting on the result. */
     INTERACTIVE = 60,
-    /** Indicates that the operation runs in background. */
     BACKGROUND = 40,
 }
diff --git a/libartservice/service/api/system-server-current.txt b/libartservice/service/api/system-server-current.txt
index 1e8711b..ad988c2 100644
--- a/libartservice/service/api/system-server-current.txt
+++ b/libartservice/service/api/system-server-current.txt
@@ -9,6 +9,7 @@
     method @NonNull public com.android.server.art.model.OptimizationStatus getOptimizationStatus(@NonNull com.android.server.pm.snapshot.PackageDataSnapshot, @NonNull String);
     method @NonNull public com.android.server.art.model.OptimizationStatus getOptimizationStatus(@NonNull com.android.server.pm.snapshot.PackageDataSnapshot, @NonNull String, int);
     method public int handleShellCommand(@NonNull android.os.Binder, @NonNull android.os.ParcelFileDescriptor, @NonNull android.os.ParcelFileDescriptor, @NonNull android.os.ParcelFileDescriptor, @NonNull String[]);
+    method @NonNull public com.android.server.art.model.OptimizeResult optimizePackage(@NonNull com.android.server.pm.snapshot.PackageDataSnapshot, @NonNull String, @NonNull com.android.server.art.model.OptimizeParams);
   }
 
 }
@@ -18,8 +19,16 @@
   public class ArtFlags {
     method public static int defaultDeleteFlags();
     method public static int defaultGetStatusFlags();
+    method public static int defaultOptimizeFlags();
+    field public static final int FLAG_FORCE = 16; // 0x10
     field public static final int FLAG_FOR_PRIMARY_DEX = 1; // 0x1
     field public static final int FLAG_FOR_SECONDARY_DEX = 2; // 0x2
+    field public static final int FLAG_SHOULD_DOWNGRADE = 8; // 0x8
+    field public static final int FLAG_SHOULD_INCLUDE_DEPENDENCIES = 4; // 0x4
+    field public static final int PRIORITY_BACKGROUND = 40; // 0x28
+    field public static final int PRIORITY_BOOT = 100; // 0x64
+    field public static final int PRIORITY_INTERACTIVE = 60; // 0x3c
+    field public static final int PRIORITY_INTERACTIVE_FAST = 80; // 0x50
   }
 
   public class DeleteResult {
@@ -38,5 +47,44 @@
     method @NonNull public String getLocationDebugString();
   }
 
+  public class OptimizeParams {
+    method @NonNull public String getCompilerFilter();
+    method public int getFlags();
+    method public int getPriorityClass();
+    method @NonNull public String getReason();
+    field public static final String COMPILER_FILTER_NOOP = "skip";
+  }
+
+  public static final class OptimizeParams.Builder {
+    ctor public OptimizeParams.Builder(@NonNull String);
+    ctor public OptimizeParams.Builder(@NonNull String, int);
+    method @NonNull public com.android.server.art.model.OptimizeParams build();
+    method @NonNull public com.android.server.art.model.OptimizeParams.Builder setCompilerFilter(@NonNull String);
+    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 {
+    ctor public OptimizeResult(@NonNull String, @NonNull String, @NonNull String, @NonNull java.util.List<com.android.server.art.model.OptimizeResult.DexFileOptimizeResult>);
+    method @NonNull public java.util.List<com.android.server.art.model.OptimizeResult.DexFileOptimizeResult> getDexFileOptimizeResults();
+    method public int getFinalStatus();
+    method @NonNull public String getPackageName();
+    method @NonNull public String getReason();
+    method @NonNull public String getRequestedCompilerFilter();
+    field public static final int OPTIMIZE_CANCELLED = 40; // 0x28
+    field public static final int OPTIMIZE_FAILED = 30; // 0x1e
+    field public static final int OPTIMIZE_PERFORMED = 20; // 0x14
+    field public static final int OPTIMIZE_SKIPPED = 10; // 0xa
+  }
+
+  public static class OptimizeResult.DexFileOptimizeResult {
+    method @NonNull public String getActualCompilerFilter();
+    method @NonNull public String getDexFile();
+    method @NonNull public String getInstructionSet();
+    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 594b89e..1f47afb 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -37,7 +37,7 @@
 import com.android.server.art.model.ArtFlags;
 import com.android.server.art.model.DeleteResult;
 import com.android.server.art.model.OptimizationStatus;
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.model.OptimizeResult;
 import com.android.server.art.wrapper.AndroidPackageApi;
 import com.android.server.art.wrapper.PackageManagerLocal;
@@ -105,6 +105,8 @@
     /**
      * Deletes optimized artifacts of a package.
      *
+     * Uses the default flags ({@link ArtFlags#defaultDeleteFlags()}).
+     *
      * @throws IllegalArgumentException if the package is not found or the flags are illegal
      * @throws IllegalStateException if an internal error occurs
      */
@@ -162,6 +164,8 @@
     /**
      * Returns the optimization status of a package.
      *
+     * Uses the default flags ({@link ArtFlags#defaultGetStatusFlags()}).
+     *
      * @throws IllegalArgumentException if the package is not found or the flags are illegal
      * @throws IllegalStateException if an internal error occurs
      */
@@ -224,11 +228,11 @@
         }
     }
 
-    /** @hide */
     @NonNull
     public OptimizeResult optimizePackage(@NonNull PackageDataSnapshot snapshot,
-            @NonNull String packageName, @NonNull OptimizeOptions options) {
-        if (!options.isForPrimaryDex() && !options.isForSecondaryDex()) {
+            @NonNull String packageName, @NonNull OptimizeParams params) {
+        if ((params.getFlags() & ArtFlags.FLAG_FOR_PRIMARY_DEX) == 0
+                && (params.getFlags() & ArtFlags.FLAG_FOR_SECONDARY_DEX) == 0) {
             throw new IllegalArgumentException("Nothing to optimize");
         }
 
@@ -236,7 +240,7 @@
         AndroidPackageApi pkg = getPackageOrThrow(pkgState);
 
         try {
-            return mInjector.getDexOptHelper().dexopt(snapshot, pkgState, pkg, options);
+            return mInjector.getDexOptHelper().dexopt(snapshot, pkgState, pkg, params);
         } catch (RemoteException e) {
             throw new IllegalStateException("An error occurred when calling artd", e);
         }
diff --git a/libartservice/service/java/com/android/server/art/ArtShellCommand.java b/libartservice/service/java/com/android/server/art/ArtShellCommand.java
index 1146aa0..c207fc4 100644
--- a/libartservice/service/java/com/android/server/art/ArtShellCommand.java
+++ b/libartservice/service/java/com/android/server/art/ArtShellCommand.java
@@ -16,6 +16,7 @@
 
 package com.android.server.art;
 
+import static com.android.server.art.model.ArtFlags.OptimizeFlags;
 import static com.android.server.art.model.OptimizationStatus.DexFileOptimizationStatus;
 
 import android.os.Binder;
@@ -25,7 +26,7 @@
 import com.android.server.art.model.ArtFlags;
 import com.android.server.art.model.DeleteResult;
 import com.android.server.art.model.OptimizationStatus;
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.model.OptimizeResult;
 import com.android.server.art.wrapper.PackageManagerLocal;
 import com.android.server.pm.snapshot.PackageDataSnapshot;
@@ -75,15 +76,15 @@
                 return 0;
             }
             case "optimize-package": {
-                var optionsBuilder = new OptimizeOptions.Builder("cmdline");
+                var paramsBuilder = new OptimizeParams.Builder("cmdline");
                 String opt;
                 while ((opt = getNextOption()) != null) {
                     switch (opt) {
                         case "-m":
-                            optionsBuilder.setCompilerFilter(getNextArgRequired());
+                            paramsBuilder.setCompilerFilter(getNextArgRequired());
                             break;
                         case "-f":
-                            optionsBuilder.setForce(true);
+                            paramsBuilder.setFlags(ArtFlags.FLAG_FORCE, ArtFlags.FLAG_FORCE);
                             break;
                         default:
                             pw.println("Error: Unknown option: " + opt);
@@ -91,7 +92,7 @@
                     }
                 }
                 OptimizeResult result = mArtManagerLocal.optimizePackage(
-                        snapshot, getNextArgRequired(), optionsBuilder.build());
+                        snapshot, getNextArgRequired(), paramsBuilder.build());
                 switch (result.getFinalStatus()) {
                     case OptimizeResult.OPTIMIZE_SKIPPED:
                         pw.println("SKIPPED");
diff --git a/libartservice/service/java/com/android/server/art/DexOptHelper.java b/libartservice/service/java/com/android/server/art/DexOptHelper.java
index f6df0c3..e73abcb 100644
--- a/libartservice/service/java/com/android/server/art/DexOptHelper.java
+++ b/libartservice/service/java/com/android/server/art/DexOptHelper.java
@@ -28,7 +28,8 @@
 import android.os.WorkSource;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.model.OptimizeResult;
 import com.android.server.art.wrapper.AndroidPackageApi;
 import com.android.server.art.wrapper.PackageState;
@@ -67,16 +68,16 @@
 
     /**
      * DO NOT use this method directly. Use {@link
-     * ArtManagerLocal#optimizePackage(PackageDataSnapshot, String, OptimizeOptions)}.
+     * ArtManagerLocal#optimizePackage(PackageDataSnapshot, String, OptimizeParams)}.
      */
     @NonNull
     public OptimizeResult dexopt(@NonNull PackageDataSnapshot snapshot,
             @NonNull PackageState pkgState, @NonNull AndroidPackageApi pkg,
-            @NonNull OptimizeOptions options) throws RemoteException {
+            @NonNull OptimizeParams params) throws RemoteException {
         List<DexFileOptimizeResult> results = new ArrayList<>();
         Supplier<OptimizeResult> createResult = ()
-                -> new OptimizeResult(pkgState.getPackageName(), options.getCompilerFilter(),
-                        options.getReason(), results);
+                -> new OptimizeResult(pkgState.getPackageName(), params.getCompilerFilter(),
+                        params.getReason(), results);
 
         if (!canOptimizePackage(pkgState, pkg)) {
             return createResult.get();
@@ -96,17 +97,17 @@
                 wakeLock.acquire(WAKE_LOCK_TIMEOUT_MS);
             }
 
-            if (options.isForPrimaryDex()) {
-                results.addAll(mInjector.getPrimaryDexOptimizer().dexopt(pkgState, pkg, options));
+            if ((params.getFlags() & ArtFlags.FLAG_FOR_PRIMARY_DEX) != 0) {
+                results.addAll(mInjector.getPrimaryDexOptimizer().dexopt(pkgState, pkg, params));
             }
 
-            if (options.isForSecondaryDex()) {
+            if ((params.getFlags() & ArtFlags.FLAG_FOR_SECONDARY_DEX) != 0) {
                 // TODO(jiakaiz): Implement this.
                 throw new UnsupportedOperationException(
                         "Optimizing secondary dex'es is not implemented yet");
             }
 
-            if (options.getIncludesDependencies()) {
+            if ((params.getFlags() & ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES) != 0) {
                 // TODO(jiakaiz): Implement this.
                 throw new UnsupportedOperationException(
                         "Optimizing dependencies is not implemented yet");
diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
index 49708b3..7d51df2 100644
--- a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
+++ b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
@@ -34,7 +34,8 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.model.OptimizeResult;
 import com.android.server.art.wrapper.AndroidPackageApi;
 import com.android.server.art.wrapper.PackageState;
@@ -61,17 +62,16 @@
 
     /**
      * DO NOT use this method directly. Use {@link
-     * ArtManagerLocal#optimizePackage(PackageDataSnapshot, String, OptimizeOptions)}.
+     * ArtManagerLocal#optimizePackage(PackageDataSnapshot, String, OptimizeParams)}.
      */
     @NonNull
     public List<DexFileOptimizeResult> dexopt(@NonNull PackageState pkgState,
-            @NonNull AndroidPackageApi pkg, @NonNull OptimizeOptions options)
-            throws RemoteException {
+            @NonNull AndroidPackageApi pkg, @NonNull OptimizeParams params) throws RemoteException {
         List<DexFileOptimizeResult> results = new ArrayList<>();
 
-        String targetCompilerFilter = adjustCompilerFilter(
-                pkgState, pkg, options.getCompilerFilter(), options.getReason());
-        if (targetCompilerFilter.equals(OptimizeOptions.COMPILER_FILTER_NOOP)) {
+        String targetCompilerFilter =
+                adjustCompilerFilter(pkgState, pkg, params.getCompilerFilter(), params.getReason());
+        if (targetCompilerFilter.equals(OptimizeParams.COMPILER_FILTER_NOOP)) {
             return results;
         }
 
@@ -94,13 +94,15 @@
                 PermissionSettings permissionSettings =
                         getPermissionSettings(pkgState, pkg, true /* canBePublic */);
 
-                DexoptOptions dexoptOptions = getDexoptOptions(pkgState, pkg, options);
+                DexoptOptions dexoptOptions = getDexoptOptions(pkgState, pkg, params);
 
                 for (String isa : Utils.getAllIsas(pkgState)) {
                     @OptimizeResult.OptimizeStatus int status = OptimizeResult.OPTIMIZE_SKIPPED;
                     try {
-                        GetDexoptNeededResult getDexoptNeededResult = getDexoptNeeded(dexInfo, isa,
-                                compilerFilter, options.getShouldDowngrade(), options.getForce());
+                        GetDexoptNeededResult getDexoptNeededResult =
+                                getDexoptNeeded(dexInfo, isa, compilerFilter,
+                                        (params.getFlags() & ArtFlags.FLAG_SHOULD_DOWNGRADE) != 0,
+                                        (params.getFlags() & ArtFlags.FLAG_FORCE) != 0);
 
                         if (!getDexoptNeededResult.isDexoptNeeded) {
                             continue;
@@ -110,7 +112,7 @@
 
                         status = dexoptFile(dexInfo, isa, isInDalvikCache, compilerFilter,
                                 inputProfile, getDexoptNeededResult, permissionSettings,
-                                options.getPriorityClass(), dexoptOptions);
+                                params.getPriorityClass(), dexoptOptions);
                     } catch (ServiceSpecificException e) {
                         // Log the error and continue.
                         Log.e(TAG,
@@ -198,9 +200,9 @@
 
     @NonNull
     private DexoptOptions getDexoptOptions(@NonNull PackageState pkgState,
-            @NonNull AndroidPackageApi pkg, @NonNull OptimizeOptions options) {
+            @NonNull AndroidPackageApi pkg, @NonNull OptimizeParams params) {
         DexoptOptions dexoptOptions = new DexoptOptions();
-        dexoptOptions.compilationReason = options.getReason();
+        dexoptOptions.compilationReason = params.getReason();
         dexoptOptions.targetSdkVersion = pkg.getTargetSdkVersion();
         dexoptOptions.debuggable = pkg.isDebuggable() || isAlwaysDebuggable();
         dexoptOptions.generateAppImage = false;
@@ -260,7 +262,7 @@
     private @OptimizeResult.OptimizeStatus int dexoptFile(@NonNull DetailedPrimaryDexInfo dexInfo,
             @NonNull String isa, boolean isInDalvikCache, @NonNull String compilerFilter,
             @Nullable ProfilePath profile, @NonNull GetDexoptNeededResult getDexoptNeededResult,
-            @NonNull PermissionSettings permissionSettings, @PriorityClass byte priorityClass,
+            @NonNull PermissionSettings permissionSettings, @PriorityClass int priorityClass,
             @NonNull DexoptOptions dexoptOptions) throws RemoteException {
         OutputArtifacts outputArtifacts = AidlUtils.buildOutputArtifacts(
                 dexInfo.dexPath(), isa, isInDalvikCache, permissionSettings);
diff --git a/libartservice/service/java/com/android/server/art/ReasonMapping.java b/libartservice/service/java/com/android/server/art/ReasonMapping.java
index 6e9f56f..107f7dc 100644
--- a/libartservice/service/java/com/android/server/art/ReasonMapping.java
+++ b/libartservice/service/java/com/android/server/art/ReasonMapping.java
@@ -16,10 +16,14 @@
 
 package com.android.server.art;
 
+import static com.android.server.art.model.ArtFlags.PriorityClassApi;
+
 import android.annotation.NonNull;
 import android.os.SystemProperties;
 import android.text.TextUtils;
 
+import com.android.server.art.model.ArtFlags;
+
 import dalvik.system.DexFile;
 
 /**
@@ -98,27 +102,27 @@
      * Returns the priority for the given reason.
      *
      * @throws IllegalArgumentException if the reason is invalid
-     * @see PriorityClass
+     * @see PriorityClassApi
      *
      * @hide
      */
-    public static @PriorityClass byte getPriorityClassForReason(@NonNull String reason) {
+    public static @PriorityClassApi byte getPriorityClassForReason(@NonNull String reason) {
         switch (reason) {
             case REASON_FIRST_BOOT:
             case REASON_BOOT_AFTER_OTA:
-                return PriorityClass.BOOT;
+                return ArtFlags.PRIORITY_BOOT;
             case REASON_INSTALL_FAST:
-                return PriorityClass.INTERACTIVE_FAST;
+                return ArtFlags.PRIORITY_INTERACTIVE_FAST;
             case REASON_INSTALL:
             case REASON_CMDLINE:
-                return PriorityClass.INTERACTIVE;
+                return ArtFlags.PRIORITY_INTERACTIVE;
             case REASON_BG_DEXOPT:
             case REASON_INACTIVE:
             case REASON_INSTALL_BULK:
             case REASON_INSTALL_BULK_SECONDARY:
             case REASON_INSTALL_BULK_DOWNGRADED:
             case REASON_INSTALL_BULK_SECONDARY_DOWNGRADED:
-                return PriorityClass.BACKGROUND;
+                return ArtFlags.PRIORITY_BACKGROUND;
             default:
                 throw new IllegalArgumentException("No priority class for reason '" + reason + "'");
         }
diff --git a/libartservice/service/java/com/android/server/art/Utils.java b/libartservice/service/java/com/android/server/art/Utils.java
index 68cdf07..9e44760 100644
--- a/libartservice/service/java/com/android/server/art/Utils.java
+++ b/libartservice/service/java/com/android/server/art/Utils.java
@@ -22,7 +22,7 @@
 import android.util.SparseArray;
 
 import com.android.server.art.ArtifactsPath;
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.wrapper.PackageManagerLocal;
 import com.android.server.art.wrapper.PackageState;
 
@@ -77,7 +77,7 @@
 
     /** Returns true if the given string is a valid compiler filter. */
     public static boolean isValidArtServiceCompilerFilter(@NonNull String compilerFilter) {
-        if (compilerFilter.equals(OptimizeOptions.COMPILER_FILTER_NOOP)) {
+        if (compilerFilter.equals(OptimizeParams.COMPILER_FILTER_NOOP)) {
             return true;
         }
         return DexFile.isValidCompilerFilter(compilerFilter);
diff --git a/libartservice/service/java/com/android/server/art/model/ArtFlags.java b/libartservice/service/java/com/android/server/art/model/ArtFlags.java
index 0ecad74..8accfc3 100644
--- a/libartservice/service/java/com/android/server/art/model/ArtFlags.java
+++ b/libartservice/service/java/com/android/server/art/model/ArtFlags.java
@@ -19,17 +19,37 @@
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
 
+import com.android.server.art.PriorityClass;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /** @hide */
 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
 public class ArtFlags {
+    // Common flags.
+
     /** Whether the operation is applied for primary dex'es. */
     public static final int FLAG_FOR_PRIMARY_DEX = 1 << 0;
     /** Whether the operation is applied for secondary dex'es. */
     public static final int FLAG_FOR_SECONDARY_DEX = 1 << 1;
 
+    // Flags specific to `optimizePackage`.
+
+    /** Whether to optimize dependency libraries as well. */
+    public static final int FLAG_SHOULD_INCLUDE_DEPENDENCIES = 1 << 2;
+    /**
+     * Whether the intention is to downgrade the compiler filter. If true, the optimization will
+     * be skipped if the target compiler filter is better than or equal to the compiler filter
+     * of the existing optimized artifacts, or optimized artifacts do not exist.
+     */
+    public static final int FLAG_SHOULD_DOWNGRADE = 1 << 3;
+    /**
+     * Whether to force optimization. If true, the optimization will be performed regardless of
+     * any existing optimized artifacts.
+     */
+    public static final int FLAG_FORCE = 1 << 4;
+
     /**
      * Flags for {@link ArtManagerLocal#deleteOptimizedArtifacts(PackageDataSnapshot, String, int)}.
      *
@@ -76,5 +96,70 @@
         return FLAG_FOR_PRIMARY_DEX;
     }
 
+    /**
+     * Flags for {@link OptimizeParams}.
+     *
+     * @hide
+     */
+    // clang-format off
+    @IntDef(flag = true, prefix = "FLAG_", value = {
+        FLAG_FOR_PRIMARY_DEX,
+        FLAG_FOR_SECONDARY_DEX,
+        FLAG_SHOULD_INCLUDE_DEPENDENCIES,
+        FLAG_SHOULD_DOWNGRADE,
+        FLAG_FORCE,
+    })
+    // clang-format on
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface OptimizeFlags {}
+
+    /**
+     * Default flags that are used when
+     * {@link OptimizeParams.Builder#Builder(String)} is called.
+     * Value: {@link #FLAG_FOR_PRIMARY_DEX}.
+     */
+    public static @OptimizeFlags int defaultOptimizeFlags() {
+        return FLAG_FOR_PRIMARY_DEX;
+    }
+
+    // Keep in sync with `PriorityClass` except for `PRIORITY_NONE`.
+
+    /**
+     * Initial value. Not expected.
+     *
+     * @hide
+     */
+    public static final int PRIORITY_NONE = -1;
+    /** Indicates that the operation blocks boot. */
+    public static final int PRIORITY_BOOT = PriorityClass.BOOT;
+    /**
+     * Indicates that a human is waiting on the result and the operation is more latency sensitive
+     * than usual.
+     */
+    public static final int PRIORITY_INTERACTIVE_FAST = PriorityClass.INTERACTIVE_FAST;
+    /** Indicates that a human is waiting on the result. */
+    public static final int PRIORITY_INTERACTIVE = PriorityClass.INTERACTIVE;
+    /** Indicates that the operation runs in background. */
+    public static final int PRIORITY_BACKGROUND = PriorityClass.BACKGROUND;
+
+    /**
+     * Indicates the priority of an operation. The value affects the resource usage and the process
+     * priority. A higher value may result in faster execution but may consume more resources and
+     * compete for resources with other processes.
+     *
+     * @hide
+     */
+    // clang-format off
+    @IntDef(prefix = "PRIORITY_", value = {
+        PRIORITY_NONE,
+        PRIORITY_BOOT,
+        PRIORITY_INTERACTIVE_FAST,
+        PRIORITY_INTERACTIVE,
+        PRIORITY_BACKGROUND,
+    })
+    // clang-format on
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PriorityClassApi {}
+
     private ArtFlags() {}
 }
diff --git a/libartservice/service/java/com/android/server/art/model/OptimizeOptions.java b/libartservice/service/java/com/android/server/art/model/OptimizeOptions.java
deleted file mode 100644
index 6e897ec..0000000
--- a/libartservice/service/java/com/android/server/art/model/OptimizeOptions.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.art.model;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.text.TextUtils;
-
-import com.android.server.art.PriorityClass;
-import com.android.server.art.ReasonMapping;
-import com.android.server.art.Utils;
-
-/** @hide */
-public class OptimizeOptions {
-    public static final class Builder {
-        private OptimizeOptions mOptions = new OptimizeOptions();
-
-        /**
-         * Creates a builder.
-         *
-         * @param reason See {@link #setReason(String)}.
-         */
-        public Builder(@NonNull String reason) {
-            setReason(reason);
-        }
-
-        /** Whether to generate optimized artifacts for primary dex'es. Default: true. */
-        public Builder setForPrimaryDex(boolean value) {
-            mOptions.mIsForPrimaryDex = value;
-            return this;
-        }
-
-        /** Whether to generate optimized artifacts for secondary dex'es. Default: false. */
-        public Builder setForSecondaryDex(boolean value) {
-            mOptions.mIsForSecondaryDex = value;
-            return this;
-        }
-
-        /** Whether to optimize dependency packages as well. Default: false. */
-        public Builder setIncludesDependencies(boolean value) {
-            mOptions.mIncludesDependencies = value;
-            return this;
-        }
-
-        /**
-         * The target compiler filter. Note that the compiler filter might be adjusted before the
-         * execution based on factors like whether the profile is available or whether the app is
-         * used by other apps. If not set, the default compiler filter for the given reason will be
-         * used.
-         */
-        public Builder setCompilerFilter(@NonNull String value) {
-            mOptions.mCompilerFilter = value;
-            return this;
-        }
-
-        /**
-         * The priority of the operation. If not set, the default priority class for the given
-         * reason will be used.
-         *
-         * @see PriorityClass
-         */
-        public Builder setPriorityClass(@PriorityClass byte value) {
-            mOptions.mPriorityClass = value;
-            return this;
-        }
-
-        /**
-         * 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 setReason(@NonNull String value) {
-            mOptions.mReason = value;
-            return this;
-        }
-
-        /**
-         * Whether the intention is to downgrade the compiler filter. If true, the compilation will
-         * be skipped if the target compiler filter is better than or equal to the compiler filter
-         * of the existing optimized artifacts, or optimized artifacts do not exist.
-         */
-        public Builder setShouldDowngrade(boolean value) {
-            mOptions.mShouldDowngrade = value;
-            return this;
-        }
-
-        /**
-         * Whether to force compilation. If true, the compilation will be performed regardless of
-         * any existing optimized artifacts.
-         */
-        public Builder setForce(boolean value) {
-            mOptions.mForce = value;
-            return this;
-        }
-
-        /**
-         * Returns the built object.
-         *
-         * @throws IllegalArgumentException if the built options would be invalid
-         */
-        public OptimizeOptions build() {
-            if (mOptions.mReason.isEmpty()) {
-                throw new IllegalArgumentException("Reason must not be empty");
-            }
-
-            if (mOptions.mCompilerFilter.isEmpty()) {
-                mOptions.mCompilerFilter =
-                        ReasonMapping.getCompilerFilterForReason(mOptions.mReason);
-            } else if (!Utils.isValidArtServiceCompilerFilter(mOptions.mCompilerFilter)) {
-                throw new IllegalArgumentException(
-                        "Invalid compiler filter '" + mOptions.mCompilerFilter + "'");
-            }
-
-            if (mOptions.mPriorityClass == -1) {
-                mOptions.mPriorityClass = ReasonMapping.getPriorityClassForReason(mOptions.mReason);
-            } else if (mOptions.mPriorityClass < 0 || mOptions.mPriorityClass > 100) {
-                throw new IllegalArgumentException("Invalid priority class "
-                        + mOptions.mPriorityClass + ". Must be between 0 and 100");
-            }
-
-            return mOptions;
-        }
-    }
-
-    /**
-     * A value indicating that dexopt shouldn't be run. This value is consumed by ART Services and
-     * is not propagated to dex2oat.
-     */
-    public static final String COMPILER_FILTER_NOOP = "skip";
-
-    private boolean mIsForPrimaryDex = true;
-    private boolean mIsForSecondaryDex = false;
-    private boolean mIncludesDependencies = false;
-    private @NonNull String mCompilerFilter = "";
-    private @PriorityClass byte mPriorityClass = -1;
-    private @NonNull String mReason = "";
-    private boolean mShouldDowngrade = false;
-    private boolean mForce = false;
-
-    private OptimizeOptions() {}
-
-    /** Whether to generate optimized artifacts for primary dex'es. */
-    public boolean isForPrimaryDex() {
-        return mIsForPrimaryDex;
-    }
-
-    /** Whether to generate optimized artifacts for secondary dex'es. */
-    public boolean isForSecondaryDex() {
-        return mIsForSecondaryDex;
-    }
-
-    /** Whether to optimize dependency packages as well. */
-    public boolean getIncludesDependencies() {
-        return mIncludesDependencies;
-    }
-
-    /** The target compiler filter. */
-    public @NonNull String getCompilerFilter() {
-        return mCompilerFilter;
-    }
-
-    /** The priority class. */
-    public @PriorityClass byte getPriorityClass() {
-        return mPriorityClass;
-    }
-
-    /**
-     * The compilation reason.
-     *
-     * DO NOT directly use the string value to determine the resource usage and the process
-     * priority. Use {@link #getPriorityClass}.
-     */
-    public @NonNull String getReason() {
-        return mReason;
-    }
-
-    /** Whether the intention is to downgrade the compiler filter. */
-    public boolean getShouldDowngrade() {
-        return mShouldDowngrade;
-    }
-
-    /** Whether to force compilation. */
-    public boolean getForce() {
-        return mForce;
-    }
-}
diff --git a/libartservice/service/java/com/android/server/art/model/OptimizeParams.java b/libartservice/service/java/com/android/server/art/model/OptimizeParams.java
new file mode 100644
index 0000000..672aebb
--- /dev/null
+++ b/libartservice/service/java/com/android/server/art/model/OptimizeParams.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.art.model;
+
+import static com.android.server.art.model.ArtFlags.OptimizeFlags;
+import static com.android.server.art.model.ArtFlags.PriorityClassApi;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.text.TextUtils;
+
+import com.android.server.art.ReasonMapping;
+import com.android.server.art.Utils;
+
+/** @hide */
+@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public class OptimizeParams {
+    public static final class Builder {
+        private OptimizeParams mParams = new OptimizeParams();
+
+        /**
+         * Creates a builder.
+         *
+         * Uses default flags ({@link ArtFlags#defaultOptimizeFlags()}).
+         *
+         * @param reason See {@link #setReason(String)}.
+         */
+        public Builder(@NonNull String reason) {
+            this(reason, ArtFlags.defaultOptimizeFlags());
+        }
+
+        /**
+         * Same as above, but allows to specify flags.
+         */
+        public Builder(@NonNull String reason, @OptimizeFlags int flags) {
+            setReason(reason);
+            setFlags(flags);
+        }
+
+        /** Replaces all flags with the given value. */
+        @NonNull
+        public Builder setFlags(@OptimizeFlags int value) {
+            mParams.mFlags = value;
+            return this;
+        }
+
+        /** Replaces the flags specified by the mask with the given value. */
+        @NonNull
+        public Builder setFlags(@OptimizeFlags int value, @OptimizeFlags int mask) {
+            mParams.mFlags = (mParams.mFlags & ~mask) | (value & mask);
+            return this;
+        }
+
+        /**
+         * The target compiler filter. Note that the compiler filter might be adjusted before the
+         * execution based on factors like whether the profile is available or whether the app is
+         * used by other apps. If not set, the default compiler filter for the given reason will be
+         * used.
+         */
+        @NonNull
+        public Builder setCompilerFilter(@NonNull String value) {
+            mParams.mCompilerFilter = value;
+            return this;
+        }
+
+        /**
+         * The priority of the operation. If not set, the default priority class for the given
+         * reason will be used.
+         *
+         * @see PriorityClassApi
+         */
+        @NonNull
+        public Builder setPriorityClass(@PriorityClassApi int value) {
+            mParams.mPriorityClass = value;
+            return this;
+        }
+
+        /**
+         * 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
+         */
+        @NonNull
+        public OptimizeParams build() {
+            if (mParams.mReason.isEmpty()) {
+                throw new IllegalArgumentException("Reason must not be empty");
+            }
+
+            if (mParams.mCompilerFilter.isEmpty()) {
+                mParams.mCompilerFilter = ReasonMapping.getCompilerFilterForReason(mParams.mReason);
+            } else if (!Utils.isValidArtServiceCompilerFilter(mParams.mCompilerFilter)) {
+                throw new IllegalArgumentException(
+                        "Invalid compiler filter '" + mParams.mCompilerFilter + "'");
+            }
+
+            if (mParams.mPriorityClass == ArtFlags.PRIORITY_NONE) {
+                mParams.mPriorityClass = ReasonMapping.getPriorityClassForReason(mParams.mReason);
+            } else if (mParams.mPriorityClass < 0 || mParams.mPriorityClass > 100) {
+                throw new IllegalArgumentException("Invalid priority class "
+                        + mParams.mPriorityClass + ". Must be between 0 and 100");
+            }
+
+            return mParams;
+        }
+    }
+
+    /**
+     * A value indicating that dexopt shouldn't be run. This value is consumed by ART Services and
+     * is not propagated to dex2oat.
+     */
+    public static final String COMPILER_FILTER_NOOP = "skip";
+
+    private @OptimizeFlags int mFlags = 0;
+    private @NonNull String mCompilerFilter = "";
+    private @PriorityClassApi int mPriorityClass = ArtFlags.PRIORITY_NONE;
+    private @NonNull String mReason = "";
+
+    private OptimizeParams() {}
+
+    /** Returns all flags. */
+    public @OptimizeFlags int getFlags() {
+        return mFlags;
+    }
+
+    /** The target compiler filter. */
+    public @NonNull String getCompilerFilter() {
+        return mCompilerFilter;
+    }
+
+    /** The priority class. */
+    public @PriorityClassApi int getPriorityClass() {
+        return mPriorityClass;
+    }
+
+    /**
+     * The compilation reason.
+     *
+     * DO NOT directly use the string value to determine the resource usage and the process
+     * priority. Use {@link #getPriorityClass}.
+     */
+    public @NonNull String getReason() {
+        return mReason;
+    }
+}
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 efebbf2..d6fdf28 100644
--- a/libartservice/service/java/com/android/server/art/model/OptimizeResult.java
+++ b/libartservice/service/java/com/android/server/art/model/OptimizeResult.java
@@ -18,12 +18,16 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 
 import com.android.internal.annotations.Immutable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
 /** @hide */
+@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
 @Immutable
 public class OptimizeResult {
     // Possible values of {@link #OptimizeStatus}.
@@ -35,8 +39,15 @@
     public static final int OPTIMIZE_CANCELLED = 40;
 
     /** @hide */
-    @IntDef(prefix = {"OPTIMIZE_"},
-            value = {OPTIMIZE_SKIPPED, OPTIMIZE_FAILED, OPTIMIZE_PERFORMED, OPTIMIZE_CANCELLED})
+    // clang-format off
+    @IntDef(prefix = {"OPTIMIZE_"}, value = {
+        OPTIMIZE_SKIPPED,
+        OPTIMIZE_FAILED,
+        OPTIMIZE_PERFORMED,
+        OPTIMIZE_CANCELLED,
+    })
+    // clang-format on
+    @Retention(RetentionPolicy.SOURCE)
     public @interface OptimizeStatus {}
 
     private final @NonNull String mPackageName;
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index ded89c9..bb1b26d 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -38,7 +38,7 @@
 
 import com.android.server.art.model.DeleteResult;
 import com.android.server.art.model.OptimizationStatus;
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.model.OptimizeResult;
 import com.android.server.art.wrapper.AndroidPackageApi;
 import com.android.server.art.wrapper.PackageManagerLocal;
@@ -219,14 +219,14 @@
 
     @Test
     public void testOptimizePackage() throws Exception {
-        var options = new OptimizeOptions.Builder("install").build();
+        var params = new OptimizeParams.Builder("install").build();
         var result = mock(OptimizeResult.class);
 
-        when(mDexOptHelper.dexopt(any(), same(mPkgState), same(mPkg), same(options)))
+        when(mDexOptHelper.dexopt(any(), same(mPkgState), same(mPkg), same(params)))
                 .thenReturn(result);
 
-        assertThat(mArtManagerLocal.optimizePackage(
-                           mock(PackageDataSnapshot.class), PKG_NAME, options))
+        assertThat(
+                mArtManagerLocal.optimizePackage(mock(PackageDataSnapshot.class), PKG_NAME, params))
                 .isSameInstanceAs(result);
     }
 
@@ -235,7 +235,7 @@
         when(mPackageManagerLocal.getPackageState(any(), anyInt(), eq(PKG_NAME))).thenReturn(null);
 
         mArtManagerLocal.optimizePackage(mock(PackageDataSnapshot.class), PKG_NAME,
-                new OptimizeOptions.Builder("install").build());
+                new OptimizeParams.Builder("install").build());
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -243,7 +243,7 @@
         when(mPkgState.getAndroidPackage()).thenReturn(null);
 
         mArtManagerLocal.optimizePackage(mock(PackageDataSnapshot.class), PKG_NAME,
-                new OptimizeOptions.Builder("install").build());
+                new OptimizeParams.Builder("install").build());
     }
 
     private AndroidPackageApi createPackage() {
diff --git a/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java b/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
index e68f21b..1b9c852 100644
--- a/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
@@ -36,7 +36,7 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.model.OptimizeResult;
 import com.android.server.art.testing.OnSuccessRule;
 import com.android.server.art.wrapper.AndroidPackageApi;
@@ -71,8 +71,8 @@
         verifyNoMoreInteractions(mPrimaryDexOptimizer);
     });
 
-    private final OptimizeOptions mOptions =
-            new OptimizeOptions.Builder("install").setCompilerFilter("speed-profile").build();
+    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),
@@ -95,11 +95,11 @@
 
     @Test
     public void testDexopt() throws Exception {
-        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mOptions)))
+        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mParams)))
                 .thenReturn(mPrimaryResults);
 
         OptimizeResult result =
-                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mOptions);
+                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams);
 
         assertThat(result.getPackageName()).isEqualTo(PKG_NAME);
         assertThat(result.getRequestedCompilerFilter()).isEqualTo("speed-profile");
@@ -113,7 +113,7 @@
         when(mPkg.isHasCode()).thenReturn(false);
 
         OptimizeResult result =
-                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mOptions);
+                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams);
 
         assertThat(result.getFinalStatus()).isEqualTo(OptimizeResult.OPTIMIZE_SKIPPED);
         assertThat(result.getDexFileOptimizeResults()).isEmpty();
@@ -125,11 +125,11 @@
         lenient().when(mAhm.isHibernatingGlobally(PKG_NAME)).thenReturn(false);
         lenient().when(mAhm.isOatArtifactDeletionEnabled()).thenReturn(true);
 
-        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mOptions)))
+        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mParams)))
                 .thenReturn(mPrimaryResults);
 
         OptimizeResult result =
-                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mOptions);
+                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams);
 
         assertThat(result.getDexFileOptimizeResults()).containsExactlyElementsIn(mPrimaryResults);
     }
@@ -141,7 +141,7 @@
         lenient().when(mAhm.isOatArtifactDeletionEnabled()).thenReturn(true);
 
         OptimizeResult result =
-                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mOptions);
+                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams);
 
         assertThat(result.getFinalStatus()).isEqualTo(OptimizeResult.OPTIMIZE_SKIPPED);
         assertThat(result.getDexFileOptimizeResults()).isEmpty();
@@ -153,11 +153,11 @@
         lenient().when(mAhm.isHibernatingGlobally(PKG_NAME)).thenReturn(true);
         lenient().when(mAhm.isOatArtifactDeletionEnabled()).thenReturn(false);
 
-        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mOptions)))
+        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mParams)))
                 .thenReturn(mPrimaryResults);
 
         OptimizeResult result =
-                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mOptions);
+                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams);
 
         assertThat(result.getDexFileOptimizeResults()).containsExactlyElementsIn(mPrimaryResults);
     }
@@ -169,11 +169,11 @@
         when(mPowerManager.newWakeLock(eq(PowerManager.PARTIAL_WAKE_LOCK), any()))
                 .thenReturn(wakeLock);
 
-        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mOptions)))
+        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mParams)))
                 .thenReturn(mPrimaryResults);
 
         OptimizeResult result =
-                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mOptions);
+                mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams);
 
         InOrder inOrder = inOrder(mPrimaryDexOptimizer, wakeLock);
         inOrder.verify(wakeLock).acquire(anyLong());
@@ -188,12 +188,12 @@
         when(mPowerManager.newWakeLock(eq(PowerManager.PARTIAL_WAKE_LOCK), any()))
                 .thenReturn(wakeLock);
 
-        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mOptions)))
+        when(mPrimaryDexOptimizer.dexopt(same(mPkgState), same(mPkg), same(mParams)))
                 .thenThrow(IllegalStateException.class);
 
         try {
-            OptimizeResult result = mDexOptHelper.dexopt(
-                    mock(PackageDataSnapshot.class), mPkgState, mPkg, mOptions);
+            OptimizeResult result =
+                    mDexOptHelper.dexopt(mock(PackageDataSnapshot.class), mPkgState, mPkg, mParams);
         } catch (Exception e) {
         }
 
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
index d1eba96..c7c779e 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
@@ -40,7 +40,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.OptimizeParams;
 import com.android.server.art.model.OptimizeResult;
 import com.android.server.art.testing.OnSuccessRule;
 import com.android.server.art.testing.TestingUtils;
@@ -65,7 +66,7 @@
         verifyNoMoreInteractions(mArtd);
     });
 
-    private OptimizeOptions mOptions;
+    private OptimizeParams mOptimizeParams;
 
     @Parameter(0) public Params mParams;
 
@@ -176,12 +177,14 @@
         lenient().when(mPkgState.isSystem()).thenReturn(mParams.mIsSystem);
         lenient().when(mPkgState.isUpdatedSystemApp()).thenReturn(mParams.mIsUpdatedSystemApp);
 
-        mOptions = new OptimizeOptions.Builder("install")
-                           .setCompilerFilter(mParams.mRequestedCompilerFilter)
-                           .setPriorityClass(PriorityClass.INTERACTIVE)
-                           .setForce(mParams.mForce)
-                           .setShouldDowngrade(mParams.mShouldDowngrade)
-                           .build();
+        mOptimizeParams =
+                new OptimizeParams.Builder("install")
+                        .setCompilerFilter(mParams.mRequestedCompilerFilter)
+                        .setPriorityClass(ArtFlags.PRIORITY_INTERACTIVE)
+                        .setFlags(mParams.mForce ? ArtFlags.FLAG_FORCE : 0, ArtFlags.FLAG_FORCE)
+                        .setFlags(mParams.mShouldDowngrade ? ArtFlags.FLAG_SHOULD_DOWNGRADE : 0,
+                                ArtFlags.FLAG_SHOULD_DOWNGRADE)
+                        .build();
     }
 
     @Test
@@ -242,7 +245,7 @@
                 eq(mParams.mExpectedCompilerFilter), isNull() /* profile */,
                 isNull() /* inputVdex */, eq(PriorityClass.INTERACTIVE), deepEq(dexoptOptions));
 
-        assertThat(mPrimaryDexOptimizer.dexopt(mPkgState, mPkg, mOptions))
+        assertThat(mPrimaryDexOptimizer.dexopt(mPkgState, mPkg, mOptimizeParams))
                 .comparingElementsUsing(TestingUtils.<DexFileOptimizeResult>deepEquality())
                 .containsExactly(
                         new DexFileOptimizeResult("/data/app/foo/base.apk", "arm64",
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
index 594d054..8db3032 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
@@ -20,7 +20,6 @@
 import static com.android.server.art.testing.TestingUtils.deepEq;
 
 import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyByte;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
@@ -29,7 +28,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.server.art.model.OptimizeOptions;
+import com.android.server.art.model.OptimizeParams;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -38,13 +37,13 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class PrimaryDexOptimizerTest extends PrimaryDexOptimizerTestBase {
-    private OptimizeOptions mOptions;
+    private OptimizeParams mOptimizeParams;
 
     @Before
     public void setUp() throws Exception {
         super.setUp();
 
-        mOptions = new OptimizeOptions.Builder("install").setCompilerFilter("verify").build();
+        mOptimizeParams = new OptimizeParams.Builder("install").setCompilerFilter("verify").build();
     }
 
     @Test
@@ -54,7 +53,7 @@
                 .when(mArtd)
                 .getDexoptNeeded(eq("/data/app/foo/base.apk"), eq("arm64"), any(), any(), anyInt());
         doReturn(true).when(mArtd).dexopt(any(), eq("/data/app/foo/base.apk"), eq("arm64"), any(),
-                any(), any(), isNull(), anyByte(), any());
+                any(), any(), isNull(), anyInt(), any());
 
         // ArtifactsPath, isInDalvikCache=true.
         doReturn(dexoptIsNeeded(ArtifactsLocation.DALVIK_CACHE))
@@ -64,7 +63,7 @@
                 any(), any(),
                 deepEq(VdexPath.artifactsPath(AidlUtils.buildArtifactsPath(
                         "/data/app/foo/base.apk", "arm", true /* isInDalvikCache */))),
-                anyByte(), any());
+                anyInt(), any());
 
         // ArtifactsPath, isInDalvikCache=false.
         doReturn(dexoptIsNeeded(ArtifactsLocation.NEXT_TO_DEX))
@@ -75,7 +74,7 @@
                 any(), any(), any(),
                 deepEq(VdexPath.artifactsPath(AidlUtils.buildArtifactsPath(
                         "/data/app/foo/split_0.apk", "arm64", false /* isInDalvikCache */))),
-                anyByte(), any());
+                anyInt(), any());
 
         // DexMetadataPath.
         doReturn(dexoptIsNeeded(ArtifactsLocation.DM))
@@ -86,8 +85,8 @@
                 any(), any(),
                 deepEq(VdexPath.dexMetadataPath(
                         AidlUtils.buildDexMetadataPath("/data/app/foo/split_0.apk"))),
-                anyByte(), any());
+                anyInt(), any());
 
-        mPrimaryDexOptimizer.dexopt(mPkgState, mPkg, mOptions);
+        mPrimaryDexOptimizer.dexopt(mPkgState, mPkg, mOptimizeParams);
     }
 }
diff --git a/libartservice/service/javatests/com/android/server/art/ReasonMappingTest.java b/libartservice/service/javatests/com/android/server/art/ReasonMappingTest.java
index 776cb0f..ea1226e 100644
--- a/libartservice/service/javatests/com/android/server/art/ReasonMappingTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ReasonMappingTest.java
@@ -25,6 +25,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.art.model.ArtFlags;
 import com.android.server.art.testing.StaticMockitoRule;
 
 import org.junit.After;
@@ -73,7 +74,7 @@
     @Test
     public void testGetPriorityClassForReason() throws Exception {
         assertThat(ReasonMapping.getPriorityClassForReason("install"))
-                .isEqualTo(PriorityClass.INTERACTIVE);
+                .isEqualTo(ArtFlags.PRIORITY_INTERACTIVE);
     }
 
     @Test(expected = IllegalArgumentException.class)
diff --git a/libartservice/service/javatests/com/android/server/art/model/OptimizeOptionsTest.java b/libartservice/service/javatests/com/android/server/art/model/OptimizeParamsTest.java
similarity index 72%
rename from libartservice/service/javatests/com/android/server/art/model/OptimizeOptionsTest.java
rename to libartservice/service/javatests/com/android/server/art/model/OptimizeParamsTest.java
index 47515c7..200bbc4 100644
--- a/libartservice/service/javatests/com/android/server/art/model/OptimizeOptionsTest.java
+++ b/libartservice/service/javatests/com/android/server/art/model/OptimizeParamsTest.java
@@ -21,49 +21,49 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.server.art.PriorityClass;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class OptimizeOptionsTest {
+public class OptimizeParamsTest {
     @Test
     public void testBuild() {
-        new OptimizeOptions.Builder("install").build();
+        new OptimizeParams.Builder("install").build();
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testBuildEmptyReason() {
-        new OptimizeOptions.Builder("").build();
+        new OptimizeParams.Builder("").build();
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testBuildInvalidCompilerFilter() {
-        new OptimizeOptions.Builder("install").setCompilerFilter("invalid").build();
+        new OptimizeParams.Builder("install").setCompilerFilter("invalid").build();
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testBuildInvalidPriorityClass() {
-        new OptimizeOptions.Builder("install").setPriorityClass((byte) 101).build();
+        new OptimizeParams.Builder("install").setPriorityClass(101).build();
     }
 
     @Test
     public void testBuildCustomReason() {
-        new OptimizeOptions.Builder("custom")
+        new OptimizeParams.Builder("custom")
                 .setCompilerFilter("speed")
-                .setPriorityClass((byte) 90)
+                .setPriorityClass(90)
                 .build();
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testBuildCustomReasonEmptyCompilerFilter() {
-        new OptimizeOptions.Builder("custom").setPriorityClass(PriorityClass.INTERACTIVE).build();
+        new OptimizeParams.Builder("custom")
+                .setPriorityClass(ArtFlags.PRIORITY_INTERACTIVE)
+                .build();
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testBuildCustomReasonEmptyPriorityClass() {
-        new OptimizeOptions.Builder("custom").setCompilerFilter("speed").build();
+        new OptimizeParams.Builder("custom").setCompilerFilter("speed").build();
     }
 }