Add a callback for overriding the compiler filter.

Bug: 286930188
Test: atest ArtServiceTests
Change-Id: I3148026f8058a8f82f5757431baf0097806aad58
diff --git a/libartservice/service/api/system-server-current.txt b/libartservice/service/api/system-server-current.txt
index 9c1220e..de687d1 100644
--- a/libartservice/service/api/system-server-current.txt
+++ b/libartservice/service/api/system-server-current.txt
@@ -6,6 +6,7 @@
     ctor public ArtManagerLocal(@NonNull android.content.Context);
     method public void addDexoptDoneCallback(boolean, @NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.DexoptDoneCallback);
     method public void cancelBackgroundDexoptJob();
+    method public void clearAdjustCompilerFilterCallback();
     method @NonNull public void clearAppProfiles(@NonNull com.android.server.pm.PackageManagerLocal.FilteredSnapshot, @NonNull String);
     method public void clearBatchDexoptStartCallback();
     method public void clearScheduleBackgroundDexoptJobCallback();
@@ -22,6 +23,7 @@
     method public void printShellCommandHelp(@NonNull java.io.PrintWriter);
     method public void removeDexoptDoneCallback(@NonNull com.android.server.art.ArtManagerLocal.DexoptDoneCallback);
     method public int scheduleBackgroundDexoptJob();
+    method public void setAdjustCompilerFilterCallback(@NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.AdjustCompilerFilterCallback);
     method public void setBatchDexoptStartCallback(@NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.BatchDexoptStartCallback);
     method public void setScheduleBackgroundDexoptJobCallback(@NonNull java.util.concurrent.Executor, @NonNull com.android.server.art.ArtManagerLocal.ScheduleBackgroundDexoptJobCallback);
     method @NonNull public android.os.ParcelFileDescriptor snapshotAppProfile(@NonNull com.android.server.pm.PackageManagerLocal.FilteredSnapshot, @NonNull String, @Nullable String) throws com.android.server.art.ArtManagerLocal.SnapshotProfileException;
@@ -30,6 +32,10 @@
     method public void unscheduleBackgroundDexoptJob();
   }
 
+  public static interface ArtManagerLocal.AdjustCompilerFilterCallback {
+    method @NonNull public String onAdjustCompilerFilter(@NonNull String, @NonNull String, @NonNull String);
+  }
+
   public static interface ArtManagerLocal.BatchDexoptStartCallback {
     method public void onBatchDexoptStart(@NonNull com.android.server.pm.PackageManagerLocal.FilteredSnapshot, @NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull com.android.server.art.model.BatchDexoptParams.Builder, @NonNull android.os.CancellationSignal);
   }
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index 8e5c1ec..ee253f9 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -928,6 +928,28 @@
     }
 
     /**
+     * Overrides the compiler filter of a package. The callback is called whenever a package is
+     * going to be dexopted. This method is thread-safe.
+     */
+    @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    public void setAdjustCompilerFilterCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull AdjustCompilerFilterCallback callback) {
+        mInjector.getConfig().setAdjustCompilerFilterCallback(executor, callback);
+    }
+
+    /**
+     * Clears the callback set by {@link
+     * #setAdjustCompilerFilterCallback(Executor, AdjustCompilerFilterCallback)}. This
+     * method is thread-safe.
+     */
+    @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    public void clearAdjustCompilerFilterCallback() {
+        mInjector.getConfig().clearAdjustCompilerFilterCallback();
+    }
+
+    /**
      * Cleans up obsolete profiles and artifacts.
      *
      * This is done in a mark-and-sweep approach.
@@ -1243,6 +1265,55 @@
         void onDexoptDone(@NonNull DexoptResult result);
     }
 
+    /** @hide */
+    @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    public interface AdjustCompilerFilterCallback {
+        /**
+         * Returns the adjusted compiler filter for the given package. If a package doesn't need
+         * adjustment, this callback must return {@code originalCompilerFilter}. The callback must
+         * be able to handle unknown {@code originalCompilerFilter} and unknown {@code reason}
+         * because more compiler filters and reasons may be added in the future.
+         *
+         * The returned compiler filter overrides any compiler filter set by {@link
+         * DexoptParams.Builder#setCompilerFilter}, no matter the dexopt is initiated by a
+         * {@link #dexoptPackage} API call or any automatic batch dexopt (e.g., dexopt on boot and
+         * background dexopt).
+         *
+         * This callback is useful for:
+         * - Consistently overriding the compiler filter regardless of the dexopt initiator, for
+         *   some performance-sensitive packages.
+         * - Providing a compiler filter for specific packages during batch dexopt.
+         *
+         * The actual compiler filter to be used for dexopt will be determined in the following
+         * order:
+         *
+         * 1. The default compiler filter for the given reason.
+         * 2. The compiler filter set explicitly by {@link DexoptParams.Builder#setCompilerFilter}.
+         * 3. ART Service's internal adjustments to upgrade the compiler filter, based on whether
+         *    the package is System UI, etc.
+         * 4. The adjustments made by this callback.
+         * 5. ART Service's internal adjustments to downgrade the compiler filter, based on whether
+         *    the profile is available, etc.
+         *
+         * @param packageName the name of the package to be dexopted
+         * @param originalCompilerFilter the compiler filter before adjustment. This is the result
+         *         of step 3 described above. It would be the input to step 5 described above if
+         *         it wasn't for this callback.
+         * @param reason the compilation reason of this dexopt operation. It is a string defined in
+         *         {@link ReasonMapping} or a custom string passed to {@link
+         *         DexoptParams.Builder#Builder(String)}
+         *
+         * @return the compiler filter after adjustment. This will be the input to step 5 described
+         *         above
+         */
+        @SuppressLint("UnflaggedApi") // Flag support for mainline is not available.
+        @NonNull
+        String onAdjustCompilerFilter(@NonNull String packageName,
+                @NonNull String originalCompilerFilter, @NonNull String reason);
+    }
+
     /**
      * Represents an error that happens when snapshotting profiles.
      *
diff --git a/libartservice/service/java/com/android/server/art/DexoptHelper.java b/libartservice/service/java/com/android/server/art/DexoptHelper.java
index c04a981..fda43ca 100644
--- a/libartservice/service/java/com/android/server/art/DexoptHelper.java
+++ b/libartservice/service/java/com/android/server/art/DexoptHelper.java
@@ -347,14 +347,16 @@
         PrimaryDexopter getPrimaryDexopter(@NonNull PackageState pkgState,
                 @NonNull AndroidPackage pkg, @NonNull DexoptParams params,
                 @NonNull CancellationSignal cancellationSignal) {
-            return new PrimaryDexopter(mContext, pkgState, pkg, params, cancellationSignal);
+            return new PrimaryDexopter(
+                    mContext, mConfig, pkgState, pkg, params, cancellationSignal);
         }
 
         @NonNull
         SecondaryDexopter getSecondaryDexopter(@NonNull PackageState pkgState,
                 @NonNull AndroidPackage pkg, @NonNull DexoptParams params,
                 @NonNull CancellationSignal cancellationSignal) {
-            return new SecondaryDexopter(mContext, pkgState, pkg, params, cancellationSignal);
+            return new SecondaryDexopter(
+                    mContext, mConfig, pkgState, pkg, params, cancellationSignal);
         }
 
         @NonNull
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index fff3935..8713ff1 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -16,11 +16,13 @@
 
 package com.android.server.art;
 
+import static com.android.server.art.ArtManagerLocal.AdjustCompilerFilterCallback;
 import static com.android.server.art.OutputArtifacts.PermissionSettings;
 import static com.android.server.art.ProfilePath.TmpProfilePath;
 import static com.android.server.art.Utils.Abi;
 import static com.android.server.art.Utils.InitProfileResult;
 import static com.android.server.art.model.ArtFlags.DexoptFlags;
+import static com.android.server.art.model.Config.Callback;
 import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult;
 
 import android.R;
@@ -45,6 +47,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalManagerRegistry;
 import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.Config;
 import com.android.server.art.model.DetailedDexInfo;
 import com.android.server.art.model.DexoptParams;
 import com.android.server.art.model.DexoptResult;
@@ -300,6 +303,8 @@
         return results;
     }
 
+    // The javadoc on `AdjustCompilerFilterCallback.onAdjustCompilerFilter` may need updating when
+    // this method is changed.
     @NonNull
     private String adjustCompilerFilter(
             @NonNull String targetCompilerFilter, @NonNull DexInfoType dexInfo) {
@@ -312,6 +317,17 @@
             targetCompilerFilter = "speed-profile";
         }
 
+        Callback<AdjustCompilerFilterCallback, Void> callback =
+                mInjector.getConfig().getAdjustCompilerFilterCallback();
+        if (callback != null) {
+            // Local variables passed to the lambda must be final or effectively final.
+            final String originalCompilerFilter = targetCompilerFilter;
+            targetCompilerFilter = Utils.executeAndWait(callback.executor(), () -> {
+                return callback.get().onAdjustCompilerFilter(
+                        mPkgState.getPackageName(), originalCompilerFilter, mParams.getReason());
+            });
+        }
+
         // Code below should only downgrade the compiler filter. Don't upgrade the compiler filter
         // beyond this point!
 
@@ -688,9 +704,11 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
     public static class Injector {
         @NonNull private final Context mContext;
+        @NonNull private final Config mConfig;
 
-        public Injector(@NonNull Context context) {
+        public Injector(@NonNull Context context, @NonNull Config config) {
             mContext = context;
+            mConfig = config;
 
             // Call the getters for various dependencies, to ensure correct initialization order.
             getUserManager();
@@ -747,5 +765,10 @@
             }
             return -1;
         }
+
+        @NonNull
+        public Config getConfig() {
+            return mConfig;
+        }
     }
 }
diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
index c6e64b6..38fca5f 100644
--- a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java
@@ -38,6 +38,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.modules.utils.pm.PackageStateModulesUtils;
 import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.Config;
 import com.android.server.art.model.DexoptParams;
 import com.android.server.art.model.DexoptResult;
 import com.android.server.pm.PackageManagerLocal;
@@ -59,10 +60,10 @@
 
     private final int mSharedGid;
 
-    public PrimaryDexopter(@NonNull Context context, @NonNull PackageState pkgState,
-            @NonNull AndroidPackage pkg, @NonNull DexoptParams params,
-            @NonNull CancellationSignal cancellationSignal) {
-        this(new Injector(context), pkgState, pkg, params, cancellationSignal);
+    public PrimaryDexopter(@NonNull Context context, @NonNull Config config,
+            @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
+            @NonNull DexoptParams params, @NonNull CancellationSignal cancellationSignal) {
+        this(new Injector(context, config), pkgState, pkg, params, cancellationSignal);
     }
 
     @VisibleForTesting
diff --git a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
index 735103c..2841ee2 100644
--- a/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
+++ b/libartservice/service/java/com/android/server/art/SecondaryDexopter.java
@@ -30,6 +30,7 @@
 import androidx.annotation.RequiresApi;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.art.model.Config;
 import com.android.server.art.model.DexoptParams;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageState;
@@ -41,10 +42,10 @@
 public class SecondaryDexopter extends Dexopter<CheckedSecondaryDexInfo> {
     private static final String TAG = ArtManagerLocal.TAG;
 
-    public SecondaryDexopter(@NonNull Context context, @NonNull PackageState pkgState,
-            @NonNull AndroidPackage pkg, @NonNull DexoptParams params,
-            @NonNull CancellationSignal cancellationSignal) {
-        this(new Injector(context), pkgState, pkg, params, cancellationSignal);
+    public SecondaryDexopter(@NonNull Context context, @NonNull Config config,
+            @NonNull PackageState pkgState, @NonNull AndroidPackage pkg,
+            @NonNull DexoptParams params, @NonNull CancellationSignal cancellationSignal) {
+        this(new Injector(context, config), pkgState, pkg, params, cancellationSignal);
     }
 
     @VisibleForTesting
diff --git a/libartservice/service/java/com/android/server/art/Utils.java b/libartservice/service/java/com/android/server/art/Utils.java
index 57d57b5..82418be 100644
--- a/libartservice/service/java/com/android/server/art/Utils.java
+++ b/libartservice/service/java/com/android/server/art/Utils.java
@@ -65,6 +65,7 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 /** @hide */
@@ -274,6 +275,10 @@
         getFuture(CompletableFuture.runAsync(runnable, executor));
     }
 
+    public static <T> T executeAndWait(@NonNull Executor executor, @NonNull Supplier<T> supplier) {
+        return getFuture(CompletableFuture.supplyAsync(supplier, executor));
+    }
+
     public static <T> T getFuture(Future<T> future) {
         try {
             return future.get();
diff --git a/libartservice/service/java/com/android/server/art/model/Config.java b/libartservice/service/java/com/android/server/art/model/Config.java
index 49bc930..2ea8230 100644
--- a/libartservice/service/java/com/android/server/art/model/Config.java
+++ b/libartservice/service/java/com/android/server/art/model/Config.java
@@ -16,6 +16,7 @@
 
 package com.android.server.art.model;
 
+import static com.android.server.art.ArtManagerLocal.AdjustCompilerFilterCallback;
 import static com.android.server.art.ArtManagerLocal.BatchDexoptStartCallback;
 import static com.android.server.art.ArtManagerLocal.DexoptDoneCallback;
 import static com.android.server.art.ArtManagerLocal.ScheduleBackgroundDexoptJobCallback;
@@ -62,6 +63,14 @@
     private LinkedHashMap<DexoptDoneCallback, Callback<DexoptDoneCallback, Boolean>>
             mDexoptDoneCallbacks = new LinkedHashMap<>();
 
+    /**
+     * @see ArtManagerLocal#setAdjustCompilerFilterCallback(Executor,
+     *         AdjustCompilerFilterCallback)
+     */
+    @GuardedBy("this")
+    @Nullable
+    private Callback<AdjustCompilerFilterCallback, Void> mAdjustCompilerFilterCallback = null;
+
     public synchronized void setBatchDexoptStartCallback(
             @NonNull Executor executor, @NonNull BatchDexoptStartCallback callback) {
         mBatchDexoptStartCallback = Callback.create(callback, executor);
@@ -109,6 +118,21 @@
         return new ArrayList<>(mDexoptDoneCallbacks.values());
     }
 
+    public synchronized void setAdjustCompilerFilterCallback(
+            @NonNull Executor executor, @NonNull AdjustCompilerFilterCallback callback) {
+        mAdjustCompilerFilterCallback = Callback.create(callback, executor);
+    }
+
+    public synchronized void clearAdjustCompilerFilterCallback() {
+        mAdjustCompilerFilterCallback = null;
+    }
+
+    @Nullable
+    public synchronized Callback<AdjustCompilerFilterCallback, Void>
+    getAdjustCompilerFilterCallback() {
+        return mAdjustCompilerFilterCallback;
+    }
+
     @AutoValue
     public static abstract class Callback<CallbackType, ExtraType> {
         public abstract @NonNull CallbackType get();
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index efe567f..b9b8bd3 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -168,6 +168,32 @@
         params.mExpectedCompilerFilter = "speed";
         list.add(params);
 
+        // It respects the adjustment made by the callback.
+        params = new Params();
+        params.mRequestedCompilerFilter = "speed-profile";
+        params.mExpectedCallbackInputCompilerFilter = "speed-profile";
+        params.mCallbackReturnedCompilerFilter = "speed";
+        params.mExpectedCompilerFilter = "speed";
+        list.add(params);
+
+        // It upgrades the compiler filter before calling the callback.
+        params = new Params();
+        params.mRequestedCompilerFilter = "speed-profile";
+        params.mIsSystemUi = true;
+        params.mExpectedCallbackInputCompilerFilter = "speed";
+        params.mCallbackReturnedCompilerFilter = "speed";
+        params.mExpectedCompilerFilter = "speed";
+        list.add(params);
+
+        // It downgrades the compiler filter after calling the callback.
+        params = new Params();
+        params.mRequestedCompilerFilter = "speed-profile";
+        params.mExpectedCallbackInputCompilerFilter = "speed-profile";
+        params.mCallbackReturnedCompilerFilter = "speed-profile";
+        params.mIsUseEmbeddedDex = true;
+        params.mExpectedCompilerFilter = "verify";
+        list.add(params);
+
         return list;
     }
 
@@ -198,6 +224,17 @@
 
         lenient().when(mArtd.isInDalvikCache(any())).thenReturn(mParams.mIsInDalvikCache);
 
+        if (mParams.mCallbackReturnedCompilerFilter != null) {
+            mConfig.setAdjustCompilerFilterCallback(
+                    Runnable::run, (packageName, originalCompilerFilter, reason) -> {
+                        assertThat(packageName).isEqualTo(PKG_NAME);
+                        assertThat(originalCompilerFilter)
+                                .isEqualTo(mParams.mExpectedCallbackInputCompilerFilter);
+                        assertThat(reason).isEqualTo("install");
+                        return mParams.mCallbackReturnedCompilerFilter;
+                    });
+        }
+
         mDexoptParams =
                 new DexoptParams.Builder("install")
                         .setCompilerFilter(mParams.mRequestedCompilerFilter)
@@ -334,6 +371,7 @@
 
         // Options.
         public String mRequestedCompilerFilter = "verify";
+        public String mCallbackReturnedCompilerFilter = null;
         public boolean mForce = false;
         public boolean mShouldDowngrade = false;
         public boolean mSkipIfStorageLow = false;
@@ -343,6 +381,7 @@
         public boolean mAlwaysDebuggable = false;
 
         // Expectations.
+        public String mExpectedCallbackInputCompilerFilter = "verify";
         public String mExpectedCompilerFilter = "verify";
         public int mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER
                 | DexoptTrigger.PRIMARY_BOOT_IMAGE_BECOMES_USABLE | DexoptTrigger.NEED_EXTRACTION;
@@ -358,19 +397,22 @@
                             + "isLauncher=%b,"
                             + "isUseEmbeddedDex=%b,"
                             + "requestedCompilerFilter=%s,"
+                            + "callbackReturnedCompilerFilter=%s,"
                             + "force=%b,"
                             + "shouldDowngrade=%b,"
                             + "skipIfStorageLow=%b,"
                             + "ignoreProfile=%b,"
                             + "alwaysDebuggable=%b"
                             + " => "
-                            + "targetCompilerFilter=%s,"
+                            + "expectedCallbackInputCompilerFilter=%s,"
+                            + "expectedCompilerFilter=%s,"
                             + "expectedDexoptTrigger=%d,"
                             + "expectedIsDebuggable=%b,"
                             + "expectedIsHiddenApiPolicyEnabled=%b",
                     mIsInDalvikCache, mHiddenApiEnforcementPolicy, mIsVmSafeMode, mIsDebuggable,
-                    mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex, mRequestedCompilerFilter, mForce,
-                    mShouldDowngrade, mSkipIfStorageLow, mIgnoreProfile, mAlwaysDebuggable,
+                    mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex, mRequestedCompilerFilter,
+                    mCallbackReturnedCompilerFilter, mForce, mShouldDowngrade, mSkipIfStorageLow,
+                    mIgnoreProfile, mAlwaysDebuggable, mExpectedCallbackInputCompilerFilter,
                     mExpectedCompilerFilter, mExpectedDexoptTrigger, mExpectedIsDebuggable,
                     mExpectedIsHiddenApiPolicyEnabled);
         }
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
index 60b6426..7a8287f 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
@@ -31,6 +31,7 @@
 import android.os.storage.StorageManager;
 
 import com.android.modules.utils.pm.PackageStateModulesUtils;
+import com.android.server.art.model.Config;
 import com.android.server.art.testing.StaticMockitoRule;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.AndroidPackageSplit;
@@ -68,9 +69,17 @@
     protected PackageUserState mPkgUserStateNotInstalled;
     protected PackageUserState mPkgUserStateInstalled;
     protected CancellationSignal mCancellationSignal;
+    protected Config mConfig;
 
     @Before
     public void setUp() throws Exception {
+        mPkgUserStateNotInstalled = createPackageUserState(false /* installed */);
+        mPkgUserStateInstalled = createPackageUserState(true /* installed */);
+        mPkgState = createPackageState();
+        mPkg = mPkgState.getAndroidPackage();
+        mCancellationSignal = new CancellationSignal();
+        mConfig = new Config();
+
         lenient().when(mInjector.getArtd()).thenReturn(mArtd);
         lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
         lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
@@ -78,6 +87,7 @@
         lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
         lenient().when(mInjector.getStorageManager()).thenReturn(mStorageManager);
         lenient().when(mInjector.getArtVersion()).thenReturn(ART_VERSION);
+        lenient().when(mInjector.getConfig()).thenReturn(mConfig);
 
         lenient()
                 .when(SystemProperties.get("dalvik.vm.systemuicompilerfilter"))
@@ -104,12 +114,6 @@
         lenient().when(mDexUseManager.isPrimaryDexUsedByOtherApps(any(), any())).thenReturn(false);
 
         lenient().when(mStorageManager.getAllocatableBytes(any())).thenReturn(1l);
-
-        mPkgUserStateNotInstalled = createPackageUserState(false /* installed */);
-        mPkgUserStateInstalled = createPackageUserState(true /* installed */);
-        mPkgState = createPackageState();
-        mPkg = mPkgState.getAndroidPackage();
-        mCancellationSignal = new CancellationSignal();
     }
 
     private AndroidPackage createPackage() {
diff --git a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
index f799b70..f80503d 100644
--- a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
@@ -43,6 +43,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.art.model.ArtFlags;
+import com.android.server.art.model.Config;
 import com.android.server.art.model.DexoptParams;
 import com.android.server.art.model.DexoptResult;
 import com.android.server.art.testing.StaticMockitoRule;
@@ -105,11 +106,17 @@
     private PackageState mPkgState;
     private AndroidPackage mPkg;
     private CancellationSignal mCancellationSignal;
+    protected Config mConfig;
 
     private SecondaryDexopter mSecondaryDexopter;
 
     @Before
     public void setUp() throws Exception {
+        mPkgState = createPackageState();
+        mPkg = mPkgState.getAndroidPackage();
+        mCancellationSignal = new CancellationSignal();
+        mConfig = new Config();
+
         lenient()
                 .when(SystemProperties.getBoolean(eq("dalvik.vm.always_debuggable"), anyBoolean()))
                 .thenReturn(false);
@@ -129,6 +136,7 @@
         lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
         lenient().when(mInjector.isLauncherPackage(any())).thenReturn(false);
         lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
+        lenient().when(mInjector.getConfig()).thenReturn(mConfig);
 
         List<CheckedSecondaryDexInfo> secondaryDexInfo = createSecondaryDexInfo();
         lenient()
@@ -136,10 +144,6 @@
                         eq(PKG_NAME), eq(true) /* excludeObsoleteDexesAndLoaders */))
                 .thenReturn(secondaryDexInfo);
 
-        mPkgState = createPackageState();
-        mPkg = mPkgState.getAndroidPackage();
-        mCancellationSignal = new CancellationSignal();
-
         prepareProfiles();
 
         // Dexopt is always needed and successful.