Add a field to DexoptResult to report extra status.

We'll use the field to report more status.

Bug: 290340704
Bug: 278080573
Test: atest ArtServiceTests
Ignore-AOSP-First: ART Service.
Change-Id: I345307d4d01d3c3b97d9bd1d07d3c3034c676271
diff --git a/libartservice/service/java/com/android/server/art/BackgroundDexoptJobStatsReporter.java b/libartservice/service/java/com/android/server/art/BackgroundDexoptJobStatsReporter.java
index 916988a..49b114d 100644
--- a/libartservice/service/java/com/android/server/art/BackgroundDexoptJobStatsReporter.java
+++ b/libartservice/service/java/com/android/server/art/BackgroundDexoptJobStatsReporter.java
@@ -58,8 +58,10 @@
                         .stream()
                         .flatMap(packageResult
                                 -> packageResult.getDexContainerFileDexoptResults().stream())
-                        .anyMatch(DexoptResult
-                                          .DexContainerFileDexoptResult::isSkippedDueToStorageLow);
+                        .anyMatch(fileResult
+                                -> (fileResult.getExtraStatus()
+                                           & DexoptResult.EXTRA_SKIPPED_STORAGE_LOW)
+                                        != 0);
         if (isSkippedDueToStorageLow) {
             return ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_NO_SPACE_LEFT;
         }
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index 446d948..6ca388f 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -165,7 +165,7 @@
                     long cpuTimeMs = 0;
                     long sizeBytes = 0;
                     long sizeBeforeBytes = 0;
-                    boolean isSkippedDueToStorageLow = false;
+                    @DexoptResult.DexoptResultExtraStatus int extraStatus = 0;
                     try {
                         var target = DexoptTarget.<DexInfoType>builder()
                                              .setDexInfo(dexInfo)
@@ -196,7 +196,7 @@
                                     && mInjector.getStorageManager().getAllocatableBytes(
                                                mPkg.getStorageUuid())
                                             <= 0) {
-                                isSkippedDueToStorageLow = true;
+                                extraStatus |= DexoptResult.EXTRA_SKIPPED_STORAGE_LOW;
                                 continue;
                             }
                         } catch (IOException e) {
@@ -239,7 +239,7 @@
                     } finally {
                         var result = DexContainerFileDexoptResult.create(dexInfo.dexPath(),
                                 abi.isPrimaryAbi(), abi.name(), compilerFilter, status, wallTimeMs,
-                                cpuTimeMs, sizeBytes, sizeBeforeBytes, isSkippedDueToStorageLow);
+                                cpuTimeMs, sizeBytes, sizeBeforeBytes, extraStatus);
                         Log.i(TAG,
                                 String.format("Dexopt result: [packageName = %s] %s",
                                         mPkgState.getPackageName(), result));
diff --git a/libartservice/service/java/com/android/server/art/model/DexoptResult.java b/libartservice/service/java/com/android/server/art/model/DexoptResult.java
index 79f9b5f..66dcfe1 100644
--- a/libartservice/service/java/com/android/server/art/model/DexoptResult.java
+++ b/libartservice/service/java/com/android/server/art/model/DexoptResult.java
@@ -28,6 +28,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 
 /** @hide */
@@ -59,6 +60,19 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface DexoptResultStatus {}
 
+    // Possible values of {@link #DexoptResultExtraStatus}.
+    /** @hide */
+    public static final int EXTRA_SKIPPED_STORAGE_LOW = 1 << 0;
+
+    /** @hide */
+    // clang-format off
+    @IntDef(flag = true, prefix = {"EXTRA_"}, value = {
+        EXTRA_SKIPPED_STORAGE_LOW,
+    })
+    // clang-format on
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DexoptResultExtraStatus {}
+
     /** @hide */
     protected DexoptResult() {}
 
@@ -125,6 +139,16 @@
         throw new IllegalArgumentException("Unknown dexopt status " + status);
     }
 
+    /** @hide */
+    @NonNull
+    public static String dexoptResultExtraStatusToString(@DexoptResultExtraStatus int extraStatus) {
+        var strs = new ArrayList<String>();
+        if ((extraStatus & DexoptResult.EXTRA_SKIPPED_STORAGE_LOW) != 0) {
+            strs.add("EXTRA_SKIPPED_STORAGE_LOW");
+        }
+        return String.join(", ", strs);
+    }
+
     /**
      * Describes the result of a package.
      *
@@ -192,10 +216,10 @@
                 boolean isPrimaryAbi, @NonNull String abi, @NonNull String compilerFilter,
                 @DexoptResultStatus int status, long dex2oatWallTimeMillis,
                 long dex2oatCpuTimeMillis, long sizeBytes, long sizeBeforeBytes,
-                boolean isSkippedDueToStorageLow) {
+                @DexoptResultExtraStatus int extraStatus) {
             return new AutoValue_DexoptResult_DexContainerFileDexoptResult(dexContainerFile,
                     isPrimaryAbi, abi, compilerFilter, status, dex2oatWallTimeMillis,
-                    dex2oatCpuTimeMillis, sizeBytes, sizeBeforeBytes, isSkippedDueToStorageLow);
+                    dex2oatCpuTimeMillis, sizeBytes, sizeBeforeBytes, extraStatus);
         }
 
         /** The absolute path to the dex container file. */
@@ -250,7 +274,7 @@
         public abstract long getSizeBeforeBytes();
 
         /** @hide */
-        public abstract boolean isSkippedDueToStorageLow();
+        public abstract @DexoptResultExtraStatus int getExtraStatus();
 
         @Override
         @NonNull
@@ -264,11 +288,13 @@
                             + "dex2oatWallTimeMillis=%d, "
                             + "dex2oatCpuTimeMillis=%d, "
                             + "sizeBytes=%d, "
-                            + "sizeBeforeBytes=%d}",
+                            + "sizeBeforeBytes=%d, "
+                            + "extraStatus=[%s]}",
                     getDexContainerFile(), isPrimaryAbi(), getAbi(), getActualCompilerFilter(),
                     DexoptResult.dexoptResultStatusToString(getStatus()),
                     getDex2oatWallTimeMillis(), getDex2oatCpuTimeMillis(), getSizeBytes(),
-                    getSizeBeforeBytes());
+                    getSizeBeforeBytes(),
+                    DexoptResult.dexoptResultExtraStatusToString(getExtraStatus()));
         }
     }
 }
diff --git a/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java b/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
index f08035d..21d89e6 100644
--- a/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DexoptHelperTest.java
@@ -822,11 +822,11 @@
         return List.of(DexContainerFileDexoptResult.create(dexPath, true /* isPrimaryAbi */,
                                "arm64-v8a", "verify", status1, 100 /* dex2oatWallTimeMillis */,
                                400 /* dex2oatCpuTimeMillis */, 0 /* sizeBytes */,
-                               0 /* sizeBeforeBytes */, false /* isSkippedDueToStorageLow */),
+                               0 /* sizeBeforeBytes */, 0 /* extraStatus */),
                 DexContainerFileDexoptResult.create(dexPath, false /* isPrimaryAbi */,
                         "armeabi-v7a", "verify", status2, 100 /* dex2oatWallTimeMillis */,
                         400 /* dex2oatCpuTimeMillis */, 0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                        false /* isSkippedDueToStorageLow */));
+                        0 /* extraStatus */));
     }
 
     private void checkPackageResult(DexoptResult result, int index, String packageName,
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index 46db32f..fe95847 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -280,25 +280,23 @@
                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_PERFORMED,
                                 100 /* dex2oatWallTimeMillis */, 400 /* dex2oatCpuTimeMillis */,
                                 30000 /* sizeBytes */, 32000 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */),
+                                0 /* extraStatus */),
                         DexContainerFileDexoptResult.create("/data/app/foo/base.apk",
                                 false /* isPrimaryAbi */, "armeabi-v7a",
                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_FAILED,
                                 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
-                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */),
+                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
                         DexContainerFileDexoptResult.create("/data/app/foo/split_0.apk",
                                 true /* isPrimaryAbi */, "arm64-v8a",
                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_SKIPPED,
                                 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
-                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */),
+                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
                         DexContainerFileDexoptResult.create("/data/app/foo/split_0.apk",
                                 false /* isPrimaryAbi */, "armeabi-v7a",
                                 mParams.mExpectedCompilerFilter, DexoptResult.DEXOPT_PERFORMED,
                                 200 /* dex2oatWallTimeMillis */, 200 /* dex2oatCpuTimeMillis */,
                                 10000 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */));
+                                0 /* extraStatus */));
 
         // Verify that there are no more calls than the ones above.
         verify(mArtd, times(3))
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
index f02ebf0..ad5f7be 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTest.java
@@ -609,13 +609,17 @@
 
         List<DexContainerFileDexoptResult> results = mPrimaryDexopter.dexopt();
         assertThat(results.get(0).getStatus()).isEqualTo(DexoptResult.DEXOPT_PERFORMED);
-        assertThat(results.get(0).isSkippedDueToStorageLow()).isFalse();
+        assertThat(results.get(0).getExtraStatus() & DexoptResult.EXTRA_SKIPPED_STORAGE_LOW)
+                .isEqualTo(0);
         assertThat(results.get(1).getStatus()).isEqualTo(DexoptResult.DEXOPT_SKIPPED);
-        assertThat(results.get(1).isSkippedDueToStorageLow()).isTrue();
+        assertThat(results.get(1).getExtraStatus() & DexoptResult.EXTRA_SKIPPED_STORAGE_LOW)
+                .isNotEqualTo(0);
         assertThat(results.get(2).getStatus()).isEqualTo(DexoptResult.DEXOPT_SKIPPED);
-        assertThat(results.get(2).isSkippedDueToStorageLow()).isTrue();
+        assertThat(results.get(2).getExtraStatus() & DexoptResult.EXTRA_SKIPPED_STORAGE_LOW)
+                .isNotEqualTo(0);
         assertThat(results.get(3).getStatus()).isEqualTo(DexoptResult.DEXOPT_PERFORMED);
-        assertThat(results.get(3).isSkippedDueToStorageLow()).isFalse();
+        assertThat(results.get(3).getExtraStatus() & DexoptResult.EXTRA_SKIPPED_STORAGE_LOW)
+                .isEqualTo(0);
 
         verify(mArtd, times(2))
                 .dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
diff --git a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
index 5d8661f..71069c5 100644
--- a/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
+++ b/libartservice/service/javatests/com/android/server/art/SecondaryDexopterTest.java
@@ -167,23 +167,19 @@
                         DexContainerFileDexoptResult.create(DEX_1, true /* isPrimaryAbi */,
                                 "arm64-v8a", "speed-profile", DexoptResult.DEXOPT_PERFORMED,
                                 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
-                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */),
+                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
                         DexContainerFileDexoptResult.create(DEX_2, true /* isPrimaryAbi */,
                                 "arm64-v8a", "speed", DexoptResult.DEXOPT_PERFORMED,
                                 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
-                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */),
+                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
                         DexContainerFileDexoptResult.create(DEX_2, false /* isPrimaryAbi */,
                                 "armeabi-v7a", "speed", DexoptResult.DEXOPT_PERFORMED,
                                 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
-                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */),
+                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */),
                         DexContainerFileDexoptResult.create(DEX_3, true /* isPrimaryAbi */,
                                 "arm64-v8a", "verify", DexoptResult.DEXOPT_PERFORMED,
                                 0 /* dex2oatWallTimeMillis */, 0 /* dex2oatCpuTimeMillis */,
-                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */,
-                                false /* isSkippedDueToStorageLow */));
+                                0 /* sizeBytes */, 0 /* sizeBeforeBytes */, 0 /* extraStatus */));
 
         // It should use profile for dex 1.