Implement compilation reason boot-after-mainline-update.

Bug: 260419279
Test: -
  1. adb shell setprop pm.dexopt.boot-after-mainline-update verify
  2. adb shell setprop dalvik.vm.systemuicompilerfilter speed
  3. adb shell pm art optimize-packages boot-after-mainline-update
Ignore-AOSP-First: ART Services.
Change-Id: I163f808399eb27393e00dbb149d5941ff3db277f
diff --git a/libartservice/service/api/system-server-current.txt b/libartservice/service/api/system-server-current.txt
index de59623..bd98d19 100644
--- a/libartservice/service/api/system-server-current.txt
+++ b/libartservice/service/api/system-server-current.txt
@@ -53,6 +53,7 @@
 
   public class ReasonMapping {
     field public static final String REASON_BG_DEXOPT = "bg-dexopt";
+    field public static final String REASON_BOOT_AFTER_MAINLINE_UPDATE = "boot-after-mainline-update";
     field public static final String REASON_BOOT_AFTER_OTA = "boot-after-ota";
     field public static final String REASON_CMDLINE = "cmdline";
     field public static final String REASON_FIRST_BOOT = "first-boot";
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index 185d113..dd9ae52 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -27,6 +27,7 @@
 import static com.android.server.art.model.Config.Callback;
 import static com.android.server.art.model.OptimizationStatus.DexContainerFileOptimizationStatus;
 
+import android.R;
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -623,12 +624,24 @@
     private List<String> getDefaultPackages(@NonNull PackageManagerLocal.FilteredSnapshot snapshot,
             @NonNull @BatchOptimizeReason String reason) {
         var packages = new ArrayList<String>();
-        // TODO(b/258818709): Filter packages by last active time.
-        snapshot.forAllPackageStates((pkgState) -> {
-            if (Utils.canOptimizePackage(pkgState, mInjector.getAppHibernationManager())) {
-                packages.add(pkgState.getPackageName());
-            }
-        });
+        switch (reason) {
+            case ReasonMapping.REASON_BOOT_AFTER_MAINLINE_UPDATE:
+                snapshot.forAllPackageStates((pkgState) -> {
+                    if (mInjector.isSystemUiPackage(pkgState.getPackageName())
+                            && Utils.canOptimizePackage(
+                                    pkgState, mInjector.getAppHibernationManager())) {
+                        packages.add(pkgState.getPackageName());
+                    }
+                });
+                break;
+            default:
+                // TODO(b/258818709): Filter packages by last active time.
+                snapshot.forAllPackageStates((pkgState) -> {
+                    if (Utils.canOptimizePackage(pkgState, mInjector.getAppHibernationManager())) {
+                        packages.add(pkgState.getPackageName());
+                    }
+                });
+        }
         return packages;
     }
 
@@ -788,5 +801,10 @@
             return Objects.requireNonNull(
                     LocalManagerRegistry.getManager(DexUseManagerLocal.class));
         }
+
+        @NonNull
+        public boolean isSystemUiPackage(@NonNull String packageName) {
+            return packageName.equals(mContext.getString(R.string.config_systemUi));
+        }
     }
 }
diff --git a/libartservice/service/java/com/android/server/art/ReasonMapping.java b/libartservice/service/java/com/android/server/art/ReasonMapping.java
index c236e21..0a44fa9 100644
--- a/libartservice/service/java/com/android/server/art/ReasonMapping.java
+++ b/libartservice/service/java/com/android/server/art/ReasonMapping.java
@@ -46,6 +46,8 @@
     public static final String REASON_FIRST_BOOT = "first-boot";
     /** Optimizing apps on the next boot after an OTA. */
     public static final String REASON_BOOT_AFTER_OTA = "boot-after-ota";
+    /** Optimizing apps on the next boot after a mainline update. */
+    public static final String REASON_BOOT_AFTER_MAINLINE_UPDATE = "boot-after-mainline-update";
     /** Installing an app after user presses the "install"/"update" button. */
     public static final String REASON_INSTALL = "install";
     /** Optimizing apps in the background. */
@@ -77,6 +79,7 @@
     @StringDef(prefix = "REASON_", value = {
         REASON_FIRST_BOOT,
         REASON_BOOT_AFTER_OTA,
+        REASON_BOOT_AFTER_MAINLINE_UPDATE,
         REASON_BG_DEXOPT,
     })
     // clang-format on
@@ -92,6 +95,7 @@
     @StringDef(prefix = "REASON_", value = {
         REASON_FIRST_BOOT,
         REASON_BOOT_AFTER_OTA,
+        REASON_BOOT_AFTER_MAINLINE_UPDATE,
     })
     // clang-format on
     @Retention(RetentionPolicy.SOURCE)
@@ -152,6 +156,7 @@
         switch (reason) {
             case REASON_FIRST_BOOT:
             case REASON_BOOT_AFTER_OTA:
+            case REASON_BOOT_AFTER_MAINLINE_UPDATE:
                 return ArtFlags.PRIORITY_BOOT;
             case REASON_INSTALL_FAST:
                 return ArtFlags.PRIORITY_INTERACTIVE_FAST;
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 cb5921d..7cd4f46 100644
--- a/libartservice/service/java/com/android/server/art/model/ArtFlags.java
+++ b/libartservice/service/java/com/android/server/art/model/ArtFlags.java
@@ -154,6 +154,7 @@
                 return FLAG_FOR_PRIMARY_DEX | FLAG_FOR_SECONDARY_DEX | FLAG_SHOULD_DOWNGRADE;
             case ReasonMapping.REASON_FIRST_BOOT:
             case ReasonMapping.REASON_BOOT_AFTER_OTA:
+            case ReasonMapping.REASON_BOOT_AFTER_MAINLINE_UPDATE:
                 return FLAG_FOR_PRIMARY_DEX | FLAG_SHOULD_INCLUDE_DEPENDENCIES;
             case ReasonMapping.REASON_BG_DEXOPT:
             case ReasonMapping.REASON_CMDLINE:
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index a50c801..0bbbb0e 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -125,13 +125,22 @@
         lenient().when(mInjector.getConfig()).thenReturn(mConfig);
         lenient().when(mInjector.getAppHibernationManager()).thenReturn(mAppHibernationManager);
         lenient().when(mInjector.getUserManager()).thenReturn(mUserManager);
+        lenient().when(mInjector.isSystemUiPackage(any())).thenReturn(false);
+        lenient().when(mInjector.isSystemUiPackage(PKG_NAME_SYS_UI)).thenReturn(true);
 
         lenient().when(SystemProperties.get(eq("pm.dexopt.install"))).thenReturn("speed-profile");
         lenient().when(SystemProperties.get(eq("pm.dexopt.bg-dexopt"))).thenReturn("speed-profile");
         lenient().when(SystemProperties.get(eq("pm.dexopt.first-boot"))).thenReturn("verify");
         lenient()
+                .when(SystemProperties.get(eq("pm.dexopt.boot-after-mainline-update")))
+                .thenReturn("verify");
+        lenient()
                 .when(SystemProperties.getInt(eq("pm.dexopt.bg-dexopt.concurrency"), anyInt()))
                 .thenReturn(3);
+        lenient()
+                .when(SystemProperties.getInt(
+                        eq("pm.dexopt.boot-after-mainline-update.concurrency"), anyInt()))
+                .thenReturn(3);
 
         // No ISA translation.
         lenient()
@@ -354,6 +363,22 @@
     }
 
     @Test
+    public void testOptimizePackagesBootAfterMainlineUpdate() throws Exception {
+        var result = mock(OptimizeResult.class);
+        var cancellationSignal = new CancellationSignal();
+
+        // It should only optimize system UI.
+        when(mDexOptHelper.dexopt(
+                     any(), deepEq(List.of(PKG_NAME_SYS_UI)), any(), any(), any(), any(), any()))
+                .thenReturn(result);
+
+        assertThat(mArtManagerLocal.optimizePackages(mSnapshot, "boot-after-mainline-update",
+                           cancellationSignal, null /* processCallbackExecutor */,
+                           null /* processCallback */))
+                .isSameInstanceAs(result);
+    }
+
+    @Test
     public void testOptimizePackagesOverride() throws Exception {
         var params = new OptimizeParams.Builder("bg-dexopt").build();
         var result = mock(OptimizeResult.class);