Use libfstab to determine whether to put artifacts in dalvik-cache.

Before this change, we used PackageState#isSystem (a.k.a.
ApplicationInfo#FLAG_SYSTEM) to determine this. Unfortunately, some OEMs
don't set this flag for some apps because the flag is used for making
security decisions in some places, although the document says it
shouldn't be.

After this change, we use libfstab as a general solution.

Bug: 287958783
Test: atest art_standalone_artd_tests
Test: atest ArtServiceTests
Change-Id: I0ef596f7009c3d19f458d58c922041ab8a7fbf5f
Merged-In: I0ef596f7009c3d19f458d58c922041ab8a7fbf5f
diff --git a/artd/Android.bp b/artd/Android.bp
index 1288ebc..cacbe28 100644
--- a/artd/Android.bp
+++ b/artd/Android.bp
@@ -42,6 +42,7 @@
     ],
     static_libs: [
         "artd-aidl-ndk",
+        "libfstab",
     ],
 }
 
diff --git a/artd/artd.cc b/artd/artd.cc
index afed965..57620c1 100644
--- a/artd/artd.cc
+++ b/artd/artd.cc
@@ -18,8 +18,8 @@
 
 #include <fcntl.h>
 #include <stdlib.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
-#include <sys/statfs.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -64,6 +64,7 @@
 #include "cmdline_types.h"
 #include "exec_utils.h"
 #include "file_utils.h"
+#include "fstab/fstab.h"
 #include "oat_file_assistant.h"
 #include "oat_file_assistant_context.h"
 #include "path_utils.h"
@@ -72,10 +73,6 @@
 #include "tools/cmdline_builder.h"
 #include "tools/tools.h"
 
-#ifdef __BIONIC__
-#include <linux/incrementalfs.h>
-#endif
-
 namespace art {
 namespace artd {
 
@@ -106,6 +103,7 @@
 using ::android::base::Split;
 using ::android::base::StringReplace;
 using ::android::base::WriteStringToFd;
+using ::android::fs_mgr::FstabEntry;
 using ::art::tools::CmdlineBuilder;
 using ::ndk::ScopedAStatus;
 
@@ -1068,22 +1066,35 @@
   return ScopedAStatus::ok();
 }
 
-ScopedAStatus Artd::isIncrementalFsPath(const std::string& in_dexFile [[maybe_unused]],
-                                        bool* _aidl_return) {
-#ifdef __BIONIC__
+ScopedAStatus Artd::isInDalvikCache(const std::string& in_dexFile, bool* _aidl_return) {
+  // The artifacts should be in the global dalvik-cache directory if:
+  // (1). the dex file is on a system partition, even if the partition is remounted read-write,
+  //      or
+  // (2). the dex file is in any other readonly location. (At the time of writing, this only
+  //      include Incremental FS.)
+  //
+  // We cannot rely on access(2) because:
+  // - It doesn't take effective capabilities into account, from which artd gets root access
+  //   to the filesystem.
+  // - The `faccessat` variant with the `AT_EACCESS` flag, which takes effective capabilities
+  //   into account, is not supported by bionic.
+
   OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
-  struct statfs st;
-  if (statfs(in_dexFile.c_str(), &st) != 0) {
-    PLOG(ERROR) << ART_FORMAT("Failed to statfs '{}'", in_dexFile);
-    *_aidl_return = false;
+
+  std::vector<FstabEntry> entries = OR_RETURN_NON_FATAL(GetProcMountsEntriesForPath(in_dexFile));
+  // The last one controls because `/proc/mounts` reflects the sequence of `mount`.
+  for (auto it = entries.rbegin(); it != entries.rend(); it++) {
+    if (it->fs_type == "overlay") {
+      // Ignore the overlays created by `remount`.
+      continue;
+    }
+    // We need to special-case Incremental FS since it is tagged as read-write while it's actually
+    // not.
+    *_aidl_return = (it->flags & MS_RDONLY) != 0 || it->fs_type == "incremental-fs";
     return ScopedAStatus::ok();
   }
-  *_aidl_return = st.f_type == INCFS_MAGIC_NUMBER;
-  return ScopedAStatus::ok();
-#else
-  *_aidl_return = false;
-  return ScopedAStatus::ok();
-#endif
+
+  return NonFatal(ART_FORMAT("Fstab entries not found for '{}'", in_dexFile));
 }
 
 Result<void> Artd::Start() {
diff --git a/artd/artd.h b/artd/artd.h
index f90110d..2386cfb 100644
--- a/artd/artd.h
+++ b/artd/artd.h
@@ -164,8 +164,7 @@
       const std::vector<aidl::com::android::server::art::VdexPath>& in_vdexFilesToKeep,
       int64_t* _aidl_return) override;
 
-  ndk::ScopedAStatus isIncrementalFsPath(const std::string& in_dexFile,
-                                         bool* _aidl_return) override;
+  ndk::ScopedAStatus isInDalvikCache(const std::string& in_dexFile, bool* _aidl_return) override;
 
   android::base::Result<void> Start();
 
diff --git a/artd/artd_test.cc b/artd/artd_test.cc
index f433fcd..a581b18 100644
--- a/artd/artd_test.cc
+++ b/artd/artd_test.cc
@@ -44,6 +44,7 @@
 #include "android-base/file.h"
 #include "android-base/logging.h"
 #include "android-base/parseint.h"
+#include "android-base/result-gmock.h"
 #include "android-base/result.h"
 #include "android-base/scopeguard.h"
 #include "android-base/strings.h"
@@ -89,6 +90,7 @@
 using ::android::base::Split;
 using ::android::base::WriteStringToFd;
 using ::android::base::WriteStringToFile;
+using ::android::base::testing::HasValue;
 using ::testing::_;
 using ::testing::AllOf;
 using ::testing::AnyNumber;
@@ -1960,6 +1962,32 @@
   }
 }
 
+TEST_F(ArtdTest, isInDalvikCache) {
+  TEST_DISABLED_FOR_HOST();
+
+  if (GetProcMountsEntriesForPath("/")->empty()) {
+    GTEST_SKIP() << "Skipped for chroot";
+  }
+
+  auto is_in_dalvik_cache = [this](const std::string& dex_file) -> Result<bool> {
+    bool result;
+    ndk::ScopedAStatus status = artd_->isInDalvikCache(dex_file, &result);
+    if (!status.isOk()) {
+      return Error() << status.getMessage();
+    }
+    return result;
+  };
+
+  EXPECT_THAT(is_in_dalvik_cache("/system/app/base.apk"), HasValue(true));
+  EXPECT_THAT(is_in_dalvik_cache("/system_ext/app/base.apk"), HasValue(true));
+  EXPECT_THAT(is_in_dalvik_cache("/vendor/app/base.apk"), HasValue(true));
+  EXPECT_THAT(is_in_dalvik_cache("/product/app/base.apk"), HasValue(true));
+  EXPECT_THAT(is_in_dalvik_cache("/data/app/base.apk"), HasValue(false));
+
+  // Test a path where we don't expect to find packages. The method should still work.
+  EXPECT_THAT(is_in_dalvik_cache("/foo"), HasValue(true));
+}
+
 }  // namespace
 }  // namespace artd
 }  // namespace art
diff --git a/artd/binder/com/android/server/art/IArtd.aidl b/artd/binder/com/android/server/art/IArtd.aidl
index a130e96..7440348 100644
--- a/artd/binder/com/android/server/art/IArtd.aidl
+++ b/artd/binder/com/android/server/art/IArtd.aidl
@@ -171,9 +171,10 @@
             in List<com.android.server.art.VdexPath> vdexFilesToKeep);
 
     /**
-     * Returns whether the dex file is in Incremental FS.
+     * Returns whether the artifacts of the primary dex files should be in the global dalvik-cache
+     * directory.
      *
-     * Throws fatal errors. On non-fatal errors, logs the error and returns false.
+     * Throws fatal and non-fatal errors.
      */
-    boolean isIncrementalFsPath(@utf8InCpp String dexFile);
+    boolean isInDalvikCache(@utf8InCpp String dexFile);
 }
diff --git a/artd/path_utils.cc b/artd/path_utils.cc
index d504bb2..6ff9b95 100644
--- a/artd/path_utils.cc
+++ b/artd/path_utils.cc
@@ -28,6 +28,7 @@
 #include "base/file_utils.h"
 #include "base/macros.h"
 #include "file_utils.h"
+#include "fstab/fstab.h"
 #include "oat_file_assistant.h"
 #include "tools/tools.h"
 
@@ -42,6 +43,10 @@
 using ::aidl::com::android::server::art::VdexPath;
 using ::android::base::Error;
 using ::android::base::Result;
+using ::android::base::StartsWith;
+using ::android::fs_mgr::Fstab;
+using ::android::fs_mgr::FstabEntry;
+using ::android::fs_mgr::ReadFstabFromProcMounts;
 
 using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath;
 using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
@@ -278,5 +283,26 @@
   return OatPathToVdexPath(OR_RETURN(BuildOatPath(vdex_path.get<VdexPath::artifactsPath>())));
 }
 
+bool PathStartsWith(std::string_view path, std::string_view prefix) {
+  CHECK(!prefix.empty() && !path.empty() && prefix[0] == '/' && path[0] == '/');
+  android::base::ConsumeSuffix(&prefix, "/");
+  return StartsWith(path, prefix) &&
+         (path.length() == prefix.length() || path[prefix.length()] == '/');
+}
+
+Result<std::vector<FstabEntry>> GetProcMountsEntriesForPath(const std::string& path) {
+  Fstab fstab;
+  if (!ReadFstabFromProcMounts(&fstab)) {
+    return Errorf("Failed to read fstab from /proc/mounts");
+  }
+  std::vector<FstabEntry> entries;
+  for (FstabEntry& entry : fstab) {
+    if (PathStartsWith(path, entry.mount_point)) {
+      entries.push_back(std::move(entry));
+    }
+  }
+  return entries;
+}
+
 }  // namespace artd
 }  // namespace art
diff --git a/artd/path_utils.h b/artd/path_utils.h
index 1063f91..a126118 100644
--- a/artd/path_utils.h
+++ b/artd/path_utils.h
@@ -23,6 +23,7 @@
 #include "aidl/com/android/server/art/BnArtd.h"
 #include "android-base/result.h"
 #include "base/file_utils.h"
+#include "fstab/fstab.h"
 
 namespace art {
 namespace artd {
@@ -82,6 +83,15 @@
 android::base::Result<std::string> BuildVdexPath(
     const aidl::com::android::server::art::VdexPath& vdex_path);
 
+// Returns true if `path` starts with `prefix` (i.e., if `prefix` represents a directory that
+// contains a file/directory at `path`, or if `prefix` and `path` represents the same
+// file/directory). Only supports absolute paths.
+bool PathStartsWith(std::string_view path, std::string_view prefix);
+
+// Returns the fstab entries in /proc/mounts for the given path.
+android::base::Result<std::vector<android::fs_mgr::FstabEntry>> GetProcMountsEntriesForPath(
+    const std::string& path);
+
 }  // namespace artd
 }  // namespace art
 
diff --git a/artd/path_utils_test.cc b/artd/path_utils_test.cc
index 77652f0..960bf97 100644
--- a/artd/path_utils_test.cc
+++ b/artd/path_utils_test.cc
@@ -258,6 +258,22 @@
       HasValue("/a/oat/arm64/b.vdex"));
 }
 
+TEST_F(PathUtilsTest, PathStartsWith) {
+  EXPECT_TRUE(PathStartsWith("/a/b", "/a"));
+  EXPECT_TRUE(PathStartsWith("/a/b", "/a/"));
+
+  EXPECT_FALSE(PathStartsWith("/a/c", "/a/b"));
+  EXPECT_FALSE(PathStartsWith("/ab", "/a"));
+
+  EXPECT_TRUE(PathStartsWith("/a", "/a"));
+  EXPECT_TRUE(PathStartsWith("/a/", "/a"));
+  EXPECT_TRUE(PathStartsWith("/a", "/a/"));
+
+  EXPECT_TRUE(PathStartsWith("/a", "/"));
+  EXPECT_TRUE(PathStartsWith("/", "/"));
+  EXPECT_FALSE(PathStartsWith("/", "/a"));
+}
+
 }  // namespace
 }  // namespace artd
 }  // namespace art
diff --git a/libartservice/service/java/com/android/server/art/Utils.java b/libartservice/service/java/com/android/server/art/Utils.java
index fc94d64..6d48c45 100644
--- a/libartservice/service/java/com/android/server/art/Utils.java
+++ b/libartservice/service/java/com/android/server/art/Utils.java
@@ -200,27 +200,15 @@
     @NonNull
     public static boolean isInDalvikCache(@NonNull PackageState pkgState, @NonNull IArtd artd)
             throws RemoteException {
-        // The artifacts should be in the global dalvik-cache directory if:
-        // (1). the package is on a system partition, even if the partition is remounted read-write,
-        //      or
-        // (2). the package is in any other readonly location. (At the time of writing, this only
-        //      include Incremental FS.)
-        //
-        // Right now, we are using some heuristics to determine this. For (1), we can potentially
-        // use "libfstab" instead as a general solution, but for (2), unfortunately, we have to
-        // stick with heuristics.
-        //
-        // We cannot rely on access(2) because:
-        // - It doesn't take effective capabilities into account, from which artd gets root access
-        //   to the filesystem.
-        // - The `faccessat` variant with the `AT_EACCESS` flag, which takes effective capabilities
-        //   into account, is not supported by bionic.
-        //
-        // We cannot rely on `f_flags` returned by statfs(2) because:
-        // - Incremental FS is tagged as read-write while it's actually not.
-        return (pkgState.isSystem() && !pkgState.isUpdatedSystemApp())
-                || artd.isIncrementalFsPath(
-                        pkgState.getAndroidPackage().getSplits().get(0).getPath());
+        try {
+            return artd.isInDalvikCache(pkgState.getAndroidPackage().getSplits().get(0).getPath());
+        } catch (ServiceSpecificException e) {
+            // This should never happen. Ignore the error and conservatively use dalvik-cache to
+            // minimize the risk.
+            // TODO(jiakaiz): Throw the error instead of ignoring it.
+            Log.e(TAG, "Failed to determine the location of the artifacts", e);
+            return true;
+        }
     }
 
     /** Returns true if the given string is a valid compiler filter. */
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index 2e3bd5f..747e516 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -125,21 +125,14 @@
     private List<DetailedSecondaryDexInfo> mSecondaryDexInfo1;
     private Config mConfig;
 
-    // True if the primary dex'es are in a system partition.
-    @Parameter(0) public boolean mIsInSystemPartition;
-    // True if the primary dex'es are in Incremental FS.
-    @Parameter(1) public boolean mIsInIncrementalFs;
     // True if the artifacts should be in dalvik-cache.
-    @Parameter(2) public boolean mExpectedIsInDalvikCache;
+    @Parameter(0) public boolean mIsInDalvikCache;
 
     private ArtManagerLocal mArtManagerLocal;
 
-    @Parameters(name = "isInReadonlyPartition={0},isInIncrementalFs={1},"
-                    + "expectedIsInDalvikCache={2}")
-    public static Iterable<Object[]>
-    data() {
-        return List.of(new Object[] {true, false, true}, new Object[] {false, true, true},
-                new Object[] {false, false, false});
+    @Parameters(name = "mIsInDalvikCache={0}")
+    public static Iterable<Object[]> data() {
+        return List.of(new Object[] {true}, new Object[] {false});
     }
 
     @Before
@@ -231,7 +224,7 @@
         mPkgState1 = mSnapshot.getPackageState(PKG_NAME_1);
         mPkg1 = mPkgState1.getAndroidPackage();
 
-        lenient().when(mArtd.isIncrementalFsPath(any())).thenReturn(mIsInIncrementalFs);
+        lenient().when(mArtd.isInDalvikCache(any())).thenReturn(mIsInDalvikCache);
 
         // By default, none of the profiles are usable.
         lenient().when(mArtd.isProfileUsable(any(), any())).thenReturn(false);
@@ -247,14 +240,14 @@
         DeleteResult result = mArtManagerLocal.deleteDexoptArtifacts(mSnapshot, PKG_NAME_1);
         assertThat(result.getFreedBytes()).isEqualTo(5);
 
+        verify(mArtd).deleteArtifacts(deepEq(
+                AidlUtils.buildArtifactsPath("/data/app/foo/base.apk", "arm64", mIsInDalvikCache)));
+        verify(mArtd).deleteArtifacts(deepEq(
+                AidlUtils.buildArtifactsPath("/data/app/foo/base.apk", "arm", mIsInDalvikCache)));
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/base.apk", "arm64", mExpectedIsInDalvikCache)));
+                "/data/app/foo/split_0.apk", "arm64", mIsInDalvikCache)));
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/base.apk", "arm", mExpectedIsInDalvikCache)));
-        verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/split_0.apk", "arm64", mExpectedIsInDalvikCache)));
-        verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/split_0.apk", "arm", mExpectedIsInDalvikCache)));
+                "/data/app/foo/split_0.apk", "arm", mIsInDalvikCache)));
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
                 "/data/user/0/foo/1.apk", "arm64", false /* isInDalvikCache */)));
 
@@ -277,13 +270,13 @@
         assertThat(result.getFreedBytes()).isEqualTo(5);
 
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/base.apk", "x86_64", mExpectedIsInDalvikCache)));
+                "/data/app/foo/base.apk", "x86_64", mIsInDalvikCache)));
+        verify(mArtd).deleteArtifacts(deepEq(
+                AidlUtils.buildArtifactsPath("/data/app/foo/base.apk", "x86", mIsInDalvikCache)));
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/base.apk", "x86", mExpectedIsInDalvikCache)));
+                "/data/app/foo/split_0.apk", "x86_64", mIsInDalvikCache)));
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/split_0.apk", "x86_64", mExpectedIsInDalvikCache)));
-        verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/split_0.apk", "x86", mExpectedIsInDalvikCache)));
+                "/data/app/foo/split_0.apk", "x86", mIsInDalvikCache)));
         // We assume that the ISA got from `DexUseManagerLocal` is already the translated one.
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
                 "/data/user/0/foo/1.apk", "x86_64", false /* isInDalvikCache */)));
@@ -446,14 +439,14 @@
         verify(mArtd).deleteProfile(deepEq(
                 AidlUtils.buildProfilePathForPrimaryCur(1 /* userId */, PKG_NAME_1, "primary")));
 
+        verify(mArtd).deleteArtifacts(deepEq(
+                AidlUtils.buildArtifactsPath("/data/app/foo/base.apk", "arm64", mIsInDalvikCache)));
+        verify(mArtd).deleteArtifacts(deepEq(
+                AidlUtils.buildArtifactsPath("/data/app/foo/base.apk", "arm", mIsInDalvikCache)));
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/base.apk", "arm64", mExpectedIsInDalvikCache)));
+                "/data/app/foo/split_0.apk", "arm64", mIsInDalvikCache)));
         verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/base.apk", "arm", mExpectedIsInDalvikCache)));
-        verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/split_0.apk", "arm64", mExpectedIsInDalvikCache)));
-        verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPath(
-                "/data/app/foo/split_0.apk", "arm", mExpectedIsInDalvikCache)));
+                "/data/app/foo/split_0.apk", "arm", mIsInDalvikCache)));
 
         verify(mArtd).deleteProfile(
                 deepEq(AidlUtils.buildProfilePathForSecondaryRef("/data/user/0/foo/1.apk")));
@@ -944,15 +937,15 @@
                                 1 /* userId */, PKG_NAME_1, "split_0.split"),
                         AidlUtils.buildProfilePathForSecondaryRef("/data/user/0/foo/1.apk"),
                         AidlUtils.buildProfilePathForSecondaryCur("/data/user/0/foo/1.apk")),
-                inAnyOrderDeepEquals(AidlUtils.buildArtifactsPath("/data/app/foo/base.apk", "arm64",
-                                             mExpectedIsInDalvikCache),
+                inAnyOrderDeepEquals(AidlUtils.buildArtifactsPath(
+                                             "/data/app/foo/base.apk", "arm64", mIsInDalvikCache),
                         AidlUtils.buildArtifactsPath(
                                 "/data/user/0/foo/1.apk", "arm64", false /* isInDalvikCache */)),
                 inAnyOrderDeepEquals(
                         VdexPath.artifactsPath(AidlUtils.buildArtifactsPath(
-                                "/data/app/foo/split_0.apk", "arm64", mExpectedIsInDalvikCache)),
+                                "/data/app/foo/split_0.apk", "arm64", mIsInDalvikCache)),
                         VdexPath.artifactsPath(AidlUtils.buildArtifactsPath(
-                                "/data/app/foo/split_0.apk", "arm", mExpectedIsInDalvikCache))));
+                                "/data/app/foo/split_0.apk", "arm", mIsInDalvikCache))));
     }
 
     private AndroidPackage createPackage(boolean multiSplit) {
@@ -996,8 +989,6 @@
         lenient().when(pkgState.getPackageName()).thenReturn(packageName);
         lenient().when(pkgState.getPrimaryCpuAbi()).thenReturn("arm64-v8a");
         lenient().when(pkgState.getSecondaryCpuAbi()).thenReturn("armeabi-v7a");
-        lenient().when(pkgState.isSystem()).thenReturn(mIsInSystemPartition);
-        lenient().when(pkgState.isUpdatedSystemApp()).thenReturn(false);
 
         AndroidPackage pkg = createPackage(multiSplit);
         lenient().when(pkgState.getAndroidPackage()).thenReturn(pkg);
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index 31ea915..46db32f 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -88,24 +88,11 @@
         list.add(params);
 
         params = new Params();
-        params.mIsSystem = true;
-        params.mExpectedIsInDalvikCache = true;
+        params.mIsInDalvikCache = true;
         list.add(params);
 
         params = new Params();
-        params.mIsSystem = true;
-        params.mIsUpdatedSystemApp = true;
-        list.add(params);
-
-        params = new Params();
-        params.mIsIncrementalFsPath = true;
-        params.mExpectedIsInDalvikCache = true;
-        list.add(params);
-
-        params = new Params();
-        params.mIsSystem = true;
         params.mHiddenApiEnforcementPolicy = ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
-        params.mExpectedIsInDalvikCache = true;
         params.mExpectedIsHiddenApiPolicyEnabled = false;
         list.add(params);
 
@@ -190,8 +177,6 @@
                 .when(mPkgState.getHiddenApiEnforcementPolicy())
                 .thenReturn(mParams.mHiddenApiEnforcementPolicy);
         lenient().when(mPkg.isUseEmbeddedDex()).thenReturn(mParams.mIsUseEmbeddedDex);
-        lenient().when(mPkgState.isSystem()).thenReturn(mParams.mIsSystem);
-        lenient().when(mPkgState.isUpdatedSystemApp()).thenReturn(mParams.mIsUpdatedSystemApp);
 
         // Make all profile-related operations succeed so that "speed-profile" doesn't fall back to
         // "verify".
@@ -199,7 +184,7 @@
         lenient().when(mArtd.getProfileVisibility(any())).thenReturn(FileVisibility.OTHER_READABLE);
         lenient().when(mArtd.mergeProfiles(any(), any(), any(), any(), any())).thenReturn(false);
 
-        lenient().when(mArtd.isIncrementalFsPath(any())).thenReturn(mParams.mIsIncrementalFsPath);
+        lenient().when(mArtd.isInDalvikCache(any())).thenReturn(mParams.mIsInDalvikCache);
 
         mDexoptParams =
                 new DexoptParams.Builder("install")
@@ -246,7 +231,7 @@
                          400 /* cpuTimeMs */, 30000 /* sizeBytes */, 32000 /* sizeBeforeBytes */))
                 .when(mArtd)
                 .dexopt(deepEq(buildOutputArtifacts("/data/app/foo/base.apk", "arm64",
-                                mParams.mExpectedIsInDalvikCache, permissionSettings)),
+                                mParams.mIsInDalvikCache, permissionSettings)),
                         eq("/data/app/foo/base.apk"), eq("arm64"), eq("PCL[]"),
                         eq(mParams.mExpectedCompilerFilter), any() /* profile */,
                         isNull() /* inputVdex */, isNull() /* dmFile */,
@@ -260,7 +245,7 @@
         doThrow(ServiceSpecificException.class)
                 .when(mArtd)
                 .dexopt(deepEq(buildOutputArtifacts("/data/app/foo/base.apk", "arm",
-                                mParams.mExpectedIsInDalvikCache, permissionSettings)),
+                                mParams.mIsInDalvikCache, permissionSettings)),
                         eq("/data/app/foo/base.apk"), eq("arm"), eq("PCL[]"),
                         eq(mParams.mExpectedCompilerFilter), any() /* profile */,
                         isNull() /* inputVdex */, isNull() /* dmFile */,
@@ -281,7 +266,7 @@
                          200 /* cpuTimeMs */, 10000 /* sizeBytes */, 0 /* sizeBeforeBytes */))
                 .when(mArtd)
                 .dexopt(deepEq(buildOutputArtifacts("/data/app/foo/split_0.apk", "arm",
-                                mParams.mExpectedIsInDalvikCache, permissionSettings)),
+                                mParams.mIsInDalvikCache, permissionSettings)),
                         eq("/data/app/foo/split_0.apk"), eq("arm"), eq("PCL[base.apk]"),
                         eq(mParams.mExpectedCompilerFilter), any() /* profile */,
                         isNull() /* inputVdex */, isNull() /* dmFile */,
@@ -323,9 +308,7 @@
 
     private static class Params {
         // Package information.
-        public boolean mIsSystem = false;
-        public boolean mIsUpdatedSystemApp = false;
-        public boolean mIsIncrementalFsPath = false;
+        public boolean mIsInDalvikCache = false;
         public int mHiddenApiEnforcementPolicy = ApplicationInfo.HIDDEN_API_ENFORCEMENT_ENABLED;
         public boolean mIsVmSafeMode = false;
         public boolean mIsDebuggable = false;
@@ -346,14 +329,11 @@
         public String mExpectedCompilerFilter = "verify";
         public int mExpectedDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER
                 | DexoptTrigger.PRIMARY_BOOT_IMAGE_BECOMES_USABLE | DexoptTrigger.NEED_EXTRACTION;
-        public boolean mExpectedIsInDalvikCache = false;
         public boolean mExpectedIsDebuggable = false;
         public boolean mExpectedIsHiddenApiPolicyEnabled = true;
 
         public String toString() {
-            return String.format("isSystem=%b,"
-                            + "isUpdatedSystemApp=%b,"
-                            + "isIncrementalFsPath=%b,"
+            return String.format("mIsInDalvikCache=%b,"
                             + "mHiddenApiEnforcementPolicy=%d,"
                             + "isVmSafeMode=%b,"
                             + "isDebuggable=%b,"
@@ -368,14 +348,12 @@
                             + " => "
                             + "targetCompilerFilter=%s,"
                             + "expectedDexoptTrigger=%d,"
-                            + "expectedIsInDalvikCache=%b,"
                             + "expectedIsDebuggable=%b,"
                             + "expectedIsHiddenApiPolicyEnabled=%b",
-                    mIsSystem, mIsUpdatedSystemApp, mIsIncrementalFsPath,
-                    mHiddenApiEnforcementPolicy, mIsVmSafeMode, mIsDebuggable, mIsSystemUi,
-                    mIsLauncher, mIsUseEmbeddedDex, mRequestedCompilerFilter, mForce,
+                    mIsInDalvikCache, mHiddenApiEnforcementPolicy, mIsVmSafeMode, mIsDebuggable,
+                    mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex, mRequestedCompilerFilter, mForce,
                     mShouldDowngrade, mSkipIfStorageLow, mAlwaysDebuggable, mExpectedCompilerFilter,
-                    mExpectedDexoptTrigger, mExpectedIsInDalvikCache, mExpectedIsDebuggable,
+                    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 94e0b48..81fe511 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
@@ -150,8 +150,6 @@
         lenient().when(pkgState.getPackageName()).thenReturn(PKG_NAME);
         lenient().when(pkgState.getPrimaryCpuAbi()).thenReturn("arm64-v8a");
         lenient().when(pkgState.getSecondaryCpuAbi()).thenReturn("armeabi-v7a");
-        lenient().when(pkgState.isSystem()).thenReturn(false);
-        lenient().when(pkgState.isUpdatedSystemApp()).thenReturn(false);
         lenient().when(pkgState.getAppId()).thenReturn(UID);
         lenient().when(pkgState.getSharedLibraryDependencies()).thenReturn(new ArrayList<>());
         lenient().when(pkgState.getStateForUser(any())).thenReturn(mPkgUserStateNotInstalled);