Snap for 8426163 from 3b0ffb30ee3666352c7932b283f464880cf24a45 to mainline-tzdata2-release

Change-Id: Ia8d138ec480f72157c64e4205bf1080c4887ebd7
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
deleted file mode 100644
index f87c6b9..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_arm64/com.android.apex.cts.shim_not_pre_installed.apex"
-  }
-  dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim_not_pre_installed.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb
index 03cf8a0..5bef6b2 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v1_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v1.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index c93ee73..f203241 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_file.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index d5922e1..d5b1515 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_additional_folder.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb
index 18e12ee..5c1ecd8 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index 00f9f6c..a3e05b5 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index 861ffa3..d4f42de 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_certificate.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index 79de375..30c1658 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_different_package_name.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index 91f5ef2..7a4ba73 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_no_hashtree.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
deleted file mode 100644
index e8f2283..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_arm64/com.android.apex.cts.shim.v2_rebootless.apex"
-  }
-  dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim.v2_rebootless.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index e56d855..e046e3a 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
deleted file mode 100644
index ec3b1d6..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_arm64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
-  }
-  dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index a8b55ab..6ea9a6b 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index 23567d8..fe76dce 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index 84c7328..c90ffbb 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index ed4ca4b..779f499 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index 5fb0fb2..0bf9288 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index 38f20a0..5a1baf9 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index ac823c9..316c8d1 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index 0281ed4..3d5c0e9 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v2_wrong_sha.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb
index 50c821d..e03ee6e 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
deleted file mode 100644
index f900c46..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_arm64/com.android.apex.cts.shim.v3_rebootless.apex"
-  }
-  dest_file: "shim/prebuilts//arm/com.android.apex.cts.shim.v3_rebootless.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index d908d0e..daecf3c 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index cb1a634..420522b 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__arm_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_arm64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
deleted file mode 100644
index 0d09fcb..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_not_pre_installed_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_x86_64/com.android.apex.cts.shim_not_pre_installed.apex"
-  }
-  dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim_not_pre_installed.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb
index 742bca4..239132a 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v1_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v1.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
index 783107c..f84e0c8 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_file_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_file.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
index 5ab45ea..635e2bb 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_additional_folder_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_additional_folder.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb
index aee50ef..cea5340 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
index 9eb21ee..2622af8 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_apk_in_apex_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
index 670489d..c25509a 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_certificate_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_certificate.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
index c5d28ff..ab8601f 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_different_package_name_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_different_package_name.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
index 17ae6c5..f1ccd78 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_no_hashtree_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_no_hashtree.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
deleted file mode 100644
index c817a79..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_rebootless.apex"
-  }
-  dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim.v2_rebootless.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
index b121049..1f24ded 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sdk_target_p_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sdk_target_p.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
deleted file mode 100644
index 39e49e1..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_sign_payload_with_different_key_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
-  }
-  dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim.v2_sign_payload_with_different_key.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
index 2056dc1..e8c48e1 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
index 229b0f3..faf0e28 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
index fc464db..5f1e664 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_signed_bob_rot_rollback_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
index cffcd60..aef234a 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_unsigned_payload_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_unsigned_payload.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
index c2168d8..87b7c50 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_post_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_post_install_hook.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
index 1f2469a..727bce0 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_with_pre_install_hook_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_with_pre_install_hook.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
index 986a459..23155ba 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_without_apk_in_apex_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_without_apk_in_apex.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
index d53ab6c..2190954 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v2_wrong_sha_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v2_wrong_sha.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb
index ca8bade..e7006ae 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
deleted file mode 100644
index e2c369f..0000000
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_rebootless_apex.asciipb
+++ /dev/null
@@ -1,15 +0,0 @@
-drops {
-  android_build_drop {
-    build_id: "7552332"
-    target: "CtsShim"
-    source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_rebootless.apex"
-  }
-  dest_file: "shim/prebuilts//x86/com.android.apex.cts.shim.v3_rebootless.apex"
-  version: ""
-  version_group: ""
-  git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
-}
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
index ea06694..bdcb62f 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
index 3d41a84..4f25858 100644
--- a/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
+++ b/.prebuilt_info/prebuilt_info_shim_prebuilts__x86_com_android_apex_cts_shim_v3_signed_bob_rot_apex.asciipb
@@ -1,6 +1,6 @@
 drops {
   android_build_drop {
-    build_id: "7552332"
+    build_id: "6508977"
     target: "CtsShim"
     source_file: "aosp_x86_64/com.android.apex.cts.shim.v3_signed_bob_rot.apex"
   }
@@ -8,8 +8,5 @@
   version: ""
   version_group: ""
   git_project: "platform/system/apex"
-  git_branch: "sc-dev"
-  transform: TRANSFORM_NONE
-  transform_options {
-  }
+  git_branch: "rvc-dev"
 }
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index b198f25..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,68 +0,0 @@
-// This introduces the module type library_linking_strategy_cc_defaults
-// To use in other Android.bp files, add the following lines:
-//    soong_config_module_type_import {
-//        from: "system/apex/Android.bp",
-//        module_types: ["library_linking_strategy_cc_defaults"],
-//    }
-
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-soong_config_string_variable {
-    name: "library_linking_strategy",
-    values: [
-        "prefer_static",
-    ],
-}
-
-soong_config_module_type {
-    name: "library_linking_strategy_cc_defaults",
-    module_type: "cc_defaults",
-    config_namespace: "ANDROID",
-    variables: ["library_linking_strategy"],
-    properties: [
-        "shared_libs",
-        "static_libs",
-        "stl",
-    ],
-}
-
-// TODO(b/178585590): delete this after testing linking strategy
-soong_config_module_type {
-    name: "library_linking_strategy_apex_defaults",
-    module_type: "apex_defaults",
-    config_namespace: "ANDROID",
-    variables: ["library_linking_strategy"],
-    properties: [
-        "manifest",
-        "min_sdk_version",
-    ],
-}
-
-library_linking_strategy_cc_defaults {
-    name: "library_linking_strategy_sample_defaults",
-    soong_config_variables: {
-        library_linking_strategy: {
-            prefer_static: {
-                static_libs: [
-                    "libbase",
-                    "liblog",
-                ],
-                stl: "c++_static",
-            },
-            conditions_default: {
-                shared_libs: [
-                    "libbase",
-                    "liblog",
-                ],
-            },
-        },
-    },
-}
-
-cc_binary {
-    name: "library_linking_strategy_sample_binary",
-    srcs: ["library_linking_strategy.cc"],
-    defaults: ["library_linking_strategy_sample_defaults"],
-}
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index ccaf5fe..4c6fbd6 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -6,7 +6,6 @@
 commit_msg_changeid_field = true
 commit_msg_test_field = true
 gofmt = true
-pylint3 = true
 
 [Builtin Hooks Options]
-clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
\ No newline at end of file
diff --git a/apexd/Android.bp b/apexd/Android.bp
index ba2de03..e8d221d 100644
--- a/apexd/Android.bp
+++ b/apexd/Android.bp
@@ -1,46 +1,25 @@
 // List of clang-tidy checks that are reported as errors.
 // Please keep this list ordered lexicographically.
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
 tidy_errors = [
-  "android-*",
-  "bugprone-infinite-loop",
-  "bugprone-macro-parentheses",
-  "bugprone-misplaced-widening-cast",
-  "bugprone-move-forwarding-reference",
-  "bugprone-sizeof-container",
-  "bugprone-sizeof-expression",
-  "bugprone-string-constructor",
-  "bugprone-terminating-continue",
-  "bugprone-undefined-memory-manipulation",
-  "bugprone-undelegated-constructor",
-  // "bugprone-unhandled-self-assignment", // found in apex_manifest.proto
-  "bugprone-unused-raii",
   "cert-err34-c",
   "google-default-arguments",
-  // "google-explicit-constructor", // found in com_android_apex.h
-  "google-readability-avoid-underscore-in-googletest-name",
-  "google-readability-todo",
+  "google-explicit-constructor",
   "google-runtime-int",
   "google-runtime-member-string-references",
   "misc-move-const-arg",
   "misc-move-forwarding-reference",
-  // "misc-unused-parameters", // found in apexd_utils.h
+  "misc-unused-parameters",
   "misc-unused-using-decls",
   "misc-use-after-move",
-  // "modernize-pass-by-value", // found in apex_database.h
+  "modernize-pass-by-value",
   "performance-faster-string-find",
   "performance-for-range-copy",
   "performance-implicit-conversion-in-loop",
   "performance-inefficient-vector-operation",
   "performance-move-const-arg",
-  // "performance-move-constructor-init", // found in apexd_loop.h
+  "performance-move-constructor-init",
   "performance-noexcept-move-constructor",
-  "performance-unnecessary-copy-initialization",
   "performance-unnecessary-value-param",
-  // "readability-avoid-const-params-in-decls", // found in apexd.h
 ]
 
 cc_defaults {
@@ -68,8 +47,8 @@
   tidy_checks: tidy_errors,
   tidy_checks_as_errors: tidy_errors,
   tidy_flags: [
-    "-format-style=file",
-    "-header-filter=system/apex/",
+    "-format-style='file'",
+    "--header-filter='system/apex/'",
   ],
 }
 
@@ -79,6 +58,7 @@
   defaults: ["libapex-deps"],
   shared_libs: [
     "libbinder",
+    "libselinux",
     "liblog",
     "liblogwrap",
   ],
@@ -89,7 +69,6 @@
     "libext2_uuid",
     "libverity_tree",
     "libvold_binder",
-    "libxml2",
   ],
   whole_static_libs: ["com.android.sysprop.apex"],
 }
@@ -102,8 +81,6 @@
     "aidl/android/apex/ApexInfoList.aidl",
     "aidl/android/apex/ApexSessionInfo.aidl",
     "aidl/android/apex/ApexSessionParams.aidl",
-    "aidl/android/apex/CompressedApexInfo.aidl",
-    "aidl/android/apex/CompressedApexInfoList.aidl",
     "aidl/android/apex/IApexService.aidl",
   ],
   local_include_dir: "aidl",
@@ -150,15 +127,14 @@
   srcs: [
     "apex_database.cpp",
     "apexd.cpp",
-    "apexd_lifecycle.cpp",
     "apexd_loop.cpp",
     "apexd_prepostinstall.cpp",
     "apexd_private.cpp",
+    "apexd_prop.cpp",
     "apexd_session.cpp",
     "apexd_verity.cpp",
   ],
   export_include_dirs: ["."],
-  generated_sources: ["apex-info-list"],
   // Don't add shared/static libs here; add to libapexd_defaults instead.
 }
 
@@ -194,9 +170,6 @@
   static_libs: [
     "libapexd",
   ],
-  cflags: [
-    "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
-  ],
 }
 
 cc_defaults {
@@ -207,7 +180,6 @@
     "libcutils",
     "libprotobuf-cpp-full",
     "libziparchive",
-    "libselinux",
   ],
   static_libs: [
     "lib_apex_session_state_proto",
@@ -217,7 +189,6 @@
   static: {
     whole_static_libs: ["libc++fs"],
   },
-  cpp_std: "experimental",
   shared: {
     static_libs: ["libc++fs"],
   },
@@ -231,8 +202,8 @@
   ],
   srcs: [
     "apex_file.cpp",
-    "apex_file_repository.cpp",
     "apex_manifest.cpp",
+    "apex_preinstalled_data.cpp",
     "apex_shim.cpp",
   ],
   host_supported: true,
@@ -252,7 +223,7 @@
 genrule {
   // Generates an apex which has a different manifest outside the filesystem
   // image.
-  name: "gen_manifest_mismatch_apex",
+  name: "gen_bad_apexes",
   out: ["apex.apexd_test_manifest_mismatch.apex"],
   srcs: [":apex.apexd_test"],
   tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
@@ -266,38 +237,6 @@
 }
 
 genrule {
-  // Generates an apex which has a different manifest outside the filesystem
-  // image.
-  name: "gen_manifest_mismatch_apex_no_hashtree",
-  out: ["apex.apexd_test_no_hashtree_manifest_mismatch.apex"],
-  srcs: [":apex.apexd_test_no_hashtree"],
-  tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
-  cmd: "unzip -q $(in) -d $(genDir) && " +
-       "$(location conv_apex_manifest) setprop version 137 $(genDir)/apex_manifest.pb && " +
-       "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
-       "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
-       "-o $(genDir)/unaligned.apex && " +
-       "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
-       "$(genDir)/apex.apexd_test_no_hashtree_manifest_mismatch.apex"
-}
-
-genrule {
-  // Generates an apex with a corrupted filesystem superblock, which should cause
-  // Apex::Open to fail
-  name: "gen_corrupt_superblock_apex",
-  out: ["apex.apexd_test_corrupt_superblock_apex.apex"],
-  srcs: [":apex.apexd_test"],
-  tools: ["soong_zip", "zipalign"],
-  cmd: "unzip -q $(in) -d $(genDir) && " +
-       "dd if=/dev/zero of=$(genDir)/apex_payload.img conv=notrunc bs=1024 seek=1 count=1 && " +
-       "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
-       "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
-       "-o $(genDir)/unaligned.apex && " +
-       "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
-       "$(genDir)/apex.apexd_test_corrupt_superblock_apex.apex"
-}
-
-genrule {
   // Generates an apex with a corrupted filesystem image, which should cause
   // dm-verity verification to fail
   name: "gen_corrupt_apex",
@@ -313,93 +252,6 @@
        "$(genDir)/apex.apexd_test_corrupt_apex.apex"
 }
 
-genrule {
-  // Extract the root digest with avbtool
-  name: "apex.apexd_test_digest",
-  out: ["apex.apexd_test_digest.txt"],
-  srcs: [":apex.apexd_test"],
-  tools: ["avbtool"],
-  cmd: "unzip -q $(in) -d $(genDir) apex_payload.img && " +
-       "$(location avbtool) print_partition_digests --image $(genDir)/apex_payload.img " +
-       "| cut -c 3-| tee $(out)"
-}
-
-genrule {
-  // Extract the root digest with avbtool
-  name: "apex.apexd_test_f2fs_digest",
-  out: ["apex.apexd_test_f2fs_digest.txt"],
-  srcs: [":apex.apexd_test_f2fs"],
-  tools: ["avbtool"],
-  cmd: "unzip -q $(in) -d $(genDir) apex_payload.img && " +
-       "$(location avbtool) print_partition_digests --image $(genDir)/apex_payload.img " +
-       "| cut -c 3-| tee $(out)"
-}
-
-genrule {
-  // Generates an apex which has same module name as apex.apexd_test.apex, but
-  // is actually signed with a different key.
-  name: "gen_key_mismatch_apex",
-  out: ["apex.apexd_test_different_key.apex"],
-  srcs: [":apex.apexd_test_no_inst_key"],
-  tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
-  cmd: "unzip -q $(in) -d $(genDir) && " +
-       "$(location conv_apex_manifest) setprop name com.android.apex.test_package $(genDir)/apex_manifest.pb && " +
-       "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
-       "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
-       "-o $(genDir)/unaligned.apex && " +
-       "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
-       "$(genDir)/apex.apexd_test_different_key.apex"
-}
-
-genrule {
-  // Generates an apex which has same module name as apex.apexd_test.apex, but
-  // is actually signed with a different key.
-  name: "gen_key_mismatch_apex_v2",
-  out: ["apex.apexd_test_different_key_v2.apex"],
-  srcs: [":apex.apexd_test_no_inst_key"],
-  tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
-  cmd: "unzip -q $(in) -d $(genDir) && " +
-       "$(location conv_apex_manifest) setprop name com.android.apex.test_package $(genDir)/apex_manifest.pb && " +
-       "$(location conv_apex_manifest) setprop version 2 $(genDir)/apex_manifest.pb && " +
-       "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
-       "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
-       "-o $(genDir)/unaligned.apex && " +
-       "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
-       "$(genDir)/apex.apexd_test_different_key_v2.apex"
-}
-
-genrule {
-  // Generates an apex which has a different manifest outside the filesystem
-  // image.
-  name: "gen_manifest_mismatch_rebootless_apex",
-  out: ["test.rebootless_apex_manifest_mismatch.apex"],
-  srcs: [":test.rebootless_apex_v1"],
-  tools: ["soong_zip", "zipalign", "conv_apex_manifest"],
-  cmd: "unzip -q $(in) -d $(genDir) && " +
-       "$(location conv_apex_manifest) setprop version 137 $(genDir)/apex_manifest.pb && " +
-       "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
-       "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
-       "-o $(genDir)/unaligned.apex && " +
-       "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
-       "$(genDir)/test.rebootless_apex_manifest_mismatch.apex"
-}
-
-genrule {
-  // Generates an apex with a corrupted filesystem image, which should cause
-  // dm-verity verification to fail
-  name: "gen_corrupt_rebootless_apex",
-  out: ["test.rebootless_apex_corrupted.apex"],
-  srcs: [":test.rebootless_apex_v1"],
-  tools: ["soong_zip", "zipalign"],
-  cmd: "unzip -q $(in) -d $(genDir) && " +
-       "dd if=/dev/zero of=$(genDir)/apex_payload.img conv=notrunc bs=1024 seek=16 count=1 && " +
-       "$(location soong_zip) -d -C $(genDir) -D $(genDir) " +
-       "-s apex_manifest.pb -s apex_payload.img -s apex_pubkey " +
-       "-o $(genDir)/unaligned.apex && " +
-       "$(location zipalign) -f 4096 $(genDir)/unaligned.apex " +
-       "$(genDir)/test.rebootless_apex_corrupted.apex"
-}
-
 cc_test {
   name: "ApexTestCases",
   defaults: [
@@ -414,32 +266,18 @@
   ],
   data: [
     ":apex.apexd_test",
-    ":apex.apexd_test_f2fs",
-    ":apex.apexd_test_digest",
-    ":apex.apexd_test_f2fs_digest",
     ":apex.apexd_test_different_app",
     ":apex.apexd_test_no_hashtree",
     ":apex.apexd_test_no_hashtree_2",
     ":apex.apexd_test_no_inst_key",
-    ":apex.apexd_test_f2fs_no_inst_key",
     ":apex.apexd_test_nocode",
     ":apex.apexd_test_postinstall",
     ":apex.apexd_test_preinstall",
     ":apex.apexd_test_prepostinstall.fail",
     ":apex.apexd_test_v2",
     ":apex.corrupted_b146895998",
-    ":apex.banned_name",
-    ":gen_key_mismatch_apex",
-    ":gen_key_mismatch_apex_v2",
-    ":gen_key_mismatch_capex",
-    ":gen_manifest_mismatch_apex",
-    ":gen_manifest_mismatch_apex_no_hashtree",
-    ":gen_corrupt_superblock_apex",
+    ":gen_bad_apexes",
     ":gen_corrupt_apex",
-    ":gen_capex_not_decompressible",
-    ":gen_capex_without_apex",
-    ":gen_capex_with_v2_apex",
-    ":gen_key_mismatch_with_original_capex",
     ":com.android.apex.cts.shim.v1_prebuilt",
     ":com.android.apex.cts.shim.v2_prebuilt",
     ":com.android.apex.cts.shim.v2_wrong_sha_prebuilt",
@@ -447,41 +285,13 @@
     ":com.android.apex.cts.shim.v2_additional_folder_prebuilt",
     ":com.android.apex.cts.shim.v2_with_pre_install_hook_prebuilt",
     ":com.android.apex.cts.shim.v2_with_post_install_hook_prebuilt",
-    ":com.android.apex.compressed_sharedlibs",
-    ":com.android.apex.compressed.v1",
-    ":com.android.apex.compressed.v1_different_digest",
-    ":com.android.apex.compressed.v1_different_digest_original",
-    ":com.android.apex.compressed.v1_original",
-    ":com.android.apex.compressed.v2",
-    ":com.android.apex.compressed.v2_original",
-    ":gen_manifest_mismatch_compressed_apex_v2",
     "apexd_testdata/com.android.apex.test_package.avbpubkey",
-    "apexd_testdata/com.android.apex.compressed.avbpubkey",
-    ":com.android.apex.test.sharedlibs_generated.v1.libvX_prebuilt",
-    ":com.android.apex.test.sharedlibs_generated.v2.libvY_prebuilt",
-    ":test.rebootless_apex_v1",
-    ":test.rebootless_apex_v2",
-    ":test.rebootless_apex_v2_no_hashtree",
-    ":gen_manifest_mismatch_rebootless_apex",
-    ":gen_corrupt_rebootless_apex",
-    ":test.rebootless_apex_provides_sharedlibs",
-    ":test.rebootless_apex_provides_native_libs",
-    ":test.rebootless_apex_requires_shared_apex_libs",
-    ":test.rebootless_apex_jni_libs",
-    ":test.rebootless_apex_add_native_lib",
-    ":test.rebootless_apex_remove_native_lib",
-    ":test.rebootless_apex_app_in_apex",
-    ":test.rebootless_apex_priv_app_in_apex",
   ],
   srcs: [
     "apex_database_test.cpp",
     "apex_file_test.cpp",
-    "apex_file_repository_test.cpp",
     "apex_manifest_test.cpp",
-    "apexd_test.cpp",
-    "apexd_session_test.cpp",
     "apexd_verity_test.cpp",
-    "apexd_utils_test.cpp",
     "apexservice_test.cpp",
   ],
   host_supported: false,
@@ -498,7 +308,6 @@
     "libfs_mgr",
     "libutils",
   ],
-  generated_sources: ["apex-info-list"],
   test_suites: ["device-tests"],
   test_config: "AndroidTest.xml",
 }
@@ -521,10 +330,3 @@
   test_config: "flattened_apex_test_config.xml",
 }
 
-xsd_config {
-  name: "apex-info-list",
-  srcs: ["ApexInfoList.xsd"],
-  package_name: "com.android.apex",
-  api_dir: "apex-info-list-api",
-  gen_writer: true,
-}
diff --git a/apexd/ApexInfoList.xsd b/apexd/ApexInfoList.xsd
deleted file mode 100644
index 440b975..0000000
--- a/apexd/ApexInfoList.xsd
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
-  <xs:element name="apex-info-list">
-    <xs:complexType>
-      <xs:sequence>
-        <xs:element ref="apex-info" minOccurs="1" maxOccurs="unbounded"/>
-      </xs:sequence>
-    </xs:complexType>
-  </xs:element>
-
-  <xs:element name="apex-info">
-    <xs:complexType>
-      <xs:attribute name="moduleName" type="xs:string" use="required"/>
-      <xs:attribute name="modulePath" type="xs:string" use="required"/>
-      <xs:attribute name="preinstalledModulePath" type="xs:string"/>
-      <xs:attribute name="versionCode" type="xs:long" use="required"/>
-      <xs:attribute name="versionName" type="xs:string" use="required"/>
-      <xs:attribute name="isFactory" type="xs:boolean" use="required"/>
-      <xs:attribute name="isActive" type="xs:boolean" use="required"/>
-      <xs:attribute name="lastUpdateMillis" type="xs:long"/>
-    </xs:complexType>
-  </xs:element>
-</xs:schema>
diff --git a/apexd/OWNERS b/apexd/OWNERS
new file mode 100644
index 0000000..ed9813e
--- /dev/null
+++ b/apexd/OWNERS
@@ -0,0 +1 @@
+agampe@google.com
diff --git a/apexd/aidl/android/apex/ApexSessionInfo.aidl b/apexd/aidl/android/apex/ApexSessionInfo.aidl
index 65da113..a7a6daf 100644
--- a/apexd/aidl/android/apex/ApexSessionInfo.aidl
+++ b/apexd/aidl/android/apex/ApexSessionInfo.aidl
@@ -29,5 +29,4 @@
     boolean isReverted;
     boolean isRevertFailed;
     @utf8InCpp String crashingNativeProcess;
-    @utf8InCpp String errorMessage;
 }
diff --git a/apexd/aidl/android/apex/CompressedApexInfo.aidl b/apexd/aidl/android/apex/CompressedApexInfo.aidl
deleted file mode 100644
index 48015bd..0000000
--- a/apexd/aidl/android/apex/CompressedApexInfo.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2021 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 android.apex;
-
-parcelable CompressedApexInfo {
-    @utf8InCpp String moduleName;
-    long versionCode;
-    long decompressedSize;
-}
diff --git a/apexd/aidl/android/apex/CompressedApexInfoList.aidl b/apexd/aidl/android/apex/CompressedApexInfoList.aidl
deleted file mode 100644
index e1620bd..0000000
--- a/apexd/aidl/android/apex/CompressedApexInfoList.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2021 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 android.apex;
-
-import android.apex.CompressedApexInfo;
-
-parcelable CompressedApexInfoList {
-    CompressedApexInfo[] apexInfos;
-}
diff --git a/apexd/aidl/android/apex/IApexService.aidl b/apexd/aidl/android/apex/IApexService.aidl
index 2d77a82..3626d9a 100644
--- a/apexd/aidl/android/apex/IApexService.aidl
+++ b/apexd/aidl/android/apex/IApexService.aidl
@@ -20,7 +20,6 @@
 import android.apex.ApexInfoList;
 import android.apex.ApexSessionInfo;
 import android.apex.ApexSessionParams;
-import android.apex.CompressedApexInfoList;
 
 interface IApexService {
    void submitStagedSession(in ApexSessionParams params, out ApexInfoList packages);
@@ -37,9 +36,9 @@
 
    /**
     * Copies the CE apex data directory for the given user to the backup
-    * location.
+    * location, and returns the inode of the snapshot directory.
     */
-   void snapshotCeData(int user_id, int rollback_id, in @utf8InCpp String apex_name);
+   long snapshotCeData(int user_id, int rollback_id, in @utf8InCpp String apex_name);
 
    /**
     * Restores the snapshot of the CE apex data directory for the given user and
@@ -53,11 +52,6 @@
    void destroyDeSnapshots(int rollback_id);
 
    /**
-    * Deletes credential-encrypted snapshots for the given user, for the given rollback id.
-    */
-   void destroyCeSnapshots(int user_id, int rollback_id);
-
-   /**
     * Deletes all credential-encrypted snapshots for the given user, except for
     * those listed in retain_rollback_ids.
     */
@@ -121,42 +115,4 @@
     * on user builds. Only root is allowed to call this method.
     */
    void remountPackages();
-   /**
-    * Forces apexd to recollect pre-installed data from the given |paths|.
-    *
-    * Not meant for use outside of testing. This call will not be functional
-    * on user builds. Only root is allowed to call this method.
-    */
-   void recollectPreinstalledData(in @utf8InCpp List<String> paths);
-   /**
-    * Forces apexd to recollect data apex from the given |path|.
-    *
-    * Not meant for use outside of testing. This call will not be functional
-    * on user builds. Only root is allowed to call this method.
-    */
-   void recollectDataApex(in @utf8InCpp String path, in@utf8InCpp String decompression_dir);
-
-   /**
-    * Informs apexd that the boot has completed.
-    */
-   void markBootCompleted();
-
-   /**
-   * Assuming the provided compressed APEX will be installed on next boot,
-   * calculate how much space will be required for decompression
-   */
-   long calculateSizeForCompressedApex(in CompressedApexInfoList compressed_apex_info_list);
-
-   /**
-   * Reserve space on /data partition for compressed APEX decompression. Returns error if
-   * reservation fails. If empty list is passed, then reserved space is deallocated.
-   */
-   void reserveSpaceForCompressedApex(in CompressedApexInfoList compressed_apex_info_list);
-
-   /**
-    * Performs a non-staged install of the given APEX.
-    * Note: don't confuse this to preInstall and postInstall binder calls which are only used to
-    * test corresponding features of APEX packages.
-    */
-   ApexInfo installAndActivatePackage(in @utf8InCpp String packagePath);
 }
diff --git a/apexd/apex-info-list-api/current.txt b/apexd/apex-info-list-api/current.txt
deleted file mode 100644
index 8db5a9a..0000000
--- a/apexd/apex-info-list-api/current.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-// Signature format: 2.0
-package com.android.apex {
-
-  public class ApexInfo {
-    ctor public ApexInfo();
-    method public boolean getIsActive();
-    method public boolean getIsFactory();
-    method public long getLastUpdateMillis();
-    method public String getModuleName();
-    method public String getModulePath();
-    method public String getPreinstalledModulePath();
-    method public long getVersionCode();
-    method public String getVersionName();
-    method public void setIsActive(boolean);
-    method public void setIsFactory(boolean);
-    method public void setLastUpdateMillis(long);
-    method public void setModuleName(String);
-    method public void setModulePath(String);
-    method public void setPreinstalledModulePath(String);
-    method public void setVersionCode(long);
-    method public void setVersionName(String);
-  }
-
-  public class ApexInfoList {
-    ctor public ApexInfoList();
-    method public java.util.List<com.android.apex.ApexInfo> getApexInfo();
-  }
-
-  public class XmlParser {
-    ctor public XmlParser();
-    method public static com.android.apex.ApexInfo readApexInfo(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static com.android.apex.ApexInfoList readApexInfoList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-  }
-
-  public class XmlWriter implements java.io.Closeable {
-    ctor public XmlWriter(java.io.PrintWriter);
-    method public void close();
-    method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfoList) throws java.io.IOException;
-    method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfo) throws java.io.IOException;
-  }
-
-}
-
diff --git a/apexd/apex-info-list-api/last_current.txt b/apexd/apex-info-list-api/last_current.txt
deleted file mode 100644
index 8db5a9a..0000000
--- a/apexd/apex-info-list-api/last_current.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-// Signature format: 2.0
-package com.android.apex {
-
-  public class ApexInfo {
-    ctor public ApexInfo();
-    method public boolean getIsActive();
-    method public boolean getIsFactory();
-    method public long getLastUpdateMillis();
-    method public String getModuleName();
-    method public String getModulePath();
-    method public String getPreinstalledModulePath();
-    method public long getVersionCode();
-    method public String getVersionName();
-    method public void setIsActive(boolean);
-    method public void setIsFactory(boolean);
-    method public void setLastUpdateMillis(long);
-    method public void setModuleName(String);
-    method public void setModulePath(String);
-    method public void setPreinstalledModulePath(String);
-    method public void setVersionCode(long);
-    method public void setVersionName(String);
-  }
-
-  public class ApexInfoList {
-    ctor public ApexInfoList();
-    method public java.util.List<com.android.apex.ApexInfo> getApexInfo();
-  }
-
-  public class XmlParser {
-    ctor public XmlParser();
-    method public static com.android.apex.ApexInfo readApexInfo(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static com.android.apex.ApexInfoList readApexInfoList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-  }
-
-  public class XmlWriter implements java.io.Closeable {
-    ctor public XmlWriter(java.io.PrintWriter);
-    method public void close();
-    method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfoList) throws java.io.IOException;
-    method public static void write(com.android.apex.XmlWriter, com.android.apex.ApexInfo) throws java.io.IOException;
-  }
-
-}
-
diff --git a/apexd/apex-info-list-api/last_removed.txt b/apexd/apex-info-list-api/last_removed.txt
deleted file mode 100644
index e69de29..0000000
--- a/apexd/apex-info-list-api/last_removed.txt
+++ /dev/null
diff --git a/apexd/apex-info-list-api/removed.txt b/apexd/apex-info-list-api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apexd/apex-info-list-api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apexd/apex_constants.h b/apexd/apex_constants.h
index 798afd5..4e98943 100644
--- a/apexd/apex_constants.h
+++ b/apexd/apex_constants.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <string>
-#include <unordered_set>
 #include <vector>
 
 namespace android {
@@ -27,8 +26,6 @@
 static constexpr const char* kActiveApexPackagesDataDir = "/data/apex/active";
 static constexpr const char* kApexBackupDir = "/data/apex/backup";
 static constexpr const char* kApexHashTreeDir = "/data/apex/hashtree";
-static constexpr const char* kApexDecompressedDir = "/data/apex/decompressed";
-static constexpr const char* kOtaReservedDir = "/data/apex/ota_reserved";
 static constexpr const char* kApexPackageSystemDir = "/system/apex";
 static constexpr const char* kApexPackageSystemExtDir = "/system_ext/apex";
 static constexpr const char* kApexPackageVendorDir = "/vendor/apex";
@@ -42,7 +39,6 @@
 static constexpr const char* kStagedSessionsDir = "/data/app-staging";
 
 static constexpr const char* kApexDataSubDir = "apexdata";
-static constexpr const char* kApexSharedLibsSubDir = "sharedlibs";
 static constexpr const char* kApexSnapshotSubDir = "apexrollback";
 static constexpr const char* kPreRestoreSuffix = "-prerestore";
 
@@ -51,26 +47,8 @@
 static constexpr const char* kCeDataDir = "/data/misc_ce";
 
 static constexpr const char* kApexPackageSuffix = ".apex";
-static constexpr const char* kCompressedApexPackageSuffix = ".capex";
-static constexpr const char* kDecompressedApexPackageSuffix =
-    ".decompressed.apex";
-static constexpr const char* kOtaApexPackageSuffix = ".ota.apex";
 
 static constexpr const char* kManifestFilenameJson = "apex_manifest.json";
 static constexpr const char* kManifestFilenamePb = "apex_manifest.pb";
-
-static constexpr const char* kApexInfoList = "apex-info-list.xml";
-
-// These should be in-sync with system/sepolicy/private/property_contexts
-static constexpr const char* kApexStatusSysprop = "apexd.status";
-static constexpr const char* kApexStatusStarting = "starting";
-static constexpr const char* kApexStatusActivated = "activated";
-static constexpr const char* kApexStatusReady = "ready";
-
-// Banned APEX names
-static const std::unordered_set<std::string> kBannedApexName = {
-    kApexSharedLibsSubDir,  // To avoid conflicts with predefined
-                            // /apex/sharedlibs directory
-};
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apex_database.cpp b/apexd/apex_database.cpp
index 7a1ee36..d027f95 100644
--- a/apexd/apex_database.cpp
+++ b/apexd/apex_database.cpp
@@ -35,9 +35,6 @@
 #include <utility>
 
 using android::base::ConsumeSuffix;
-using android::base::EndsWith;
-using android::base::ErrnoError;
-using android::base::Error;
 using android::base::ParseInt;
 using android::base::ReadFileToString;
 using android::base::Result;
@@ -79,12 +76,12 @@
   fs::path DevPath() const { return kDevBlock / name; }
 
   Result<std::string> GetProperty(const std::string& property) const {
-    auto property_file = SysPath() / property;
-    std::string property_value;
-    if (!ReadFileToString(property_file, &property_value)) {
+    auto propertyFile = SysPath() / property;
+    std::string propertyValue;
+    if (!ReadFileToString(propertyFile, &propertyValue)) {
       return ErrnoError() << "Fail to read";
     }
-    return Trim(property_value);
+    return Trim(propertyValue);
   }
 
   std::vector<BlockDevice> GetSlaves() const {
@@ -103,17 +100,17 @@
   }
 };
 
-std::pair<fs::path, fs::path> ParseMountInfo(const std::string& mount_info) {
-  const auto& tokens = Split(mount_info, " ");
+std::pair<fs::path, fs::path> parseMountInfo(const std::string& mountInfo) {
+  const auto& tokens = Split(mountInfo, " ");
   if (tokens.size() < 2) {
     return std::make_pair("", "");
   }
   return std::make_pair(tokens[0], tokens[1]);
 }
 
-std::pair<std::string, int> ParseMountPoint(const std::string& mount_point) {
-  auto package_id = fs::path(mount_point).filename();
-  auto split = Split(package_id, "@");
+std::pair<std::string, int> parseMountPoint(const std::string& mountPoint) {
+  auto packageId = fs::path(mountPoint).filename();
+  auto split = Split(packageId, "@");
   if (split.size() == 2) {
     int version;
     if (!ParseInt(split[1], &version)) {
@@ -121,17 +118,14 @@
     }
     return std::make_pair(split[0], version);
   }
-  return std::make_pair(package_id, -1);
+  return std::make_pair(packageId, -1);
 }
 
-bool IsActiveMountPoint(const std::string& mount_point) {
-  return (mount_point.find('@') == std::string::npos);
+bool isActiveMountPoint(const std::string& mountPoint) {
+  return (mountPoint.find('@') == std::string::npos);
 }
 
 Result<void> PopulateLoopInfo(const BlockDevice& top_device,
-                              const std::string& active_apex_dir,
-                              const std::string& decompression_dir,
-                              const std::string& apex_hash_tree_dir,
                               MountedApexData* apex_data) {
   std::vector<BlockDevice> slaves = top_device.GetSlaves();
   if (slaves.size() != 1 && slaves.size() != 2) {
@@ -153,22 +147,18 @@
   // Enforce following invariant:
   //  * slaves[0] always represents a data loop device
   //  * if size = 2 then slaves[1] represents an external hashtree loop device
-  auto is_data_loop_device = [&](const std::string& backing_file) {
-    return StartsWith(backing_file, active_apex_dir) ||
-           StartsWith(backing_file, decompression_dir);
-  };
   if (slaves.size() == 2) {
-    if (!is_data_loop_device(backing_files[0])) {
+    if (!StartsWith(backing_files[0], kActiveApexPackagesDataDir)) {
       std::swap(slaves[0], slaves[1]);
       std::swap(backing_files[0], backing_files[1]);
     }
   }
-  if (!is_data_loop_device(backing_files[0])) {
+  if (!StartsWith(backing_files[0], kActiveApexPackagesDataDir)) {
     return Error() << "Data loop device " << slaves[0].DevPath()
                    << " has unexpected backing file " << backing_files[0];
   }
   if (slaves.size() == 2) {
-    if (!StartsWith(backing_files[1], apex_hash_tree_dir)) {
+    if (!StartsWith(backing_files[1], kApexHashTreeDir)) {
       return Error() << "Hashtree loop device " << slaves[1].DevPath()
                      << " has unexpected backing file " << backing_files[1];
     }
@@ -181,7 +171,7 @@
 
 // This is not the right place to do this normalization, but proper solution
 // will require some refactoring first. :(
-// TODO(b/158469911): introduce MountedApexDataBuilder and delegate all
+// TODO(ioffe): introduce MountedApexDataBuilder and delegate all
 //  building/normalization logic to it.
 void NormalizeIfDeleted(MountedApexData* apex_data) {
   std::string_view full_path = apex_data->full_path;
@@ -198,22 +188,18 @@
   apex_data->full_path = full_path;
 }
 
-Result<MountedApexData> ResolveMountInfo(
-    const BlockDevice& block, const std::string& mount_point,
-    const std::string& active_apex_dir, const std::string& decompression_dir,
-    const std::string& apex_hash_tree_dir) {
-  bool temp_mount = EndsWith(mount_point, ".tmp");
+Result<MountedApexData> resolveMountInfo(const BlockDevice& block,
+                                         const std::string& mountPoint) {
   // Now, see if it is dm-verity or loop mounted
   switch (block.GetType()) {
     case LoopDevice: {
-      auto backing_file = block.GetProperty("loop/backing_file");
-      if (!backing_file.ok()) {
-        return backing_file.error();
+      auto backingFile = block.GetProperty("loop/backing_file");
+      if (!backingFile.ok()) {
+        return backingFile.error();
       }
-      auto result = MountedApexData(block.DevPath(), *backing_file, mount_point,
+      auto result = MountedApexData(block.DevPath(), *backingFile, mountPoint,
                                     /* device_name= */ "",
-                                    /* hashtree_loop_name= */ "",
-                                    /* is_temp_mount */ temp_mount);
+                                    /* hashtree_loop_name= */ "");
       NormalizeIfDeleted(&result);
       return result;
     }
@@ -223,12 +209,9 @@
         return name.error();
       }
       MountedApexData result;
-      result.mount_point = mount_point;
+      result.mount_point = mountPoint;
       result.device_name = *name;
-      result.is_temp_mount = temp_mount;
-      auto status = PopulateLoopInfo(block, active_apex_dir, decompression_dir,
-                                     apex_hash_tree_dir, &result);
-      if (!status.ok()) {
+      if (auto status = PopulateLoopInfo(block, &result); !status.ok()) {
         return status.error();
       }
       NormalizeIfDeleted(&result);
@@ -263,45 +246,40 @@
 // By synchronizing the mounts info with Database on startup,
 // Apexd serves the correct package list even on the devices
 // which are not ro.apex.updatable.
-void MountedApexDatabase::PopulateFromMounts(
-    const std::string& active_apex_dir, const std::string& decompression_dir,
-    const std::string& apex_hash_tree_dir) REQUIRES(!mounted_apexes_mutex_) {
+void MountedApexDatabase::PopulateFromMounts() {
   LOG(INFO) << "Populating APEX database from mounts...";
 
-  std::unordered_map<std::string, int> active_versions;
+  std::unordered_map<std::string, int> activeVersions;
 
   std::ifstream mounts("/proc/mounts");
   std::string line;
-  std::lock_guard lock(mounted_apexes_mutex_);
   while (std::getline(mounts, line)) {
-    auto [block, mount_point] = ParseMountInfo(line);
-    // TODO(b/158469914): distinguish between temp and non-temp mounts
-    if (fs::path(mount_point).parent_path() != kApexRoot) {
+    auto [block, mountPoint] = parseMountInfo(line);
+    // TODO(jooyung): ignore tmp mount?
+    if (fs::path(mountPoint).parent_path() != kApexRoot) {
       continue;
     }
-    if (IsActiveMountPoint(mount_point)) {
+    if (isActiveMountPoint(mountPoint)) {
       continue;
     }
 
-    auto mount_data =
-        ResolveMountInfo(BlockDevice(block), mount_point, active_apex_dir,
-                         decompression_dir, apex_hash_tree_dir);
-    if (!mount_data.ok()) {
-      LOG(WARNING) << "Can't resolve mount info " << mount_data.error();
+    auto mountData = resolveMountInfo(BlockDevice(block), mountPoint);
+    if (!mountData.ok()) {
+      LOG(WARNING) << "Can't resolve mount info " << mountData.error();
       continue;
     }
 
-    auto [package, version] = ParseMountPoint(mount_point);
-    AddMountedApexLocked(package, false, *mount_data);
+    auto [package, version] = parseMountPoint(mountPoint);
+    AddMountedApex(package, false, *mountData);
 
-    auto active = active_versions[package] < version;
+    auto active = activeVersions[package] < version;
     if (active) {
-      active_versions[package] = version;
-      SetLatestLocked(package, mount_data->full_path);
+      activeVersions[package] = version;
+      SetLatest(package, mountData->full_path);
     }
-    LOG(INFO) << "Found " << mount_point << " backed by"
-              << (mount_data->deleted ? " deleted " : " ") << "file "
-              << mount_data->full_path;
+    LOG(INFO) << "Found " << mountPoint << " backed by"
+              << (mountData->deleted ? " deleted " : " ") << "file "
+              << mountData->full_path;
   }
 
   LOG(INFO) << mounted_apexes_.size() << " packages restored.";
diff --git a/apexd/apex_database.h b/apexd/apex_database.h
index 113b88e..1fb5bd3 100644
--- a/apexd/apex_database.h
+++ b/apexd/apex_database.h
@@ -18,14 +18,10 @@
 #define ANDROID_APEXD_APEX_DATABASE_H_
 
 #include <map>
-#include <mutex>
-#include <optional>
 #include <string>
 #include <unordered_set>
 
 #include <android-base/logging.h>
-#include <android-base/result.h>
-#include <android-base/thread_annotations.h>
 
 namespace android {
 namespace apex {
@@ -44,21 +40,17 @@
     std::string hashtree_loop_name;
     // Whenever apex file specified in full_path was deleted.
     bool deleted;
-    // Whether the mount is a temp mount or not.
-    bool is_temp_mount;
 
     MountedApexData() {}
     MountedApexData(const std::string& loop_name, const std::string& full_path,
                     const std::string& mount_point,
                     const std::string& device_name,
-                    const std::string& hashtree_loop_name,
-                    bool is_temp_mount = false)
+                    const std::string& hashtree_loop_name)
         : loop_name(loop_name),
           full_path(full_path),
           mount_point(mount_point),
           device_name(device_name),
-          hashtree_loop_name(hashtree_loop_name),
-          is_temp_mount(is_temp_mount) {}
+          hashtree_loop_name(hashtree_loop_name) {}
 
     inline bool operator<(const MountedApexData& rhs) const {
       int compare_val = loop_name.compare(rhs.loop_name);
@@ -89,10 +81,42 @@
     }
   };
 
+  inline void CheckAtMostOneLatest() {
+    for (const auto& apex_set : mounted_apexes_) {
+      size_t count = 0;
+      for (const auto& pair : apex_set.second) {
+        if (pair.second) {
+          count++;
+        }
+      }
+      CHECK_LE(count, 1u) << apex_set.first;
+    }
+  }
+
+  inline void CheckUniqueLoopDm() {
+    std::unordered_set<std::string> loop_devices;
+    std::unordered_set<std::string> dm_devices;
+    for (const auto& apex_set : mounted_apexes_) {
+      for (const auto& pair : apex_set.second) {
+        if (pair.first.loop_name != "") {
+          CHECK(loop_devices.insert(pair.first.loop_name).second)
+              << "Duplicate loop device: " << pair.first.loop_name;
+        }
+        if (pair.first.device_name != "") {
+          CHECK(dm_devices.insert(pair.first.device_name).second)
+              << "Duplicate dm device: " << pair.first.device_name;
+        }
+        if (pair.first.hashtree_loop_name != "") {
+          CHECK(loop_devices.insert(pair.first.hashtree_loop_name).second)
+              << "Duplicate loop device: " << pair.first.hashtree_loop_name;
+        }
+      }
+    }
+  }
+
   template <typename... Args>
-  inline void AddMountedApexLocked(const std::string& package, bool latest,
-                                   Args&&... args)
-      REQUIRES(mounted_apexes_mutex_) {
+  inline void AddMountedApex(const std::string& package, bool latest,
+                             Args&&... args) {
     auto it = mounted_apexes_.find(package);
     if (it == mounted_apexes_.end()) {
       auto insert_it =
@@ -109,18 +133,8 @@
     CheckUniqueLoopDm();
   }
 
-  template <typename... Args>
-  inline void AddMountedApex(const std::string& package, bool latest,
-                             Args&&... args) REQUIRES(!mounted_apexes_mutex_) {
-    std::lock_guard lock(mounted_apexes_mutex_);
-    AddMountedApexLocked(package, latest, args...);
-  }
-
   inline void RemoveMountedApex(const std::string& package,
-                                const std::string& full_path,
-                                bool match_temp_mounts = false)
-      REQUIRES(!mounted_apexes_mutex_) {
-    std::lock_guard lock(mounted_apexes_mutex_);
+                                const std::string& full_path) {
     auto it = mounted_apexes_.find(package);
     if (it == mounted_apexes_.end()) {
       return;
@@ -129,8 +143,7 @@
     auto& pkg_map = it->second;
 
     for (auto pkg_it = pkg_map.begin(); pkg_it != pkg_map.end(); ++pkg_it) {
-      if (pkg_it->first.full_path == full_path &&
-          pkg_it->first.is_temp_mount == match_temp_mounts) {
+      if (pkg_it->first.full_path == full_path) {
         pkg_map.erase(pkg_it);
         return;
       }
@@ -138,15 +151,7 @@
   }
 
   inline void SetLatest(const std::string& package,
-                        const std::string& full_path)
-      REQUIRES(!mounted_apexes_mutex_) {
-    std::lock_guard lock(mounted_apexes_mutex_);
-    SetLatestLocked(package, full_path);
-  }
-
-  inline void SetLatestLocked(const std::string& package,
-                              const std::string& full_path)
-      REQUIRES(mounted_apexes_mutex_) {
+                        const std::string& full_path) {
     auto it = mounted_apexes_.find(package);
     CHECK(it != mounted_apexes_.end());
 
@@ -168,108 +173,47 @@
     LOG(FATAL) << "Did not find " << package << " " << full_path;
   }
 
+  inline void UnsetLatestForall(const std::string& package) {
+    auto it = mounted_apexes_.find(package);
+    if (it == mounted_apexes_.end()) {
+      return;
+    }
+    for (auto& data : it->second) {
+      data.second = false;
+    }
+  }
+
   template <typename T>
-  inline void ForallMountedApexes(const std::string& package, const T& handler,
-                                  bool match_temp_mounts = false) const
-      REQUIRES(!mounted_apexes_mutex_) {
-    std::lock_guard lock(mounted_apexes_mutex_);
+  inline void ForallMountedApexes(const std::string& package,
+                                  const T& handler) const {
     auto it = mounted_apexes_.find(package);
     if (it == mounted_apexes_.end()) {
       return;
     }
     for (auto& pair : it->second) {
-      if (pair.first.is_temp_mount == match_temp_mounts) {
-        handler(pair.first, pair.second);
-      }
+      handler(pair.first, pair.second);
     }
   }
 
   template <typename T>
-  inline void ForallMountedApexes(const T& handler,
-                                  bool match_temp_mounts = false) const
-      REQUIRES(!mounted_apexes_mutex_) {
-    std::lock_guard lock(mounted_apexes_mutex_);
+  inline void ForallMountedApexes(const T& handler) const {
     for (const auto& pkg : mounted_apexes_) {
       for (const auto& pair : pkg.second) {
-        if (pair.first.is_temp_mount == match_temp_mounts) {
-          handler(pkg.first, pair.first, pair.second);
-        }
+        handler(pkg.first, pair.first, pair.second);
       }
     }
   }
 
-  inline std::optional<MountedApexData> GetLatestMountedApex(
-      const std::string& package) REQUIRES(!mounted_apexes_mutex_) {
-    std::optional<MountedApexData> ret;
-    ForallMountedApexes(package,
-                        [&ret](const MountedApexData& data, bool latest) {
-                          if (latest) {
-                            ret.emplace(data);
-                          }
-                        });
-    return ret;
-  }
-
-  void PopulateFromMounts(const std::string& active_apex_dir,
-                          const std::string& decompression_dir,
-                          const std::string& apex_hash_tree_dir);
-
-  // Resets state of the database. Should only be used in testing.
-  inline void Reset() REQUIRES(!mounted_apexes_mutex_) {
-    std::lock_guard lock(mounted_apexes_mutex_);
-    mounted_apexes_.clear();
-  }
+  void PopulateFromMounts();
 
  private:
   // A map from package name to mounted apexes.
   // Note: using std::maps to
   //         a) so we do not have to worry about iterator invalidation.
   //         b) do not have to const_cast (over std::set)
-  // TODO(b/158467745): This structure (and functions) need to be guarded by
-  //   locks.
-  std::map<std::string, std::map<MountedApexData, bool>> mounted_apexes_
-      GUARDED_BY(mounted_apexes_mutex_);
-
-  // To fix thread safety negative capability warning
-  class Mutex : public std::mutex {
-   public:
-    // for negative capabilities
-    const Mutex& operator!() const { return *this; }
-  };
-  mutable Mutex mounted_apexes_mutex_;
-
-  inline void CheckAtMostOneLatest() REQUIRES(mounted_apexes_mutex_) {
-    for (const auto& apex_set : mounted_apexes_) {
-      size_t count = 0;
-      for (const auto& pair : apex_set.second) {
-        if (pair.second) {
-          count++;
-        }
-      }
-      CHECK_LE(count, 1u) << apex_set.first;
-    }
-  }
-
-  inline void CheckUniqueLoopDm() REQUIRES(mounted_apexes_mutex_) {
-    std::unordered_set<std::string> loop_devices;
-    std::unordered_set<std::string> dm_devices;
-    for (const auto& apex_set : mounted_apexes_) {
-      for (const auto& pair : apex_set.second) {
-        if (pair.first.loop_name != "") {
-          CHECK(loop_devices.insert(pair.first.loop_name).second)
-              << "Duplicate loop device: " << pair.first.loop_name;
-        }
-        if (pair.first.device_name != "") {
-          CHECK(dm_devices.insert(pair.first.device_name).second)
-              << "Duplicate dm device: " << pair.first.device_name;
-        }
-        if (pair.first.hashtree_loop_name != "") {
-          CHECK(loop_devices.insert(pair.first.hashtree_loop_name).second)
-              << "Duplicate loop device: " << pair.first.hashtree_loop_name;
-        }
-      }
-    }
-  }
+  // TODO: Eventually this structure (and functions) need to be guarded by
+  // locks.
+  std::map<std::string, std::map<MountedApexData, bool>> mounted_apexes_;
 };
 
 }  // namespace apex
diff --git a/apexd/apex_database_test.cpp b/apexd/apex_database_test.cpp
index 8c3a98d..522619f 100644
--- a/apexd/apex_database_test.cpp
+++ b/apexd/apex_database_test.cpp
@@ -35,7 +35,6 @@
   constexpr const char* kDm[] = {"dm1", "dm2", "dm3"};
   constexpr const char* kHashtreeLoopName[] = {"hash-loop1", "hash-loop2",
                                                "hash-loop3"};
-  // NOLINTNEXTLINE(bugprone-sizeof-expression)
   constexpr size_t kCount = arraysize(kLoopName) * arraysize(kPath) *
                             arraysize(kMount) * arraysize(kDm);
 
@@ -201,37 +200,6 @@
                               kDeviceName[3], kHashtreeLoopName[3]));
 }
 
-TEST(ApexDatabaseTest, GetLatestMountedApex) {
-  constexpr const char* kPackage = "package";
-  constexpr const char* kLoopName = "loop";
-  constexpr const char* kPath = "path";
-  constexpr const char* kMountPoint = "mount";
-  constexpr const char* kDeviceName = "dev";
-  constexpr const char* kHashtreeLoopName = "hash-loop";
-
-  MountedApexDatabase db;
-  ASSERT_EQ(CountPackages(db), 0u);
-
-  db.AddMountedApex(kPackage, true, kLoopName, kPath, kMountPoint, kDeviceName,
-                    kHashtreeLoopName);
-
-  auto ret = db.GetLatestMountedApex(kPackage);
-  MountedApexData expected(kLoopName, kPath, kMountPoint, kDeviceName,
-                           kHashtreeLoopName);
-  ASSERT_TRUE(ret.has_value());
-  ASSERT_EQ(ret->loop_name, std::string(kLoopName));
-  ASSERT_EQ(ret->full_path, std::string(kPath));
-  ASSERT_EQ(ret->mount_point, std::string(kMountPoint));
-  ASSERT_EQ(ret->device_name, std::string(kDeviceName));
-  ASSERT_EQ(ret->hashtree_loop_name, std::string(kHashtreeLoopName));
-}
-
-TEST(ApexDatabaseTest, GetLatestMountedApexReturnsNullopt) {
-  MountedApexDatabase db;
-  auto ret = db.GetLatestMountedApex("no-such-name");
-  ASSERT_FALSE(ret.has_value());
-}
-
 #pragma clang diagnostic push
 // error: 'ReturnSentinel' was marked unused but was used
 // [-Werror,-Wused-but-marked-unused]
diff --git a/apexd/apex_file.cpp b/apexd/apex_file.cpp
index c043def..f91b5d1 100644
--- a/apexd/apex_file.cpp
+++ b/apexd/apex_file.cpp
@@ -23,108 +23,61 @@
 
 #include <filesystem>
 #include <fstream>
-#include <span>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/scopeguard.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <google/protobuf/util/message_differencer.h>
 #include <libavb/libavb.h>
-#include <ziparchive/zip_archive.h>
 
 #include "apex_constants.h"
+#include "apex_preinstalled_data.h"
 #include "apexd_utils.h"
+#include "string_log.h"
 
-using android::base::borrowed_fd;
-using android::base::ErrnoError;
+using android::base::EndsWith;
 using android::base::Error;
 using android::base::ReadFullyAtOffset;
-using android::base::RemoveFileIfExists;
 using android::base::Result;
+using android::base::StartsWith;
 using android::base::unique_fd;
-using ::apex::proto::ApexManifest;
+using google::protobuf::util::MessageDifferencer;
 
 namespace android {
 namespace apex {
 namespace {
 
 constexpr const char* kImageFilename = "apex_payload.img";
-constexpr const char* kCompressedApexFilename = "original_apex";
 constexpr const char* kBundledPublicKeyFilename = "apex_pubkey";
 
-struct FsMagic {
-  const char* type;
-  int32_t offset;
-  int16_t len;
-  const char* magic;
-};
-constexpr const FsMagic kFsType[] = {{"f2fs", 1024, 4, "\x10\x20\xf5\xf2"},
-                                     {"ext4", 1024 + 0x38, 2, "\123\357"}};
-
-Result<std::string> RetrieveFsType(borrowed_fd fd, int32_t image_offset) {
-  for (const auto& fs : kFsType) {
-    char buf[fs.len];
-    if (!ReadFullyAtOffset(fd, buf, fs.len, image_offset + fs.offset)) {
-      return ErrnoError() << "Couldn't read filesystem magic";
-    }
-    if (memcmp(buf, fs.magic, fs.len) == 0) {
-      return std::string(fs.type);
-    }
-  }
-  return Error() << "Couldn't find filesystem magic";
-}
-
 }  // namespace
 
 Result<ApexFile> ApexFile::Open(const std::string& path) {
-  std::optional<int32_t> image_offset;
-  std::optional<size_t> image_size;
+  int32_t image_offset;
+  size_t image_size;
   std::string manifest_content;
   std::string pubkey;
-  std::optional<std::string> fs_type;
-  ZipEntry entry;
-
-  unique_fd fd(open(path.c_str(), O_RDONLY | O_BINARY | O_CLOEXEC));
-  if (fd < 0) {
-    return Error() << "Failed to open package " << path << ": "
-                   << "I/O error";
-  }
 
   ZipArchiveHandle handle;
   auto handle_guard =
       android::base::make_scope_guard([&handle] { CloseArchive(handle); });
-  int ret = OpenArchiveFd(fd.get(), path.c_str(), &handle, false);
+  int ret = OpenArchive(path.c_str(), &handle);
   if (ret < 0) {
     return Error() << "Failed to open package " << path << ": "
                    << ErrorCodeString(ret);
   }
 
-  bool is_compressed = true;
-  ret = FindEntry(handle, kCompressedApexFilename, &entry);
+  // Locate the mountable image within the zipfile and store offset and size.
+  ZipEntry entry;
+  ret = FindEntry(handle, kImageFilename, &entry);
   if (ret < 0) {
-    is_compressed = false;
+    return Error() << "Could not find entry \"" << kImageFilename
+                   << "\" in package " << path << ": " << ErrorCodeString(ret);
   }
-
-  if (!is_compressed) {
-    // Locate the mountable image within the zipfile and store offset and size.
-    ret = FindEntry(handle, kImageFilename, &entry);
-    if (ret < 0) {
-      return Error() << "Could not find entry \"" << kImageFilename
-                     << "\" or \"" << kCompressedApexFilename
-                     << "\" in package " << path << ": "
-                     << ErrorCodeString(ret);
-    }
-    image_offset = entry.offset;
-    image_size = entry.uncompressed_length;
-
-    auto fs_type_result = RetrieveFsType(fd, image_offset.value());
-    if (!fs_type_result.ok()) {
-      return Error() << "Failed to retrieve filesystem type for " << path
-                     << ": " << fs_type_result.error();
-    }
-    fs_type = std::move(*fs_type_result);
-  }
+  image_offset = entry.offset;
+  image_size = entry.uncompressed_length;
 
   ret = FindEntry(handle, kManifestFilenamePb, &entry);
   if (ret < 0) {
@@ -159,20 +112,8 @@
     return manifest.error();
   }
 
-  if (is_compressed && manifest->providesharedapexlibs()) {
-    return Error() << "Apex providing sharedlibs shouldn't be compressed";
-  }
-
-  // b/179211712 the stored path should be the realpath, otherwise the path we
-  // get by scanning the directory would be different from the path we get
-  // by reading /proc/mounts, if the apex file is on a symlink dir.
-  std::string realpath;
-  if (!android::base::Realpath(path, &realpath)) {
-    return ErrnoError() << "can't get realpath of " << path;
-  }
-
-  return ApexFile(realpath, image_offset, image_size, std::move(*manifest),
-                  pubkey, fs_type, is_compressed);
+  return ApexFile(path, image_offset, image_size, std::move(*manifest), pubkey,
+                  isPathForBuiltinApexes(path));
 }
 
 // AVB-related code.
@@ -181,7 +122,7 @@
 
 static constexpr int kVbMetaMaxSize = 64 * 1024;
 
-std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) {
+std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) {
   std::ostringstream s;
 
   s << std::hex << std::setfill('0');
@@ -191,32 +132,28 @@
   return s.str();
 }
 
-std::string GetSalt(const AvbHashtreeDescriptor& desc,
-                    const uint8_t* trailing_data) {
-  const uint8_t* desc_salt = trailing_data + desc.partition_name_len;
+std::string getSalt(const AvbHashtreeDescriptor& desc,
+                    const uint8_t* trailingData) {
+  const uint8_t* desc_salt = trailingData + desc.partition_name_len;
 
-  return BytesToHex(desc_salt, desc.salt_len);
+  return bytes_to_hex(desc_salt, desc.salt_len);
 }
 
-std::string GetDigest(const AvbHashtreeDescriptor& desc,
-                      const uint8_t* trailing_data) {
+std::string getDigest(const AvbHashtreeDescriptor& desc,
+                      const uint8_t* trailingData) {
   const uint8_t* desc_digest =
-      trailing_data + desc.partition_name_len + desc.salt_len;
+      trailingData + desc.partition_name_len + desc.salt_len;
 
-  return BytesToHex(desc_digest, desc.root_digest_len);
+  return bytes_to_hex(desc_digest, desc.root_digest_len);
 }
 
-Result<std::unique_ptr<AvbFooter>> GetAvbFooter(const ApexFile& apex,
+Result<std::unique_ptr<AvbFooter>> getAvbFooter(const ApexFile& apex,
                                                 const unique_fd& fd) {
   std::array<uint8_t, AVB_FOOTER_SIZE> footer_data;
   auto footer = std::make_unique<AvbFooter>();
 
   // The AVB footer is located in the last part of the image
-  if (!apex.GetImageOffset() || !apex.GetImageSize()) {
-    return Error() << "Cannot check avb footer without image offset and size";
-  }
-  off_t offset = apex.GetImageSize().value() + apex.GetImageOffset().value() -
-                 AVB_FOOTER_SIZE;
+  off_t offset = apex.GetImageSize() + apex.GetImageOffset() - AVB_FOOTER_SIZE;
   int ret = lseek(fd, offset, SEEK_SET);
   if (ret == -1) {
     return ErrnoError() << "Couldn't seek to AVB footer";
@@ -242,10 +179,8 @@
          memcmp(&public_key_content[0], key, length) == 0;
 }
 
-// Verifies correctness of vbmeta and returns public key it was signed with.
-Result<std::span<const uint8_t>> VerifyVbMetaSignature(const ApexFile& apex,
-                                                       const uint8_t* data,
-                                                       size_t length) {
+Result<void> verifyVbMetaSignature(const ApexFile& apex, const uint8_t* data,
+                                   size_t length) {
   const uint8_t* pk;
   size_t pk_len;
   AvbVBMetaVerifyResult res;
@@ -266,46 +201,49 @@
       return Error() << "Error verifying " << apex.GetPath() << ": "
                      << "unsupported version";
     default:
-      return Error() << "Unknown vmbeta_image_verify return value : " << res;
+      return Errorf("Unknown vmbeta_image_verify return value");
   }
 
-  return std::span<const uint8_t>(pk, pk_len);
+  Result<const std::string> public_key = getApexKey(apex.GetManifest().name());
+  if (public_key.ok()) {
+    // TODO(b/115718846)
+    // We need to decide whether we need rollback protection, and whether
+    // we can use the rollback protection provided by libavb.
+    if (!CompareKeys(pk, pk_len, *public_key)) {
+      return Error() << "Error verifying " << apex.GetPath() << ": "
+                     << "public key doesn't match the pre-installed one";
+    }
+  } else {
+    return public_key.error();
+  }
+  LOG(VERBOSE) << apex.GetPath() << ": public key matches.";
+  return {};
 }
 
-Result<std::unique_ptr<uint8_t[]>> VerifyVbMeta(const ApexFile& apex,
+Result<std::unique_ptr<uint8_t[]>> verifyVbMeta(const ApexFile& apex,
                                                 const unique_fd& fd,
-                                                const AvbFooter& footer,
-                                                const std::string& public_key) {
+                                                const AvbFooter& footer) {
   if (footer.vbmeta_size > kVbMetaMaxSize) {
     return Errorf("VbMeta size in footer exceeds kVbMetaMaxSize.");
   }
 
-  if (!apex.GetImageOffset()) {
-    return Error() << "Cannot check VbMeta size without image offset";
-  }
-
-  off_t offset = apex.GetImageOffset().value() + footer.vbmeta_offset;
+  off_t offset = apex.GetImageOffset() + footer.vbmeta_offset;
   std::unique_ptr<uint8_t[]> vbmeta_buf(new uint8_t[footer.vbmeta_size]);
 
   if (!ReadFullyAtOffset(fd, vbmeta_buf.get(), footer.vbmeta_size, offset)) {
     return ErrnoError() << "Couldn't read AVB meta-data";
   }
 
-  Result<std::span<const uint8_t>> st =
-      VerifyVbMetaSignature(apex, vbmeta_buf.get(), footer.vbmeta_size);
+  Result<void> st =
+      verifyVbMetaSignature(apex, vbmeta_buf.get(), footer.vbmeta_size);
   if (!st.ok()) {
     return st.error();
   }
 
-  if (!CompareKeys(st->data(), st->size(), public_key)) {
-    return Error() << "Error verifying " << apex.GetPath() << " : "
-                   << "public key doesn't match the pre-installed one";
-  }
-
   return vbmeta_buf;
 }
 
-Result<const AvbHashtreeDescriptor*> FindDescriptor(uint8_t* vbmeta_data,
+Result<const AvbHashtreeDescriptor*> findDescriptor(uint8_t* vbmeta_data,
                                                     size_t vbmeta_size) {
   const AvbDescriptor** descriptors;
   size_t num_descriptors;
@@ -339,128 +277,119 @@
   return Errorf("Couldn't find any AVB hashtree descriptors.");
 }
 
-Result<std::unique_ptr<AvbHashtreeDescriptor>> VerifyDescriptor(
+Result<std::unique_ptr<AvbHashtreeDescriptor>> verifyDescriptor(
     const AvbHashtreeDescriptor* desc) {
-  auto verified_desc = std::make_unique<AvbHashtreeDescriptor>();
+  auto verifiedDesc = std::make_unique<AvbHashtreeDescriptor>();
 
   if (!avb_hashtree_descriptor_validate_and_byteswap(desc,
-                                                     verified_desc.get())) {
+                                                     verifiedDesc.get())) {
     return Errorf("Couldn't validate AvbDescriptor.");
   }
 
-  return verified_desc;
+  return verifiedDesc;
 }
 
 }  // namespace
 
-Result<ApexVerityData> ApexFile::VerifyApexVerity(
-    const std::string& public_key) const {
-  if (IsCompressed()) {
-    return Error() << "Cannot verify ApexVerity of compressed APEX";
-  }
-
-  ApexVerityData verity_data;
+Result<ApexVerityData> ApexFile::VerifyApexVerity() const {
+  ApexVerityData verityData;
 
   unique_fd fd(open(GetPath().c_str(), O_RDONLY | O_CLOEXEC));
   if (fd.get() == -1) {
     return ErrnoError() << "Failed to open " << GetPath();
   }
 
-  Result<std::unique_ptr<AvbFooter>> footer = GetAvbFooter(*this, fd);
+  Result<std::unique_ptr<AvbFooter>> footer = getAvbFooter(*this, fd);
   if (!footer.ok()) {
     return footer.error();
   }
 
   Result<std::unique_ptr<uint8_t[]>> vbmeta_data =
-      VerifyVbMeta(*this, fd, **footer, public_key);
+      verifyVbMeta(*this, fd, **footer);
   if (!vbmeta_data.ok()) {
     return vbmeta_data.error();
   }
 
   Result<const AvbHashtreeDescriptor*> descriptor =
-      FindDescriptor(vbmeta_data->get(), (*footer)->vbmeta_size);
+      findDescriptor(vbmeta_data->get(), (*footer)->vbmeta_size);
   if (!descriptor.ok()) {
     return descriptor.error();
   }
 
-  Result<std::unique_ptr<AvbHashtreeDescriptor>> verified_descriptor =
-      VerifyDescriptor(*descriptor);
-  if (!verified_descriptor.ok()) {
-    return verified_descriptor.error();
+  Result<std::unique_ptr<AvbHashtreeDescriptor>> verifiedDescriptor =
+      verifyDescriptor(*descriptor);
+  if (!verifiedDescriptor.ok()) {
+    return verifiedDescriptor.error();
   }
-  verity_data.desc = std::move(*verified_descriptor);
+  verityData.desc = std::move(*verifiedDescriptor);
 
   // This area is now safe to access, because we just verified it
-  const uint8_t* trailing_data =
+  const uint8_t* trailingData =
       (const uint8_t*)*descriptor + sizeof(AvbHashtreeDescriptor);
-  verity_data.hash_algorithm =
+  verityData.hash_algorithm =
       reinterpret_cast<const char*>((*descriptor)->hash_algorithm);
-  verity_data.salt = GetSalt(*verity_data.desc, trailing_data);
-  verity_data.root_digest = GetDigest(*verity_data.desc, trailing_data);
+  verityData.salt = getSalt(*verityData.desc, trailingData);
+  verityData.root_digest = getDigest(*verityData.desc, trailingData);
 
-  return verity_data;
+  return verityData;
 }
 
-Result<void> ApexFile::Decompress(const std::string& dest_path) const {
-  const std::string& src_path = GetPath();
-
-  LOG(INFO) << "Decompressing" << src_path << " to " << dest_path;
-
-  // We should decompress compressed APEX files only
-  if (!IsCompressed()) {
-    return ErrnoError() << "Cannot decompress an uncompressed APEX";
+Result<void> ApexFile::VerifyManifestMatches(
+    const std::string& mount_path) const {
+  Result<ApexManifest> verifiedManifest =
+      ReadManifest(mount_path + "/" + kManifestFilenamePb);
+  if (!verifiedManifest.ok()) {
+    return verifiedManifest.error();
   }
 
-  // Get file descriptor of the compressed apex file
-  unique_fd src_fd(open(src_path.c_str(), O_RDONLY | O_CLOEXEC));
-  if (src_fd.get() == -1) {
-    return ErrnoError() << "Failed to open compressed APEX " << GetPath();
+  if (!MessageDifferencer::Equals(manifest_, *verifiedManifest)) {
+    return Errorf(
+        "Manifest inside filesystem does not match manifest outside it");
   }
 
-  // Open it as a zip file
-  ZipArchiveHandle handle;
-  int ret = OpenArchiveFd(src_fd.get(), src_path.c_str(), &handle, false);
-  if (ret < 0) {
-    return Error() << "Failed to open package " << src_path << ": "
-                   << ErrorCodeString(ret);
-  }
-  auto handle_guard =
-      android::base::make_scope_guard([&handle] { CloseArchive(handle); });
-
-  // Find the original apex file inside the zip and extract to dest
-  ZipEntry entry;
-  ret = FindEntry(handle, kCompressedApexFilename, &entry);
-  if (ret < 0) {
-    return Error() << "Could not find entry \"" << kCompressedApexFilename
-                   << "\" in package " << src_path << ": "
-                   << ErrorCodeString(ret);
-  }
-
-  // Open destination file descriptor
-  unique_fd dest_fd(
-      open(dest_path.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT | O_EXCL, 0644));
-  if (dest_fd.get() == -1) {
-    return ErrnoError() << "Failed to open decompression destination "
-                        << dest_path.c_str();
-  }
-
-  // Prepare a guard that deletes the extracted file if anything goes wrong
-  auto decompressed_guard = android::base::make_scope_guard(
-      [&dest_path] { RemoveFileIfExists(dest_path); });
-
-  // Extract the original_apex to dest_path
-  ret = ExtractEntryToFile(handle, &entry, dest_fd.get());
-  if (ret < 0) {
-    return Error() << "Could not decompress to file " << dest_path << " "
-                   << ErrorCodeString(ret);
-  }
-
-  // Verification complete. Accept the decompressed file
-  decompressed_guard.Disable();
-  LOG(VERBOSE) << "Decompressed " << src_path << " to " << dest_path;
-
   return {};
 }
 
+Result<std::vector<std::string>> FindApexes(
+    const std::vector<std::string>& paths) {
+  std::vector<std::string> result;
+  for (const auto& path : paths) {
+    auto exist = PathExists(path);
+    if (!exist.ok()) {
+      return exist.error();
+    }
+    if (!*exist) continue;
+
+    const auto& apexes = FindApexFilesByName(path);
+    if (!apexes.ok()) {
+      return apexes;
+    }
+
+    result.insert(result.end(), apexes->begin(), apexes->end());
+  }
+  return result;
+}
+
+Result<std::vector<std::string>> FindApexFilesByName(const std::string& path) {
+  auto filter_fn = [](const std::filesystem::directory_entry& entry) {
+    std::error_code ec;
+    if (entry.is_regular_file(ec) &&
+        EndsWith(entry.path().filename().string(), kApexPackageSuffix)) {
+      return true;  // APEX file, take.
+    }
+    return false;
+  };
+  return ReadDir(path, filter_fn);
+}
+
+bool isPathForBuiltinApexes(const std::string& path) {
+  for (const auto& dir : kApexPackageBuiltinDirs) {
+    if (StartsWith(path, dir)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apex_file.h b/apexd/apex_file.h
index 60d5feb..0476911 100644
--- a/apexd/apex_file.h
+++ b/apexd/apex_file.h
@@ -23,7 +23,9 @@
 
 #include <android-base/result.h>
 #include <libavb/libavb.h>
+#include <ziparchive/zip_archive.h>
 
+#include "apex_constants.h"
 #include "apex_manifest.h"
 
 namespace android {
@@ -44,42 +46,43 @@
   static android::base::Result<ApexFile> Open(const std::string& path);
   ApexFile() = delete;
   ApexFile(ApexFile&&) = default;
-  ApexFile& operator=(ApexFile&&) = default;
 
   const std::string& GetPath() const { return apex_path_; }
-  const std::optional<int32_t>& GetImageOffset() const { return image_offset_; }
-  const std::optional<size_t>& GetImageSize() const { return image_size_; }
-  const ::apex::proto::ApexManifest& GetManifest() const { return manifest_; }
+  int32_t GetImageOffset() const { return image_offset_; }
+  size_t GetImageSize() const { return image_size_; }
+  const ApexManifest& GetManifest() const { return manifest_; }
   const std::string& GetBundledPublicKey() const { return apex_pubkey_; }
-  const std::optional<std::string>& GetFsType() const { return fs_type_; }
-  android::base::Result<ApexVerityData> VerifyApexVerity(
-      const std::string& public_key) const;
-  bool IsCompressed() const { return is_compressed_; }
-  android::base::Result<void> Decompress(const std::string& output_path) const;
+  bool IsBuiltin() const { return is_builtin_; }
+  android::base::Result<ApexVerityData> VerifyApexVerity() const;
+  android::base::Result<void> VerifyManifestMatches(
+      const std::string& mount_path) const;
 
  private:
-  ApexFile(const std::string& apex_path,
-           const std::optional<int32_t>& image_offset,
-           const std::optional<size_t>& image_size,
-           ::apex::proto::ApexManifest manifest, const std::string& apex_pubkey,
-           const std::optional<std::string>& fs_type, bool is_compressed)
+  ApexFile(const std::string& apex_path, int32_t image_offset,
+           size_t image_size, ApexManifest manifest,
+           const std::string& apex_pubkey, bool is_builtin)
       : apex_path_(apex_path),
         image_offset_(image_offset),
         image_size_(image_size),
         manifest_(std::move(manifest)),
         apex_pubkey_(apex_pubkey),
-        fs_type_(fs_type),
-        is_compressed_(is_compressed) {}
+        is_builtin_(is_builtin) {}
 
   std::string apex_path_;
-  std::optional<int32_t> image_offset_;
-  std::optional<size_t> image_size_;
-  ::apex::proto::ApexManifest manifest_;
+  int32_t image_offset_;
+  size_t image_size_;
+  ApexManifest manifest_;
   std::string apex_pubkey_;
-  std::optional<std::string> fs_type_;
-  bool is_compressed_;
+  bool is_builtin_;
 };
 
+android::base::Result<std::vector<std::string>> FindApexes(
+    const std::vector<std::string>& paths);
+android::base::Result<std::vector<std::string>> FindApexFilesByName(
+    const std::string& path);
+
+bool isPathForBuiltinApexes(const std::string& path);
+
 }  // namespace apex
 }  // namespace android
 
diff --git a/apexd/apex_file_repository.cpp b/apexd/apex_file_repository.cpp
deleted file mode 100644
index c50d136..0000000
--- a/apexd/apex_file_repository.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#define LOG_TAG "apexd"
-
-#include "apex_file_repository.h"
-
-#include <unordered_map>
-
-#include <android-base/file.h>
-#include <android-base/properties.h>
-#include <android-base/result.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
-#include "apex_constants.h"
-#include "apex_file.h"
-#include "apexd_utils.h"
-
-using android::base::EndsWith;
-using android::base::Error;
-using android::base::GetProperty;
-using android::base::Result;
-
-namespace android {
-namespace apex {
-
-Result<void> ApexFileRepository::ScanBuiltInDir(const std::string& dir) {
-  LOG(INFO) << "Scanning " << dir << " for pre-installed ApexFiles";
-  if (access(dir.c_str(), F_OK) != 0 && errno == ENOENT) {
-    LOG(WARNING) << dir << " does not exist. Skipping";
-    return {};
-  }
-
-  Result<std::vector<std::string>> all_apex_files = FindFilesBySuffix(
-      dir, {kApexPackageSuffix, kCompressedApexPackageSuffix});
-  if (!all_apex_files.ok()) {
-    return all_apex_files.error();
-  }
-
-  // TODO(b/179248390): scan parallelly if possible
-  for (const auto& file : *all_apex_files) {
-    LOG(INFO) << "Found pre-installed APEX " << file;
-    Result<ApexFile> apex_file = ApexFile::Open(file);
-    if (!apex_file.ok()) {
-      return Error() << "Failed to open " << file << " : " << apex_file.error();
-    }
-
-    const std::string& name = apex_file->GetManifest().name();
-    auto it = pre_installed_store_.find(name);
-    if (it == pre_installed_store_.end()) {
-      pre_installed_store_.emplace(name, std::move(*apex_file));
-    } else if (it->second.GetPath() != apex_file->GetPath()) {
-      auto level = base::FATAL;
-      // On some development (non-REL) builds the VNDK apex could be in /vendor.
-      // When testing CTS-on-GSI on these builds, there would be two VNDK apexes
-      // in the system, one in /system and one in /vendor.
-      static constexpr char kVndkApexModuleNamePrefix[] = "com.android.vndk.";
-      static constexpr char kPlatformVersionCodenameProperty[] =
-          "ro.build.version.codename";
-      if (android::base::StartsWith(name, kVndkApexModuleNamePrefix) &&
-          GetProperty(kPlatformVersionCodenameProperty, "REL") != "REL") {
-        level = android::base::INFO;
-      }
-      LOG(level) << "Found two apex packages " << it->second.GetPath()
-                 << " and " << apex_file->GetPath()
-                 << " with the same module name " << name;
-    } else if (it->second.GetBundledPublicKey() !=
-               apex_file->GetBundledPublicKey()) {
-      LOG(FATAL) << "Public key of apex package " << it->second.GetPath()
-                 << " (" << name << ") has unexpectedly changed";
-    }
-  }
-  return {};
-}
-
-ApexFileRepository& ApexFileRepository::GetInstance() {
-  static ApexFileRepository instance;
-  return instance;
-}
-
-android::base::Result<void> ApexFileRepository::AddPreInstalledApex(
-    const std::vector<std::string>& prebuilt_dirs) {
-  for (const auto& dir : prebuilt_dirs) {
-    if (auto result = ScanBuiltInDir(dir); !result.ok()) {
-      return result.error();
-    }
-  }
-  return {};
-}
-
-// TODO(b/179497746): AddDataApex should not concern with filtering out invalid
-//   apex.
-Result<void> ApexFileRepository::AddDataApex(const std::string& data_dir) {
-  LOG(INFO) << "Scanning " << data_dir << " for data ApexFiles";
-  if (access(data_dir.c_str(), F_OK) != 0 && errno == ENOENT) {
-    LOG(WARNING) << data_dir << " does not exist. Skipping";
-    return {};
-  }
-
-  Result<std::vector<std::string>> active_apex =
-      FindFilesBySuffix(data_dir, {kApexPackageSuffix});
-  if (!active_apex.ok()) {
-    return active_apex.error();
-  }
-
-  // TODO(b/179248390): scan parallelly if possible
-  for (const auto& file : *active_apex) {
-    LOG(INFO) << "Found updated apex " << file;
-    Result<ApexFile> apex_file = ApexFile::Open(file);
-    if (!apex_file.ok()) {
-      LOG(ERROR) << "Failed to open " << file << " : " << apex_file.error();
-      continue;
-    }
-
-    const std::string& name = apex_file->GetManifest().name();
-    if (!HasPreInstalledVersion(name)) {
-      LOG(ERROR) << "Skipping " << file << " : no preisntalled apex";
-      // Ignore data apex without corresponding pre-installed apex
-      continue;
-    }
-    auto pre_installed_public_key = GetPublicKey(name);
-    if (!pre_installed_public_key.ok() ||
-        apex_file->GetBundledPublicKey() != *pre_installed_public_key) {
-      // Ignore data apex if public key doesn't match with pre-installed apex
-      LOG(ERROR) << "Skipping " << file
-                 << " : public key doesn't match pre-installed one";
-      continue;
-    }
-
-    if (EndsWith(apex_file->GetPath(), kDecompressedApexPackageSuffix)) {
-      LOG(WARNING) << "Skipping " << file
-                   << " : Non-decompressed APEX should not have "
-                   << kDecompressedApexPackageSuffix << " suffix";
-      continue;
-    }
-
-    auto it = data_store_.find(name);
-    if (it == data_store_.end()) {
-      data_store_.emplace(name, std::move(*apex_file));
-      continue;
-    }
-
-    const auto& existing_version = it->second.GetManifest().version();
-    const auto new_version = apex_file->GetManifest().version();
-    // If multiple data apexs are preset, select the one with highest version
-    bool prioritize_higher_version = new_version > existing_version;
-    // For same version, non-decompressed apex gets priority
-    if (prioritize_higher_version) {
-      it->second = std::move(*apex_file);
-    }
-  }
-  return {};
-}
-
-// TODO(b/179497746): remove this method when we add api for fetching ApexFile
-//  by name
-Result<const std::string> ApexFileRepository::GetPublicKey(
-    const std::string& name) const {
-  auto it = pre_installed_store_.find(name);
-  if (it == pre_installed_store_.end()) {
-    return Error() << "No preinstalled apex found for package " << name;
-  }
-  return it->second.GetBundledPublicKey();
-}
-
-// TODO(b/179497746): remove this method when we add api for fetching ApexFile
-//  by name
-Result<const std::string> ApexFileRepository::GetPreinstalledPath(
-    const std::string& name) const {
-  auto it = pre_installed_store_.find(name);
-  if (it == pre_installed_store_.end()) {
-    return Error() << "No preinstalled data found for package " << name;
-  }
-  return it->second.GetPath();
-}
-
-// TODO(b/179497746): remove this method when we add api for fetching ApexFile
-//  by name
-Result<const std::string> ApexFileRepository::GetDataPath(
-    const std::string& name) const {
-  auto it = data_store_.find(name);
-  if (it == data_store_.end()) {
-    return Error() << "No data apex found for package " << name;
-  }
-  return it->second.GetPath();
-}
-
-bool ApexFileRepository::HasPreInstalledVersion(const std::string& name) const {
-  return pre_installed_store_.find(name) != pre_installed_store_.end();
-}
-
-bool ApexFileRepository::HasDataVersion(const std::string& name) const {
-  return data_store_.find(name) != data_store_.end();
-}
-
-// ApexFile is considered a decompressed APEX if it is located in decompression
-// dir
-bool ApexFileRepository::IsDecompressedApex(const ApexFile& apex) const {
-  return apex.GetPath().starts_with(decompression_dir_);
-}
-
-bool ApexFileRepository::IsPreInstalledApex(const ApexFile& apex) const {
-  auto it = pre_installed_store_.find(apex.GetManifest().name());
-  if (it == pre_installed_store_.end()) {
-    return false;
-  }
-  return it->second.GetPath() == apex.GetPath() || IsDecompressedApex(apex);
-}
-
-std::vector<ApexFileRef> ApexFileRepository::GetPreInstalledApexFiles() const {
-  std::vector<ApexFileRef> result;
-  for (const auto& it : pre_installed_store_) {
-    result.emplace_back(std::cref(it.second));
-  }
-  return std::move(result);
-}
-
-std::vector<ApexFileRef> ApexFileRepository::GetDataApexFiles() const {
-  std::vector<ApexFileRef> result;
-  for (const auto& it : data_store_) {
-    result.emplace_back(std::cref(it.second));
-  }
-  return std::move(result);
-}
-
-// Group pre-installed APEX and data APEX by name
-std::unordered_map<std::string, std::vector<ApexFileRef>>
-ApexFileRepository::AllApexFilesByName() const {
-  // Collect all apex files
-  std::vector<ApexFileRef> all_apex_files;
-  auto pre_installed_apexs = GetPreInstalledApexFiles();
-  auto data_apexs = GetDataApexFiles();
-  std::move(pre_installed_apexs.begin(), pre_installed_apexs.end(),
-            std::back_inserter(all_apex_files));
-  std::move(data_apexs.begin(), data_apexs.end(),
-            std::back_inserter(all_apex_files));
-
-  // Group them by name
-  std::unordered_map<std::string, std::vector<ApexFileRef>> result;
-  for (const auto& apex_file_ref : all_apex_files) {
-    const ApexFile& apex_file = apex_file_ref.get();
-    const std::string& package_name = apex_file.GetManifest().name();
-    if (result.find(package_name) == result.end()) {
-      result[package_name] = std::vector<ApexFileRef>{};
-    }
-    result[package_name].emplace_back(apex_file_ref);
-  }
-
-  return std::move(result);
-}
-
-ApexFileRef ApexFileRepository::GetDataApex(const std::string& name) const {
-  auto it = data_store_.find(name);
-  CHECK(it != data_store_.end());
-  return std::cref(it->second);
-}
-
-ApexFileRef ApexFileRepository::GetPreInstalledApex(
-    const std::string& name) const {
-  auto it = pre_installed_store_.find(name);
-  CHECK(it != pre_installed_store_.end());
-  return std::cref(it->second);
-}
-
-}  // namespace apex
-}  // namespace android
diff --git a/apexd/apex_file_repository.h b/apexd/apex_file_repository.h
deleted file mode 100644
index e9ccf7e..0000000
--- a/apexd/apex_file_repository.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#pragma once
-
-#include <functional>
-#include <string>
-#include <unordered_map>
-#include <vector>
-#include "apex_constants.h"
-#include "apex_file.h"
-
-#include <android-base/result.h>
-
-namespace android {
-namespace apex {
-
-using ApexFileRef = std::reference_wrapper<const android::apex::ApexFile>;
-
-// This class serves as a ApexFile repository for all apexes on device. It also
-// provides information about the ApexFiles it hosts, such as which are
-// pre-installed and which are data. Such information can be used, for example,
-// to verify validity of an apex before trying to mount it.
-//
-// It's expected to have a single instance of this class in a process that
-// mounts apexes (e.g. apexd, otapreopt_chroot).
-class ApexFileRepository final {
- public:
-  // c-tor and d-tor are exposed for testing.
-  explicit ApexFileRepository(
-      const std::string& decompression_dir = kApexDecompressedDir)
-      : decompression_dir_(decompression_dir){};
-
-  ~ApexFileRepository() {
-    pre_installed_store_.clear();
-    data_store_.clear();
-  };
-
-  // Returns a singletone instance of this class.
-  static ApexFileRepository& GetInstance();
-
-  // Populate instance by collecting pre-installed apex files from the given
-  // |prebuilt_dirs|.
-  // Note: this call is **not thread safe** and is expected to be performed in a
-  // single thread during initialization of apexd. After initialization is
-  // finished, all queries to the instance are thread safe.
-  android::base::Result<void> AddPreInstalledApex(
-      const std::vector<std::string>& prebuilt_dirs);
-
-  // Populate instance by collecting data apex files from the given |data_dir|.
-  // Note: this call is **not thread safe** and is expected to be performed in a
-  // single thread during initialization of apexd. After initialization is
-  // finished, all queries to the instance are thread safe.
-  android::base::Result<void> AddDataApex(const std::string& data_dir);
-
-  // Returns trusted public key for an apex with the given |name|.
-  android::base::Result<const std::string> GetPublicKey(
-      const std::string& name) const;
-
-  // Returns path to the pre-installed version of an apex with the given |name|.
-  android::base::Result<const std::string> GetPreinstalledPath(
-      const std::string& name) const;
-
-  // Returns path to the data version of an apex with the given |name|.
-  android::base::Result<const std::string> GetDataPath(
-      const std::string& name) const;
-
-  // Checks whether there is a pre-installed version of an apex with the given
-  // |name|.
-  bool HasPreInstalledVersion(const std::string& name) const;
-
-  // Checks whether there is a data version of an apex with the given |name|.
-  bool HasDataVersion(const std::string& name) const;
-
-  // Checks if given |apex| is pre-installed.
-  bool IsPreInstalledApex(const ApexFile& apex) const;
-
-  // Checks if given |apex| is decompressed from a pre-installed APEX
-  bool IsDecompressedApex(const ApexFile& apex) const;
-
-  // Returns reference to all pre-installed APEX on device
-  std::vector<ApexFileRef> GetPreInstalledApexFiles() const;
-
-  // Returns reference to all data APEX on device
-  std::vector<ApexFileRef> GetDataApexFiles() const;
-
-  // Group all ApexFiles on device by their package name
-  std::unordered_map<std::string, std::vector<ApexFileRef>> AllApexFilesByName()
-      const;
-
-  // Returns a pre-installed version of apex with the given name. Caller is
-  // expected to check if there is a pre-installed apex with the given name
-  // using |HasPreinstalledVersion| function.
-  ApexFileRef GetPreInstalledApex(const std::string& name) const;
-  // Returns a data version of apex with the given name. Caller is
-  // expected to check if there is a data apex with the given name
-  // using |HasDataVersion| function.
-  ApexFileRef GetDataApex(const std::string& name) const;
-
-  // Clears ApexFileRepostiry.
-  // Only use in tests.
-  void Reset(const std::string& decompression_dir = kApexDecompressedDir) {
-    pre_installed_store_.clear();
-    data_store_.clear();
-    decompression_dir_ = decompression_dir;
-  }
-
- private:
-  // Non-copyable && non-moveable.
-  ApexFileRepository(const ApexFileRepository&) = delete;
-  ApexFileRepository& operator=(const ApexFileRepository&) = delete;
-  ApexFileRepository& operator=(ApexFileRepository&&) = delete;
-  ApexFileRepository(ApexFileRepository&&) = delete;
-
-  // Scans apexes in the given directory and adds collected data into
-  // |pre_installed_store_|.
-  android::base::Result<void> ScanBuiltInDir(const std::string& dir);
-
-  std::unordered_map<std::string, ApexFile> pre_installed_store_, data_store_;
-  // Decompression directory which will be used to determine if apex is
-  // decompressed or not
-  std::string decompression_dir_;
-};
-
-}  // namespace apex
-}  // namespace android
diff --git a/apexd/apex_file_repository_test.cpp b/apexd/apex_file_repository_test.cpp
deleted file mode 100644
index c1f5d53..0000000
--- a/apexd/apex_file_repository_test.cpp
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#include <filesystem>
-#include <string>
-
-#include <errno.h>
-#include <sys/stat.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "apex_file.h"
-#include "apex_file_repository.h"
-#include "apexd_test_utils.h"
-#include "apexd_verity.h"
-
-namespace android {
-namespace apex {
-
-using namespace std::literals;
-
-namespace fs = std::filesystem;
-
-using android::apex::testing::ApexFileEq;
-using android::apex::testing::IsOk;
-using android::base::GetExecutableDirectory;
-using android::base::StringPrintf;
-using ::testing::ByRef;
-using ::testing::UnorderedElementsAre;
-
-static std::string GetTestDataDir() { return GetExecutableDirectory(); }
-static std::string GetTestFile(const std::string& name) {
-  return GetTestDataDir() + "/" + name;
-}
-
-namespace {
-// Copies the compressed apex to |built_in_dir| and decompresses it to
-// |decompression_dir
-void PrepareCompressedApex(const std::string& name,
-                           const std::string& built_in_dir,
-                           const std::string& decompression_dir) {
-  fs::copy(GetTestFile(name), built_in_dir);
-  auto compressed_apex =
-      ApexFile::Open(StringPrintf("%s/%s", built_in_dir.c_str(), name.c_str()));
-
-  const auto& pkg_name = compressed_apex->GetManifest().name();
-  const int version = compressed_apex->GetManifest().version();
-
-  auto decompression_path =
-      StringPrintf("%s/%s@%d%s", decompression_dir.c_str(), pkg_name.c_str(),
-                   version, kDecompressedApexPackageSuffix);
-  compressed_apex->Decompress(decompression_path);
-}
-}  // namespace
-
-TEST(ApexFileRepositoryTest, InitializeSuccess) {
-  // Prepare test data.
-  TemporaryDir built_in_dir, data_dir, decompression_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("apex.apexd_test_different_app.apex"),
-           built_in_dir.path);
-
-  fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
-  fs::copy(GetTestFile("apex.apexd_test_different_app.apex"), data_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  // Now test that apexes were scanned correctly;
-  auto test_fn = [&](const std::string& apex_name) {
-    auto apex = ApexFile::Open(GetTestFile(apex_name));
-    ASSERT_TRUE(IsOk(apex));
-
-    {
-      auto ret = instance.GetPublicKey(apex->GetManifest().name());
-      ASSERT_TRUE(IsOk(ret));
-      ASSERT_EQ(apex->GetBundledPublicKey(), *ret);
-    }
-
-    {
-      auto ret = instance.GetPreinstalledPath(apex->GetManifest().name());
-      ASSERT_TRUE(IsOk(ret));
-      ASSERT_EQ(StringPrintf("%s/%s", built_in_dir.path, apex_name.c_str()),
-                *ret);
-    }
-
-    {
-      auto ret = instance.GetDataPath(apex->GetManifest().name());
-      ASSERT_TRUE(IsOk(ret));
-      ASSERT_EQ(StringPrintf("%s/%s", data_dir.path, apex_name.c_str()), *ret);
-    }
-
-    ASSERT_TRUE(instance.HasPreInstalledVersion(apex->GetManifest().name()));
-    ASSERT_TRUE(instance.HasDataVersion(apex->GetManifest().name()));
-  };
-
-  test_fn("apex.apexd_test.apex");
-  test_fn("apex.apexd_test_different_app.apex");
-
-  // Check that second call will succeed as well.
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  test_fn("apex.apexd_test.apex");
-  test_fn("apex.apexd_test_different_app.apex");
-}
-
-TEST(ApexFileRepositoryTest, InitializeFailureCorruptApex) {
-  // Prepare test data.
-  TemporaryDir td;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
-  fs::copy(GetTestFile("apex.apexd_test_corrupt_superblock_apex.apex"),
-           td.path);
-
-  ApexFileRepository instance;
-  ASSERT_FALSE(IsOk(instance.AddPreInstalledApex({td.path})));
-}
-
-TEST(ApexFileRepositoryTest, InitializeCompressedApexWithoutApex) {
-  // Prepare test data.
-  TemporaryDir td;
-  fs::copy(GetTestFile("com.android.apex.compressed.v1_without_apex.capex"),
-           td.path);
-
-  ApexFileRepository instance;
-  // Compressed APEX without APEX cannot be opened
-  ASSERT_FALSE(IsOk(instance.AddPreInstalledApex({td.path})));
-}
-
-TEST(ApexFileRepositoryTest, InitializeSameNameDifferentPathAborts) {
-  // Prepare test data.
-  TemporaryDir td;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
-  fs::copy(GetTestFile("apex.apexd_test.apex"),
-           StringPrintf("%s/other.apex", td.path));
-
-  ASSERT_DEATH(
-      {
-        ApexFileRepository instance;
-        instance.AddPreInstalledApex({td.path});
-      },
-      "");
-}
-
-TEST(ApexFileRepositoryTest,
-     InitializeSameNameDifferentPathAbortsCompressedApex) {
-  // Prepare test data.
-  TemporaryDir td;
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
-           StringPrintf("%s/other.capex", td.path));
-
-  ASSERT_DEATH(
-      {
-        ApexFileRepository instance;
-        instance.AddPreInstalledApex({td.path});
-      },
-      "");
-}
-
-TEST(ApexFileRepositoryTest, InitializePublicKeyUnexpectdlyChangedAborts) {
-  // Prepare test data.
-  TemporaryDir td;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
-
-  // Check that apex was loaded.
-  auto path = instance.GetPreinstalledPath("com.android.apex.test_package");
-  ASSERT_TRUE(IsOk(path));
-  ASSERT_EQ(StringPrintf("%s/apex.apexd_test.apex", td.path), *path);
-
-  auto public_key = instance.GetPublicKey("com.android.apex.test_package");
-  ASSERT_TRUE(IsOk(public_key));
-
-  // Substitute it with another apex with the same name, but different public
-  // key.
-  fs::copy(GetTestFile("apex.apexd_test_different_key.apex"), *path,
-           fs::copy_options::overwrite_existing);
-
-  {
-    auto apex = ApexFile::Open(*path);
-    ASSERT_TRUE(IsOk(apex));
-    // Check module name hasn't changed.
-    ASSERT_EQ("com.android.apex.test_package", apex->GetManifest().name());
-    // Check public key has changed.
-    ASSERT_NE(*public_key, apex->GetBundledPublicKey());
-  }
-
-  ASSERT_DEATH({ instance.AddPreInstalledApex({td.path}); }, "");
-}
-
-TEST(ApexFileRepositoryTest,
-     InitializePublicKeyUnexpectdlyChangedAbortsCompressedApex) {
-  // Prepare test data.
-  TemporaryDir td;
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
-
-  // Check that apex was loaded.
-  auto path = instance.GetPreinstalledPath("com.android.apex.compressed");
-  ASSERT_TRUE(IsOk(path));
-  ASSERT_EQ(StringPrintf("%s/com.android.apex.compressed.v1.capex", td.path),
-            *path);
-
-  auto public_key = instance.GetPublicKey("com.android.apex.compressed");
-  ASSERT_TRUE(IsOk(public_key));
-
-  // Substitute it with another apex with the same name, but different public
-  // key.
-  fs::copy(GetTestFile("com.android.apex.compressed_different_key.capex"),
-           *path, fs::copy_options::overwrite_existing);
-
-  {
-    auto apex = ApexFile::Open(*path);
-    ASSERT_TRUE(IsOk(apex));
-    // Check module name hasn't changed.
-    ASSERT_EQ("com.android.apex.compressed", apex->GetManifest().name());
-    // Check public key has changed.
-    ASSERT_NE(*public_key, apex->GetBundledPublicKey());
-  }
-
-  ASSERT_DEATH({ instance.AddPreInstalledApex({td.path}); }, "");
-}
-
-TEST(ApexFileRepositoryTest, IsPreInstalledApex) {
-  // Prepare test data.
-  TemporaryDir td;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
-
-  auto compressed_apex = ApexFile::Open(
-      StringPrintf("%s/com.android.apex.compressed.v1.capex", td.path));
-  ASSERT_TRUE(IsOk(compressed_apex));
-  ASSERT_TRUE(instance.IsPreInstalledApex(*compressed_apex));
-
-  auto apex1 = ApexFile::Open(StringPrintf("%s/apex.apexd_test.apex", td.path));
-  ASSERT_TRUE(IsOk(apex1));
-  ASSERT_TRUE(instance.IsPreInstalledApex(*apex1));
-
-  // It's same apex, but path is different. Shouldn't be treated as
-  // pre-installed.
-  auto apex2 = ApexFile::Open(GetTestFile("apex.apexd_test.apex"));
-  ASSERT_TRUE(IsOk(apex2));
-  ASSERT_FALSE(instance.IsPreInstalledApex(*apex2));
-
-  auto apex3 =
-      ApexFile::Open(GetTestFile("apex.apexd_test_different_app.apex"));
-  ASSERT_TRUE(IsOk(apex3));
-  ASSERT_FALSE(instance.IsPreInstalledApex(*apex3));
-}
-
-TEST(ApexFileRepositoryTest, IsDecompressedApex) {
-  // Prepare instance
-  TemporaryDir decompression_dir;
-  ApexFileRepository instance(decompression_dir.path);
-
-  // Prepare decompressed apex
-  std::string filename = "com.android.apex.compressed.v1_original.apex";
-  fs::copy(GetTestFile(filename), decompression_dir.path);
-  auto decompressed_path =
-      StringPrintf("%s/%s", decompression_dir.path, filename.c_str());
-  auto decompressed_apex = ApexFile::Open(decompressed_path);
-
-  // Any file which is already located in |decompression_dir| should be
-  // considered decompressed
-  ASSERT_TRUE(instance.IsDecompressedApex(*decompressed_apex));
-
-  // Hard links with same file name is not considered decompressed
-  TemporaryDir active_dir;
-  auto active_path = StringPrintf("%s/%s", active_dir.path, filename.c_str());
-  std::error_code ec;
-  fs::create_hard_link(decompressed_path, active_path, ec);
-  ASSERT_FALSE(ec) << "Failed to create hardlink";
-  auto active_apex = ApexFile::Open(active_path);
-  ASSERT_FALSE(instance.IsDecompressedApex(*active_apex));
-}
-
-TEST(ApexFileRepositoryTest, AddAndGetDataApex) {
-  // Prepare test data.
-  TemporaryDir built_in_dir, data_dir, decompression_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex",
-                        built_in_dir.path, decompression_dir.path);
-  // Add a data apex that has kDecompressedApexPackageSuffix
-  fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
-           StringPrintf("%s/com.android.apex.compressed@1%s", data_dir.path,
-                        kDecompressedApexPackageSuffix));
-
-  ApexFileRepository instance(decompression_dir.path);
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  // ApexFileRepository should only deal with APEX in /data/apex/active.
-  // Decompressed APEX should not be included
-  auto data_apexs = instance.GetDataApexFiles();
-  auto normal_apex =
-      ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
-  ASSERT_THAT(data_apexs,
-              UnorderedElementsAre(ApexFileEq(ByRef(*normal_apex))));
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexIgnoreCompressedApex) {
-  // Prepare test data.
-  TemporaryDir data_dir, decompression_dir;
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), data_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  auto data_apexs = instance.GetDataApexFiles();
-  ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexIgnoreIfNotPreInstalled) {
-  // Prepare test data.
-  TemporaryDir data_dir, decompression_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  auto data_apexs = instance.GetDataApexFiles();
-  ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexPrioritizeHigherVersionApex) {
-  // Prepare test data.
-  TemporaryDir built_in_dir, data_dir, decompression_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
-  fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  auto data_apexs = instance.GetDataApexFiles();
-  auto normal_apex =
-      ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
-  ASSERT_THAT(data_apexs,
-              UnorderedElementsAre(ApexFileEq(ByRef(*normal_apex))));
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexDoesNotScanDecompressedApex) {
-  // Prepare test data.
-  TemporaryDir built_in_dir, data_dir, decompression_dir;
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex",
-                        built_in_dir.path, decompression_dir.path);
-
-  ApexFileRepository instance(decompression_dir.path);
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  auto data_apexs = instance.GetDataApexFiles();
-  ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, AddDataApexIgnoreWrongPublicKey) {
-  // Prepare test data.
-  TemporaryDir built_in_dir, data_dir, decompression_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("apex.apexd_test_different_key.apex"), data_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  auto data_apexs = instance.GetDataApexFiles();
-  ASSERT_EQ(data_apexs.size(), 0u);
-}
-
-TEST(ApexFileRepositoryTest, GetPreInstalledApexFiles) {
-  // Prepare test data.
-  TemporaryDir built_in_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
-           built_in_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-
-  auto pre_installed_apexs = instance.GetPreInstalledApexFiles();
-  auto pre_apex_1 = ApexFile::Open(
-      StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
-  auto pre_apex_2 = ApexFile::Open(StringPrintf(
-      "%s/com.android.apex.compressed.v1.capex", built_in_dir.path));
-  ASSERT_THAT(pre_installed_apexs,
-              UnorderedElementsAre(ApexFileEq(ByRef(*pre_apex_1)),
-                                   ApexFileEq(ByRef(*pre_apex_2))));
-}
-
-TEST(ApexFileRepositoryTest, AllApexFilesByName) {
-  TemporaryDir built_in_dir, decompression_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
-           built_in_dir.path);
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-
-  TemporaryDir data_dir;
-  fs::copy(GetTestFile("com.android.apex.cts.shim.v2.apex"), data_dir.path);
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  auto result = instance.AllApexFilesByName();
-
-  // Verify the contents of result
-  auto apexd_test_file = ApexFile::Open(
-      StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
-  auto shim_v1 = ApexFile::Open(
-      StringPrintf("%s/com.android.apex.cts.shim.apex", built_in_dir.path));
-  auto compressed_apex = ApexFile::Open(StringPrintf(
-      "%s/com.android.apex.compressed.v1.capex", built_in_dir.path));
-  auto shim_v2 = ApexFile::Open(
-      StringPrintf("%s/com.android.apex.cts.shim.v2.apex", data_dir.path));
-
-  ASSERT_EQ(result.size(), 3u);
-  ASSERT_THAT(result[apexd_test_file->GetManifest().name()],
-              UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file))));
-  ASSERT_THAT(result[shim_v1->GetManifest().name()],
-              UnorderedElementsAre(ApexFileEq(ByRef(*shim_v1)),
-                                   ApexFileEq(ByRef(*shim_v2))));
-  ASSERT_THAT(result[compressed_apex->GetManifest().name()],
-              UnorderedElementsAre(ApexFileEq(ByRef(*compressed_apex))));
-}
-
-TEST(ApexFileRepositoryTest, GetDataApex) {
-  // Prepare test data.
-  TemporaryDir built_in_dir, data_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-  fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
-
-  auto apex =
-      ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
-  ASSERT_RESULT_OK(apex);
-
-  auto ret = instance.GetDataApex("com.android.apex.test_package");
-  ASSERT_THAT(ret, ApexFileEq(ByRef(*apex)));
-}
-
-TEST(ApexFileRepositoryTest, GetDataApexNoSuchApexAborts) {
-  ASSERT_DEATH(
-      {
-        ApexFileRepository instance;
-        instance.GetDataApex("whatever");
-      },
-      "");
-}
-
-TEST(ApexFileRepositoryTest, GetPreInstalledApex) {
-  // Prepare test data.
-  TemporaryDir built_in_dir;
-  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
-
-  ApexFileRepository instance;
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
-
-  auto apex = ApexFile::Open(
-      StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
-  ASSERT_RESULT_OK(apex);
-
-  auto ret = instance.GetPreInstalledApex("com.android.apex.test_package");
-  ASSERT_THAT(ret, ApexFileEq(ByRef(*apex)));
-}
-
-TEST(ApexFileRepositoryTest, GetPreInstalledApexNoSuchApexAborts) {
-  ASSERT_DEATH(
-      {
-        ApexFileRepository instance;
-        instance.GetPreInstalledApex("whatever");
-      },
-      "");
-}
-
-}  // namespace apex
-}  // namespace android
diff --git a/apexd/apex_file_test.cpp b/apexd/apex_file_test.cpp
index 3da7448..711d024 100644
--- a/apexd/apex_file_test.cpp
+++ b/apexd/apex_file_test.cpp
@@ -19,47 +19,31 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/scopeguard.h>
-#include <android-base/strings.h>
-#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <libavb/libavb.h>
 #include <ziparchive/zip_archive.h>
 
 #include "apex_file.h"
-#include "apexd_test_utils.h"
-#include "apexd_utils.h"
+#include "apex_preinstalled_data.h"
 
-using android::base::GetExecutableDirectory;
 using android::base::Result;
 
-static const std::string kTestDataDir = GetExecutableDirectory() + "/";
+static std::string testDataDir = android::base::GetExecutableDirectory() + "/";
 
 namespace android {
 namespace apex {
 namespace {
 
-struct ApexFileTestParam {
-  const char* type;
-  const char* prefix;
-};
-
-constexpr const ApexFileTestParam kParameters[] = {
-    {"ext4", "apex.apexd_test"}, {"f2fs", "apex.apexd_test_f2fs"}};
-
-class ApexFileTest : public ::testing::TestWithParam<ApexFileTestParam> {};
-
-INSTANTIATE_TEST_SUITE_P(Apex, ApexFileTest, ::testing::ValuesIn(kParameters));
-
-TEST_P(ApexFileTest, GetOffsetOfSimplePackage) {
-  const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_TRUE(apex_file.ok());
+TEST(ApexFileTest, GetOffsetOfSimplePackage) {
+  const std::string filePath = testDataDir + "apex.apexd_test.apex";
+  Result<ApexFile> apexFile = ApexFile::Open(filePath);
+  ASSERT_TRUE(apexFile.ok());
 
   int32_t zip_image_offset;
   size_t zip_image_size;
   {
     ZipArchiveHandle handle;
-    int32_t rc = OpenArchive(file_path.c_str(), &handle);
+    int32_t rc = OpenArchive(filePath.c_str(), &handle);
     ASSERT_EQ(0, rc);
     auto close_guard =
         android::base::make_scope_guard([&handle]() { CloseArchive(handle); });
@@ -74,33 +58,34 @@
     EXPECT_EQ(zip_image_size, entry.compressed_length);
   }
 
-  EXPECT_EQ(zip_image_offset, apex_file->GetImageOffset().value());
-  EXPECT_EQ(zip_image_size, apex_file->GetImageSize().value());
+  EXPECT_EQ(zip_image_offset, apexFile->GetImageOffset());
+  EXPECT_EQ(zip_image_size, apexFile->GetImageSize());
 }
 
 TEST(ApexFileTest, GetOffsetMissingFile) {
-  const std::string file_path = kTestDataDir + "missing.apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_FALSE(apex_file.ok());
-  ASSERT_THAT(apex_file.error().message(),
-              ::testing::HasSubstr("Failed to open package"));
+  const std::string filePath = testDataDir + "missing.apex";
+  Result<ApexFile> apexFile = ApexFile::Open(filePath);
+  ASSERT_FALSE(apexFile.ok());
+  EXPECT_NE(std::string::npos,
+            apexFile.error().message().find("Failed to open package"))
+      << apexFile.error();
 }
 
-TEST_P(ApexFileTest, GetApexManifest) {
-  const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
-  EXPECT_EQ("com.android.apex.test_package", apex_file->GetManifest().name());
-  EXPECT_EQ(1u, apex_file->GetManifest().version());
+TEST(ApexFileTest, GetApexManifest) {
+  const std::string filePath = testDataDir + "apex.apexd_test.apex";
+  Result<ApexFile> apexFile = ApexFile::Open(filePath);
+  ASSERT_RESULT_OK(apexFile);
+  EXPECT_EQ("com.android.apex.test_package", apexFile->GetManifest().name());
+  EXPECT_EQ(1u, apexFile->GetManifest().version());
 }
 
-TEST_P(ApexFileTest, VerifyApexVerity) {
-  const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
+TEST(ApexFileTest, VerifyApexVerity) {
+  ASSERT_RESULT_OK(collectPreinstalledData({"/system_ext/apex"}));
+  const std::string filePath = testDataDir + "apex.apexd_test.apex";
+  Result<ApexFile> apexFile = ApexFile::Open(filePath);
+  ASSERT_RESULT_OK(apexFile);
 
-  auto verity_or =
-      apex_file->VerifyApexVerity(apex_file->GetBundledPublicKey());
+  auto verity_or = apexFile->VerifyApexVerity();
   ASSERT_RESULT_OK(verity_or);
 
   const ApexVerityData& data = *verity_or;
@@ -108,229 +93,52 @@
   EXPECT_EQ(std::string("368a22e64858647bc45498e92f749f85482ac468"
                         "50ca7ec8071f49dfa47a243c"),
             data.salt);
-
-  const std::string digest_path =
-      kTestDataDir + GetParam().prefix + "_digest.txt";
-  std::string root_digest;
-  ASSERT_TRUE(android::base::ReadFileToString(digest_path, &root_digest))
-      << "Failed to read " << digest_path;
-  root_digest = android::base::Trim(root_digest);
-
-  EXPECT_EQ(std::string(root_digest), data.root_digest);
+  EXPECT_EQ(
+      std::string(
+          "8e841019e41e8c40bca6dd6304cbf163ea257ba0a268304832c4105eba1c2747"),
+      data.root_digest);
 }
 
-TEST_P(ApexFileTest, VerifyApexVerityWrongKey) {
-  const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
+// TODO: May consider packaging a debug key in debug builds (again).
+TEST(ApexFileTest, DISABLED_VerifyApexVerityNoKeyDir) {
+  const std::string filePath = testDataDir + "apex.apexd_test.apex";
+  Result<ApexFile> apexFile = ApexFile::Open(filePath);
+  ASSERT_RESULT_OK(apexFile);
 
-  auto verity_or = apex_file->VerifyApexVerity("wrong-key");
+  auto verity_or = apexFile->VerifyApexVerity();
   ASSERT_FALSE(verity_or.ok());
 }
 
-TEST_P(ApexFileTest, GetBundledPublicKey) {
-  const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
+TEST(ApexFileTest, VerifyApexVerityNoKeyInst) {
+  const std::string filePath = testDataDir + "apex.apexd_test_no_inst_key.apex";
+  Result<ApexFile> apexFile = ApexFile::Open(filePath);
+  ASSERT_RESULT_OK(apexFile);
 
-  const std::string key_path =
-      kTestDataDir + "apexd_testdata/com.android.apex.test_package.avbpubkey";
-  std::string key_content;
-  ASSERT_TRUE(android::base::ReadFileToString(key_path, &key_content))
-      << "Failed to read " << key_path;
-
-  EXPECT_EQ(key_content, apex_file->GetBundledPublicKey());
+  auto verity_or = apexFile->VerifyApexVerity();
+  ASSERT_FALSE(verity_or.ok());
 }
 
-TEST(ApexFileTest, CorrutedApexB146895998) {
-  const std::string apex_path = kTestDataDir + "corrupted_b146895998.apex";
+TEST(ApexFileTest, GetBundledPublicKey) {
+  const std::string filePath = testDataDir + "apex.apexd_test.apex";
+  Result<ApexFile> apexFile = ApexFile::Open(filePath);
+  ASSERT_RESULT_OK(apexFile);
+
+  const std::string keyPath =
+      testDataDir + "apexd_testdata/com.android.apex.test_package.avbpubkey";
+  std::string keyContent;
+  ASSERT_TRUE(android::base::ReadFileToString(keyPath, &keyContent))
+      << "Failed to read " << keyPath;
+
+  EXPECT_EQ(keyContent, apexFile->GetBundledPublicKey());
+}
+
+TEST(ApexFileTest, CorrutedApex_b146895998) {
+  const std::string apex_path = testDataDir + "corrupted_b146895998.apex";
   Result<ApexFile> apex = ApexFile::Open(apex_path);
   ASSERT_RESULT_OK(apex);
-  ASSERT_FALSE(apex->VerifyApexVerity("ignored").ok());
+  ASSERT_FALSE(apex->VerifyApexVerity());
 }
 
-TEST_P(ApexFileTest, RetrieveFsType) {
-  const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_TRUE(apex_file.ok());
-
-  EXPECT_EQ(std::string(GetParam().type), apex_file->GetFsType().value());
-}
-
-TEST(ApexFileTest, OpenInvalidFilesystem) {
-  const std::string file_path =
-      kTestDataDir + "apex.apexd_test_corrupt_superblock_apex.apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_FALSE(apex_file.ok());
-  ASSERT_THAT(apex_file.error().message(),
-              ::testing::HasSubstr("Failed to retrieve filesystem type"));
-}
-
-TEST(ApexFileTest, OpenCompressedApexFile) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1.capex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_TRUE(apex_file.ok());
-
-  ASSERT_TRUE(apex_file->IsCompressed());
-  ASSERT_FALSE(apex_file->GetImageOffset().has_value());
-  ASSERT_FALSE(apex_file->GetImageSize().has_value());
-  ASSERT_FALSE(apex_file->GetFsType().has_value());
-}
-
-TEST(ApexFileTest, OpenFailureForCompressedApexWithoutApex) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1_without_apex.capex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_FALSE(apex_file.ok());
-  ASSERT_THAT(apex_file.error().message(),
-              ::testing::HasSubstr("Could not find entry"));
-}
-
-TEST(ApexFileTest, GetCompressedApexManifest) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1.capex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
-  EXPECT_EQ("com.android.apex.compressed", apex_file->GetManifest().name());
-  EXPECT_EQ(1u, apex_file->GetManifest().version());
-}
-
-TEST(ApexFileTest, GetBundledPublicKeyOfCompressedApex) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1.capex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
-
-  const std::string key_path =
-      kTestDataDir + "apexd_testdata/com.android.apex.compressed.avbpubkey";
-  std::string key_content;
-  ASSERT_TRUE(android::base::ReadFileToString(key_path, &key_content))
-      << "Failed to read " << key_path;
-
-  EXPECT_EQ(key_content, apex_file->GetBundledPublicKey());
-}
-
-TEST(ApexFileTest, CannotVerifyApexVerityForCompressedApex) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1.capex";
-  auto apex = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex);
-  auto result = apex->VerifyApexVerity(apex->GetBundledPublicKey());
-  ASSERT_FALSE(result.ok());
-  ASSERT_THAT(
-      result.error().message(),
-      ::testing::HasSubstr("Cannot verify ApexVerity of compressed APEX"));
-}
-
-TEST(ApexFileTest, DecompressCompressedApex) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1.capex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
-
-  // Create a temp dir for decompression
-  TemporaryDir tmp_dir;
-
-  const std::string package_name = apex_file->GetManifest().name();
-  const std::string decompression_file_path =
-      tmp_dir.path + package_name + ".capex";
-
-  auto result = apex_file->Decompress(decompression_file_path);
-  ASSERT_RESULT_OK(result);
-
-  // Assert output path is not empty
-  auto exists = PathExists(decompression_file_path);
-  ASSERT_RESULT_OK(exists);
-  ASSERT_TRUE(*exists) << decompression_file_path << " does not exist";
-
-  // Assert that decompressed apex is same as original apex
-  const std::string original_apex_file_path =
-      kTestDataDir + "com.android.apex.compressed.v1_original.apex";
-  auto comparison_result =
-      CompareFiles(original_apex_file_path, decompression_file_path);
-  ASSERT_RESULT_OK(comparison_result);
-  ASSERT_TRUE(*comparison_result);
-}
-
-TEST(ApexFileTest, DecompressFailForNormalApex) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1_original.apex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-  ASSERT_RESULT_OK(apex_file);
-
-  TemporaryFile decompression_file;
-
-  auto result = apex_file->Decompress(decompression_file.path);
-  ASSERT_FALSE(result.ok());
-  ASSERT_THAT(result.error().message(),
-              ::testing::HasSubstr("Cannot decompress an uncompressed APEX"));
-}
-
-TEST(ApexFileTest, DecompressFailIfDecompressionPathExists) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed.v1.capex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-
-  // Attempt to decompress in a path that already exists
-  TemporaryFile decompression_file;
-  auto exists = PathExists(decompression_file.path);
-  ASSERT_RESULT_OK(exists);
-  ASSERT_TRUE(*exists) << decompression_file.path << " does not exist";
-
-  auto result = apex_file->Decompress(decompression_file.path);
-  ASSERT_FALSE(result.ok());
-  ASSERT_THAT(result.error().message(),
-              ::testing::HasSubstr("Failed to open decompression destination"));
-}
-
-TEST(ApexFileTest, GetPathReturnsRealpath) {
-  const std::string real_path = kTestDataDir + "apex.apexd_test.apex";
-  const std::string symlink_path =
-      kTestDataDir + "apex.apexd_test.symlink.apex";
-
-  // In case the link already exists
-  int ret = unlink(symlink_path.c_str());
-  ASSERT_TRUE(ret == 0 || errno == ENOENT)
-      << "failed to unlink " << symlink_path;
-
-  ret = symlink(real_path.c_str(), symlink_path.c_str());
-  ASSERT_EQ(0, ret) << "failed to create symlink at " << symlink_path;
-
-  // Open with the symlink. Realpath is expected.
-  Result<ApexFile> apex_file = ApexFile::Open(symlink_path);
-  ASSERT_RESULT_OK(apex_file);
-  ASSERT_EQ(real_path, apex_file->GetPath());
-}
-
-TEST(ApexFileTest, CompressedSharedLibsApexIsRejected) {
-  const std::string file_path =
-      kTestDataDir + "com.android.apex.compressed_sharedlibs.capex";
-  Result<ApexFile> apex_file = ApexFile::Open(file_path);
-
-  ASSERT_FALSE(apex_file.ok());
-  ASSERT_THAT(apex_file.error().message(),
-              ::testing::HasSubstr("Apex providing sharedlibs shouldn't "
-                                   "be compressed"));
-}
-
-// Check if CAPEX contains originalApexDigest in its manifest
-TEST(ApexFileTest, OriginalApexDigest) {
-  const std::string capex_path =
-      kTestDataDir + "com.android.apex.compressed.v1.capex";
-  auto capex = ApexFile::Open(capex_path);
-  ASSERT_TRUE(capex.ok());
-  const std::string decompressed_apex_path =
-      kTestDataDir + "com.android.apex.compressed.v1_original.apex";
-  auto decompressed_apex = ApexFile::Open(decompressed_apex_path);
-  ASSERT_TRUE(decompressed_apex.ok());
-  // Validate root digest
-  auto digest = decompressed_apex->VerifyApexVerity(
-      decompressed_apex->GetBundledPublicKey());
-  ASSERT_TRUE(digest.ok());
-  ASSERT_EQ(digest->root_digest,
-            capex->GetManifest().capexmetadata().originalapexdigest());
-}
 }  // namespace
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apex_manifest.cpp b/apexd/apex_manifest.cpp
index bfba216..1994633 100644
--- a/apexd/apex_manifest.cpp
+++ b/apexd/apex_manifest.cpp
@@ -22,7 +22,6 @@
 
 using android::base::Error;
 using android::base::Result;
-using ::apex::proto::ApexManifest;
 
 namespace android {
 namespace apex {
@@ -47,8 +46,8 @@
   return apex_manifest;
 }
 
-std::string GetPackageId(const ApexManifest& apex_manifest) {
-  return apex_manifest.name() + "@" + std::to_string(apex_manifest.version());
+std::string GetPackageId(const ApexManifest& apexManifest) {
+  return apexManifest.name() + "@" + std::to_string(apexManifest.version());
 }
 
 Result<ApexManifest> ReadManifest(const std::string& path) {
diff --git a/apexd/apex_manifest.h b/apexd/apex_manifest.h
index 5bdd43b..f299648 100644
--- a/apexd/apex_manifest.h
+++ b/apexd/apex_manifest.h
@@ -23,16 +23,16 @@
 
 #include <string>
 
+using ::apex::proto::ApexManifest;
+
 namespace android {
 namespace apex {
 // Parses and validates APEX manifest.
-android::base::Result<::apex::proto::ApexManifest> ParseManifest(
-    const std::string& content);
+android::base::Result<ApexManifest> ParseManifest(const std::string& content);
 // Returns package id of an ApexManifest
-std::string GetPackageId(const ::apex::proto::ApexManifest& apex_manifest);
+std::string GetPackageId(const ApexManifest& apex_manifest);
 // Reads and parses APEX manifest from the file on disk.
-android::base::Result<::apex::proto::ApexManifest> ReadManifest(
-    const std::string& path);
+android::base::Result<ApexManifest> ReadManifest(const std::string& path);
 }  // namespace apex
 }  // namespace android
 
diff --git a/apexd/apex_manifest_test.cpp b/apexd/apex_manifest_test.cpp
index f5bc93c..5a4e3da 100644
--- a/apexd/apex_manifest_test.cpp
+++ b/apexd/apex_manifest_test.cpp
@@ -22,8 +22,6 @@
 
 #include "apex_manifest.h"
 
-using ::apex::proto::ApexManifest;
-
 namespace android {
 namespace apex {
 
diff --git a/apexd/apex_preinstalled_data.cpp b/apexd/apex_preinstalled_data.cpp
new file mode 100644
index 0000000..d62c28c
--- /dev/null
+++ b/apexd/apex_preinstalled_data.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#define LOG_TAG "apexd"
+
+#include "apex_preinstalled_data.h"
+
+#include <unordered_map>
+
+#include <android-base/file.h>
+#include <android-base/result.h>
+#include <android-base/strings.h>
+
+#include "apex_constants.h"
+#include "apex_file.h"
+#include "apexd_utils.h"
+#include "string_log.h"
+
+using android::base::Error;
+using android::base::Result;
+
+namespace android {
+namespace apex {
+
+namespace {
+
+struct ApexPreinstalledData {
+  std::string name;
+  std::string key;
+  std::string path;
+};
+
+std::unordered_map<std::string, ApexPreinstalledData> gScannedPreinstalledData;
+
+Result<std::vector<ApexPreinstalledData>> collectPreinstalleDataFromDir(
+    const std::string& dir) {
+  LOG(INFO) << "Scanning " << dir << " for preinstalled data";
+  std::vector<ApexPreinstalledData> ret;
+  if (access(dir.c_str(), F_OK) != 0 && errno == ENOENT) {
+    LOG(INFO) << "... does not exist. Skipping";
+    return ret;
+  }
+  const bool scanBuiltinApexes = isPathForBuiltinApexes(dir);
+  if (!scanBuiltinApexes) {
+    return Error() << "Can't scan preinstalled APEX data from " << dir;
+  }
+  Result<std::vector<std::string>> apex_files = FindApexFilesByName(dir);
+  if (!apex_files.ok()) {
+    return apex_files.error();
+  }
+
+  for (const auto& file : *apex_files) {
+    Result<ApexFile> apex_file = ApexFile::Open(file);
+    if (!apex_file.ok()) {
+      return Error() << "Failed to open " << file << " : " << apex_file.error();
+    }
+    ApexPreinstalledData apexPreInstalledData;
+    apexPreInstalledData.name = apex_file->GetManifest().name();
+    apexPreInstalledData.key = apex_file->GetBundledPublicKey();
+    apexPreInstalledData.path = apex_file->GetPath();
+    ret.push_back(apexPreInstalledData);
+  }
+  return ret;
+}
+
+Result<void> updatePreinstalledData(
+    const std::vector<ApexPreinstalledData>& apexes) {
+  for (const ApexPreinstalledData& apex : apexes) {
+    if (gScannedPreinstalledData.find(apex.name) ==
+        gScannedPreinstalledData.end()) {
+      gScannedPreinstalledData.insert({apex.name, apex});
+    } else {
+      const std::string& existing_key =
+          gScannedPreinstalledData.at(apex.name).key;
+      if (existing_key != apex.key) {
+        return Error() << "Key for package " << apex.name
+                       << " does not match with previously scanned key";
+      }
+    }
+  }
+  return {};
+}
+
+}  // namespace
+
+Result<void> collectPreinstalledData(const std::vector<std::string>& dirs) {
+  for (const auto& dir : dirs) {
+    Result<std::vector<ApexPreinstalledData>> preinstalledData =
+        collectPreinstalleDataFromDir(dir);
+    if (!preinstalledData.ok()) {
+      return Error() << "Failed to collect keys from " << dir << " : "
+                     << preinstalledData.error();
+    }
+    Result<void> st = updatePreinstalledData(*preinstalledData);
+    if (!st.ok()) {
+      return st;
+    }
+  }
+  return {};
+}
+
+Result<const std::string> getApexKey(const std::string& name) {
+  if (gScannedPreinstalledData.find(name) == gScannedPreinstalledData.end()) {
+    return Error() << "No preinstalled data found for package " << name;
+  }
+  return gScannedPreinstalledData[name].key;
+}
+
+Result<const std::string> getApexPreinstalledPath(const std::string& name) {
+  if (gScannedPreinstalledData.find(name) == gScannedPreinstalledData.end()) {
+    return Error() << "No preinstalled data found for package " << name;
+  }
+  return gScannedPreinstalledData[name].path;
+}
+
+bool HasPreInstalledVersion(const std::string& name) {
+  return gScannedPreinstalledData.find(name) != gScannedPreinstalledData.end();
+}
+
+}  // namespace apex
+}  // namespace android
diff --git a/apexd/apex_preinstalled_data.h b/apexd/apex_preinstalled_data.h
new file mode 100644
index 0000000..1b80aad
--- /dev/null
+++ b/apexd/apex_preinstalled_data.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <android-base/result.h>
+
+namespace android {
+namespace apex {
+
+android::base::Result<void> collectPreinstalledData(
+    const std::vector<std::string>& apex_dirs);
+android::base::Result<const std::string> getApexKey(const std::string& name);
+android::base::Result<const std::string> getApexPreinstalledPath(
+    const std::string& name);
+bool HasPreInstalledVersion(const std::string& name);
+}  // namespace apex
+}  // namespace android
diff --git a/apexd/apex_shim.cpp b/apexd/apex_shim.cpp
index 0031c3f..d1ff90d 100644
--- a/apexd/apex_shim.cpp
+++ b/apexd/apex_shim.cpp
@@ -33,7 +33,6 @@
 using android::base::ErrnoError;
 using android::base::Error;
 using android::base::Result;
-using ::apex::proto::ApexManifest;
 
 namespace android {
 namespace apex {
@@ -127,6 +126,7 @@
   // Unfortunately fs::recursive_directory_iterator::operator++ can throw an
   // exception, which means that it's impossible to use range-based for loop
   // here.
+  // TODO: wrap into a non-throwing iterator to support range-based for loop.
   while (iter != fs::end(iter)) {
     auto path = iter->path();
     // Resolve the mount point to ensure any trailing slash is removed.
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index e0562f0..80e075a 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -15,26 +15,25 @@
  */
 
 #include "apexd.h"
-#include "apex_file_repository.h"
 #include "apexd_private.h"
 
 #include "apex_constants.h"
 #include "apex_database.h"
 #include "apex_file.h"
 #include "apex_manifest.h"
+#include "apex_preinstalled_data.h"
 #include "apex_shim.h"
 #include "apexd_checkpoint.h"
-#include "apexd_lifecycle.h"
 #include "apexd_loop.h"
 #include "apexd_prepostinstall.h"
+#include "apexd_prop.h"
 #include "apexd_rollback_utils.h"
 #include "apexd_session.h"
 #include "apexd_utils.h"
 #include "apexd_verity.h"
-#include "com_android_apex.h"
+#include "string_log.h"
 
 #include <ApexProperties.sysprop.h>
-#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
@@ -44,7 +43,6 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
-#include <google/protobuf/util/message_differencer.h>
 #include <libavb/libavb.h>
 #include <libdm/dm.h>
 #include <libdm/dm_table.h>
@@ -53,17 +51,15 @@
 
 #include <dirent.h>
 #include <fcntl.h>
-#include <linux/f2fs.h>
 #include <linux/loop.h>
+#include <log/log.h>
 #include <stdlib.h>
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
-#include <sys/sysinfo.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <algorithm>
 
 #include <algorithm>
 #include <array>
@@ -71,40 +67,31 @@
 #include <cstdlib>
 #include <filesystem>
 #include <fstream>
-#include <future>
 #include <iomanip>
 #include <iterator>
 #include <memory>
-#include <mutex>
 #include <optional>
-#include <queue>
-#include <sstream>
 #include <string>
-#include <string_view>
 #include <thread>
 #include <unordered_map>
 #include <unordered_set>
 
-using android::base::boot_clock;
-using android::base::ConsumePrefix;
 using android::base::ErrnoError;
 using android::base::Error;
 using android::base::GetProperty;
 using android::base::Join;
 using android::base::ParseUint;
 using android::base::ReadFully;
-using android::base::RemoveFileIfExists;
 using android::base::Result;
-using android::base::SetProperty;
+using android::base::StartsWith;
 using android::base::StringPrintf;
 using android::base::unique_fd;
 using android::dm::DeviceMapper;
 using android::dm::DmDeviceState;
 using android::dm::DmTable;
 using android::dm::DmTargetVerity;
-using ::apex::proto::ApexManifest;
+
 using apex::proto::SessionState;
-using google::protobuf::util::MessageDifferencer;
 
 namespace android {
 namespace apex {
@@ -113,6 +100,12 @@
 
 namespace {
 
+// These should be in-sync with system/sepolicy/public/property_contexts
+static constexpr const char* kApexStatusSysprop = "apexd.status";
+static constexpr const char* kApexStatusStarting = "starting";
+static constexpr const char* kApexStatusActivated = "activated";
+static constexpr const char* kApexStatusReady = "ready";
+
 static constexpr const char* kBuildFingerprintSysprop = "ro.build.fingerprint";
 
 // This should be in UAPI, but it's not :-(
@@ -121,20 +114,20 @@
 
 MountedApexDatabase gMountedApexes;
 
-std::optional<ApexdConfig> gConfig;
-
 CheckpointInterface* gVoldService;
 bool gSupportsFsCheckpoints = false;
 bool gInFsCheckpointMode = false;
 
 static constexpr size_t kLoopDeviceSetupAttempts = 3u;
 
-// Please DO NOT add new modules to this list without contacting mainline-modularization@ first.
+bool gBootstrap = false;
 static const std::vector<std::string> kBootstrapApexes = ([]() {
   std::vector<std::string> ret = {
+      "com.android.art",
       "com.android.i18n",
       "com.android.runtime",
       "com.android.tzdata",
+      "com.android.os.statsd",
   };
 
   auto vendor_vndk_ver = GetProperty("ro.vndk.version", "");
@@ -150,39 +143,14 @@
 
 static constexpr const int kNumRetriesWhenCheckpointingEnabled = 1;
 
-bool IsBootstrapApex(const ApexFile& apex) {
+bool isBootstrapApex(const ApexFile& apex) {
   return std::find(kBootstrapApexes.begin(), kBootstrapApexes.end(),
                    apex.GetManifest().name()) != kBootstrapApexes.end();
 }
 
-void ReleaseF2fsCompressedBlocks(const std::string& file_path) {
-  unique_fd fd(
-      TEMP_FAILURE_RETRY(open(file_path.c_str(), O_RDONLY | O_CLOEXEC, 0)));
-  if (fd.get() == -1) {
-    PLOG(ERROR) << "Failed to open " << file_path;
-    return;
-  }
-  unsigned int flags;
-  if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) {
-    PLOG(ERROR) << "Failed to call FS_IOC_GETFLAGS on " << file_path;
-    return;
-  }
-  if ((flags & FS_COMPR_FL) == 0) {
-    // Doesn't support f2fs-compression.
-    return;
-  }
-  uint64_t blk_cnt;
-  if (ioctl(fd, F2FS_IOC_RELEASE_COMPRESS_BLOCKS, &blk_cnt) == -1) {
-    PLOG(ERROR) << "Failed to call F2FS_IOC_RELEASE_COMPRESS_BLOCKS on "
-                << file_path;
-  }
-  LOG(INFO) << "Released " << blk_cnt << " compressed blocks from "
-            << file_path;
-}
-
 // Pre-allocate loop devices so that we don't have to wait for them
 // later when actually activating APEXes.
-Result<void> PreAllocateLoopDevices() {
+Result<void> preAllocateLoopDevices() {
   auto scan = FindApexes(kApexPackageBuiltinDirs);
   if (!scan.ok()) {
     return scan.error();
@@ -190,28 +158,28 @@
 
   auto size = 0;
   for (const auto& path : *scan) {
-    auto apex_file = ApexFile::Open(path);
-    if (!apex_file.ok()) {
+    auto apexFile = ApexFile::Open(path);
+    if (!apexFile.ok()) {
       continue;
     }
     size++;
     // bootstrap Apexes may be activated on separate namespaces.
-    if (IsBootstrapApex(*apex_file)) {
+    if (isBootstrapApex(*apexFile)) {
       size++;
     }
   }
 
-  // note: do not call PreAllocateLoopDevices() if size == 0.
+  // note: do not call preAllocateLoopDevices() if size == 0.
   // For devices (e.g. ARC) which doesn't support loop-control
-  // PreAllocateLoopDevices() can cause problem when it tries
+  // preAllocateLoopDevices() can cause problem when it tries
   // to access /dev/loop-control.
   if (size == 0) {
     return {};
   }
-  return loop::PreAllocateLoopDevices(size);
+  return loop::preAllocateLoopDevices(size);
 }
 
-std::unique_ptr<DmTable> CreateVerityTable(const ApexVerityData& verity_data,
+std::unique_ptr<DmTable> createVerityTable(const ApexVerityData& verity_data,
                                            const std::string& block_device,
                                            const std::string& hash_device,
                                            bool restart_on_corruption) {
@@ -242,18 +210,9 @@
 
 // Deletes a dm-verity device with a given name and path
 // Synchronizes on the device actually being deleted from userspace.
-Result<void> DeleteVerityDevice(const std::string& name, bool deferred) {
+Result<void> DeleteVerityDevice(const std::string& name) {
   DeviceMapper& dm = DeviceMapper::Instance();
-  if (deferred) {
-    if (!dm.DeleteDeviceDeferred(name)) {
-      return ErrnoError() << "Failed to issue deferred delete of verity device "
-                          << name;
-    }
-    return {};
-  }
-  auto timeout = std::chrono::milliseconds(
-      android::sysprop::ApexProperties::dm_delete_timeout().value_or(750));
-  if (!dm.DeleteDevice(name, timeout)) {
+  if (!dm.DeleteDevice(name, 750ms)) {
     return Error() << "Failed to delete dm-device " << name;
   }
   return {};
@@ -286,7 +245,7 @@
 
   ~DmVerityDevice() {
     if (!cleared_) {
-      Result<void> ret = DeleteVerityDevice(name_, /* deferred= */ false);
+      Result<void> ret = DeleteVerityDevice(name_);
       if (!ret.ok()) {
         LOG(ERROR) << ret.error();
       }
@@ -304,46 +263,32 @@
   bool cleared_;
 };
 
-Result<DmVerityDevice> CreateVerityDevice(const std::string& name,
+Result<DmVerityDevice> createVerityDevice(const std::string& name,
                                           const DmTable& table) {
   DeviceMapper& dm = DeviceMapper::Instance();
 
   if (dm.GetState(name) != DmDeviceState::INVALID) {
-    // Delete dangling dm-device. This can happen if apexd fails to delete it
-    // while unmounting an apex.
+    // TODO: since apexd tears down devices during unmount, can this happen?
     LOG(WARNING) << "Deleting existing dm device " << name;
-    auto result = DeleteVerityDevice(name, /* deferred= */ false);
+    const Result<void>& result = DeleteVerityDevice(name);
     if (!result.ok()) {
-      return result.error();
+      // TODO: should we fail instead?
+      LOG(ERROR) << "Failed to delete device " << name << " : "
+                 << result.error();
     }
   }
 
-  auto timeout = std::chrono::milliseconds(
-      android::sysprop::ApexProperties::dm_create_timeout().value_or(1000));
   std::string dev_path;
-  if (!dm.CreateDevice(name, table, &dev_path, timeout)) {
+  if (!dm.CreateDevice(name, table, &dev_path, 500ms)) {
     return Errorf("Couldn't create verity device.");
   }
   return DmVerityDevice(name, dev_path);
 }
 
-/**
- * When we create hardlink for a new apex package in kActiveApexPackagesDataDir,
- * there might be an older version of the same package already present in there.
- * Since a new version of the same package is being installed on this boot, the
- * old one needs to deleted so that we don't end up activating same package
- * twice.
- *
- * @param affected_packages package names of the news apex that are being
- * installed in this boot
- * @param files_to_keep path to the new apex packages in
- * kActiveApexPackagesDataDir
- */
 Result<void> RemovePreviouslyActiveApexFiles(
     const std::unordered_set<std::string>& affected_packages,
     const std::unordered_set<std::string>& files_to_keep) {
-  auto all_active_apex_files =
-      FindFilesBySuffix(gConfig->active_apex_data_dir, {kApexPackageSuffix});
+  auto all_active_apex_files = FindApexFilesByName(kActiveApexPackagesDataDir);
 
   if (!all_active_apex_files.ok()) {
     return all_active_apex_files.error();
@@ -377,14 +322,13 @@
 }
 
 // Reads the entire device to verify the image is authenticatic
-Result<void> ReadVerityDevice(const std::string& verity_device,
+Result<void> readVerityDevice(const std::string& verity_device,
                               uint64_t device_size) {
   static constexpr int kBlockSize = 4096;
   static constexpr size_t kBufSize = 1024 * kBlockSize;
   std::vector<uint8_t> buffer(kBufSize);
 
-  unique_fd fd(
-      TEMP_FAILURE_RETRY(open(verity_device.c_str(), O_RDONLY | O_CLOEXEC)));
+  unique_fd fd(TEMP_FAILURE_RETRY(open(verity_device.c_str(), O_RDONLY)));
   if (fd.get() == -1) {
     return ErrnoError() << "Can't open " << verity_device;
   }
@@ -403,16 +347,9 @@
 
 Result<void> VerifyMountedImage(const ApexFile& apex,
                                 const std::string& mount_point) {
-  // Verify that apex_manifest.pb inside mounted image matches the one in the
-  // outer .apex container.
-  Result<ApexManifest> verified_manifest =
-      ReadManifest(mount_point + "/" + kManifestFilenamePb);
-  if (!verified_manifest.ok()) {
-    return verified_manifest.error();
-  }
-  if (!MessageDifferencer::Equals(*verified_manifest, apex.GetManifest())) {
-    return Errorf(
-        "Manifest inside filesystem does not match manifest outside it");
+  auto result = apex.VerifyManifestMatches(mount_point);
+  if (!result.ok()) {
+    return result;
   }
   if (shim::IsShimApex(apex)) {
     return shim::ValidateShimApex(mount_point, apex);
@@ -421,18 +358,11 @@
 }
 
 Result<MountedApexData> MountPackageImpl(const ApexFile& apex,
-                                         const std::string& mount_point,
+                                         const std::string& mountPoint,
                                          const std::string& device_name,
                                          const std::string& hashtree_file,
-                                         bool verify_image,
-                                         bool temp_mount = false) {
-  if (apex.IsCompressed()) {
-    return Error() << "Cannot directly mount compressed APEX "
-                   << apex.GetPath();
-  }
-
-  LOG(VERBOSE) << "Creating mount point: " << mount_point;
-  auto time_started = boot_clock::now();
+                                         bool verifyImage) {
+  LOG(VERBOSE) << "Creating mount point: " << mountPoint;
   // Note: the mount point could exist in case when the APEX was activated
   // during the bootstrap phase (e.g., the runtime or tzdata APEX).
   // Although we have separate mount namespaces to separate the early activated
@@ -441,34 +371,31 @@
   // mounted at / which is (and has to be) a shared mount. Therefore, if apexd
   // finds an empty directory under /apex, it's not a problem and apexd can use
   // it.
-  auto exists = PathExists(mount_point);
+  auto exists = PathExists(mountPoint);
   if (!exists.ok()) {
     return exists.error();
   }
-  if (!*exists && mkdir(mount_point.c_str(), kMkdirMode) != 0) {
-    return ErrnoError() << "Could not create mount point " << mount_point;
+  if (!*exists && mkdir(mountPoint.c_str(), kMkdirMode) != 0) {
+    return ErrnoError() << "Could not create mount point " << mountPoint;
   }
-  auto deleter = [&mount_point]() {
-    if (rmdir(mount_point.c_str()) != 0) {
-      PLOG(WARNING) << "Could not rmdir " << mount_point;
+  auto deleter = [&mountPoint]() {
+    if (rmdir(mountPoint.c_str()) != 0) {
+      PLOG(WARNING) << "Could not rmdir " << mountPoint;
     }
   };
   auto scope_guard = android::base::make_scope_guard(deleter);
-  if (!IsEmptyDirectory(mount_point)) {
-    return ErrnoError() << mount_point << " is not empty";
+  if (!IsEmptyDirectory(mountPoint)) {
+    return ErrnoError() << mountPoint << " is not empty";
   }
 
   const std::string& full_path = apex.GetPath();
 
-  if (!apex.GetImageOffset() || !apex.GetImageSize()) {
-    return Error() << "Cannot create mount point without image offset and size";
-  }
-  loop::LoopbackDeviceUniqueFd loopback_device;
+  loop::LoopbackDeviceUniqueFd loopbackDevice;
   for (size_t attempts = 1;; ++attempts) {
-    Result<loop::LoopbackDeviceUniqueFd> ret = loop::CreateLoopDevice(
-        full_path, apex.GetImageOffset().value(), apex.GetImageSize().value());
+    Result<loop::LoopbackDeviceUniqueFd> ret = loop::createLoopDevice(
+        full_path, apex.GetImageOffset(), apex.GetImageSize());
     if (ret.ok()) {
-      loopback_device = std::move(*ret);
+      loopbackDevice = std::move(*ret);
       break;
     }
     if (attempts >= kLoopDeviceSetupAttempts) {
@@ -476,43 +403,33 @@
                      << ret.error();
     }
   }
-  LOG(VERBOSE) << "Loopback device created: " << loopback_device.name;
+  LOG(VERBOSE) << "Loopback device created: " << loopbackDevice.name;
 
-  auto& instance = ApexFileRepository::GetInstance();
-
-  auto public_key = instance.GetPublicKey(apex.GetManifest().name());
-  if (!public_key.ok()) {
-    return public_key.error();
-  }
-
-  auto verity_data = apex.VerifyApexVerity(*public_key);
-  if (!verity_data.ok()) {
+  auto verityData = apex.VerifyApexVerity();
+  if (!verityData.ok()) {
     return Error() << "Failed to verify Apex Verity data for " << full_path
-                   << ": " << verity_data.error();
+                   << ": " << verityData.error();
   }
-  std::string block_device = loopback_device.name;
-  MountedApexData apex_data(loopback_device.name, apex.GetPath(), mount_point,
+  std::string blockDevice = loopbackDevice.name;
+  MountedApexData apex_data(loopbackDevice.name, apex.GetPath(), mountPoint,
                             /* device_name = */ "",
-                            /* hashtree_loop_name = */ "",
-                            /* is_temp_mount */ temp_mount);
+                            /* hashtree_loop_name = */ "");
 
   // for APEXes in immutable partitions, we don't need to mount them on
   // dm-verity because they are already in the dm-verity protected partition;
   // system. However, note that we don't skip verification to ensure that APEXes
   // are correctly signed.
-  const bool mount_on_verity =
-      !instance.IsPreInstalledApex(apex) || instance.IsDecompressedApex(apex);
-
-  DmVerityDevice verity_dev;
+  const bool mountOnVerity = !isPathForBuiltinApexes(full_path);
+  DmVerityDevice verityDev;
   loop::LoopbackDeviceUniqueFd loop_for_hash;
-  if (mount_on_verity) {
-    std::string hash_device = loopback_device.name;
-    if (verity_data->desc->tree_size == 0) {
-      if (auto st = PrepareHashTree(apex, *verity_data, hashtree_file);
+  if (mountOnVerity) {
+    std::string hash_device = loopbackDevice.name;
+    if (verityData->desc->tree_size == 0) {
+      if (auto st = PrepareHashTree(apex, *verityData, hashtree_file);
           !st.ok()) {
         return st.error();
       }
-      auto create_loop_status = loop::CreateLoopDevice(hashtree_file, 0, 0);
+      auto create_loop_status = loop::createLoopDevice(hashtree_file, 0, 0);
       if (!create_loop_status.ok()) {
         return create_loop_status.error();
       }
@@ -520,59 +437,54 @@
       hash_device = loop_for_hash.name;
       apex_data.hashtree_loop_name = hash_device;
     }
-    auto verity_table =
-        CreateVerityTable(*verity_data, loopback_device.name, hash_device,
-                          /* restart_on_corruption = */ !verify_image);
-    Result<DmVerityDevice> verity_dev_res =
-        CreateVerityDevice(device_name, *verity_table);
-    if (!verity_dev_res.ok()) {
+    auto verityTable =
+        createVerityTable(*verityData, loopbackDevice.name, hash_device,
+                          /* restart_on_corruption = */ !verifyImage);
+    Result<DmVerityDevice> verityDevRes =
+        createVerityDevice(device_name, *verityTable);
+    if (!verityDevRes.ok()) {
       return Error() << "Failed to create Apex Verity device " << full_path
-                     << ": " << verity_dev_res.error();
+                     << ": " << verityDevRes.error();
     }
-    verity_dev = std::move(*verity_dev_res);
+    verityDev = std::move(*verityDevRes);
     apex_data.device_name = device_name;
-    block_device = verity_dev.GetDevPath();
+    blockDevice = verityDev.GetDevPath();
 
-    Result<void> read_ahead_status =
-        loop::ConfigureReadAhead(verity_dev.GetDevPath());
-    if (!read_ahead_status.ok()) {
-      return read_ahead_status.error();
+    Result<void> readAheadStatus =
+        loop::configureReadAhead(verityDev.GetDevPath());
+    if (!readAheadStatus.ok()) {
+      return readAheadStatus.error();
     }
   }
-  // TODO(b/158467418): consider moving this inside RunVerifyFnInsideTempMount.
-  if (mount_on_verity && verify_image) {
-    Result<void> verity_status =
-        ReadVerityDevice(block_device, (*verity_data).desc->image_size);
-    if (!verity_status.ok()) {
-      return verity_status.error();
+  // TODO: consider moving this inside RunVerifyFnInsideTempMount.
+  if (mountOnVerity && verifyImage) {
+    Result<void> verityStatus =
+        readVerityDevice(blockDevice, (*verityData).desc->image_size);
+    if (!verityStatus.ok()) {
+      return verityStatus.error();
     }
   }
 
-  uint32_t mount_flags = MS_NOATIME | MS_NODEV | MS_DIRSYNC | MS_RDONLY;
+  uint32_t mountFlags = MS_NOATIME | MS_NODEV | MS_DIRSYNC | MS_RDONLY;
   if (apex.GetManifest().nocode()) {
-    mount_flags |= MS_NOEXEC;
+    mountFlags |= MS_NOEXEC;
   }
 
-  if (!apex.GetFsType()) {
-    return Error() << "Cannot mount package without FsType";
-  }
-  if (mount(block_device.c_str(), mount_point.c_str(),
-            apex.GetFsType().value().c_str(), mount_flags, nullptr) == 0) {
-    auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
-        boot_clock::now() - time_started).count();
+  if (mount(blockDevice.c_str(), mountPoint.c_str(), "ext4", mountFlags,
+            nullptr) == 0) {
     LOG(INFO) << "Successfully mounted package " << full_path << " on "
-              << mount_point << " duration=" << time_elapsed;
-    auto status = VerifyMountedImage(apex, mount_point);
+              << mountPoint;
+    auto status = VerifyMountedImage(apex, mountPoint);
     if (!status.ok()) {
-      if (umount2(mount_point.c_str(), UMOUNT_NOFOLLOW) != 0) {
-        PLOG(ERROR) << "Failed to umount " << mount_point;
+      if (umount2(mountPoint.c_str(), UMOUNT_NOFOLLOW) != 0) {
+        PLOG(ERROR) << "Failed to umount " << mountPoint;
       }
       return Error() << "Failed to verify " << full_path << ": "
                      << status.error();
     }
     // Time to accept the temporaries as good.
-    verity_dev.Release();
-    loopback_device.CloseGood();
+    verityDev.Release();
+    loopbackDevice.CloseGood();
     loop_for_hash.CloseGood();
 
     scope_guard.Disable();  // Accept the mount.
@@ -583,9 +495,8 @@
 }
 
 std::string GetHashTreeFileName(const ApexFile& apex, bool is_new) {
-  const std::string& id = GetPackageId(apex.GetManifest());
   std::string ret =
-      StringPrintf("%s/%s", gConfig->apex_hash_tree_dir, id.c_str());
+      std::string(kApexHashTreeDir) + "/" + GetPackageId(apex.GetManifest());
   return is_new ? ret + ".new" : ret;
 }
 
@@ -601,40 +512,28 @@
       return ErrnoError() << "Failed to unlink " << hashtree_file;
     }
   }
-  auto ret =
-      MountPackageImpl(apex, mount_point, temp_device_name, hashtree_file,
-                       /* verify_image = */ true, /* temp_mount = */ true);
-  if (!ret.ok()) {
-    LOG(DEBUG) << "Cleaning up " << hashtree_file;
-    if (TEMP_FAILURE_RETRY(unlink(hashtree_file.c_str())) != 0) {
-      PLOG(ERROR) << "Failed to unlink " << hashtree_file;
-    }
-  } else {
-    gMountedApexes.AddMountedApex(apex.GetManifest().name(), false, *ret);
-  }
-  return ret;
+  return MountPackageImpl(apex, mount_point, temp_device_name,
+                          GetHashTreeFileName(apex, /* is_new = */ true),
+                          /* verifyImage = */ true);
 }
 
-}  // namespace
-
-Result<void> Unmount(const MountedApexData& data, bool deferred) {
+Result<void> Unmount(const MountedApexData& data) {
   LOG(DEBUG) << "Unmounting " << data.full_path << " from mount point "
-             << data.mount_point << " deferred = " << deferred;
+             << data.mount_point;
   // Lazily try to umount whatever is mounted.
   if (umount2(data.mount_point.c_str(), UMOUNT_NOFOLLOW) != 0 &&
       errno != EINVAL && errno != ENOENT) {
     return ErrnoError() << "Failed to unmount directory " << data.mount_point;
   }
-
-  if (!deferred) {
-    if (rmdir(data.mount_point.c_str()) != 0) {
-      PLOG(ERROR) << "Failed to rmdir " << data.mount_point;
-    }
+  // Attempt to delete the folder. If the folder is retained, other
+  // data may be incorrect.
+  if (rmdir(data.mount_point.c_str()) != 0) {
+    PLOG(ERROR) << "Failed to rmdir directory " << data.mount_point;
   }
 
   // Try to free up the device-mapper device.
   if (!data.device_name.empty()) {
-    const auto& result = DeleteVerityDevice(data.device_name, deferred);
+    const auto& result = DeleteVerityDevice(data.device_name);
     if (!result.ok()) {
       return result;
     }
@@ -644,28 +543,19 @@
   auto log_fn = [](const std::string& path, const std::string& /*id*/) {
     LOG(VERBOSE) << "Freeing loop device " << path << " for unmount.";
   };
-
-  // Since we now use LO_FLAGS_AUTOCLEAR when configuring loop devices, in
-  // theory we don't need to manually call DestroyLoopDevice here even if
-  // |deferred| is false. However we prefer to call it to ensure the invariant
-  // of SubmitStagedSession (after it's done, loop devices created for temp
-  // mount are freed).
-  if (!data.loop_name.empty() && !deferred) {
+  if (!data.loop_name.empty()) {
     loop::DestroyLoopDevice(data.loop_name, log_fn);
   }
-  if (!data.hashtree_loop_name.empty() && !deferred) {
+  if (!data.hashtree_loop_name.empty()) {
     loop::DestroyLoopDevice(data.hashtree_loop_name, log_fn);
   }
 
   return {};
 }
 
-namespace {
-
 template <typename VerifyFn>
 Result<void> RunVerifyFnInsideTempMount(const ApexFile& apex,
-                                        const VerifyFn& verify_fn,
-                                        bool unmount_during_cleanup) {
+                                        const VerifyFn& verify_fn) {
   // Temp mount image of this apex to validate it was properly signed;
   // this will also read the entire block device through dm-verity, so
   // we can be sure there is no corruption.
@@ -681,33 +571,19 @@
   }
   auto cleaner = [&]() {
     LOG(DEBUG) << "Unmounting " << temp_mount_point;
-    Result<void> result = Unmount(*mount_status, /* deferred= */ false);
+    Result<void> result = Unmount(*mount_status);
     if (!result.ok()) {
       LOG(WARNING) << "Failed to unmount " << temp_mount_point << " : "
                    << result.error();
     }
-    gMountedApexes.RemoveMountedApex(apex.GetManifest().name(), apex.GetPath(),
-                                     true);
   };
   auto scope_guard = android::base::make_scope_guard(cleaner);
-  auto result = verify_fn(temp_mount_point);
-  if (!result.ok()) {
-    return result.error();
-  }
-  if (!unmount_during_cleanup) {
-    scope_guard.Disable();
-  }
-  return {};
+  return verify_fn(temp_mount_point);
 }
 
 template <typename HookFn, typename HookCall>
 Result<void> PrePostinstallPackages(const std::vector<ApexFile>& apexes,
                                     HookFn fn, HookCall call) {
-  auto scope_guard = android::base::make_scope_guard([&]() {
-    for (const ApexFile& apex_file : apexes) {
-      apexd_private::UnmountTempMount(apex_file);
-    }
-  });
   if (apexes.empty()) {
     return Errorf("Empty set of inputs");
   }
@@ -721,26 +597,9 @@
     }
   }
 
-  // 2) If we found hooks, temp mount if required, and run the pre/post-install.
+  // 2) If we found hooks, run the pre/post-install.
   if (has_hooks) {
-    std::vector<std::string> mount_points;
-    for (const ApexFile& apex : apexes) {
-      // Retrieve the mount data if the apex is already temp mounted, temp
-      // mount it otherwise.
-      std::string mount_point =
-          apexd_private::GetPackageTempMountPoint(apex.GetManifest());
-      Result<MountedApexData> mount_data =
-          apexd_private::GetTempMountedApexData(apex.GetManifest().name());
-      if (!mount_data.ok()) {
-        mount_data = VerifyAndTempMountPackage(apex, mount_point);
-        if (!mount_data.ok()) {
-          return mount_data.error();
-        }
-      }
-      mount_points.push_back(mount_point);
-    }
-
-    Result<void> install_status = (*call)(apexes, mount_points);
+    Result<void> install_status = (*call)(apexes);
     if (!install_status.ok()) {
       return install_status;
     }
@@ -759,23 +618,20 @@
                                 &StagePostInstall);
 }
 
-// Converts a list of apex file paths into a list of ApexFile objects
-//
-// Returns error when trying to open empty set of inputs.
-Result<std::vector<ApexFile>> OpenApexFiles(
-    const std::vector<std::string>& paths) {
-  if (paths.empty()) {
-    return Errorf("Empty set of inputs");
-  }
-  std::vector<ApexFile> ret;
+template <typename RetType, typename Fn>
+RetType HandlePackages(const std::vector<std::string>& paths, Fn fn) {
+  // 1) Open all APEXes.
+  std::vector<ApexFile> apex_files;
   for (const std::string& path : paths) {
     Result<ApexFile> apex_file = ApexFile::Open(path);
     if (!apex_file.ok()) {
       return apex_file.error();
     }
-    ret.emplace_back(std::move(*apex_file));
+    apex_files.emplace_back(std::move(*apex_file));
   }
-  return ret;
+
+  // 2) Dispatch.
+  return fn(apex_files);
 }
 
 Result<void> ValidateStagingShimApex(const ApexFile& to) {
@@ -788,20 +644,14 @@
   auto verify_fn = [&](const std::string& system_apex_path) {
     return shim::ValidateUpdate(system_apex_path, to.GetPath());
   };
-  return RunVerifyFnInsideTempMount(*system_shim, verify_fn, true);
+  return RunVerifyFnInsideTempMount(*system_shim, verify_fn);
 }
 
 // A version of apex verification that happens during boot.
 // This function should only verification checks that are necessary to run on
 // each boot. Try to avoid putting expensive checks inside this function.
 Result<void> VerifyPackageBoot(const ApexFile& apex_file) {
-  // TODO(ioffe): why do we need this here?
-  auto& instance = ApexFileRepository::GetInstance();
-  auto public_key = instance.GetPublicKey(apex_file.GetManifest().name());
-  if (!public_key.ok()) {
-    return public_key.error();
-  }
-  Result<ApexVerityData> verity_or = apex_file.VerifyApexVerity(*public_key);
+  Result<ApexVerityData> verity_or = apex_file.VerifyApexVerity();
   if (!verity_or.ok()) {
     return verity_or.error();
   }
@@ -818,48 +668,49 @@
   return {};
 }
 
-// A version of apex verification that happens on SubmitStagedSession.
+// A version of apex verification that happens on submitStagedSession.
 // This function contains checks that might be expensive to perform, e.g. temp
 // mounting a package and reading entire dm-verity device, and shouldn't be run
 // during boot.
-Result<void> VerifyPackageStagedInstall(const ApexFile& apex_file) {
+Result<void> VerifyPackageInstall(const ApexFile& apex_file) {
   const auto& verify_package_boot_status = VerifyPackageBoot(apex_file);
   if (!verify_package_boot_status.ok()) {
     return verify_package_boot_status;
   }
+  Result<ApexVerityData> verity_or = apex_file.VerifyApexVerity();
 
   constexpr const auto kSuccessFn = [](const std::string& /*mount_point*/) {
     return Result<void>{};
   };
-  return RunVerifyFnInsideTempMount(apex_file, kSuccessFn, false);
+  return RunVerifyFnInsideTempMount(apex_file, kSuccessFn);
 }
 
 template <typename VerifyApexFn>
-Result<std::vector<ApexFile>> VerifyPackages(
+Result<std::vector<ApexFile>> verifyPackages(
     const std::vector<std::string>& paths, const VerifyApexFn& verify_apex_fn) {
-  Result<std::vector<ApexFile>> apex_files = OpenApexFiles(paths);
-  if (!apex_files.ok()) {
-    return apex_files.error();
+  if (paths.empty()) {
+    return Errorf("Empty set of inputs");
   }
+  LOG(DEBUG) << "verifyPackages() for " << Join(paths, ',');
 
-  LOG(DEBUG) << "VerifyPackages() for " << Join(paths, ',');
-
-  for (const ApexFile& apex_file : *apex_files) {
-    Result<void> result = verify_apex_fn(apex_file);
-    if (!result.ok()) {
-      return result.error();
+  auto verify_fn = [&](std::vector<ApexFile>& apexes) {
+    for (const ApexFile& apex_file : apexes) {
+      Result<void> result = verify_apex_fn(apex_file);
+      if (!result.ok()) {
+        return Result<std::vector<ApexFile>>(result.error());
+      }
     }
-  }
-  return std::move(*apex_files);
+    return Result<std::vector<ApexFile>>(std::move(apexes));
+  };
+  return HandlePackages<Result<std::vector<ApexFile>>>(paths, verify_fn);
 }
 
-Result<ApexFile> VerifySessionDir(const int session_id) {
-  std::string session_dir_path = std::string(kStagedSessionsDir) + "/session_" +
-                                 std::to_string(session_id);
-  LOG(INFO) << "Scanning " << session_dir_path
+Result<ApexFile> verifySessionDir(const int session_id) {
+  std::string sessionDirPath = std::string(kStagedSessionsDir) + "/session_" +
+                               std::to_string(session_id);
+  LOG(INFO) << "Scanning " << sessionDirPath
             << " looking for packages to be validated";
-  Result<std::vector<std::string>> scan =
-      FindFilesBySuffix(session_dir_path, {kApexPackageSuffix});
+  Result<std::vector<std::string>> scan = FindApexFilesByName(sessionDirPath);
   if (!scan.ok()) {
     LOG(WARNING) << scan.error();
     return scan.error();
@@ -870,7 +721,7 @@
         "More than one APEX package found in the same session directory.");
   }
 
-  auto verified = VerifyPackages(*scan, VerifyPackageStagedInstall);
+  auto verified = verifyPackages(*scan, VerifyPackageInstall);
   if (!verified.ok()) {
     return verified.error();
   }
@@ -891,27 +742,25 @@
 }
 
 Result<void> BackupActivePackages() {
-  LOG(DEBUG) << "Initializing  backup of " << gConfig->active_apex_data_dir;
+  LOG(DEBUG) << "Initializing  backup of " << kActiveApexPackagesDataDir;
 
   // Previous restore might've delete backups folder.
-  auto create_status = CreateDirIfNeeded(kApexBackupDir, 0700);
+  auto create_status = createDirIfNeeded(kApexBackupDir, 0700);
   if (!create_status.ok()) {
     return Error() << "Backup failed : " << create_status.error();
   }
 
-  auto apex_active_exists =
-      PathExists(std::string(gConfig->active_apex_data_dir));
+  auto apex_active_exists = PathExists(std::string(kActiveApexPackagesDataDir));
   if (!apex_active_exists.ok()) {
     return Error() << "Backup failed : " << apex_active_exists.error();
   }
   if (!*apex_active_exists) {
-    LOG(DEBUG) << gConfig->active_apex_data_dir
+    LOG(DEBUG) << kActiveApexPackagesDataDir
                << " does not exist. Nothing to backup";
     return {};
   }
 
-  auto active_packages =
-      FindFilesBySuffix(gConfig->active_apex_data_dir, {kApexPackageSuffix});
+  auto active_packages = FindApexFilesByName(kActiveApexPackagesDataDir);
   if (!active_packages.ok()) {
     return Error() << "Backup failed : " << active_packages.error();
   }
@@ -952,7 +801,7 @@
 }
 
 Result<void> RestoreActivePackages() {
-  LOG(DEBUG) << "Initializing  restore of " << gConfig->active_apex_data_dir;
+  LOG(DEBUG) << "Initializing  restore of " << kActiveApexPackagesDataDir;
 
   auto backup_exists = PathExists(std::string(kApexBackupDir));
   if (!backup_exists.ok()) {
@@ -963,38 +812,37 @@
   }
 
   struct stat stat_data;
-  if (stat(gConfig->active_apex_data_dir, &stat_data) != 0) {
-    return ErrnoError() << "Failed to access " << gConfig->active_apex_data_dir;
+  if (stat(kActiveApexPackagesDataDir, &stat_data) != 0) {
+    return ErrnoError() << "Failed to access " << kActiveApexPackagesDataDir;
   }
 
-  LOG(DEBUG) << "Deleting existing packages in "
-             << gConfig->active_apex_data_dir;
+  LOG(DEBUG) << "Deleting existing packages in " << kActiveApexPackagesDataDir;
   auto delete_status =
-      DeleteDirContent(std::string(gConfig->active_apex_data_dir));
+      DeleteDirContent(std::string(kActiveApexPackagesDataDir));
   if (!delete_status.ok()) {
     return delete_status;
   }
 
   LOG(DEBUG) << "Renaming " << kApexBackupDir << " to "
-             << gConfig->active_apex_data_dir;
-  if (rename(kApexBackupDir, gConfig->active_apex_data_dir) != 0) {
+             << kActiveApexPackagesDataDir;
+  if (rename(kApexBackupDir, kActiveApexPackagesDataDir) != 0) {
     return ErrnoError() << "Failed to rename " << kApexBackupDir << " to "
-                        << gConfig->active_apex_data_dir;
+                        << kActiveApexPackagesDataDir;
   }
 
   LOG(DEBUG) << "Restoring original permissions for "
-             << gConfig->active_apex_data_dir;
-  if (chmod(gConfig->active_apex_data_dir, stat_data.st_mode & ALLPERMS) != 0) {
+             << kActiveApexPackagesDataDir;
+  if (chmod(kActiveApexPackagesDataDir, stat_data.st_mode & ALLPERMS) != 0) {
+    // TODO: should we wipe out /data/apex/active if chmod fails?
     return ErrnoError() << "Failed to restore original permissions for "
-                        << gConfig->active_apex_data_dir;
+                        << kActiveApexPackagesDataDir;
   }
 
   return {};
 }
 
-Result<void> UnmountPackage(const ApexFile& apex, bool allow_latest,
-                            bool deferred) {
-  LOG(INFO) << "Unmounting " << GetPackageId(apex.GetManifest());
+Result<void> UnmountPackage(const ApexFile& apex, bool allow_latest) {
+  LOG(VERBOSE) << "Unmounting " << GetPackageId(apex.GetManifest());
 
   const ApexManifest& manifest = apex.GetManifest();
 
@@ -1013,39 +861,33 @@
     return Error() << "Did not find " << apex.GetPath();
   }
 
-  // Concept of latest sharedlibs apex is somewhat blurred. Since this is only
-  // used in testing, it is ok to always allow unmounting sharedlibs apex.
-  if (latest && !manifest.providesharedapexlibs()) {
+  if (latest) {
     if (!allow_latest) {
       return Error() << "Package " << apex.GetPath() << " is active";
     }
     std::string mount_point = apexd_private::GetActiveMountPoint(manifest);
-    LOG(INFO) << "Unmounting " << mount_point;
+    LOG(VERBOSE) << "Unmounting and deleting " << mount_point;
     if (umount2(mount_point.c_str(), UMOUNT_NOFOLLOW) != 0) {
       return ErrnoError() << "Failed to unmount " << mount_point;
     }
-
-    if (!deferred) {
-      if (rmdir(mount_point.c_str()) != 0) {
-        PLOG(ERROR) << "Failed to rmdir " << mount_point;
-      }
+    if (rmdir(mount_point.c_str()) != 0) {
+      PLOG(ERROR) << "Could not rmdir " << mount_point;
+      // Continue here.
     }
   }
 
   // Clean up gMountedApexes now, even though we're not fully done.
   gMountedApexes.RemoveMountedApex(manifest.name(), apex.GetPath());
-  return Unmount(*data, deferred);
+  return Unmount(*data);
 }
 
 }  // namespace
 
-void SetConfig(const ApexdConfig& config) { gConfig = config; }
-
-Result<void> MountPackage(const ApexFile& apex, const std::string& mount_point,
-                          const std::string& device_name) {
-  auto ret = MountPackageImpl(apex, mount_point, device_name,
-                              GetHashTreeFileName(apex, /* is_new= */ false),
-                              /* verify_image = */ false);
+Result<void> MountPackage(const ApexFile& apex, const std::string& mountPoint) {
+  auto ret =
+      MountPackageImpl(apex, mountPoint, GetPackageId(apex.GetManifest()),
+                       GetHashTreeFileName(apex, /* is_new = */ false),
+                       /* verifyImage = */ false);
   if (!ret.ok()) {
     return ret.error();
   }
@@ -1056,41 +898,15 @@
 
 namespace apexd_private {
 
-Result<void> UnmountTempMount(const ApexFile& apex) {
-  const ApexManifest& manifest = apex.GetManifest();
-  LOG(VERBOSE) << "Unmounting all temp mounts for package " << manifest.name();
-
-  bool finished_unmounting = false;
-  // If multiple temp mounts exist, ensure that all are unmounted.
-  while (!finished_unmounting) {
-    Result<MountedApexData> data =
-        apexd_private::GetTempMountedApexData(manifest.name());
-    if (!data.ok()) {
-      finished_unmounting = true;
-    } else {
-      gMountedApexes.RemoveMountedApex(manifest.name(), data->full_path, true);
-      Unmount(*data, /* deferred= */ false);
-    }
-  }
-  return {};
+Result<MountedApexData> TempMountPackage(const ApexFile& apex,
+                                         const std::string& mount_point) {
+  // TODO(ioffe): consolidate these two methods.
+  return android::apex::VerifyAndTempMountPackage(apex, mount_point);
 }
 
-Result<MountedApexData> GetTempMountedApexData(const std::string& package) {
-  bool found = false;
-  Result<MountedApexData> mount_data;
-  gMountedApexes.ForallMountedApexes(
-      package,
-      [&](const MountedApexData& data, [[maybe_unused]] bool latest) {
-        if (!found) {
-          mount_data = data;
-          found = true;
-        }
-      },
-      true);
-  if (found) {
-    return mount_data;
-  }
-  return Error() << "No temp mount data found for " << package;
+Result<void> Unmount(const MountedApexData& data) {
+  // TODO(ioffe): consolidate these two methods.
+  return android::apex::Unmount(data);
 }
 
 bool IsMounted(const std::string& full_path) {
@@ -1119,219 +935,77 @@
 
 }  // namespace apexd_private
 
-Result<void> ResumeRevertIfNeeded() {
+Result<void> resumeRevertIfNeeded() {
   auto sessions =
       ApexSession::GetSessionsInState(SessionState::REVERT_IN_PROGRESS);
   if (sessions.empty()) {
     return {};
   }
-  return RevertActiveSessions("", "");
+  return revertActiveSessions("");
 }
 
-Result<void> ActivateSharedLibsPackage(const std::string& mount_point) {
-  for (const auto& lib_path : {"lib", "lib64"}) {
-    std::string apex_lib_path = mount_point + "/" + lib_path;
-    auto lib_dir = PathExists(apex_lib_path);
-    if (!lib_dir.ok() || !*lib_dir) {
-      continue;
-    }
-
-    auto iter = std::filesystem::directory_iterator(apex_lib_path);
-    std::error_code ec;
-
-    while (iter != std::filesystem::end(iter)) {
-      const auto& lib_entry = *iter;
-      if (!lib_entry.is_directory()) {
-        iter = iter.increment(ec);
-        if (ec) {
-          return Error() << "Failed to scan " << apex_lib_path << " : "
-                         << ec.message();
-        }
-        continue;
-      }
-
-      const auto library_name = lib_entry.path().filename();
-      const std::string library_symlink_dir =
-          StringPrintf("%s/%s/%s/%s", kApexRoot, kApexSharedLibsSubDir,
-                       lib_path, library_name.c_str());
-
-      auto symlink_dir = PathExists(library_symlink_dir);
-      if (!symlink_dir.ok() || !*symlink_dir) {
-        std::filesystem::create_directory(library_symlink_dir, ec);
-        if (ec) {
-          return Error() << "Failed to create directory " << library_symlink_dir
-                         << ": " << ec.message();
-        }
-      }
-
-      auto inner_iter =
-          std::filesystem::directory_iterator(lib_entry.path().string());
-
-      while (inner_iter != std::filesystem::end(inner_iter)) {
-        const auto& lib_items = *inner_iter;
-        const auto hash_value = lib_items.path().filename();
-        const std::string library_symlink_hash = StringPrintf(
-            "%s/%s", library_symlink_dir.c_str(), hash_value.c_str());
-
-        auto hash_dir = PathExists(library_symlink_hash);
-        if (hash_dir.ok() && *hash_dir) {
-          // Compare file size for two library files with same name and hash
-          // value
-          auto existing_file_path =
-              library_symlink_hash + "/" + library_name.string();
-          auto existing_file_size = GetFileSize(existing_file_path);
-          if (!existing_file_size.ok()) {
-            return existing_file_size.error();
-          }
-
-          auto new_file_path =
-              lib_items.path().string() + "/" + library_name.string();
-          auto new_file_size = GetFileSize(new_file_path);
-          if (!new_file_size.ok()) {
-            return new_file_size.error();
-          }
-
-          if (*existing_file_size != *new_file_size) {
-            return Error() << "There are two libraries with same hash and "
-                              "different file size : "
-                           << existing_file_path << " and " << new_file_path;
-          }
-
-          inner_iter = inner_iter.increment(ec);
-          if (ec) {
-            return Error() << "Failed to scan " << lib_entry.path().string()
-                           << " : " << ec.message();
-          }
-          continue;
-        }
-        std::filesystem::create_directory_symlink(lib_items.path(),
-                                                  library_symlink_hash, ec);
-        if (ec) {
-          return Error() << "Failed to create symlink from " << lib_items.path()
-                         << " to " << library_symlink_hash << ec.message();
-        }
-
-        inner_iter = inner_iter.increment(ec);
-        if (ec) {
-          return Error() << "Failed to scan " << lib_entry.path().string()
-                         << " : " << ec.message();
-        }
-      }
-
-      iter = iter.increment(ec);
-      if (ec) {
-        return Error() << "Failed to scan " << apex_lib_path << " : "
-                       << ec.message();
-      }
-    }
-  }
-
-  return {};
-}
-
-bool IsValidPackageName(const std::string& package_name) {
-  return kBannedApexName.count(package_name) == 0;
-}
-
-Result<void> ActivatePackageImpl(const ApexFile& apex_file,
-                                 const std::string& device_name) {
+Result<void> activatePackageImpl(const ApexFile& apex_file) {
   const ApexManifest& manifest = apex_file.GetManifest();
 
-  if (!IsValidPackageName(manifest.name())) {
-    return Errorf("Package name {} is not allowed.", manifest.name());
-  }
-
-  // Validate upgraded shim apex
-  if (shim::IsShimApex(apex_file) &&
-      !ApexFileRepository::GetInstance().IsPreInstalledApex(apex_file)) {
-    // This is not cheap for shim apex, but it is fine here since we have
-    // upgraded shim apex only during CTS tests.
-    Result<void> result = VerifyPackageBoot(apex_file);
-    if (!result.ok()) {
-      LOG(ERROR) << "Failed to validate shim apex: " << apex_file.GetPath();
-      return result;
-    }
+  if (gBootstrap && !isBootstrapApex(apex_file)) {
+    return {};
   }
 
   // See whether we think it's active, and do not allow to activate the same
   // version. Also detect whether this is the highest version.
   // We roll this into a single check.
   bool is_newest_version = true;
+  bool found_other_version = false;
   bool version_found_mounted = false;
   {
     uint64_t new_version = manifest.version();
     bool version_found_active = false;
     gMountedApexes.ForallMountedApexes(
         manifest.name(), [&](const MountedApexData& data, bool latest) {
-          Result<ApexFile> other_apex = ApexFile::Open(data.full_path);
-          if (!other_apex.ok()) {
+          Result<ApexFile> otherApex = ApexFile::Open(data.full_path);
+          if (!otherApex.ok()) {
             return;
           }
-          if (static_cast<uint64_t>(other_apex->GetManifest().version()) ==
+          found_other_version = true;
+          if (static_cast<uint64_t>(otherApex->GetManifest().version()) ==
               new_version) {
             version_found_mounted = true;
             version_found_active = latest;
           }
-          if (static_cast<uint64_t>(other_apex->GetManifest().version()) >
+          if (static_cast<uint64_t>(otherApex->GetManifest().version()) >
               new_version) {
             is_newest_version = false;
           }
         });
-    // If the package provides shared libraries to other APEXs, we need to
-    // activate all versions available (i.e. preloaded on /system/apex and
-    // available on /data/apex/active). The reason is that there might be some
-    // APEXs loaded from /system/apex that reference the libraries contained on
-    // the preloaded version of the apex providing shared libraries.
-    if (version_found_active && !manifest.providesharedapexlibs()) {
+    if (version_found_active) {
       LOG(DEBUG) << "Package " << manifest.name() << " with version "
                  << manifest.version() << " already active";
       return {};
     }
   }
 
-  const std::string& mount_point =
-      apexd_private::GetPackageMountPoint(manifest);
+  const std::string& mountPoint = apexd_private::GetPackageMountPoint(manifest);
 
   if (!version_found_mounted) {
-    auto mount_status = MountPackage(apex_file, mount_point, device_name);
-    if (!mount_status.ok()) {
-      return mount_status;
+    auto mountStatus = MountPackage(apex_file, mountPoint);
+    if (!mountStatus.ok()) {
+      return mountStatus;
     }
   }
 
-  // For packages providing shared libraries, avoid creating a bindmount since
-  // there is no use for the /apex/<package_name> directory. However, mark the
-  // highest version as latest so that the latest version of the package can be
-  // properly reported to PackageManager.
-  if (manifest.providesharedapexlibs()) {
-    if (is_newest_version) {
-      gMountedApexes.SetLatest(manifest.name(), apex_file.GetPath());
-    }
-  } else {
-    bool mounted_latest = false;
-    // Bind mount the latest version to /apex/<package_name>, unless the
-    // package provides shared libraries to other APEXs.
-    if (is_newest_version) {
-      const Result<void>& update_st = apexd_private::BindMount(
-          apexd_private::GetActiveMountPoint(manifest), mount_point);
-      mounted_latest = update_st.has_value();
-      if (!update_st.ok()) {
-        return Error() << "Failed to update package " << manifest.name()
-                       << " to version " << manifest.version() << " : "
-                       << update_st.error();
-      }
-    }
-    if (mounted_latest) {
-      gMountedApexes.SetLatest(manifest.name(), apex_file.GetPath());
+  bool mounted_latest = false;
+  if (is_newest_version) {
+    const Result<void>& update_st = apexd_private::BindMount(
+        apexd_private::GetActiveMountPoint(manifest), mountPoint);
+    mounted_latest = update_st.has_value();
+    if (!update_st.ok()) {
+      return Error() << "Failed to update package " << manifest.name()
+                     << " to version " << manifest.version() << " : "
+                     << update_st.error();
     }
   }
-
-  if (manifest.providesharedapexlibs()) {
-    const auto& handle_shared_libs_apex =
-        ActivateSharedLibsPackage(mount_point);
-    if (!handle_shared_libs_apex.ok()) {
-      return handle_shared_libs_apex;
-    }
+  if (mounted_latest) {
+    gMountedApexes.SetLatest(manifest.name(), apex_file.GetPath());
   }
 
   LOG(DEBUG) << "Successfully activated " << apex_file.GetPath()
@@ -1340,30 +1014,28 @@
   return {};
 }
 
-Result<void> ActivatePackage(const std::string& full_path) {
+Result<void> activatePackage(const std::string& full_path) {
   LOG(INFO) << "Trying to activate " << full_path;
 
   Result<ApexFile> apex_file = ApexFile::Open(full_path);
   if (!apex_file.ok()) {
     return apex_file.error();
   }
-  return ActivatePackageImpl(*apex_file,
-                             GetPackageId(apex_file->GetManifest()));
+  return activatePackageImpl(*apex_file);
 }
 
-Result<void> DeactivatePackage(const std::string& full_path) {
+Result<void> deactivatePackage(const std::string& full_path) {
   LOG(INFO) << "Trying to deactivate " << full_path;
 
-  Result<ApexFile> apex_file = ApexFile::Open(full_path);
-  if (!apex_file.ok()) {
-    return apex_file.error();
+  Result<ApexFile> apexFile = ApexFile::Open(full_path);
+  if (!apexFile.ok()) {
+    return apexFile.error();
   }
 
-  return UnmountPackage(*apex_file, /* allow_latest= */ true,
-                        /* deferred= */ false);
+  return UnmountPackage(*apexFile, /* allow_latest= */ true);
 }
 
-std::vector<ApexFile> GetActivePackages() {
+std::vector<ApexFile> getActivePackages() {
   std::vector<ApexFile> ret;
   gMountedApexes.ForallMountedApexes(
       [&](const std::string&, const MountedApexData& data, bool latest) {
@@ -1371,84 +1043,20 @@
           return;
         }
 
-        Result<ApexFile> apex_file = ApexFile::Open(data.full_path);
-        if (!apex_file.ok()) {
+        Result<ApexFile> apexFile = ApexFile::Open(data.full_path);
+        if (!apexFile.ok()) {
+          // TODO: Fail?
           return;
         }
-        ret.emplace_back(std::move(*apex_file));
+        ret.emplace_back(std::move(*apexFile));
       });
 
   return ret;
 }
 
-std::vector<ApexFile> CalculateInactivePackages(
-    const std::vector<ApexFile>& active) {
-  std::vector<ApexFile> inactive = GetFactoryPackages();
-  auto new_end = std::remove_if(
-      inactive.begin(), inactive.end(), [&active](const ApexFile& apex) {
-        return std::any_of(active.begin(), active.end(),
-                           [&apex](const ApexFile& active_apex) {
-                             return apex.GetPath() == active_apex.GetPath();
-                           });
-      });
-  inactive.erase(new_end, inactive.end());
-  return std::move(inactive);
-}
-
-Result<void> EmitApexInfoList(bool is_bootstrap) {
-  // on a non-updatable device, we don't have APEX database to emit
-  if (!android::sysprop::ApexProperties::updatable().value_or(false)) {
-    return {};
-  }
-
-  // Apexd runs both in "bootstrap" and "default" mount namespace.
-  // To expose /apex/apex-info-list.xml separately in each mount namespaces,
-  // we write /apex/.<namespace>-apex-info-list .xml file first and then
-  // bind mount it to the canonical file (/apex/apex-info-list.xml).
-  const std::string file_name =
-      fmt::format("{}/.{}-{}", kApexRoot,
-                  is_bootstrap ? "bootstrap" : "default", kApexInfoList);
-
-  unique_fd fd(TEMP_FAILURE_RETRY(
-      open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
-  if (fd.get() == -1) {
-    return ErrnoErrorf("Can't open {}", file_name);
-  }
-
-  const std::vector<ApexFile> active(GetActivePackages());
-
-  std::vector<ApexFile> inactive;
-  // we skip for non-activated built-in apexes in bootstrap mode
-  // in order to avoid boottime increase
-  if (!is_bootstrap) {
-    inactive = CalculateInactivePackages(active);
-  }
-
-  std::stringstream xml;
-  CollectApexInfoList(xml, active, inactive);
-
-  if (!android::base::WriteStringToFd(xml.str(), fd)) {
-    return ErrnoErrorf("Can't write to {}", file_name);
-  }
-
-  fd.reset();
-
-  const std::string mount_point =
-      fmt::format("{}/{}", kApexRoot, kApexInfoList);
-  if (access(mount_point.c_str(), F_OK) != 0) {
-    close(open(mount_point.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
-               0644));
-  }
-  if (mount(file_name.c_str(), mount_point.c_str(), nullptr, MS_BIND,
-            nullptr) == -1) {
-    return ErrnoErrorf("Can't bind mount {} to {}", file_name, mount_point);
-  }
-  return RestoreconPath(file_name);
-}
-
 namespace {
 std::unordered_map<std::string, uint64_t> GetActivePackagesMap() {
-  std::vector<ApexFile> active_packages = GetActivePackages();
+  std::vector<ApexFile> active_packages = getActivePackages();
   std::unordered_map<std::string, uint64_t> ret;
   for (const auto& package : active_packages) {
     const ApexManifest& manifest = package.GetManifest();
@@ -1459,50 +1067,28 @@
 
 }  // namespace
 
-std::vector<ApexFile> GetFactoryPackages() {
+std::vector<ApexFile> getFactoryPackages() {
   std::vector<ApexFile> ret;
-
-  // Decompressed APEX is considered factory package
-  std::vector<std::string> decompressed_pkg_names;
-  auto active_pkgs = GetActivePackages();
-  for (ApexFile& apex : active_pkgs) {
-    if (ApexFileRepository::GetInstance().IsDecompressedApex(apex)) {
-      decompressed_pkg_names.push_back(apex.GetManifest().name());
-      ret.emplace_back(std::move(apex));
-    }
-  }
-
-  for (const auto& dir : gConfig->apex_built_in_dirs) {
-    auto all_apex_files = FindFilesBySuffix(
-        dir, {kApexPackageSuffix, kCompressedApexPackageSuffix});
-    if (!all_apex_files.ok()) {
-      LOG(ERROR) << all_apex_files.error();
+  for (const auto& dir : kApexPackageBuiltinDirs) {
+    auto apex_files = FindApexFilesByName(dir);
+    if (!apex_files.ok()) {
+      LOG(ERROR) << apex_files.error();
       continue;
     }
-
-    for (const std::string& path : *all_apex_files) {
+    for (const std::string& path : *apex_files) {
       Result<ApexFile> apex_file = ApexFile::Open(path);
       if (!apex_file.ok()) {
         LOG(ERROR) << apex_file.error();
-        continue;
+      } else {
+        ret.emplace_back(std::move(*apex_file));
       }
-      // Ignore compressed APEX if it has been decompressed already
-      if (apex_file->IsCompressed() &&
-          std::find(decompressed_pkg_names.begin(),
-                    decompressed_pkg_names.end(),
-                    apex_file->GetManifest().name()) !=
-              decompressed_pkg_names.end()) {
-        continue;
-      }
-
-      ret.emplace_back(std::move(*apex_file));
     }
   }
   return ret;
 }
 
-Result<ApexFile> GetActivePackage(const std::string& packageName) {
-  std::vector<ApexFile> packages = GetActivePackages();
+Result<ApexFile> getActivePackage(const std::string& packageName) {
+  std::vector<ApexFile> packages = getActivePackages();
   for (ApexFile& apex : packages) {
     if (apex.GetManifest().name() == packageName) {
       return std::move(apex);
@@ -1517,7 +1103,7 @@
  *
  * Returns without error only if session was successfully aborted.
  **/
-Result<void> AbortStagedSession(int session_id) {
+Result<void> abortStagedSession(int session_id) {
   auto session = ApexSession::GetSession(session_id);
   if (!session.ok()) {
     return Error() << "No session found with id " << session_id;
@@ -1532,29 +1118,23 @@
   }
 }
 
+// TODO(ioffe): cleanup activation logic to avoid unnecessary scanning.
 namespace {
 
-// TODO(b/179497746): Avoid scanning apex directly here
-// Only used in OnBootstrap. Should we remove this function?
-Result<std::vector<ApexFile>> ScanApexFiles(const char* apex_package_dir,
-                                            bool include_compressed = false) {
+Result<std::vector<ApexFile>> ScanApexFiles(const char* apex_package_dir) {
   LOG(INFO) << "Scanning " << apex_package_dir << " looking for APEX packages.";
   if (access(apex_package_dir, F_OK) != 0 && errno == ENOENT) {
     LOG(INFO) << "... does not exist. Skipping";
     return {};
   }
-  std::vector<std::string> suffix_list = {kApexPackageSuffix};
-  if (include_compressed) {
-    suffix_list.push_back(kCompressedApexPackageSuffix);
-  }
-  Result<std::vector<std::string>> scan =
-      FindFilesBySuffix(apex_package_dir, suffix_list);
+  Result<std::vector<std::string>> scan = FindApexFilesByName(apex_package_dir);
   if (!scan.ok()) {
     return Error() << "Failed to scan " << apex_package_dir << " : "
                    << scan.error();
   }
   std::vector<ApexFile> ret;
   for (const auto& name : *scan) {
+    LOG(INFO) << "Found " << name;
     Result<ApexFile> apex_file = ApexFile::Open(name);
     if (!apex_file.ok()) {
       LOG(ERROR) << "Failed to scan " << name << " : " << apex_file.error();
@@ -1565,152 +1145,64 @@
   return ret;
 }
 
-std::vector<Result<void>> ActivateApexWorker(
-    bool is_ota_chroot, std::queue<const ApexFile*>& apex_queue,
-    std::mutex& mutex) {
-  std::vector<Result<void>> ret;
-
-  while (true) {
-    const ApexFile* apex;
-    {
-      std::lock_guard lock(mutex);
-      if (apex_queue.empty()) break;
-      apex = apex_queue.front();
-      apex_queue.pop();
-    }
-
-    std::string device_name = GetPackageId(apex->GetManifest());
-    if (is_ota_chroot) {
-      device_name += ".chroot";
-    }
-    if (auto res = ActivatePackageImpl(*apex, device_name); !res.ok()) {
-      ret.push_back(Error() << "Failed to activate " << apex->GetPath() << " : "
-                            << res.error());
-    } else {
-      ret.push_back({});
-    }
-  }
-
-  return ret;
-}
-
-Result<void> ActivateApexPackages(const std::vector<ApexFileRef>& apexes,
-                                  bool is_ota_chroot) {
-  std::queue<const ApexFile*> apex_queue;
-  std::mutex apex_queue_mutex;
-
-  for (const ApexFile& apex : apexes) {
-    apex_queue.emplace(&apex);
-  }
-
-  // Creates threads as many as half number of cores for the performance.
-  size_t worker_num = std::max(get_nprocs_conf() >> 1, 1);
-  worker_num = std::min(apex_queue.size(), worker_num);
-
-  // On -eng builds there might be two different pre-installed art apexes.
-  // Attempting to activate them in parallel will result in UB (e.g.
-  // apexd-bootstrap might crash). In order to avoid this, for the time being on
-  // -eng builds activate apexes sequentially.
-  // TODO(b/176497601): remove this.
-  if (GetProperty("ro.build.type", "") == "eng") {
-    worker_num = 1;
-  }
-
-  std::vector<std::future<std::vector<Result<void>>>> futures;
-  futures.reserve(worker_num);
-  for (size_t i = 0; i < worker_num; i++) {
-    futures.push_back(std::async(std::launch::async, ActivateApexWorker,
-                                 std::ref(is_ota_chroot), std::ref(apex_queue),
-                                 std::ref(apex_queue_mutex)));
-  }
-
-  size_t activated_cnt = 0;
+Result<void> ActivateApexPackages(const std::vector<ApexFile>& apexes) {
+  const auto& packages_with_code = GetActivePackagesMap();
   size_t failed_cnt = 0;
-  std::string error_message;
-  for (size_t i = 0; i < futures.size(); i++) {
-    for (const auto& res : futures[i].get()) {
-      if (res.ok()) {
-        ++activated_cnt;
-      } else {
-        ++failed_cnt;
-        LOG(ERROR) << res.error();
-        if (failed_cnt == 1) {
-          error_message = res.error().message();
-        }
-      }
+  size_t skipped_cnt = 0;
+  size_t activated_cnt = 0;
+  for (const auto& apex : apexes) {
+    uint64_t new_version = static_cast<uint64_t>(apex.GetManifest().version());
+    const auto& it = packages_with_code.find(apex.GetManifest().name());
+    if (it != packages_with_code.end() && it->second >= new_version) {
+      LOG(INFO) << "Skipping activation of " << apex.GetPath()
+                << " same package with higher version " << it->second
+                << " is already active";
+      skipped_cnt++;
+      continue;
+    }
+
+    if (auto res = activatePackageImpl(apex); !res.ok()) {
+      LOG(ERROR) << "Failed to activate " << apex.GetPath() << " : "
+                 << res.error();
+      failed_cnt++;
+    } else {
+      activated_cnt++;
     }
   }
-
   if (failed_cnt > 0) {
-    return Error() << "Failed to activate " << failed_cnt
-                   << " APEX packages. One of the errors: " << error_message;
+    return Error() << "Failed to activate " << failed_cnt << " APEX packages";
   }
-  LOG(INFO) << "Activated " << activated_cnt << " packages.";
+  LOG(INFO) << "Activated " << activated_cnt
+            << " packages. Skipped: " << skipped_cnt;
   return {};
 }
 
-// A fallback function in case some of the apexes failed to activate. For all
-// such apexes that were coming from /data partition we will attempt to activate
-// their corresponding pre-installed copies.
-Result<void> ActivateMissingApexes(const std::vector<ApexFileRef>& apexes,
-                                   bool is_ota_chroot) {
-  LOG(INFO) << "Trying to activate pre-installed versions of missing apexes";
-  const auto& file_repository = ApexFileRepository::GetInstance();
-  const auto& activated_apexes = GetActivePackagesMap();
-  std::vector<ApexFileRef> fallback_apexes;
-  for (const auto& apex_ref : apexes) {
-    const auto& apex = apex_ref.get();
-    if (apex.GetManifest().providesharedapexlibs()) {
-      // We must mount both versions of sharedlibs apex anyway. Not much we can
-      // do here.
-      continue;
-    }
-    if (file_repository.IsPreInstalledApex(apex)) {
-      // We tried to activate pre-installed apex in the first place. No need to
-      // try again.
-      continue;
-    }
-    const std::string& name = apex.GetManifest().name();
-    if (activated_apexes.find(name) == activated_apexes.end()) {
-      fallback_apexes.push_back(file_repository.GetPreInstalledApex(name));
-    }
-  }
-
-  // Process compressed APEX, if any
-  std::vector<ApexFileRef> compressed_apex;
-  for (auto it = fallback_apexes.begin(); it != fallback_apexes.end();) {
-    if (it->get().IsCompressed()) {
-      compressed_apex.emplace_back(*it);
-      it = fallback_apexes.erase(it);
-    } else {
-      it++;
-    }
-  }
-  std::vector<ApexFile> decompressed_apex;
-  if (!compressed_apex.empty()) {
-    decompressed_apex =
-        ProcessCompressedApex(compressed_apex, /* is_ota_chroot= */ false);
-    for (const ApexFile& apex_file : decompressed_apex) {
-      fallback_apexes.emplace_back(std::cref(apex_file));
-    }
-  }
-  return ActivateApexPackages(fallback_apexes, is_ota_chroot);
+bool ShouldActivateApexOnData(const ApexFile& apex) {
+  return HasPreInstalledVersion(apex.GetManifest().name());
 }
 
 }  // namespace
 
+Result<void> scanPackagesDirAndActivate(const char* apex_package_dir) {
+  auto apexes = ScanApexFiles(apex_package_dir);
+  if (!apexes) {
+    return apexes.error();
+  }
+  return ActivateApexPackages(*apexes);
+}
+
 /**
  * Snapshots data from base_dir/apexdata/<apex name> to
  * base_dir/apexrollback/<rollback id>/<apex name>.
  */
-Result<void> SnapshotDataDirectory(const std::string& base_dir,
+Result<void> snapshotDataDirectory(const std::string& base_dir,
                                    const int rollback_id,
                                    const std::string& apex_name,
                                    bool pre_restore = false) {
   auto rollback_path =
       StringPrintf("%s/%s/%d%s", base_dir.c_str(), kApexSnapshotSubDir,
                    rollback_id, pre_restore ? kPreRestoreSuffix : "");
-  const Result<void> result = CreateDirIfNeeded(rollback_path, 0700);
+  const Result<void> result = createDirIfNeeded(rollback_path, 0700);
   if (!result.ok()) {
     return Error() << "Failed to create snapshot directory for rollback "
                    << rollback_id << " : " << result.error();
@@ -1728,7 +1220,7 @@
  * to base_dir/apexdata/<apex name>.
  * Note the snapshot will be deleted after restoration succeeded.
  */
-Result<void> RestoreDataDirectory(const std::string& base_dir,
+Result<void> restoreDataDirectory(const std::string& base_dir,
                                   const int rollback_id,
                                   const std::string& apex_name,
                                   bool pre_restore = false) {
@@ -1752,13 +1244,13 @@
   return {};
 }
 
-void SnapshotOrRestoreDeIfNeeded(const std::string& base_dir,
+void snapshotOrRestoreDeIfNeeded(const std::string& base_dir,
                                  const ApexSession& session) {
   if (session.HasRollbackEnabled()) {
     for (const auto& apex_name : session.GetApexNames()) {
       Result<void> result =
-          SnapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name);
-      if (!result.ok()) {
+          snapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name);
+      if (!result) {
         LOG(ERROR) << "Snapshot failed for " << apex_name << ": "
                    << result.error();
       }
@@ -1767,11 +1259,11 @@
     for (const auto& apex_name : session.GetApexNames()) {
       if (!gSupportsFsCheckpoints) {
         // Snapshot before restore so this rollback can be reverted.
-        SnapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name,
+        snapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name,
                               true /* pre_restore */);
       }
       Result<void> result =
-          RestoreDataDirectory(base_dir, session.GetRollbackId(), apex_name);
+          restoreDataDirectory(base_dir, session.GetRollbackId(), apex_name);
       if (!result.ok()) {
         LOG(ERROR) << "Restore of data failed for " << apex_name << ": "
                    << result.error();
@@ -1780,18 +1272,18 @@
   }
 }
 
-void SnapshotOrRestoreDeSysData() {
+void snapshotOrRestoreDeSysData() {
   auto sessions = ApexSession::GetSessionsInState(SessionState::ACTIVATED);
 
   for (const ApexSession& session : sessions) {
-    SnapshotOrRestoreDeIfNeeded(kDeSysDataDir, session);
+    snapshotOrRestoreDeIfNeeded(kDeSysDataDir, session);
   }
 }
 
-int SnapshotOrRestoreDeUserData() {
+int snapshotOrRestoreDeUserData() {
   auto user_dirs = GetDeUserDirs();
 
-  if (!user_dirs.ok()) {
+  if (!user_dirs) {
     LOG(ERROR) << "Error reading dirs " << user_dirs.error();
     return 1;
   }
@@ -1800,69 +1292,93 @@
 
   for (const ApexSession& session : sessions) {
     for (const auto& user_dir : *user_dirs) {
-      SnapshotOrRestoreDeIfNeeded(user_dir, session);
+      snapshotOrRestoreDeIfNeeded(user_dir, session);
     }
   }
 
   return 0;
 }
 
-Result<void> SnapshotCeData(const int user_id, const int rollback_id,
-                            const std::string& apex_name) {
+Result<ino_t> snapshotCeData(const int user_id, const int rollback_id,
+                             const std::string& apex_name) {
   auto base_dir = StringPrintf("%s/%d", kCeDataDir, user_id);
-  return SnapshotDataDirectory(base_dir, rollback_id, apex_name);
+  Result<void> result = snapshotDataDirectory(base_dir, rollback_id, apex_name);
+  if (!result) {
+    return result.error();
+  }
+  auto ce_snapshot_path =
+      StringPrintf("%s/%s/%d/%s", base_dir.c_str(), kApexSnapshotSubDir,
+                   rollback_id, apex_name.c_str());
+  return get_path_inode(ce_snapshot_path);
 }
 
-Result<void> RestoreCeData(const int user_id, const int rollback_id,
+Result<void> restoreCeData(const int user_id, const int rollback_id,
                            const std::string& apex_name) {
   auto base_dir = StringPrintf("%s/%d", kCeDataDir, user_id);
-  return RestoreDataDirectory(base_dir, rollback_id, apex_name);
+  return restoreDataDirectory(base_dir, rollback_id, apex_name);
 }
 
 //  Migrates sessions directory from /data/apex/sessions to
 //  /metadata/apex/sessions, if necessary.
-Result<void> MigrateSessionsDirIfNeeded() {
-  return ApexSession::MigrateToMetadataSessionsDir();
+Result<void> migrateSessionsDirIfNeeded() {
+  namespace fs = std::filesystem;
+  auto from_path = std::string(kApexDataDir) + "/sessions";
+  auto exists = PathExists(from_path);
+  if (!exists) {
+    return Error() << "Failed to access " << from_path << ": "
+                   << exists.error();
+  }
+  if (!*exists) {
+    LOG(DEBUG) << from_path << " does not exist. Nothing to migrate.";
+    return {};
+  }
+  auto to_path = kApexSessionsDir;
+  std::error_code error_code;
+  fs::copy(from_path, to_path, fs::copy_options::recursive, error_code);
+  if (error_code) {
+    return Error() << "Failed to copy old sessions directory"
+                   << error_code.message();
+  }
+  fs::remove_all(from_path, error_code);
+  if (error_code) {
+    return Error() << "Failed to delete old sessions directory "
+                   << error_code.message();
+  }
+  return {};
 }
 
-Result<void> DestroySnapshots(const std::string& base_dir,
+Result<void> destroySnapshots(const std::string& base_dir,
                               const int rollback_id) {
   auto path = StringPrintf("%s/%s/%d", base_dir.c_str(), kApexSnapshotSubDir,
                            rollback_id);
   return DeleteDir(path);
 }
 
-Result<void> DestroyDeSnapshots(const int rollback_id) {
-  DestroySnapshots(kDeSysDataDir, rollback_id);
+Result<void> destroyDeSnapshots(const int rollback_id) {
+  destroySnapshots(kDeSysDataDir, rollback_id);
 
   auto user_dirs = GetDeUserDirs();
-  if (!user_dirs.ok()) {
+  if (!user_dirs) {
     return Error() << "Error reading user dirs " << user_dirs.error();
   }
 
   for (const auto& user_dir : *user_dirs) {
-    DestroySnapshots(user_dir, rollback_id);
+    destroySnapshots(user_dir, rollback_id);
   }
 
   return {};
 }
 
-Result<void> DestroyCeSnapshots(const int user_id, const int rollback_id) {
-  auto path = StringPrintf("%s/%d/%s/%d", kCeDataDir, user_id,
-                           kApexSnapshotSubDir, rollback_id);
-  return DeleteDir(path);
-}
-
 /**
  * Deletes all credential-encrypted snapshots for the given user, except for
  * those listed in retain_rollback_ids.
  */
-Result<void> DestroyCeSnapshotsNotSpecified(
+Result<void> destroyCeSnapshotsNotSpecified(
     int user_id, const std::vector<int>& retain_rollback_ids) {
   auto snapshot_root =
       StringPrintf("%s/%d/%s", kCeDataDir, user_id, kApexSnapshotSubDir);
   auto snapshot_dirs = GetSubdirs(snapshot_root);
-  if (!snapshot_dirs.ok()) {
+  if (!snapshot_dirs) {
     return Error() << "Error reading snapshot dirs " << snapshot_dirs.error();
   }
 
@@ -1874,7 +1390,7 @@
         std::find(retain_rollback_ids.begin(), retain_rollback_ids.end(),
                   snapshot_id) == retain_rollback_ids.end()) {
       Result<void> result = DeleteDir(snapshot_dir);
-      if (!result.ok()) {
+      if (!result) {
         return Error() << "Destroy CE snapshot failed for " << snapshot_dir
                        << " : " << result.error();
       }
@@ -1883,16 +1399,16 @@
   return {};
 }
 
-void RestorePreRestoreSnapshotsIfPresent(const std::string& base_dir,
+void restorePreRestoreSnapshotsIfPresent(const std::string& base_dir,
                                          const ApexSession& session) {
   auto pre_restore_snapshot_path =
       StringPrintf("%s/%s/%d%s", base_dir.c_str(), kApexSnapshotSubDir,
                    session.GetRollbackId(), kPreRestoreSuffix);
-  if (PathExists(pre_restore_snapshot_path).ok()) {
+  if (PathExists(pre_restore_snapshot_path)) {
     for (const auto& apex_name : session.GetApexNames()) {
-      Result<void> result = RestoreDataDirectory(
+      Result<void> result = restoreDataDirectory(
           base_dir, session.GetRollbackId(), apex_name, true /* pre_restore */);
-      if (!result.ok()) {
+      if (!result) {
         LOG(ERROR) << "Restore of pre-restore snapshot failed for " << apex_name
                    << ": " << result.error();
       }
@@ -1900,77 +1416,71 @@
   }
 }
 
-void RestoreDePreRestoreSnapshotsIfPresent(const ApexSession& session) {
-  RestorePreRestoreSnapshotsIfPresent(kDeSysDataDir, session);
+void restoreDePreRestoreSnapshotsIfPresent(const ApexSession& session) {
+  restorePreRestoreSnapshotsIfPresent(kDeSysDataDir, session);
 
   auto user_dirs = GetDeUserDirs();
-  if (!user_dirs.ok()) {
+  if (!user_dirs) {
     LOG(ERROR) << "Error reading user dirs to restore pre-restore snapshots"
                << user_dirs.error();
   }
 
   for (const auto& user_dir : *user_dirs) {
-    RestorePreRestoreSnapshotsIfPresent(user_dir, session);
+    restorePreRestoreSnapshotsIfPresent(user_dir, session);
   }
 }
 
-void DeleteDePreRestoreSnapshots(const std::string& base_dir,
+void deleteDePreRestoreSnapshots(const std::string& base_dir,
                                  const ApexSession& session) {
   auto pre_restore_snapshot_path =
       StringPrintf("%s/%s/%d%s", base_dir.c_str(), kApexSnapshotSubDir,
                    session.GetRollbackId(), kPreRestoreSuffix);
   Result<void> result = DeleteDir(pre_restore_snapshot_path);
-  if (!result.ok()) {
+  if (!result) {
     LOG(ERROR) << "Deletion of pre-restore snapshot failed: " << result.error();
   }
 }
 
-void DeleteDePreRestoreSnapshots(const ApexSession& session) {
-  DeleteDePreRestoreSnapshots(kDeSysDataDir, session);
+void deleteDePreRestoreSnapshots(const ApexSession& session) {
+  deleteDePreRestoreSnapshots(kDeSysDataDir, session);
 
   auto user_dirs = GetDeUserDirs();
-  if (!user_dirs.ok()) {
+  if (!user_dirs) {
     LOG(ERROR) << "Error reading user dirs to delete pre-restore snapshots"
                << user_dirs.error();
   }
 
   for (const auto& user_dir : *user_dirs) {
-    DeleteDePreRestoreSnapshots(user_dir, session);
+    deleteDePreRestoreSnapshots(user_dir, session);
   }
 }
 
-void OnBootCompleted() {
-  ApexdLifecycle::GetInstance().MarkBootCompleted();
-  BootCompletedCleanup();
-}
-
-// Returns true if any session gets staged
-void ScanStagedSessionsDirAndStage() {
-  LOG(INFO) << "Scanning " << ApexSession::GetSessionsDir()
+void scanStagedSessionsDirAndStage() {
+  LOG(INFO) << "Scanning " << kApexSessionsDir
             << " looking for sessions to be activated.";
 
-  auto sessions_to_activate =
+  auto sessionsToActivate =
       ApexSession::GetSessionsInState(SessionState::STAGED);
   if (gSupportsFsCheckpoints) {
     // A session that is in the ACTIVATED state should still be re-activated if
     // fs checkpointing is supported. In this case, a session may be in the
     // ACTIVATED state yet the data/apex/active directory may have been
     // reverted. The session should be reverted in this scenario.
-    auto activated_sessions =
+    auto activatedSessions =
         ApexSession::GetSessionsInState(SessionState::ACTIVATED);
-    sessions_to_activate.insert(sessions_to_activate.end(),
-                                activated_sessions.begin(),
-                                activated_sessions.end());
+    sessionsToActivate.insert(sessionsToActivate.end(),
+                              activatedSessions.begin(),
+                              activatedSessions.end());
   }
 
-  for (auto& session : sessions_to_activate) {
-    auto session_id = session.GetId();
+  for (auto& session : sessionsToActivate) {
+    auto sessionId = session.GetId();
 
     auto session_failed_fn = [&]() {
-      LOG(WARNING) << "Marking session " << session_id << " as failed.";
+      LOG(WARNING) << "Marking session " << sessionId << " as failed.";
       auto st = session.UpdateStateAndCommit(SessionState::ACTIVATION_FAILED);
       if (!st.ok()) {
-        LOG(WARNING) << "Failed to mark session " << session_id
+        LOG(WARNING) << "Failed to mark session " << sessionId
                      << " as failed : " << st.error();
       }
     };
@@ -1978,101 +1488,74 @@
 
     std::string build_fingerprint = GetProperty(kBuildFingerprintSysprop, "");
     if (session.GetBuildFingerprint().compare(build_fingerprint) != 0) {
-      auto error_message = "APEX build fingerprint has changed";
-      LOG(ERROR) << error_message;
-      session.SetErrorMessage(error_message);
+      LOG(ERROR) << "APEX build fingerprint has changed";
       continue;
     }
 
-    // If device supports fs-checkpoint, then apex session should only be
-    // installed when in checkpoint-mode. Otherwise, we will not be able to
-    // revert /data on error.
-    if (gSupportsFsCheckpoints && !gInFsCheckpointMode) {
-      auto error_message =
-          "Cannot install apex session if not in fs-checkpoint mode";
-      LOG(ERROR) << error_message;
-      session.SetErrorMessage(error_message);
-      continue;
-    }
-
-    std::vector<std::string> dirs_to_scan;
+    std::vector<std::string> dirsToScan;
     if (session.GetChildSessionIds().empty()) {
-      dirs_to_scan.push_back(std::string(gConfig->staged_session_dir) +
-                             "/session_" + std::to_string(session_id));
+      dirsToScan.push_back(std::string(kStagedSessionsDir) + "/session_" +
+                           std::to_string(sessionId));
     } else {
-      for (auto child_session_id : session.GetChildSessionIds()) {
-        dirs_to_scan.push_back(std::string(gConfig->staged_session_dir) +
-                               "/session_" + std::to_string(child_session_id));
+      for (auto childSessionId : session.GetChildSessionIds()) {
+        dirsToScan.push_back(std::string(kStagedSessionsDir) + "/session_" +
+                             std::to_string(childSessionId));
       }
     }
 
     std::vector<std::string> apexes;
-    bool scan_successful = true;
-    for (const auto& dir_to_scan : dirs_to_scan) {
-      Result<std::vector<std::string>> scan =
-          FindFilesBySuffix(dir_to_scan, {kApexPackageSuffix});
+    bool scanSuccessful = true;
+    for (const auto& dirToScan : dirsToScan) {
+      Result<std::vector<std::string>> scan = FindApexFilesByName(dirToScan);
       if (!scan.ok()) {
         LOG(WARNING) << scan.error();
-        session.SetErrorMessage(scan.error().message());
-        scan_successful = false;
+        scanSuccessful = false;
         break;
       }
 
       if (scan->size() > 1) {
-        std::string error_message = StringPrintf(
-            "More than one APEX package found in the same session directory %s "
-            ", skipping activation",
-            dir_to_scan.c_str());
-        LOG(WARNING) << error_message;
-        session.SetErrorMessage(error_message);
-        scan_successful = false;
+        LOG(WARNING) << "More than one APEX package found in the same session "
+                     << "directory " << dirToScan << ", skipping activation.";
+        scanSuccessful = false;
         break;
       }
 
       if (scan->empty()) {
-        std::string error_message = StringPrintf(
-            "No APEX packages found while scanning %s session id: %d.",
-            dir_to_scan.c_str(), session_id);
-        LOG(WARNING) << error_message;
-        session.SetErrorMessage(error_message);
-        scan_successful = false;
+        LOG(WARNING) << "No APEX packages found while scanning " << dirToScan
+                     << " session id: " << sessionId << ".";
+        scanSuccessful = false;
         break;
       }
       apexes.push_back(std::move((*scan)[0]));
     }
 
-    if (!scan_successful) {
+    if (!scanSuccessful) {
       continue;
     }
 
     // Run postinstall, if necessary.
-    Result<void> postinstall_status = PostinstallPackages(apexes);
+    Result<void> postinstall_status = postinstallPackages(apexes);
     if (!postinstall_status.ok()) {
-      std::string error_message =
-          StringPrintf("Postinstall failed for session %d %s", session_id,
-                       postinstall_status.error().message().c_str());
-      LOG(ERROR) << error_message;
-      session.SetErrorMessage(error_message);
+      LOG(ERROR) << "Postinstall failed for session "
+                 << std::to_string(sessionId) << ": "
+                 << postinstall_status.error();
       continue;
     }
 
     for (const auto& apex : apexes) {
-      // TODO(b/158470836): Avoid opening ApexFile repeatedly.
+      // TODO: Avoid opening ApexFile repeatedly.
       Result<ApexFile> apex_file = ApexFile::Open(apex);
-      if (!apex_file.ok()) {
+      if (!apex_file) {
         LOG(ERROR) << "Cannot open apex file during staging: " << apex;
         continue;
       }
       session.AddApexName(apex_file->GetManifest().name());
     }
 
-    const Result<void> result = StagePackages(apexes);
+    const Result<void> result = stagePackages(apexes);
     if (!result.ok()) {
-      std::string error_message = StringPrintf(
-          "Activation failed for packages %s : %s", Join(apexes, ',').c_str(),
-          result.error().message().c_str());
-      LOG(ERROR) << error_message;
-      session.SetErrorMessage(error_message);
+      LOG(ERROR) << "Activation failed for packages " << Join(apexes, ',')
+                 << ": " << result.error();
       continue;
     }
 
@@ -2087,61 +1570,49 @@
   }
 }
 
-Result<void> PreinstallPackages(const std::vector<std::string>& paths) {
-  Result<std::vector<ApexFile>> apex_files = OpenApexFiles(paths);
-  if (!apex_files.ok()) {
-    return apex_files.error();
+Result<void> preinstallPackages(const std::vector<std::string>& paths) {
+  if (paths.empty()) {
+    return Errorf("Empty set of inputs");
   }
-  LOG(DEBUG) << "PreinstallPackages() for " << Join(paths, ',');
-  return PreinstallPackages(*apex_files);
+  LOG(DEBUG) << "preinstallPackages() for " << Join(paths, ',');
+  return HandlePackages<Result<void>>(paths, PreinstallPackages);
 }
 
-Result<void> PostinstallPackages(const std::vector<std::string>& paths) {
-  Result<std::vector<ApexFile>> apex_files = OpenApexFiles(paths);
-  if (!apex_files.ok()) {
-    return apex_files.error();
+Result<void> postinstallPackages(const std::vector<std::string>& paths) {
+  if (paths.empty()) {
+    return Errorf("Empty set of inputs");
   }
-  LOG(DEBUG) << "PostinstallPackages() for " << Join(paths, ',');
-  return PostinstallPackages(*apex_files);
+  LOG(DEBUG) << "postinstallPackages() for " << Join(paths, ',');
+  return HandlePackages<Result<void>>(paths, PostinstallPackages);
 }
 
 namespace {
 std::string StageDestPath(const ApexFile& apex_file) {
-  return StringPrintf("%s/%s%s", gConfig->active_apex_data_dir,
+  return StringPrintf("%s/%s%s", kActiveApexPackagesDataDir,
                       GetPackageId(apex_file.GetManifest()).c_str(),
                       kApexPackageSuffix);
 }
 
 }  // namespace
 
-Result<void> StagePackages(const std::vector<std::string>& tmp_paths) {
-  if (tmp_paths.empty()) {
+Result<void> stagePackages(const std::vector<std::string>& tmpPaths) {
+  if (tmpPaths.empty()) {
     return Errorf("Empty set of inputs");
   }
-  LOG(DEBUG) << "StagePackages() for " << Join(tmp_paths, ',');
+  LOG(DEBUG) << "stagePackages() for " << Join(tmpPaths, ',');
 
   // Note: this function is temporary. As such the code is not optimized, e.g.,
   //       it will open ApexFiles multiple times.
 
   // 1) Verify all packages.
-  Result<std::vector<ApexFile>> apex_files = OpenApexFiles(tmp_paths);
-  if (!apex_files.ok()) {
-    return apex_files.error();
-  }
-  for (const ApexFile& apex_file : *apex_files) {
-    if (shim::IsShimApex(apex_file)) {
-      // Shim apex will be validated on every boot. No need to do it here.
-      continue;
-    }
-    Result<void> result = VerifyPackageBoot(apex_file);
-    if (!result.ok()) {
-      return result.error();
-    }
+  auto verify_status = verifyPackages(tmpPaths, VerifyPackageBoot);
+  if (!verify_status.ok()) {
+    return verify_status.error();
   }
 
   // Make sure that kActiveApexPackagesDataDir exists.
   auto create_dir_status =
-      CreateDirIfNeeded(std::string(gConfig->active_apex_data_dir), 0755);
+      createDirIfNeeded(std::string(kActiveApexPackagesDataDir), 0755);
   if (!create_dir_status.ok()) {
     return create_dir_status.error();
   }
@@ -2166,12 +1637,16 @@
   auto scope_guard = android::base::make_scope_guard(deleter);
 
   std::unordered_set<std::string> staged_packages;
-  for (const ApexFile& apex_file : *apex_files) {
+  for (const std::string& path : tmpPaths) {
+    Result<ApexFile> apex_file = ApexFile::Open(path);
+    if (!apex_file.ok()) {
+      return apex_file.error();
+    }
     // First promote new hashtree file to the one that will be used when
     // mounting apex.
-    std::string new_hashtree_file = GetHashTreeFileName(apex_file,
+    std::string new_hashtree_file = GetHashTreeFileName(*apex_file,
                                                         /* is_new = */ true);
-    std::string old_hashtree_file = GetHashTreeFileName(apex_file,
+    std::string old_hashtree_file = GetHashTreeFileName(*apex_file,
                                                         /* is_new = */ false);
     if (access(new_hashtree_file.c_str(), F_OK) == 0) {
       if (TEMP_FAILURE_RETRY(rename(new_hashtree_file.c_str(),
@@ -2182,7 +1657,7 @@
       changed_hashtree_files.emplace_back(std::move(old_hashtree_file));
     }
     // And only then move apex to /data/apex/active.
-    std::string dest_path = StageDestPath(apex_file);
+    std::string dest_path = StageDestPath(*apex_file);
     if (access(dest_path.c_str(), F_OK) == 0) {
       LOG(DEBUG) << dest_path << " already exists. Deleting";
       if (TEMP_FAILURE_RETRY(unlink(dest_path.c_str())) != 0) {
@@ -2190,14 +1665,15 @@
       }
     }
 
-    if (link(apex_file.GetPath().c_str(), dest_path.c_str()) != 0) {
-      return ErrnoError() << "Unable to link " << apex_file.GetPath() << " to "
+    if (link(apex_file->GetPath().c_str(), dest_path.c_str()) != 0) {
+      // TODO: Get correct binder error status.
+      return ErrnoError() << "Unable to link " << apex_file->GetPath() << " to "
                           << dest_path;
     }
     staged_files.insert(dest_path);
-    staged_packages.insert(apex_file.GetManifest().name());
+    staged_packages.insert(apex_file->GetManifest().name());
 
-    LOG(DEBUG) << "Success linking " << apex_file.GetPath() << " to "
+    LOG(DEBUG) << "Success linking " << apex_file->GetPath() << " to "
                << dest_path;
   }
 
@@ -2206,19 +1682,18 @@
   return RemovePreviouslyActiveApexFiles(staged_packages, staged_files);
 }
 
-Result<void> UnstagePackages(const std::vector<std::string>& paths) {
+Result<void> unstagePackages(const std::vector<std::string>& paths) {
   if (paths.empty()) {
     return Errorf("Empty set of inputs");
   }
-  LOG(DEBUG) << "UnstagePackages() for " << Join(paths, ',');
+  LOG(DEBUG) << "unstagePackages() for " << Join(paths, ',');
+
+  // TODO: to make unstage safer, we can copy to be unstaged packages to a
+  // temporary folder and restore state from it in case unstagePackages fails.
 
   for (const std::string& path : paths) {
-    auto apex = ApexFile::Open(path);
-    if (!apex.ok()) {
-      return apex.error();
-    }
-    if (ApexFileRepository::GetInstance().IsPreInstalledApex(*apex)) {
-      return Error() << "Can't uninstall pre-installed apex " << path;
+    if (access(path.c_str(), F_OK) != 0) {
+      return ErrnoError() << "Can't access " << path;
     }
   }
 
@@ -2240,57 +1715,59 @@
  * Also, we need to put staged sessions in /data/apex/sessions in REVERTED state
  * so that they do not get activated on next reboot.
  */
-Result<void> RevertActiveSessions(const std::string& crashing_native_process,
-                                  const std::string& error_message) {
+Result<void> revertActiveSessions(const std::string& crashing_native_process) {
   // First check whenever there is anything to revert. If there is none, then
   // fail. This prevents apexd from boot looping a device in case a native
   // process is crashing and there are no apex updates.
-  auto active_sessions = ApexSession::GetActiveSessions();
-  if (active_sessions.empty()) {
+  auto activeSessions = ApexSession::GetActiveSessions();
+  if (activeSessions.empty()) {
     return Error() << "Revert requested, when there are no active sessions.";
   }
 
-  for (auto& session : active_sessions) {
+  for (auto& session : activeSessions) {
     if (!crashing_native_process.empty()) {
       session.SetCrashingNativeProcess(crashing_native_process);
     }
-    if (!error_message.empty()) {
-      session.SetErrorMessage(error_message);
-    }
     auto status =
         session.UpdateStateAndCommit(SessionState::REVERT_IN_PROGRESS);
-    if (!status.ok()) {
+    if (!status) {
+      // TODO: should we continue with a revert?
       return Error() << "Revert of session " << session
                      << " failed : " << status.error();
     }
   }
 
+  if (!gInFsCheckpointMode) {
+    // SafetyNet logging for b/19393765
+    android_errorWriteLog(0x534e4554, "193932765");
+  }
+
   if (!gSupportsFsCheckpoints) {
-    auto restore_status = RestoreActivePackages();
-    if (!restore_status.ok()) {
-      for (auto& session : active_sessions) {
+    auto restoreStatus = RestoreActivePackages();
+    if (!restoreStatus.ok()) {
+      for (auto& session : activeSessions) {
         auto st = session.UpdateStateAndCommit(SessionState::REVERT_FAILED);
         LOG(DEBUG) << "Marking " << session << " as failed to revert";
-        if (!st.ok()) {
+        if (!st) {
           LOG(WARNING) << "Failed to mark session " << session
                        << " as failed to revert : " << st.error();
         }
       }
-      return restore_status;
+      return restoreStatus;
     }
   } else {
     LOG(INFO) << "Not restoring active packages in checkpoint mode.";
   }
 
-  for (auto& session : active_sessions) {
+  for (auto& session : activeSessions) {
     if (!gSupportsFsCheckpoints && session.IsRollback()) {
       // If snapshots have already been restored, undo that by restoring the
       // pre-restore snapshot.
-      RestoreDePreRestoreSnapshotsIfPresent(session);
+      restoreDePreRestoreSnapshotsIfPresent(session);
     }
 
     auto status = session.UpdateStateAndCommit(SessionState::REVERTED);
-    if (!status.ok()) {
+    if (!status) {
       LOG(WARNING) << "Failed to mark session " << session
                    << " as reverted : " << status.error();
     }
@@ -2299,10 +1776,9 @@
   return {};
 }
 
-Result<void> RevertActiveSessionsAndReboot(
-    const std::string& crashing_native_process,
-    const std::string& error_message) {
-  auto status = RevertActiveSessions(crashing_native_process, error_message);
+Result<void> revertActiveSessionsAndReboot(
+    const std::string& crashing_native_process) {
+  auto status = revertActiveSessions(crashing_native_process);
   if (!status.ok()) {
     return status;
   }
@@ -2318,101 +1794,49 @@
   return {};
 }
 
-Result<void> CreateSharedLibsApexDir() {
-  // Creates /apex/sharedlibs/lib{,64} for SharedLibs APEXes.
-  std::string shared_libs_sub_dir =
-      StringPrintf("%s/%s", kApexRoot, kApexSharedLibsSubDir);
-  auto dir_exists = PathExists(shared_libs_sub_dir);
-  if (!dir_exists.ok() || !*dir_exists) {
-    std::error_code error_code;
-    std::filesystem::create_directory(shared_libs_sub_dir, error_code);
-    if (error_code) {
-      return Error() << "Failed to create directory " << shared_libs_sub_dir
-                     << ": " << error_code.message();
-    }
-  }
-  for (const auto& lib_path : {"lib", "lib64"}) {
-    std::string apex_lib_path =
-        StringPrintf("%s/%s", shared_libs_sub_dir.c_str(), lib_path);
-    auto lib_dir_exists = PathExists(apex_lib_path);
-    if (!lib_dir_exists.ok() || !*lib_dir_exists) {
-      std::error_code error_code;
-      std::filesystem::create_directory(apex_lib_path, error_code);
-      if (error_code) {
-        return Error() << "Failed to create directory " << apex_lib_path << ": "
-                       << error_code.message();
-      }
-    }
-  }
+int onBootstrap() {
+  gBootstrap = true;
 
-  return {};
-}
-
-int OnBootstrap() {
-  auto time_started = boot_clock::now();
-  Result<void> pre_allocate = PreAllocateLoopDevices();
-  if (!pre_allocate.ok()) {
+  Result<void> preAllocate = preAllocateLoopDevices();
+  if (!preAllocate.ok()) {
     LOG(ERROR) << "Failed to pre-allocate loop devices : "
-               << pre_allocate.error();
+               << preAllocate.error();
   }
 
-  ApexFileRepository& instance = ApexFileRepository::GetInstance();
-  static const std::vector<std::string> kBootstrapApexDirs{
+  std::vector<std::string> bootstrap_apex_dirs{
       kApexPackageSystemDir, kApexPackageSystemExtDir, kApexPackageVendorDir};
-  Result<void> status = instance.AddPreInstalledApex(kBootstrapApexDirs);
+  Result<void> status = collectPreinstalledData(bootstrap_apex_dirs);
   if (!status.ok()) {
     LOG(ERROR) << "Failed to collect APEX keys : " << status.error();
     return 1;
   }
 
-  // Create directories for APEX shared libraries.
-  auto sharedlibs_apex_dir = CreateSharedLibsApexDir();
-  if (!sharedlibs_apex_dir.ok()) {
-    LOG(ERROR) << sharedlibs_apex_dir.error();
-    return 1;
-  }
-
-  // Find all bootstrap apexes
-  std::vector<ApexFile> bootstrap_apexes;
-  for (const auto& dir : kBootstrapApexDirs) {
-    auto scan = ScanApexFiles(dir.c_str());
-    if (!scan.ok()) {
+  // Activate built-in APEXes for processes launched before /data is mounted.
+  for (const auto& dir : bootstrap_apex_dirs) {
+    auto scan_status = ScanApexFiles(dir.c_str());
+    if (!scan_status.ok()) {
       LOG(ERROR) << "Failed to scan APEX files in " << dir << " : "
-                 << scan.error();
+                 << scan_status.error();
       return 1;
     }
-    std::copy_if(std::make_move_iterator(scan->begin()),
-                 std::make_move_iterator(scan->end()),
-                 std::back_inserter(bootstrap_apexes), IsBootstrapApex);
+    if (auto ret = ActivateApexPackages(*scan_status); !ret.ok()) {
+      LOG(ERROR) << "Failed to activate APEX files in " << dir << " : "
+                 << ret.error();
+      return 1;
+    }
   }
-
-  // Now activate bootstrap apexes.
-  std::vector<ApexFileRef> bootstrap_apexes_ref;
-  std::transform(bootstrap_apexes.begin(), bootstrap_apexes.end(),
-                 std::back_inserter(bootstrap_apexes_ref),
-                 [](const auto& x) { return std::cref(x); });
-  auto ret = ActivateApexPackages(bootstrap_apexes_ref,
-                                  /* is_ota_chroot= */ false);
-  if (!ret.ok()) {
-    LOG(ERROR) << "Failed to activate bootstrap apex files : " << ret.error();
-    return 1;
-  }
-
-  OnAllPackagesActivated(/*is_bootstrap=*/true);
-  auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
-    boot_clock::now() - time_started).count();
-  LOG(INFO) << "OnBootstrap done, duration=" << time_elapsed;
+  LOG(INFO) << "Bootstrapping done";
   return 0;
 }
 
-Result<void> RemountApexFile(const std::string& path) {
-  if (auto ret = DeactivatePackage(path); !ret.ok()) {
+Result<void> remountApexFile(const std::string& path) {
+  if (auto ret = deactivatePackage(path); !ret.ok()) {
     return ret;
   }
-  return ActivatePackage(path);
+  return activatePackage(path);
 }
 
-void InitializeVold(CheckpointInterface* checkpoint_service) {
+void initializeVold(CheckpointInterface* checkpoint_service) {
   if (checkpoint_service != nullptr) {
     gVoldService = checkpoint_service;
     Result<bool> supports_fs_checkpoints =
@@ -2435,327 +1859,21 @@
   }
 }
 
-void Initialize(CheckpointInterface* checkpoint_service) {
-  InitializeVold(checkpoint_service);
-  ApexFileRepository& instance = ApexFileRepository::GetInstance();
-  Result<void> status = instance.AddPreInstalledApex(kApexPackageBuiltinDirs);
+void initialize(CheckpointInterface* checkpoint_service) {
+  initializeVold(checkpoint_service);
+  Result<void> status = collectPreinstalledData(kApexPackageBuiltinDirs);
   if (!status.ok()) {
-    LOG(ERROR) << "Failed to collect pre-installed APEX files : "
-               << status.error();
+    LOG(ERROR) << "Failed to collect APEX keys : " << status.error();
     return;
   }
-  gMountedApexes.PopulateFromMounts(gConfig->active_apex_data_dir,
-                                    gConfig->decompression_dir,
-                                    gConfig->apex_hash_tree_dir);
+
+  gMountedApexes.PopulateFromMounts();
 }
 
-// Note: Pre-installed apex are initialized in Initialize(CheckpointInterface*)
-// TODO(b/172911822): Consolidate this with Initialize() when
-//  ApexFileRepository can act as cache and re-scanning is not expensive
-void InitializeDataApex() {
-  ApexFileRepository& instance = ApexFileRepository::GetInstance();
-  Result<void> status = instance.AddDataApex(kActiveApexPackagesDataDir);
-  if (!status.ok()) {
-    LOG(ERROR) << "Failed to collect data APEX files : " << status.error();
-    return;
-  }
-}
-
-/**
- * For every package X, there can be at most two APEX, pre-installed vs
- * installed on data. We usually select only one of these APEX for each package
- * based on the following conditions:
- *   - Package X must be pre-installed on one of the built-in directories.
- *   - If there are multiple APEX, we select the one with highest version.
- *   - If there are multiple with same version, we give priority to APEX on
- * /data partition.
- *
- * Typically, only one APEX is activated for each package, but APEX that provide
- * shared libs are exceptions. We have to activate both APEX for them.
- *
- * @param all_apex all the APEX grouped by their package name
- * @return list of ApexFile that needs to be activated
- */
-std::vector<ApexFileRef> SelectApexForActivation(
-    const std::unordered_map<std::string, std::vector<ApexFileRef>>& all_apex,
-    const ApexFileRepository& instance) {
-  LOG(INFO) << "Selecting APEX for activation";
-  std::vector<ApexFileRef> activation_list;
-  // For every package X, select which APEX to activate
-  for (auto& apex_it : all_apex) {
-    const std::string& package_name = apex_it.first;
-    const std::vector<ApexFileRef>& apex_files = apex_it.second;
-
-    if (apex_files.size() > 2 || apex_files.size() == 0) {
-      LOG(FATAL) << "Unexpectedly found more than two versions or none for "
-                    "APEX package "
-                 << package_name;
-      continue;
-    }
-
-    // The package must have a pre-installed version before we consider it for
-    // activation
-    if (!instance.HasPreInstalledVersion(package_name)) {
-      LOG(INFO) << "Package " << package_name << " is not pre-installed";
-      continue;
-    }
-
-    if (apex_files.size() == 1) {
-      LOG(DEBUG) << "Selecting the only APEX: " << package_name << " "
-                 << apex_files[0].get().GetPath();
-      activation_list.emplace_back(apex_files[0]);
-      continue;
-    }
-
-    // TODO(b/179497746): Now that we are dealing with list of reference, this
-    //  selection process can be simplified by sorting the vector.
-
-    // Given an APEX A and the version of the other APEX B, should we activate
-    // it?
-    auto select_apex = [&instance, &activation_list](
-                           const ApexFileRef& a_ref,
-                           const int version_b) mutable {
-      const ApexFile& a = a_ref.get();
-      // If A has higher version than B, then it should be activated
-      const bool higher_version = a.GetManifest().version() > version_b;
-      // If A has same version as B, then data version should get activated
-      const bool same_version_priority_to_data =
-          a.GetManifest().version() == version_b &&
-          !instance.IsPreInstalledApex(a);
-
-      // APEX that provides shared library are special:
-      //  - if preinstalled version is lower than data version, both versions
-      //    are activated.
-      //  - if preinstalled version is equal to data version, data version only
-      //    is activated.
-      //  - if preinstalled version is higher than data version, preinstalled
-      //    version only is activated.
-      const bool provides_shared_apex_libs =
-          a.GetManifest().providesharedapexlibs();
-      bool activate = false;
-      if (provides_shared_apex_libs) {
-        // preinstalled version gets activated in all cases except when same
-        // version as data.
-        if (instance.IsPreInstalledApex(a) &&
-            (a.GetManifest().version() != version_b)) {
-          LOG(DEBUG) << "Activating preinstalled shared libs APEX: "
-                     << a.GetManifest().name() << " " << a.GetPath();
-          activate = true;
-        }
-        // data version gets activated in all cases except when its version
-        // is lower than preinstalled version.
-        if (!instance.IsPreInstalledApex(a) &&
-            (a.GetManifest().version() >= version_b)) {
-          LOG(DEBUG) << "Activating shared libs APEX: "
-                     << a.GetManifest().name() << " " << a.GetPath();
-          activate = true;
-        }
-      } else if (higher_version || same_version_priority_to_data) {
-        LOG(DEBUG) << "Selecting between two APEX: " << a.GetManifest().name()
-                   << " " << a.GetPath();
-        activate = true;
-      }
-      if (activate) {
-        activation_list.emplace_back(a_ref);
-      }
-    };
-    const int version_0 = apex_files[0].get().GetManifest().version();
-    const int version_1 = apex_files[1].get().GetManifest().version();
-    select_apex(apex_files[0].get(), version_1);
-    select_apex(apex_files[1].get(), version_0);
-  }
-  return activation_list;
-}
-
-namespace {
-
-Result<ApexFile> OpenAndValidateDecompressedApex(const ApexFile& capex,
-                                                 const std::string& apex_path) {
-  auto apex = ApexFile::Open(apex_path);
-  if (!apex.ok()) {
-    return Error() << "Failed to open decompressed APEX: " << apex.error();
-  }
-  auto result = ValidateDecompressedApex(capex, *apex);
-  if (!result.ok()) {
-    return result.error();
-  }
-  return std::move(*apex);
-}
-
-// Process a single compressed APEX. Returns the decompressed APEX if
-// successful.
-Result<ApexFile> ProcessCompressedApex(const ApexFile& capex,
-                                       bool is_ota_chroot) {
-  LOG(INFO) << "Processing compressed APEX " << capex.GetPath();
-  const auto decompressed_apex_path =
-      StringPrintf("%s/%s%s", gConfig->decompression_dir,
-                   GetPackageId(capex.GetManifest()).c_str(),
-                   kDecompressedApexPackageSuffix);
-  // Check if decompressed APEX already exist
-  auto decompressed_path_exists = PathExists(decompressed_apex_path);
-  if (decompressed_path_exists.ok() && *decompressed_path_exists) {
-    // Check if existing decompressed APEX is valid
-    auto result =
-        OpenAndValidateDecompressedApex(capex, decompressed_apex_path);
-    if (result.ok()) {
-      LOG(INFO) << "Skipping decompression for " << capex.GetPath();
-      return result;
-    }
-    // Do not delete existing decompressed APEX when is_ota_chroot is true
-    if (!is_ota_chroot) {
-      // Existing decompressed APEX is not valid. We will have to redecompress
-      LOG(WARNING) << "Existing decompressed APEX is invalid: "
-                   << result.error();
-      RemoveFileIfExists(decompressed_apex_path);
-    }
-  }
-
-  // We can also reuse existing OTA APEX, depending on situation
-  auto ota_apex_path = StringPrintf("%s/%s%s", gConfig->decompression_dir,
-                                    GetPackageId(capex.GetManifest()).c_str(),
-                                    kOtaApexPackageSuffix);
-  auto ota_path_exists = PathExists(ota_apex_path);
-  if (ota_path_exists.ok() && *ota_path_exists) {
-    if (is_ota_chroot) {
-      // During ota_chroot, we try to reuse ota APEX as is
-      auto result = OpenAndValidateDecompressedApex(capex, ota_apex_path);
-      if (result.ok()) {
-        LOG(INFO) << "Skipping decompression for " << ota_apex_path;
-        return result;
-      }
-      // Existing ota_apex is not valid. We will have to decompress
-      LOG(WARNING) << "Existing decompressed OTA APEX is invalid: "
-                   << result.error();
-      RemoveFileIfExists(ota_apex_path);
-    } else {
-      // During boot, we can avoid decompression by renaming OTA apex
-      // to expected decompressed_apex path
-
-      // Check if ota_apex APEX is valid
-      auto result = OpenAndValidateDecompressedApex(capex, ota_apex_path);
-      if (result.ok()) {
-        // ota_apex matches with capex. Slot has been switched.
-
-        // Rename ota_apex to expected decompressed_apex path
-        if (rename(ota_apex_path.c_str(), decompressed_apex_path.c_str()) ==
-            0) {
-          // Check if renamed decompressed APEX is valid
-          result =
-              OpenAndValidateDecompressedApex(capex, decompressed_apex_path);
-          if (result.ok()) {
-            LOG(INFO) << "Renamed " << ota_apex_path << " to "
-                      << decompressed_apex_path;
-            return result;
-          }
-          // Renamed ota_apex is not valid. We will have to decompress
-          LOG(WARNING) << "Renamed decompressed APEX from " << ota_apex_path
-                       << " to " << decompressed_apex_path
-                       << " is invalid: " << result.error();
-          RemoveFileIfExists(decompressed_apex_path);
-        } else {
-          PLOG(ERROR) << "Failed to rename file " << ota_apex_path;
-        }
-      }
-    }
-  }
-
-  // There was no way to avoid decompression
-
-  // Clean up reserved space before decompressing capex
-  if (auto ret = DeleteDirContent(gConfig->ota_reserved_dir); !ret.ok()) {
-    LOG(ERROR) << "Failed to clean up reserved space: " << ret.error();
-  }
-
-  auto decompression_dest =
-      is_ota_chroot ? ota_apex_path : decompressed_apex_path;
-  auto scope_guard = android::base::make_scope_guard(
-      [&]() { RemoveFileIfExists(decompression_dest); });
-
-  auto decompression_result = capex.Decompress(decompression_dest);
-  if (!decompression_result.ok()) {
-    return Error() << "Failed to decompress : " << capex.GetPath().c_str()
-                   << " " << decompression_result.error();
-  }
-
-  // Fix label of decompressed file
-  auto restore = RestoreconPath(decompression_dest);
-  if (!restore.ok()) {
-    return restore.error();
-  }
-
-  // Validate the newly decompressed APEX
-  auto return_apex = OpenAndValidateDecompressedApex(capex, decompression_dest);
-  if (!return_apex.ok()) {
-    return Error() << "Failed to decompress CAPEX: " << return_apex.error();
-  }
-
-  /// Release compressed blocks in case decompression_dest is on f2fs-compressed
-  // filesystem.
-  ReleaseF2fsCompressedBlocks(decompression_dest);
-
-  scope_guard.Disable();
-  return return_apex;
-}
-}  // namespace
-
-/**
- * For each compressed APEX, decompress it to kApexDecompressedDir
- * and return the decompressed APEX.
- *
- * Returns list of decompressed APEX.
- */
-std::vector<ApexFile> ProcessCompressedApex(
-    const std::vector<ApexFileRef>& compressed_apex, bool is_ota_chroot) {
-  LOG(INFO) << "Processing compressed APEX";
-
-  std::vector<ApexFile> decompressed_apex_list;
-  for (const ApexFile& capex : compressed_apex) {
-    if (!capex.IsCompressed()) {
-      continue;
-    }
-
-    auto decompressed_apex = ProcessCompressedApex(capex, is_ota_chroot);
-    if (decompressed_apex.ok()) {
-      decompressed_apex_list.emplace_back(std::move(*decompressed_apex));
-      continue;
-    }
-    LOG(ERROR) << "Failed to process compressed APEX: "
-               << decompressed_apex.error();
-  }
-  return std::move(decompressed_apex_list);
-}
-
-Result<void> ValidateDecompressedApex(const ApexFile& capex,
-                                      const ApexFile& apex) {
-  // Decompressed APEX must have same public key as CAPEX
-  if (capex.GetBundledPublicKey() != apex.GetBundledPublicKey()) {
-    return Error()
-           << "Public key of compressed APEX is different than original "
-           << "APEX for " << apex.GetPath();
-  }
-  // Decompressed APEX must have same version as CAPEX
-  if (capex.GetManifest().version() != apex.GetManifest().version()) {
-    return Error()
-           << "Compressed APEX has different version than decompressed APEX "
-           << apex.GetPath();
-  }
-  // Decompressed APEX must have same root digest as what is stored in CAPEX
-  auto apex_verity = apex.VerifyApexVerity(apex.GetBundledPublicKey());
-  if (!apex_verity.ok() ||
-      capex.GetManifest().capexmetadata().originalapexdigest() !=
-          apex_verity->root_digest) {
-    return Error() << "Root digest of " << apex.GetPath()
-                   << " does not match with"
-                   << " expected root digest in " << capex.GetPath();
-  }
-  return {};
-}
-
-void OnStart() {
+void onStart() {
   LOG(INFO) << "Marking APEXd as starting";
-  auto time_started = boot_clock::now();
-  if (!SetProperty(gConfig->apex_status_sysprop, kApexStatusStarting)) {
-    PLOG(ERROR) << "Failed to set " << gConfig->apex_status_sysprop << " to "
+  if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusStarting)) {
+    PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
                 << kApexStatusStarting;
   }
 
@@ -2771,134 +1889,98 @@
       LOG(INFO) << "Exceeded number of session retries ("
                 << kNumRetriesWhenCheckpointingEnabled
                 << "). Starting a revert";
-      RevertActiveSessions("", "");
+      revertActiveSessions("");
     }
   }
 
-  // Create directories for APEX shared libraries.
-  auto sharedlibs_apex_dir = CreateSharedLibsApexDir();
-  if (!sharedlibs_apex_dir.ok()) {
-    LOG(ERROR) << sharedlibs_apex_dir.error();
-  }
-
-  // If there is any new apex to be installed on /data/app-staging, hardlink
-  // them to /data/apex/active first.
-  ScanStagedSessionsDirAndStage();
-  if (auto status = ApexFileRepository::GetInstance().AddDataApex(
-          gConfig->active_apex_data_dir);
-      !status.ok()) {
-    LOG(ERROR) << "Failed to collect data APEX files : " << status.error();
-  }
-
-  auto status = ResumeRevertIfNeeded();
+  // Activate APEXes from /data/apex. If one in the directory is newer than the
+  // system one, the new one will eclipse the old one.
+  scanStagedSessionsDirAndStage();
+  auto status = resumeRevertIfNeeded();
   if (!status.ok()) {
     LOG(ERROR) << "Failed to resume revert : " << status.error();
   }
 
-  // Group every ApexFile on device by name
-  const auto& instance = ApexFileRepository::GetInstance();
-  const auto& all_apex = instance.AllApexFilesByName();
-  // There can be multiple APEX packages with package name X. Determine which
-  // one to activate.
-  auto activation_list = SelectApexForActivation(all_apex, instance);
-
-  // Process compressed APEX, if any
-  std::vector<ApexFileRef> compressed_apex;
-  for (auto it = activation_list.begin(); it != activation_list.end();) {
-    if (it->get().IsCompressed()) {
-      compressed_apex.emplace_back(*it);
-      it = activation_list.erase(it);
-    } else {
-      it++;
+  std::vector<ApexFile> data_apex;
+  if (auto scan = ScanApexFiles(kActiveApexPackagesDataDir); !scan.ok()) {
+    LOG(ERROR) << "Failed to scan packages from " << kActiveApexPackagesDataDir
+               << " : " << scan.error();
+    if (auto revert = revertActiveSessionsAndReboot(""); !revert.ok()) {
+      LOG(ERROR) << "Failed to revert : " << revert.error();
     }
-  }
-  std::vector<ApexFile> decompressed_apex;
-  if (!compressed_apex.empty()) {
-    decompressed_apex =
-        ProcessCompressedApex(compressed_apex, /* is_ota_chroot= */ false);
-    for (const ApexFile& apex_file : decompressed_apex) {
-      activation_list.emplace_back(std::cref(apex_file));
-    }
+  } else {
+    auto filter_fn = [](const ApexFile& apex) {
+      if (!ShouldActivateApexOnData(apex)) {
+        LOG(WARNING) << "Skipping " << apex.GetPath();
+        return false;
+      }
+      return true;
+    };
+    std::copy_if(std::make_move_iterator(scan->begin()),
+                 std::make_move_iterator(scan->end()),
+                 std::back_inserter(data_apex), filter_fn);
   }
 
-  int data_apex_cnt = std::count_if(
-      activation_list.begin(), activation_list.end(), [](const auto& a) {
-        return !ApexFileRepository::GetInstance().IsPreInstalledApex(a.get());
-      });
-  if (data_apex_cnt > 0) {
-    Result<void> pre_allocate = loop::PreAllocateLoopDevices(data_apex_cnt);
-    if (!pre_allocate.ok()) {
-      LOG(ERROR) << "Failed to pre-allocate loop devices : "
-                 << pre_allocate.error();
-    }
-  }
-
-  // TODO(b/179248390): activate parallelly if possible
-  auto activate_status =
-      ActivateApexPackages(activation_list, /* is_ota_chroot= */ false);
-  if (!activate_status.ok()) {
-    std::string error_message =
-        StringPrintf("Failed to activate packages: %s",
-                     activate_status.error().message().c_str());
-    LOG(ERROR) << error_message;
-    Result<void> revert_status =
-        RevertActiveSessionsAndReboot("", error_message);
+  if (auto ret = ActivateApexPackages(data_apex); !ret.ok()) {
+    LOG(ERROR) << "Failed to activate packages from "
+               << kActiveApexPackagesDataDir << " : " << status.error();
+    Result<void> revert_status = revertActiveSessionsAndReboot("");
     if (!revert_status.ok()) {
-      LOG(ERROR) << "Failed to revert : " << revert_status.error();
+      // TODO: should we kill apexd in this case?
+      LOG(ERROR) << "Failed to revert : " << revert_status.error()
+                 << kActiveApexPackagesDataDir << " : " << ret.error();
     }
-    auto retry_status = ActivateMissingApexes(activation_list,
-                                              /* is_ota_chroot= */ false);
-    if (!retry_status.ok()) {
-      LOG(ERROR) << retry_status.error();
+  }
+
+  // Now also scan and activate APEXes from pre-installed directories.
+  for (const auto& dir : kApexPackageBuiltinDirs) {
+    auto scan_status = ScanApexFiles(dir.c_str());
+    if (!scan_status.ok()) {
+      LOG(ERROR) << "Failed to scan APEX packages from " << dir << " : "
+                 << scan_status.error();
+      if (auto revert = revertActiveSessionsAndReboot(""); !revert.ok()) {
+        LOG(ERROR) << "Failed to revert : " << revert.error();
+      }
+    }
+    if (auto activate = ActivateApexPackages(*scan_status); !activate.ok()) {
+      // This should never happen. Like **really** never.
+      // TODO: should we kill apexd in this case?
+      LOG(ERROR) << "Failed to activate packages from " << dir << " : "
+                 << activate.error();
     }
   }
 
   // Now that APEXes are mounted, snapshot or restore DE_sys data.
-  SnapshotOrRestoreDeSysData();
-
-  auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
-    boot_clock::now() - time_started).count();
-  LOG(INFO) << "OnStart done, duration=" << time_elapsed;
+  snapshotOrRestoreDeSysData();
 }
 
-void OnAllPackagesActivated(bool is_bootstrap) {
-  auto result = EmitApexInfoList(is_bootstrap);
-  if (!result.ok()) {
-    LOG(ERROR) << "cannot emit apex info list: " << result.error();
-  }
-
-  // Because apexd in bootstrap mode runs in blocking mode
-  // we don't have to set as activated.
-  if (is_bootstrap) {
-    return;
-  }
-
+void onAllPackagesActivated() {
   // Set a system property to let other components know that APEXs are
   // activated, but are not yet ready to be used. init is expected to wait
   // for this status before performing configuration based on activated
   // apexes. Other components that need to use APEXs should wait for the
   // ready state instead.
   LOG(INFO) << "Marking APEXd as activated";
-  if (!SetProperty(gConfig->apex_status_sysprop, kApexStatusActivated)) {
-    PLOG(ERROR) << "Failed to set " << gConfig->apex_status_sysprop << " to "
+  if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusActivated)) {
+    PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
                 << kApexStatusActivated;
   }
 }
 
-void OnAllPackagesReady() {
+void onAllPackagesReady() {
   // Set a system property to let other components know that APEXs are
   // correctly mounted and ready to be used. Before using any file from APEXs,
   // they can query this system property to ensure that they are okay to
   // access. Or they may have a on-property trigger to delay a task until
   // APEXs become ready.
   LOG(INFO) << "Marking APEXd as ready";
-  if (!SetProperty(gConfig->apex_status_sysprop, kApexStatusReady)) {
-    PLOG(ERROR) << "Failed to set " << gConfig->apex_status_sysprop << " to "
+  if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusReady)) {
+    PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
                 << kApexStatusReady;
   }
 }
 
-Result<std::vector<ApexFile>> SubmitStagedSession(
+Result<std::vector<ApexFile>> submitStagedSession(
     const int session_id, const std::vector<int>& child_session_ids,
     const bool has_rollback_enabled, const bool is_rollback,
     const int rollback_id) {
@@ -2922,13 +2004,8 @@
   }
 
   std::vector<ApexFile> ret;
-  auto guard = android::base::make_scope_guard([&ret]() {
-    for (const auto& apex : ret) {
-      apexd_private::UnmountTempMount(apex);
-    }
-  });
   for (int id_to_scan : ids_to_scan) {
-    auto verified = VerifySessionDir(id_to_scan);
+    auto verified = verifySessionDir(id_to_scan);
     if (!verified.ok()) {
       return verified.error();
     }
@@ -2962,15 +2039,10 @@
     return commit_status.error();
   }
 
-  for (const auto& apex : ret) {
-    // Release compressed blocks in case /data is f2fs-compressed filesystem.
-    ReleaseF2fsCompressedBlocks(apex.GetPath());
-  }
-
   return ret;
 }
 
-Result<void> MarkStagedSessionReady(const int session_id) {
+Result<void> markStagedSessionReady(const int session_id) {
   auto session = ApexSession::GetSession(session_id);
   if (!session.ok()) {
     return session.error();
@@ -2989,7 +2061,7 @@
                  << ". Cannot mark it as ready.";
 }
 
-Result<void> MarkStagedSessionSuccessful(const int session_id) {
+Result<void> markStagedSessionSuccessful(const int session_id) {
   auto session = ApexSession::GetSession(session_id);
   if (!session.ok()) {
     return session.error();
@@ -3005,7 +2077,7 @@
                      << " as successful : " << cleanup_status.error();
     }
     if (session->IsRollback() && !gSupportsFsCheckpoints) {
-      DeleteDePreRestoreSnapshots(*session);
+      deleteDePreRestoreSnapshots(*session);
     }
     return session->UpdateStateAndCommit(SessionState::SUCCESS);
   } else {
@@ -3013,63 +2085,86 @@
   }
 }
 
-// Removes APEXes on /data that have not been activated
-void RemoveInactiveDataApex() {
-  std::vector<std::string> all_apex_files;
-  Result<std::vector<std::string>> active_apex =
-      FindFilesBySuffix(gConfig->active_apex_data_dir, {kApexPackageSuffix});
-  if (!active_apex.ok()) {
-    LOG(ERROR) << "Failed to scan " << gConfig->active_apex_data_dir << " : "
-               << active_apex.error();
-  } else {
-    all_apex_files.insert(all_apex_files.end(),
-                          std::make_move_iterator(active_apex->begin()),
-                          std::make_move_iterator(active_apex->end()));
-  }
-  Result<std::vector<std::string>> decompressed_apex = FindFilesBySuffix(
-      gConfig->decompression_dir, {kDecompressedApexPackageSuffix});
-  if (!decompressed_apex.ok()) {
-    LOG(ERROR) << "Failed to scan " << gConfig->decompression_dir << " : "
-               << decompressed_apex.error();
-  } else {
-    all_apex_files.insert(all_apex_files.end(),
-                          std::make_move_iterator(decompressed_apex->begin()),
-                          std::make_move_iterator(decompressed_apex->end()));
+namespace {
+
+// Find dangling mounts and unmount them.
+// If one is on /data/apex/active, remove it.
+void UnmountDanglingMounts() {
+  std::multimap<std::string, MountedApexData> danglings;
+  gMountedApexes.ForallMountedApexes([&](const std::string& package,
+                                         const MountedApexData& data,
+                                         bool latest) {
+    if (!latest) {
+      danglings.insert({package, data});
+    }
+  });
+
+  for (const auto& [package, data] : danglings) {
+    const std::string& path = data.full_path;
+    LOG(VERBOSE) << "Unmounting " << data.mount_point;
+    gMountedApexes.RemoveMountedApex(package, path);
+    if (auto st = Unmount(data); !st.ok()) {
+      LOG(ERROR) << st.error();
+    }
+    if (StartsWith(path, kActiveApexPackagesDataDir)) {
+      LOG(VERBOSE) << "Deleting old APEX " << path;
+      if (unlink(path.c_str()) != 0) {
+        PLOG(ERROR) << "Failed to delete " << path;
+      }
+    }
   }
 
-  for (const auto& path : all_apex_files) {
-    if (!apexd_private::IsMounted(path)) {
-      LOG(INFO) << "Removing inactive data APEX " << path;
+  RemoveObsoleteHashTrees();
+}
+
+// Removes APEXes on /data that don't have corresponding pre-installed version
+// or that are corrupt
+void RemoveOrphanedApexes() {
+  auto data_apexes = FindApexFilesByName(kActiveApexPackagesDataDir);
+  if (!data_apexes.ok()) {
+    LOG(ERROR) << "Failed to scan " << kActiveApexPackagesDataDir << " : "
+               << data_apexes.error();
+    return;
+  }
+  for (const auto& path : *data_apexes) {
+    auto apex = ApexFile::Open(path);
+    if (!apex.ok()) {
+      LOG(DEBUG) << "Failed to open APEX " << path << " : " << apex.error();
+      // before removing, double-check if the path is active or not
+      // just in case ApexFile::Open() fails with valid APEX
+      if (!apexd_private::IsMounted(path)) {
+        LOG(DEBUG) << "Removing corrupt APEX " << path;
+        if (unlink(path.c_str()) != 0) {
+          PLOG(ERROR) << "Failed to unlink " << path;
+        }
+      }
+      continue;
+    }
+    if (!ShouldActivateApexOnData(*apex)) {
+      LOG(DEBUG) << "Removing orphaned APEX " << path;
       if (unlink(path.c_str()) != 0) {
-        PLOG(ERROR) << "Failed to unlink inactive data APEX " << path;
+        PLOG(ERROR) << "Failed to unlink " << path;
       }
     }
   }
 }
 
-void BootCompletedCleanup() {
-  RemoveInactiveDataApex();
-  ApexSession::DeleteFinalizedSessions();
+}  // namespace
+
+void bootCompletedCleanup() {
+  UnmountDanglingMounts();
+  RemoveOrphanedApexes();
 }
 
-int UnmountAll() {
-  gMountedApexes.PopulateFromMounts(gConfig->active_apex_data_dir,
-                                    gConfig->decompression_dir,
-                                    gConfig->apex_hash_tree_dir);
+int unmountAll() {
+  gMountedApexes.PopulateFromMounts();
   int ret = 0;
   gMountedApexes.ForallMountedApexes([&](const std::string& /*package*/,
                                          const MountedApexData& data,
                                          bool latest) {
     LOG(INFO) << "Unmounting " << data.full_path << " mounted on "
               << data.mount_point;
-    auto apex = ApexFile::Open(data.full_path);
-    if (!apex.ok()) {
-      LOG(ERROR) << "Failed to open " << data.full_path << " : "
-                 << apex.error();
-      ret = 1;
-      return;
-    }
-    if (latest && !apex->GetManifest().providesharedapexlibs()) {
+    if (latest) {
       auto pos = data.mount_point.find('@');
       CHECK(pos != std::string::npos);
       std::string bind_mount = data.mount_point.substr(0, pos);
@@ -3078,7 +2173,7 @@
         ret = 1;
       }
     }
-    if (auto status = Unmount(data, /* deferred= */ false); !status.ok()) {
+    if (auto status = Unmount(data); !status.ok()) {
       LOG(ERROR) << "Failed to unmount " << data.mount_point << " : "
                  << status.error();
       ret = 1;
@@ -3087,7 +2182,12 @@
   return ret;
 }
 
-Result<void> RemountPackages() {
+bool isBooting() {
+  auto status = GetProperty(kApexStatusSysprop, "");
+  return status != kApexStatusReady && status != kApexStatusActivated;
+}
+
+Result<void> remountPackages() {
   std::vector<std::string> apexes;
   gMountedApexes.ForallMountedApexes([&apexes](const std::string& /*package*/,
                                                const MountedApexData& data,
@@ -3101,7 +2201,7 @@
   for (const std::string& apex : apexes) {
     // Since this is only used during development workflow, we are trying to
     // remount as many apexes as possible instead of failing fast.
-    if (auto ret = RemountApexFile(apex); !ret.ok()) {
+    if (auto ret = remountApexFile(apex); !ret) {
       LOG(WARNING) << "Failed to remount " << apex << " : " << ret.error();
       failed.emplace_back(apex);
     }
@@ -3118,596 +2218,5 @@
   return {};
 }
 
-// Given a single new APEX incoming via OTA, should we allocate space for it?
-Result<bool> ShouldAllocateSpaceForDecompression(
-    const std::string& new_apex_name, const int64_t new_apex_version,
-    const ApexFileRepository& instance) {
-  // An apex at most will have two versions on device: pre-installed and data.
-
-  // Check if there is a pre-installed version for the new apex.
-  if (!instance.HasPreInstalledVersion(new_apex_name)) {
-    // We are introducing a new APEX that doesn't exist at all
-    return true;
-  }
-
-  // Check if there is a data apex
-  if (!instance.HasDataVersion(new_apex_name)) {
-    // Data apex doesn't exist. Compare against pre-installed APEX
-    auto pre_installed_apex = instance.GetPreInstalledApex(new_apex_name);
-    if (!pre_installed_apex.get().IsCompressed()) {
-      // Compressing an existing uncompressed system APEX.
-      return true;
-    }
-    // Since there is no data apex, it means device is using the compressed
-    // pre-installed version. If new apex has higher version, we are upgrading
-    // the pre-install version and if new apex has lower version, we are
-    // downgrading it. So the current decompressed apex should be replaced
-    // with the new decompressed apex to reflect that.
-    const int64_t pre_installed_version =
-        instance.GetPreInstalledApex(new_apex_name)
-            .get()
-            .GetManifest()
-            .version();
-    return new_apex_version != pre_installed_version;
-  }
-
-  // From here on, data apex exists. So we should compare directly against data
-  // apex.
-  auto data_apex = instance.GetDataApex(new_apex_name);
-  // Compare the data apex version with new apex
-  const int64_t data_version = data_apex.get().GetManifest().version();
-  // We only decompress the new_apex if it has higher version than data apex.
-  return new_apex_version > data_version;
-}
-
-void CollectApexInfoList(std::ostream& os,
-                         const std::vector<ApexFile>& active_apexs,
-                         const std::vector<ApexFile>& inactive_apexs) {
-  std::vector<com::android::apex::ApexInfo> apex_infos;
-
-  auto convert_to_autogen = [&apex_infos](const ApexFile& apex,
-                                          bool is_active) {
-    auto& instance = ApexFileRepository::GetInstance();
-
-    auto preinstalled_path =
-        instance.GetPreinstalledPath(apex.GetManifest().name());
-    std::optional<std::string> preinstalled_module_path;
-    if (preinstalled_path.ok()) {
-      preinstalled_module_path = *preinstalled_path;
-    }
-
-    std::optional<int64_t> mtime;
-    struct stat stat_buf;
-    if (stat(apex.GetPath().c_str(), &stat_buf) == 0) {
-      mtime.emplace(stat_buf.st_mtime);
-    } else {
-      PLOG(WARNING) << "Failed to stat " << apex.GetPath();
-    }
-    com::android::apex::ApexInfo apex_info(
-        apex.GetManifest().name(), apex.GetPath(), preinstalled_module_path,
-        apex.GetManifest().version(), apex.GetManifest().versionname(),
-        instance.IsPreInstalledApex(apex), is_active, mtime);
-    apex_infos.emplace_back(apex_info);
-  };
-  for (const auto& apex : active_apexs) {
-    convert_to_autogen(apex, /* is_active= */ true);
-  }
-  for (const auto& apex : inactive_apexs) {
-    convert_to_autogen(apex, /* is_active= */ false);
-  }
-  com::android::apex::ApexInfoList apex_info_list(apex_infos);
-  com::android::apex::write(os, apex_info_list);
-}
-
-// Reserve |size| bytes in |dest_dir| by creating a zero-filled file.
-// Also, we always clean up ota_apex that has been processed as
-// part of pre-reboot decompression whenever we reserve space.
-Result<void> ReserveSpaceForCompressedApex(int64_t size,
-                                           const std::string& dest_dir) {
-  if (size < 0) {
-    return Error() << "Cannot reserve negative byte of space";
-  }
-
-  // Since we are reserving space, then we must be preparing for a new OTA.
-  // Clean up any processed ota_apex from previous OTA.
-  auto ota_apex_files =
-      FindFilesBySuffix(gConfig->decompression_dir, {kOtaApexPackageSuffix});
-  if (!ota_apex_files.ok()) {
-    return Error() << "Failed to clean up ota_apex: " << ota_apex_files.error();
-  }
-  for (const std::string& ota_apex : *ota_apex_files) {
-    RemoveFileIfExists(ota_apex);
-  }
-
-  auto file_path = StringPrintf("%s/full.tmp", dest_dir.c_str());
-  if (size == 0) {
-    LOG(INFO) << "Cleaning up reserved space for compressed APEX";
-    // Ota is being cancelled. Clean up reserved space
-    RemoveFileIfExists(file_path);
-    return {};
-  }
-
-  LOG(INFO) << "Reserving " << size << " bytes for compressed APEX";
-  unique_fd dest_fd(
-      open(file_path.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT, 0644));
-  if (dest_fd.get() == -1) {
-    return ErrnoError() << "Failed to open file for reservation "
-                        << file_path.c_str();
-  }
-
-  // Resize to required size
-  std::error_code ec;
-  std::filesystem::resize_file(file_path, size, ec);
-  if (ec) {
-    RemoveFileIfExists(file_path);
-    return ErrnoError() << "Failed to resize file " << file_path.c_str()
-                        << " : " << ec.message();
-  }
-
-  return {};
-}
-
-int OnOtaChrootBootstrap() {
-  auto& instance = ApexFileRepository::GetInstance();
-  if (auto status = instance.AddPreInstalledApex(gConfig->apex_built_in_dirs);
-      !status.ok()) {
-    LOG(ERROR) << "Failed to scan pre-installed apexes from "
-               << Join(gConfig->apex_built_in_dirs, ',');
-    return 1;
-  }
-  if (auto status = instance.AddDataApex(gConfig->active_apex_data_dir);
-      !status.ok()) {
-    LOG(ERROR) << "Failed to scan upgraded apexes from "
-               << gConfig->active_apex_data_dir;
-    // Failing to scan upgraded apexes is not fatal, since we can still try to
-    // run otapreopt using only pre-installed apexes. Worst case, apps will be
-    // re-optimized on next boot.
-  }
-
-  // Create directories for APEX shared libraries.
-  if (auto status = CreateSharedLibsApexDir(); !status.ok()) {
-    LOG(ERROR) << "Failed to create /apex/sharedlibs : " << status.ok();
-    return 1;
-  }
-
-  auto activation_list =
-      SelectApexForActivation(instance.AllApexFilesByName(), instance);
-
-  // TODO(b/179497746): This is the third time we are duplicating this code
-  // block. This will be easier to dedup once we start opening ApexFiles via
-  // ApexFileRepository. That way, ProcessCompressedApex can return list of
-  // ApexFileRef, instead of ApexFile.
-
-  // Process compressed APEX, if any
-  std::vector<ApexFileRef> compressed_apex;
-  for (auto it = activation_list.begin(); it != activation_list.end();) {
-    if (it->get().IsCompressed()) {
-      compressed_apex.emplace_back(*it);
-      it = activation_list.erase(it);
-    } else {
-      it++;
-    }
-  }
-  std::vector<ApexFile> decompressed_apex;
-  if (!compressed_apex.empty()) {
-    decompressed_apex =
-        ProcessCompressedApex(compressed_apex, /* is_ota_chroot= */ true);
-
-    for (const ApexFile& apex_file : decompressed_apex) {
-      activation_list.emplace_back(std::cref(apex_file));
-    }
-  }
-
-  auto activate_status = ActivateApexPackages(activation_list,
-                                              /* is_ota_chroot= */ true);
-  if (!activate_status.ok()) {
-    LOG(ERROR) << "Failed to activate apex packages : "
-               << activate_status.error();
-    auto retry_status = ActivateMissingApexes(activation_list,
-                                              /* is_ota_chroot= */ true);
-    if (!retry_status.ok()) {
-      LOG(ERROR) << retry_status.error();
-    }
-  }
-
-  // There are a bunch of places that are producing apex-info.xml file.
-  // We should consolidate the logic in one function and make all other places
-  // use it.
-  auto active_apexes = GetActivePackages();
-  std::vector<ApexFile> inactive_apexes = GetFactoryPackages();
-  auto new_end = std::remove_if(
-      inactive_apexes.begin(), inactive_apexes.end(),
-      [&active_apexes](const ApexFile& apex) {
-        return std::any_of(active_apexes.begin(), active_apexes.end(),
-                           [&apex](const ApexFile& active_apex) {
-                             return apex.GetPath() == active_apex.GetPath();
-                           });
-      });
-  inactive_apexes.erase(new_end, inactive_apexes.end());
-  std::stringstream xml;
-  CollectApexInfoList(xml, active_apexes, inactive_apexes);
-  std::string file_name = StringPrintf("%s/%s", kApexRoot, kApexInfoList);
-  unique_fd fd(TEMP_FAILURE_RETRY(
-      open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
-  if (fd.get() == -1) {
-    PLOG(ERROR) << "Can't open " << file_name;
-    return 1;
-  }
-
-  if (!android::base::WriteStringToFd(xml.str(), fd)) {
-    PLOG(ERROR) << "Can't write to " << file_name;
-    return 1;
-  }
-
-  fd.reset();
-
-  if (auto status = RestoreconPath(file_name); !status.ok()) {
-    LOG(ERROR) << "Failed to restorecon " << file_name << " : "
-               << status.error();
-    return 1;
-  }
-
-  return 0;
-}
-
-int OnOtaChrootBootstrapFlattenedApex() {
-  LOG(INFO) << "OnOtaChrootBootstrapFlattenedApex";
-
-  std::vector<com::android::apex::ApexInfo> apex_infos;
-
-  for (const std::string& dir : gConfig->apex_built_in_dirs) {
-    LOG(INFO) << "Scanning " << dir;
-    auto dir_content = ReadDir(dir, [](const auto& entry) {
-      std::error_code ec;
-      return entry.is_directory(ec);
-    });
-
-    if (!dir_content.ok()) {
-      LOG(ERROR) << "Failed to scan " << dir << " : " << dir_content.error();
-      continue;
-    }
-
-    // Sort to make sure that /apex/apex-info-list.xml generation doesn't depend
-    // on the unstable directory scan.
-    std::vector<std::string> entries = std::move(*dir_content);
-    std::sort(entries.begin(), entries.end());
-
-    for (const std::string& apex_dir : entries) {
-      std::string manifest_file = apex_dir + "/" + kManifestFilenamePb;
-      if (access(manifest_file.c_str(), F_OK) != 0) {
-        PLOG(ERROR) << "Failed to access " << manifest_file;
-        continue;
-      }
-
-      auto manifest = ReadManifest(manifest_file);
-      if (!manifest.ok()) {
-        LOG(ERROR) << "Failed to read apex manifest from " << manifest_file
-                   << " : " << manifest.error();
-        continue;
-      }
-
-      std::string mount_point = std::string(kApexRoot) + "/" + manifest->name();
-      if (mkdir(mount_point.c_str(), 0755) != 0) {
-        PLOG(ERROR) << "Failed to mkdir " << mount_point;
-        continue;
-      }
-
-      LOG(INFO) << "Bind mounting " << apex_dir << " onto " << mount_point;
-      if (mount(apex_dir.c_str(), mount_point.c_str(), nullptr, MS_BIND,
-                nullptr) != 0) {
-        PLOG(ERROR) << "Failed to bind mount " << apex_dir << " to "
-                    << mount_point;
-        continue;
-      }
-
-      apex_infos.emplace_back(manifest->name(), /* modulePath= */ apex_dir,
-                              /* preinstalledModulePath= */ apex_dir,
-                              /* versionCode= */ manifest->version(),
-                              /* versionName= */ manifest->versionname(),
-                              /* isFactory= */ true, /* isActive= */ true,
-                              /* lastUpdateMillis= */ 0);
-    }
-  }
-
-  std::string file_name = StringPrintf("%s/%s", kApexRoot, kApexInfoList);
-  unique_fd fd(TEMP_FAILURE_RETRY(
-      open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
-  if (fd.get() == -1) {
-    PLOG(ERROR) << "Can't open " << file_name;
-    return 1;
-  }
-
-  std::ostringstream xml;
-  com::android::apex::ApexInfoList apex_info_list(apex_infos);
-  com::android::apex::write(xml, apex_info_list);
-  if (!android::base::WriteStringToFd(xml.str(), fd)) {
-    PLOG(ERROR) << "Can't write to " << file_name;
-    return 1;
-  }
-  fd.reset();
-
-  if (auto status = RestoreconPath(file_name); !status.ok()) {
-    LOG(ERROR) << "Failed to restorecon " << file_name << " : "
-               << status.error();
-    return 1;
-  }
-
-  return 0;
-}
-
-android::apex::MountedApexDatabase& GetApexDatabaseForTesting() {
-  return gMountedApexes;
-}
-
-// A version of apex verification that happens during non-staged APEX
-// installation.
-Result<void> VerifyPackageNonStagedInstall(const ApexFile& apex_file) {
-  const auto& verify_package_boot_status = VerifyPackageBoot(apex_file);
-  if (!verify_package_boot_status.ok()) {
-    return verify_package_boot_status;
-  }
-
-  auto check_fn = [&apex_file](const std::string& mount_point) -> Result<void> {
-    auto dirs = GetSubdirs(mount_point);
-    if (!dirs.ok()) {
-      return dirs.error();
-    }
-    if (std::find(dirs->begin(), dirs->end(), mount_point + "/app") !=
-        dirs->end()) {
-      return Error() << apex_file.GetPath() << " contains app inside";
-    }
-    if (std::find(dirs->begin(), dirs->end(), mount_point + "/priv-app") !=
-        dirs->end()) {
-      return Error() << apex_file.GetPath() << " contains priv-app inside";
-    }
-    return Result<void>{};
-  };
-  return RunVerifyFnInsideTempMount(apex_file, check_fn, true);
-}
-
-Result<void> CheckSupportsNonStagedInstall(const ApexFile& cur_apex,
-                                           const ApexFile& new_apex) {
-  const auto& cur_manifest = cur_apex.GetManifest();
-  const auto& new_manifest = new_apex.GetManifest();
-
-  if (!new_manifest.supportsrebootlessupdate()) {
-    return Error() << new_apex.GetPath()
-                   << " does not support non-staged update";
-  }
-
-  // Check if update will impact linkerconfig.
-
-  // Updates to shared libs APEXes must be done via staged install flow.
-  if (new_manifest.providesharedapexlibs()) {
-    return Error() << new_apex.GetPath() << " is a shared libs APEX";
-  }
-
-  // This APEX provides native libs to other parts of the platform. It can only
-  // be updated via staged install flow.
-  if (new_manifest.providenativelibs_size() > 0) {
-    return Error() << new_apex.GetPath() << " provides native libs";
-  }
-
-  // This APEX requires libs provided by dynamic common library APEX, hence it
-  // can only be installed using staged install flow.
-  if (new_manifest.requiresharedapexlibs_size() > 0) {
-    return Error() << new_apex.GetPath() << " requires shared apex libs";
-  }
-
-  // We don't allow non-staged updates of APEXES that have java libs inside.
-  if (new_manifest.jnilibs_size() > 0) {
-    return Error() << new_apex.GetPath() << " requires JNI libs";
-  }
-
-  // For requireNativeLibs bit, we only allow updates that don't change list of
-  // required libs.
-
-  std::vector<std::string> cur_required_libs(
-      cur_manifest.requirenativelibs().begin(),
-      cur_manifest.requirenativelibs().end());
-  sort(cur_required_libs.begin(), cur_required_libs.end());
-
-  std::vector<std::string> new_required_libs(
-      new_manifest.requirenativelibs().begin(),
-      new_manifest.requirenativelibs().end());
-  sort(new_required_libs.begin(), new_required_libs.end());
-
-  if (cur_required_libs != new_required_libs) {
-    return Error() << "Set of native libs required by " << new_apex.GetPath()
-                   << " differs from the one required by the currently active "
-                   << cur_apex.GetPath();
-  }
-
-  auto expected_public_key =
-      ApexFileRepository::GetInstance().GetPublicKey(new_manifest.name());
-  if (!expected_public_key.ok()) {
-    return expected_public_key.error();
-  }
-  auto verity_data = new_apex.VerifyApexVerity(*expected_public_key);
-  if (!verity_data.ok()) {
-    return verity_data.error();
-  }
-  // Supporting non-staged install of APEXes without a hashtree is additional
-  // hassle, it's easier not to support it.
-  if (verity_data->desc->tree_size == 0) {
-    return Error() << new_apex.GetPath()
-                   << " does not have an embedded hash tree";
-  }
-  return {};
-}
-
-Result<size_t> ComputePackageIdMinor(const ApexFile& apex) {
-  static constexpr size_t kMaxVerityDevicesPerApexName = 3u;
-  DeviceMapper& dm = DeviceMapper::Instance();
-  std::vector<DeviceMapper::DmBlockDevice> dm_devices;
-  if (!dm.GetAvailableDevices(&dm_devices)) {
-    return Error() << "Failed to list dm devices";
-  }
-  size_t devices = 0;
-  size_t next_minor = 1;
-  for (const auto& dm_device : dm_devices) {
-    std::string_view dm_name(dm_device.name());
-    // Format is <module_name>@<version_code>[_<minor>]
-    if (!ConsumePrefix(&dm_name, apex.GetManifest().name())) {
-      continue;
-    }
-    devices++;
-    auto pos = dm_name.find_last_of('_');
-    if (pos == std::string_view::npos) {
-      continue;
-    }
-    size_t minor;
-    if (!ParseUint(std::string(dm_name.substr(pos + 1)), &minor)) {
-      return Error() << "Unexpected dm device name " << dm_device.name();
-    }
-    if (next_minor < minor + 1) {
-      next_minor = minor + 1;
-    }
-  }
-  if (devices > kMaxVerityDevicesPerApexName) {
-    return Error() << "There are too many (" << devices
-                   << ") dm block devices associated with package "
-                   << apex.GetManifest().name();
-  }
-  while (true) {
-    std::string target_file =
-        StringPrintf("%s/%s_%zu.apex", gConfig->active_apex_data_dir,
-                     GetPackageId(apex.GetManifest()).c_str(), next_minor);
-    if (access(target_file.c_str(), F_OK) == 0) {
-      next_minor++;
-    } else {
-      break;
-    }
-  }
-
-  return next_minor;
-}
-
-Result<void> UpdateApexInfoList() {
-  std::vector<ApexFile> active(GetActivePackages());
-  std::vector<ApexFile> inactive = CalculateInactivePackages(active);
-
-  std::stringstream xml;
-  CollectApexInfoList(xml, active, inactive);
-
-  std::string name = StringPrintf("%s/.default-%s", kApexRoot, kApexInfoList);
-  unique_fd fd(TEMP_FAILURE_RETRY(
-      open(name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)));
-  if (fd.get() == -1) {
-    return ErrnoError() << "Can't open " << name;
-  }
-  if (!WriteStringToFd(xml.str(), fd)) {
-    return ErrnoError() << "Failed to write to " << name;
-  }
-
-  return {};
-}
-
-Result<ApexFile> InstallPackage(const std::string& package_path) {
-  LOG(INFO) << "Installing " << package_path;
-  auto temp_apex = ApexFile::Open(package_path);
-  if (!temp_apex.ok()) {
-    return temp_apex.error();
-  }
-
-  const std::string& module_name = temp_apex->GetManifest().name();
-  // Don't allow non-staged update if there are no active versions of this APEX.
-  auto cur_mounted_data = gMountedApexes.GetLatestMountedApex(module_name);
-  if (!cur_mounted_data.has_value()) {
-    return Error() << "No active version found for package " << module_name;
-  }
-
-  auto cur_apex = ApexFile::Open(cur_mounted_data->full_path);
-  if (!cur_apex.ok()) {
-    return cur_apex.error();
-  }
-
-  // Do a quick check if this APEX can be installed without a reboot.
-  // Note that passing this check doesn't guarantee that APEX will be
-  // successfully installed.
-  if (auto r = CheckSupportsNonStagedInstall(*cur_apex, *temp_apex); !r.ok()) {
-    return r.error();
-  }
-
-  // 1. Verify that APEX is correct. This is a heavy check that involves
-  // mounting an APEX on a temporary mount point and reading the entire
-  // dm-verity block device.
-  if (auto verify = VerifyPackageNonStagedInstall(*temp_apex); !verify.ok()) {
-    return verify.error();
-  }
-
-  // 2. Compute params for mounting new apex.
-  auto new_id_minor = ComputePackageIdMinor(*temp_apex);
-  if (!new_id_minor.ok()) {
-    return new_id_minor.error();
-  }
-
-  std::string new_id = GetPackageId(temp_apex->GetManifest()) + "_" +
-                       std::to_string(*new_id_minor);
-
-  // 2. Unmount currently active APEX.
-  if (auto res = UnmountPackage(*cur_apex, /* allow_latest= */ true,
-                                /* deferred= */ true);
-      !res.ok()) {
-    return res.error();
-  }
-
-  // 3. Hard link to final destination.
-  std::string target_file =
-      StringPrintf("%s/%s.apex", gConfig->active_apex_data_dir, new_id.c_str());
-
-  auto guard = android::base::make_scope_guard([&]() {
-    if (unlink(target_file.c_str()) != 0 && errno != ENOENT) {
-      PLOG(ERROR) << "Failed to unlink " << target_file;
-    }
-    // We can't really rely on the fact that dm-verity device backing up
-    // previously active APEX is still around. We need to create a new one.
-    std::string old_new_id = GetPackageId(temp_apex->GetManifest()) + "_" +
-                             std::to_string(*new_id_minor + 1);
-    if (auto res = ActivatePackageImpl(*cur_apex, old_new_id); !res.ok()) {
-      // At this point not much we can do... :(
-      LOG(ERROR) << res.error();
-    }
-  });
-
-  // At this point it should be safe to hard link |temp_apex| to
-  // |params->target_file|. In case reboot happens during one of the stages
-  // below, then on next boot apexd will pick up the new verified APEX.
-  if (link(package_path.c_str(), target_file.c_str()) != 0) {
-    return ErrnoError() << "Failed to link " << package_path << " to "
-                        << target_file;
-  }
-
-  auto new_apex = ApexFile::Open(target_file);
-  if (!new_apex.ok()) {
-    return new_apex.error();
-  }
-
-  // 4. And activate new one.
-  if (auto res = ActivatePackageImpl(*new_apex, new_id); !res.ok()) {
-    return res.error();
-  }
-
-  // Accept the install.
-  guard.Disable();
-
-  // 4. Now we can unlink old APEX if it's not pre-installed.
-  if (!ApexFileRepository::GetInstance().IsPreInstalledApex(*cur_apex)) {
-    if (unlink(cur_mounted_data->full_path.c_str()) != 0) {
-      PLOG(ERROR) << "Failed to unlink " << cur_mounted_data->full_path;
-    }
-  }
-
-  if (auto res = UpdateApexInfoList(); !res.ok()) {
-    LOG(ERROR) << res.error();
-  }
-
-  // Release compressed blocks in case target_file is on f2fs-compressed
-  // filesystem.
-  ReleaseF2fsCompressedBlocks(target_file);
-
-  return new_apex;
-}
-
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apexd.h b/apexd/apexd.h
index 2465bde..36f72be 100644
--- a/apexd/apexd.h
+++ b/apexd/apexd.h
@@ -17,7 +17,6 @@
 #ifndef ANDROID_APEXD_APEXD_H_
 #define ANDROID_APEXD_APEXD_H_
 
-#include <ostream>
 #include <string>
 #include <vector>
 
@@ -25,177 +24,101 @@
 #include <android-base/result.h>
 
 #include "apex_constants.h"
-#include "apex_database.h"
 #include "apex_file.h"
-#include "apex_file_repository.h"
-#include "apexd_session.h"
 
 namespace android {
 namespace apex {
 
-// A structure containing all the values that might need to be injected for
-// testing (e.g. apexd status property, etc.)
-//
-// Ideally we want to introduce Apexd class and use dependency injection for
-// such values, but that will require a sizeable refactoring. For the time being
-// this config should do the trick.
-struct ApexdConfig {
-  const char* apex_status_sysprop;
-  std::vector<std::string> apex_built_in_dirs;
-  const char* active_apex_data_dir;
-  const char* decompression_dir;
-  const char* ota_reserved_dir;
-  const char* apex_hash_tree_dir;
-  const char* staged_session_dir;
-};
-
-static const ApexdConfig kDefaultConfig = {
-    kApexStatusSysprop,   kApexPackageBuiltinDirs, kActiveApexPackagesDataDir,
-    kApexDecompressedDir, kOtaReservedDir,         kApexHashTreeDir,
-    kStagedSessionsDir,
-};
-
 class CheckpointInterface;
 
-void SetConfig(const ApexdConfig& config);
+android::base::Result<void> resumeRevertIfNeeded();
 
-// Exposed only for testing.
-android::base::Result<void> Unmount(
-    const MountedApexDatabase::MountedApexData& data, bool deferred);
-
-android::base::Result<void> ResumeRevertIfNeeded();
-
-android::base::Result<void> PreinstallPackages(
+// Keep it for now to make otapreopt_chroot keep happy.
+// TODO(b/137086602): remove this function.
+android::base::Result<void> scanPackagesDirAndActivate(
+    const char* apex_package_dir);
+void scanStagedSessionsDirAndStage();
+android::base::Result<void> preinstallPackages(
     const std::vector<std::string>& paths) WARN_UNUSED;
-android::base::Result<void> PostinstallPackages(
+android::base::Result<void> postinstallPackages(
     const std::vector<std::string>& paths) WARN_UNUSED;
 
-android::base::Result<void> StagePackages(
+android::base::Result<void> stagePackages(
     const std::vector<std::string>& tmpPaths) WARN_UNUSED;
-android::base::Result<void> UnstagePackages(
+android::base::Result<void> unstagePackages(
     const std::vector<std::string>& paths) WARN_UNUSED;
 
-android::base::Result<std::vector<ApexFile>> SubmitStagedSession(
+android::base::Result<std::vector<ApexFile>> submitStagedSession(
     const int session_id, const std::vector<int>& child_session_ids,
     const bool has_rollback_enabled, const bool is_rollback,
     const int rollback_id) WARN_UNUSED;
-android::base::Result<void> MarkStagedSessionReady(const int session_id)
+android::base::Result<void> markStagedSessionReady(const int session_id)
     WARN_UNUSED;
-android::base::Result<void> MarkStagedSessionSuccessful(const int session_id)
+android::base::Result<void> markStagedSessionSuccessful(const int session_id)
     WARN_UNUSED;
-// Only only of the parameters should be passed during revert
-android::base::Result<void> RevertActiveSessions(
-    const std::string& crashing_native_process,
-    const std::string& error_message);
-// Only only of the parameters should be passed during revert
-android::base::Result<void> RevertActiveSessionsAndReboot(
-    const std::string& crashing_native_process,
-    const std::string& error_message);
+android::base::Result<void> revertActiveSessions(
+    const std::string& crashing_native_process);
+android::base::Result<void> revertActiveSessionsAndReboot(
+    const std::string& crashing_native_process);
 
-android::base::Result<void> ActivatePackage(const std::string& full_path)
+android::base::Result<void> activatePackage(const std::string& full_path)
     WARN_UNUSED;
-android::base::Result<void> DeactivatePackage(const std::string& full_path)
+android::base::Result<void> deactivatePackage(const std::string& full_path)
     WARN_UNUSED;
 
-std::vector<ApexFile> GetActivePackages();
-android::base::Result<ApexFile> GetActivePackage(
+std::vector<ApexFile> getActivePackages();
+android::base::Result<ApexFile> getActivePackage(
     const std::string& package_name);
 
-std::vector<ApexFile> GetFactoryPackages();
+std::vector<ApexFile> getFactoryPackages();
 
-android::base::Result<void> AbortStagedSession(const int session_id);
+android::base::Result<void> abortStagedSession(const int session_id);
+android::base::Result<void> abortActiveSession();
 
-android::base::Result<void> SnapshotCeData(const int user_id,
-                                           const int rollback_id,
-                                           const std::string& apex_name);
-android::base::Result<void> RestoreCeData(const int user_id,
+android::base::Result<ino_t> snapshotCeData(const int user_id,
+                                            const int rollback_id,
+                                            const std::string& apex_name);
+android::base::Result<void> restoreCeData(const int user_id,
                                           const int rollback_id,
                                           const std::string& apex_name);
-
-android::base::Result<void> DestroyDeSnapshots(const int rollback_id);
-android::base::Result<void> DestroyCeSnapshots(const int user_id,
-                                               const int rollback_id);
-android::base::Result<void> DestroyCeSnapshotsNotSpecified(
+android::base::Result<void> destroyDeSnapshots(const int rollback_id);
+android::base::Result<void> destroyCeSnapshotsNotSpecified(
     int user_id, const std::vector<int>& retain_rollback_ids);
 
-int OnBootstrap();
+int onBootstrap();
+// Small helper function to tell if device is currently booting.
+bool isBooting();
 // Sets the values of gVoldService and gInFsCheckpointMode.
-void InitializeVold(CheckpointInterface* checkpoint_service);
+void initializeVold(CheckpointInterface* checkpoint_service);
 // Initializes in-memory state (e.g. pre-installed data, activated apexes).
 // Must be called first before calling any other boot sequence related function.
-void Initialize(CheckpointInterface* checkpoint_service);
-// Initializes data apex as in-memory state. Should be called only if we are
-// not booting, since initialization timing is different when booting
-void InitializeDataApex();
+void initialize(CheckpointInterface* checkpoint_service);
 // Migrates sessions from /data/apex/session to /metadata/session.i
 // Must only be called during boot (i.e apexd.status is not "ready" or
 // "activated").
-android::base::Result<void> MigrateSessionsDirIfNeeded();
+android::base::Result<void> migrateSessionsDirIfNeeded();
 // Apex activation logic. Scans staged apex sessions and activates apexes.
 // Must only be called during boot (i.e apexd.status is not "ready" or
 // "activated").
-void OnStart();
-// For every package X, there can be at most two APEX, pre-installed vs
-// installed on data. We decide which ones should be activated and return them
-// as a list
-std::vector<ApexFileRef> SelectApexForActivation(
-    const std::unordered_map<std::string, std::vector<ApexFileRef>>& all_apex,
-    const ApexFileRepository& instance);
-std::vector<ApexFile> ProcessCompressedApex(
-    const std::vector<ApexFileRef>& compressed_apex, bool is_ota_chroot);
-// Validate |apex| is same as |capex|
-android::base::Result<void> ValidateDecompressedApex(const ApexFile& capex,
-                                                     const ApexFile& apex);
+void onStart();
 // Notifies system that apexes are activated by setting apexd.status property to
 // "activated".
 // Must only be called during boot (i.e. apexd.status is not "ready" or
 // "activated").
-void OnAllPackagesActivated(bool is_bootstrap);
+void onAllPackagesActivated();
 // Notifies system that apexes are ready by setting apexd.status property to
 // "ready".
 // Must only be called during boot (i.e. apexd.status is not "ready" or
 // "activated").
-void OnAllPackagesReady();
-void OnBootCompleted();
-// Exposed for testing
-void RemoveInactiveDataApex();
-void BootCompletedCleanup();
-int SnapshotOrRestoreDeUserData();
+void onAllPackagesReady();
+void bootCompletedCleanup();
+int snapshotOrRestoreDeUserData();
 
-int UnmountAll();
-
-android::base::Result<MountedApexDatabase::MountedApexData>
-GetTempMountedApexData(const std::string& package);
+int unmountAll();
 
 // Optimistically tries to remount as many APEX packages as possible.
 // For more documentation see corresponding binder call in IApexService.aidl.
-android::base::Result<void> RemountPackages();
-
-// Exposed for unit tests
-android::base::Result<bool> ShouldAllocateSpaceForDecompression(
-    const std::string& new_apex_name, int64_t new_apex_version,
-    const ApexFileRepository& instance);
-
-void CollectApexInfoList(std::ostream& os,
-                         const std::vector<ApexFile>& active_apexs,
-                         const std::vector<ApexFile>& inactive_apexs);
-
-// Reserve |size| bytes in |dest_dir| by creating a zero-filled file
-android::base::Result<void> ReserveSpaceForCompressedApex(
-    int64_t size, const std::string& dest_dir);
-
-// Activates apexes in otapreot_chroot environment.
-// TODO(b/172911822): support compressed apexes.
-int OnOtaChrootBootstrap();
-
-// Activates flattened apexes in otapreopt_chroot environment.
-int OnOtaChrootBootstrapFlattenedApex();
-
-android::apex::MountedApexDatabase& GetApexDatabaseForTesting();
-
-// Performs a non-staged install of an APEX specified by |package_path|.
-// TODO(ioffe): add more documentation.
-android::base::Result<ApexFile> InstallPackage(const std::string& package_path);
+android::base::Result<void> remountPackages();
 
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apexd_checkpoint.h b/apexd/apexd_checkpoint.h
index 2b4c3a1..7177c04 100644
--- a/apexd/apexd_checkpoint.h
+++ b/apexd/apexd_checkpoint.h
@@ -32,7 +32,7 @@
 
   virtual android::base::Result<bool> NeedsCheckpoint() = 0;
   virtual android::base::Result<bool> NeedsRollback() = 0;
-  virtual android::base::Result<void> StartCheckpoint(int32_t num_retries) = 0;
+  virtual android::base::Result<void> StartCheckpoint(int32_t numRetries) = 0;
 
   virtual android::base::Result<void> AbortChanges(const std::string& msg,
                                                    bool retry) = 0;
diff --git a/apexd/apexd_checkpoint_vold.cpp b/apexd/apexd_checkpoint_vold.cpp
index 8a8d0ff..ca29209 100644
--- a/apexd/apexd_checkpoint_vold.cpp
+++ b/apexd/apexd_checkpoint_vold.cpp
@@ -31,11 +31,11 @@
 namespace apex {
 
 Result<VoldCheckpointInterface> VoldCheckpointInterface::Create() {
-  auto vold_service =
+  auto voldService =
       defaultServiceManager()->getService(android::String16("vold"));
-  if (vold_service != nullptr) {
+  if (voldService != nullptr) {
     return VoldCheckpointInterface(
-        android::interface_cast<android::os::IVold>(vold_service));
+        android::interface_cast<android::os::IVold>(voldService));
   }
   return Errorf("Failed to retrieve vold service.");
 }
@@ -91,10 +91,9 @@
   return false;
 }
 
-Result<void> VoldCheckpointInterface::StartCheckpoint(int32_t num_retries) {
+Result<void> VoldCheckpointInterface::StartCheckpoint(int32_t numRetries) {
   if (supports_fs_checkpoints_) {
-    android::binder::Status status =
-        vold_service_->startCheckpoint(num_retries);
+    android::binder::Status status = vold_service_->startCheckpoint(numRetries);
     if (!status.isOk()) {
       return Error() << status.toString8().c_str();
     }
diff --git a/apexd/apexd_checkpoint_vold.h b/apexd/apexd_checkpoint_vold.h
index f547532..dbd190d 100644
--- a/apexd/apexd_checkpoint_vold.h
+++ b/apexd/apexd_checkpoint_vold.h
@@ -44,7 +44,7 @@
   android::base::Result<void> StartCheckpoint(int32_t retry) override;
 
   android::base::Result<void> AbortChanges(const std::string& msg,
-                                           bool num_retries) override;
+                                           bool numRetries) override;
 
   static android::base::Result<VoldCheckpointInterface> Create();
 
diff --git a/apexd/apexd_lifecycle.h b/apexd/apexd_lifecycle.h
deleted file mode 100644
index ecdef96..0000000
--- a/apexd/apexd_lifecycle.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#ifndef ANDROID_APEXD_APEXD_LIFECYCLE_H_
-#define ANDROID_APEXD_APEXD_LIFECYCLE_H_
-
-#include <android-base/result.h>
-
-namespace android {
-namespace apex {
-
-class ApexdLifecycle {
- private:
-  ApexdLifecycle(){};
-  std::atomic<bool> boot_completed_;
-
-  // Non-copyable && non-moveable.
-  ApexdLifecycle(const ApexdLifecycle&) = delete;
-  ApexdLifecycle& operator=(const ApexdLifecycle&) = delete;
-  ApexdLifecycle& operator=(ApexdLifecycle&&) = delete;
-
- public:
-  static ApexdLifecycle& GetInstance() {
-    static ApexdLifecycle instance;
-    return instance;
-  }
-  bool IsBooting();
-  void MarkBootCompleted();
-  void WaitForBootStatus(android::base::Result<void> (&rollback_fn)(
-      const std::string&, const std::string&));
-};
-}  // namespace apex
-}  // namespace android
-
-#endif  // ANDROID_APEXD_APEXD_LIFECYCLE_H
diff --git a/apexd/apexd_loop.cpp b/apexd/apexd_loop.cpp
index 08805ea..568eb05 100644
--- a/apexd/apexd_loop.cpp
+++ b/apexd/apexd_loop.cpp
@@ -18,49 +18,29 @@
 
 #include "apexd_loop.h"
 
-#include <mutex>
-
 #include <dirent.h>
 #include <fcntl.h>
 #include <linux/fs.h>
 #include <linux/loop.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
-#include <sys/statfs.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
 #include "apexd_utils.h"
 #include "string_log.h"
 
-using android::base::Basename;
-using android::base::ErrnoError;
 using android::base::Error;
-using android::base::GetBoolProperty;
-using android::base::ParseUint;
 using android::base::Result;
 using android::base::StartsWith;
 using android::base::StringPrintf;
 using android::base::unique_fd;
 
-#ifndef LOOP_CONFIGURE
-// These can be removed whenever we pull in the Linux v5.8 UAPI headers
-struct loop_config {
-  __u32 fd;
-  __u32 block_size;
-  struct loop_info64 info;
-  __u64 __reserved[8];
-};
-#define LOOP_CONFIGURE 0x4C0A
-#endif
-
 namespace android {
 namespace apex {
 namespace loop {
@@ -86,9 +66,13 @@
   }
 }
 
-Result<void> ConfigureReadAhead(const std::string& device_path) {
-  CHECK(StartsWith(device_path, "/dev/"));
-  std::string device_name = Basename(device_path);
+Result<void> configureReadAhead(const std::string& device_path) {
+  auto pos = device_path.find("/dev/block/");
+  if (pos != 0) {
+    return Error() << "Device path does not start with /dev/block.";
+  }
+  pos = device_path.find_last_of('/');
+  std::string device_name = device_path.substr(pos + 1, std::string::npos);
 
   std::string sysfs_device =
       StringPrintf("/sys/block/%s/queue/read_ahead_kb", device_name.c_str());
@@ -106,10 +90,10 @@
   return {};
 }
 
-Result<void> PreAllocateLoopDevices(size_t num) {
-  Result<void> loop_ready = WaitForFile("/dev/loop-control", 20s);
-  if (!loop_ready.ok()) {
-    return loop_ready;
+Result<void> preAllocateLoopDevices(size_t num) {
+  Result<void> loopReady = WaitForFile("/dev/loop-control", 20s);
+  if (!loopReady.ok()) {
+    return loopReady;
   }
   unique_fd ctl_fd(
       TEMP_FAILURE_RETRY(open("/dev/loop-control", O_RDWR | O_CLOEXEC)));
@@ -117,30 +101,13 @@
     return ErrnoError() << "Failed to open loop-control";
   }
 
-  bool found = false;
-  size_t start_id = 0;
-  constexpr const char* kLoopPrefix = "loop";
-  WalkDir("/dev/block", [&](const std::filesystem::directory_entry& entry) {
-    std::string devname = entry.path().filename().string();
-    if (StartsWith(devname, kLoopPrefix)) {
-      size_t id;
-      auto parse_ok = ParseUint(
-          devname.substr(std::char_traits<char>::length(kLoopPrefix)), &id);
-      if (parse_ok && id > start_id) {
-        start_id = id;
-        found = true;
-      }
-    }
-  });
-  if (found) ++start_id;
-
   // Assumption: loop device ID [0..num) is valid.
   // This is because pre-allocation happens during bootstrap.
   // Anyway Kernel pre-allocated loop devices
   // as many as CONFIG_BLK_DEV_LOOP_MIN_COUNT,
   // Within the amount of kernel-pre-allocation,
   // LOOP_CTL_ADD will fail with EEXIST
-  for (size_t id = start_id; id < num + start_id; ++id) {
+  for (size_t id = 0ul; id < num; ++id) {
     int ret = ioctl(ctl_fd.get(), LOOP_CTL_ADD, id);
     if (ret < 0 && errno != EEXIST) {
       return ErrnoError() << "Failed LOOP_CTL_ADD";
@@ -153,30 +120,25 @@
   // just optimistally hope that they are all created when we actually
   // access them for activating APEXes. If the dev nodes are not ready
   // even then, we wait 50ms and warning message will be printed (see below
-  // CreateLoopDevice()).
+  // createLoopDevice()).
   LOG(INFO) << "Pre-allocated " << num << " loopback devices";
   return {};
 }
 
-Result<void> ConfigureLoopDevice(const int device_fd, const std::string& target,
-                                 const int32_t image_offset,
-                                 const size_t image_size) {
-  static bool use_loop_configure;
-  static std::once_flag once_flag;
-  std::call_once(once_flag, [&]() {
-    // LOOP_CONFIGURE is a new ioctl in Linux 5.8 (and backported in Android
-    // common) that allows atomically configuring a loop device. It is a lot
-    // faster than the traditional LOOP_SET_FD/LOOP_SET_STATUS64 combo, but
-    // it may not be available on updating devices, so try once before
-    // deciding.
-    struct loop_config config;
-    memset(&config, 0, sizeof(config));
-    config.fd = -1;
-    if (ioctl(device_fd, LOOP_CONFIGURE, &config) == -1 && errno == EBADF) {
-      // If the IOCTL exists, it will fail with EBADF for the -1 fd
-      use_loop_configure = true;
-    }
-  });
+Result<LoopbackDeviceUniqueFd> createLoopDevice(const std::string& target,
+                                                const int32_t imageOffset,
+                                                const size_t imageSize) {
+  unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
+  if (ctl_fd.get() == -1) {
+    return ErrnoError() << "Failed to open loop-control";
+  }
+
+  int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
+  if (num == -1) {
+    return ErrnoError() << "Failed LOOP_CTL_GET_FREE";
+  }
+
+  std::string device = StringPrintf("/dev/block/loop%d", num);
 
   /*
    * Using O_DIRECT will tell the kernel that we want to use Direct I/O
@@ -189,151 +151,74 @@
    */
   unique_fd target_fd(open(target.c_str(), O_RDONLY | O_CLOEXEC | O_DIRECT));
   if (target_fd.get() == -1) {
-    struct statfs stbuf;
-    int saved_errno = errno;
-    // let's give another try with buffered I/O for EROFS and squashfs
-    if (statfs(target.c_str(), &stbuf) != 0 ||
-        (stbuf.f_type != EROFS_SUPER_MAGIC_V1 &&
-         stbuf.f_type != SQUASHFS_MAGIC &&
-         stbuf.f_type != OVERLAYFS_SUPER_MAGIC)) {
-      return Error(saved_errno) << "Failed to open " << target;
+    return ErrnoError() << "Failed to open " << target;
+  }
+  LoopbackDeviceUniqueFd device_fd;
+  {
+    // See comment on kLoopDeviceRetryAttempts.
+    unique_fd sysfs_fd;
+    for (size_t i = 0; i != kLoopDeviceRetryAttempts; ++i) {
+      sysfs_fd.reset(open(device.c_str(), O_RDWR | O_CLOEXEC));
+      if (sysfs_fd.get() != -1) {
+        break;
+      }
+      PLOG(WARNING) << "Loopback device " << device
+                    << " not ready. Waiting 50ms...";
+      usleep(50000);
     }
-    LOG(WARNING) << "Fallback to buffered I/O for " << target;
-    target_fd.reset(open(target.c_str(), O_RDONLY | O_CLOEXEC));
-    if (target_fd.get() == -1) {
-      return ErrnoError() << "Failed to open " << target;
+    if (sysfs_fd.get() == -1) {
+      return ErrnoError() << "Failed to open " << device;
     }
+    device_fd = LoopbackDeviceUniqueFd(std::move(sysfs_fd), device);
+    CHECK_NE(device_fd.get(), -1);
+  }
+
+  if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) {
+    return ErrnoError() << "Failed to LOOP_SET_FD";
   }
 
   struct loop_info64 li;
   memset(&li, 0, sizeof(li));
   strlcpy((char*)li.lo_crypt_name, kApexLoopIdPrefix, LO_NAME_SIZE);
-  li.lo_offset = image_offset;
-  li.lo_sizelimit = image_size;
-  // Automatically free loop device on last close.
-  li.lo_flags |= LO_FLAGS_AUTOCLEAR;
-
-  if (use_loop_configure) {
-    struct loop_config config;
-    memset(&config, 0, sizeof(config));
-    li.lo_flags |= LO_FLAGS_DIRECT_IO;
-    config.fd = target_fd.get();
-    config.info = li;
-    config.block_size = 4096;
-
-    if (ioctl(device_fd, LOOP_CONFIGURE, &config) == -1) {
-      return ErrnoError() << "Failed to LOOP_CONFIGURE";
-    }
-
-    return {};
-  } else {
-    if (ioctl(device_fd, LOOP_SET_FD, target_fd.get()) == -1) {
-      return ErrnoError() << "Failed to LOOP_SET_FD";
-    }
-
-    if (ioctl(device_fd, LOOP_SET_STATUS64, &li) == -1) {
-      return ErrnoError() << "Failed to LOOP_SET_STATUS64";
-    }
-
-    if (ioctl(device_fd, BLKFLSBUF, 0) == -1) {
-      // This works around a kernel bug where the following happens.
-      // 1) The device runs with a value of loop.max_part > 0
-      // 2) As part of LOOP_SET_FD above, we do a partition scan, which loads
-      //    the first 2 pages of the underlying file into the buffer cache
-      // 3) When we then change the offset with LOOP_SET_STATUS64, those pages
-      //    are not invalidated from the cache.
-      // 4) When we try to mount an ext4 filesystem on the loop device, the ext4
-      //    code will try to find a superblock by reading 4k at offset 0; but,
-      //    because we still have the old pages at offset 0 lying in the cache,
-      //    those pages will be returned directly. However, those pages contain
-      //    the data at offset 0 in the underlying file, not at the offset that
-      //    we configured
-      // 5) the ext4 driver fails to find a superblock in the (wrong) data, and
-      //    fails to mount the filesystem.
-      //
-      // To work around this, explicitly flush the block device, which will
-      // flush the buffer cache and make sure we actually read the data at the
-      // correct offset.
-      return ErrnoError() << "Failed to flush buffers on the loop device";
-    }
-
-    // Direct-IO requires the loop device to have the same block size as the
-    // underlying filesystem.
-    if (ioctl(device_fd, LOOP_SET_BLOCK_SIZE, 4096) == -1) {
-      PLOG(WARNING) << "Failed to LOOP_SET_BLOCK_SIZE";
-    }
-  }
-  return {};
-}
-
-Result<LoopbackDeviceUniqueFd> WaitForDevice(int num) {
-  std::string opened_device;
-  const std::vector<std::string> candidate_devices = {
-      StringPrintf("/dev/block/loop%d", num),
-      StringPrintf("/dev/loop%d", num),
-  };
-
-  // apexd-bootstrap runs in parallel with ueventd to optimize boot time. In
-  // rare cases apexd would try attempt to mount an apex before ueventd created
-  // a loop device for it. To work around this we keep polling for loop device
-  // to be created until ueventd's cold boot sequence is done.
-  // See comment on kLoopDeviceRetryAttempts.
-  unique_fd sysfs_fd;
-  bool cold_boot_done = GetBoolProperty("ro.cold_boot_done", false);
-  for (size_t i = 0; i != kLoopDeviceRetryAttempts; ++i) {
-    if (!cold_boot_done) {
-      cold_boot_done = GetBoolProperty("ro.cold_boot_done", false);
-    }
-    for (const auto& device : candidate_devices) {
-      sysfs_fd.reset(open(device.c_str(), O_RDWR | O_CLOEXEC));
-      if (sysfs_fd.get() != -1) {
-        return LoopbackDeviceUniqueFd(std::move(sysfs_fd), device);
-      }
-    }
-    PLOG(WARNING) << "Loopback device " << num << " not ready. Waiting 50ms...";
-    usleep(50000);
-    if (!cold_boot_done) {
-      // ueventd hasn't finished cold boot yet, keep trying.
-      i = 0;
-    }
+  li.lo_offset = imageOffset;
+  li.lo_sizelimit = imageSize;
+  if (ioctl(device_fd.get(), LOOP_SET_STATUS64, &li) == -1) {
+    return ErrnoError() << "Failed to LOOP_SET_STATUS64";
   }
 
-  return Error() << "Faled to open loopback device " << num;
-}
-
-Result<LoopbackDeviceUniqueFd> CreateLoopDevice(const std::string& target,
-                                                const int32_t image_offset,
-                                                const size_t image_size) {
-  unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
-  if (ctl_fd.get() == -1) {
-    return ErrnoError() << "Failed to open loop-control";
+  if (ioctl(device_fd.get(), BLKFLSBUF, 0) == -1) {
+    // This works around a kernel bug where the following happens.
+    // 1) The device runs with a value of loop.max_part > 0
+    // 2) As part of LOOP_SET_FD above, we do a partition scan, which loads
+    //    the first 2 pages of the underlying file into the buffer cache
+    // 3) When we then change the offset with LOOP_SET_STATUS64, those pages
+    //    are not invalidated from the cache.
+    // 4) When we try to mount an ext4 filesystem on the loop device, the ext4
+    //    code will try to find a superblock by reading 4k at offset 0; but,
+    //    because we still have the old pages at offset 0 lying in the cache,
+    //    those pages will be returned directly. However, those pages contain
+    //    the data at offset 0 in the underlying file, not at the offset that
+    //    we configured
+    // 5) the ext4 driver fails to find a superblock in the (wrong) data, and
+    //    fails to mount the filesystem.
+    //
+    // To work around this, explicitly flush the block device, which will flush
+    // the buffer cache and make sure we actually read the data at the correct
+    // offset.
+    return ErrnoError() << "Failed to flush buffers on the loop device";
   }
 
-  static std::mutex mlock;
-  std::lock_guard lock(mlock);
-  int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
-  if (num == -1) {
-    return ErrnoError() << "Failed LOOP_CTL_GET_FREE";
+  // Direct-IO requires the loop device to have the same block size as the
+  // underlying filesystem.
+  if (ioctl(device_fd.get(), LOOP_SET_BLOCK_SIZE, 4096) == -1) {
+    PLOG(WARNING) << "Failed to LOOP_SET_BLOCK_SIZE";
   }
 
-  Result<LoopbackDeviceUniqueFd> loop_device = WaitForDevice(num);
-  if (!loop_device.ok()) {
-    return loop_device.error();
+  Result<void> readAheadStatus = configureReadAhead(device);
+  if (!readAheadStatus.ok()) {
+    return readAheadStatus.error();
   }
-  CHECK_NE(loop_device->device_fd.get(), -1);
-
-  Result<void> configureStatus = ConfigureLoopDevice(
-      loop_device->device_fd.get(), target, image_offset, image_size);
-  if (!configureStatus.ok()) {
-    return configureStatus.error();
-  }
-
-  Result<void> read_ahead_status = ConfigureReadAhead(loop_device->name);
-  if (!read_ahead_status.ok()) {
-    return read_ahead_status.error();
-  }
-
-  return loop_device;
+  return device_fd;
 }
 
 void DestroyLoopDevice(const std::string& path, const DestroyLoopFn& extra) {
diff --git a/apexd/apexd_loop.h b/apexd/apexd_loop.h
index c727944..8341675 100644
--- a/apexd/apexd_loop.h
+++ b/apexd/apexd_loop.h
@@ -38,7 +38,7 @@
       : device_fd(std::move(fd)), name(name) {}
 
   LoopbackDeviceUniqueFd(LoopbackDeviceUniqueFd&& fd) noexcept
-      : device_fd(std::move(fd.device_fd)), name(std::move(fd.name)) {}
+      : device_fd(std::move(fd.device_fd)), name(fd.name) {}
   LoopbackDeviceUniqueFd& operator=(LoopbackDeviceUniqueFd&& other) noexcept {
     MaybeCloseBad();
     device_fd = std::move(other.device_fd);
@@ -52,16 +52,16 @@
 
   void CloseGood() { device_fd.reset(-1); }
 
-  int Get() { return device_fd.get(); }
+  int get() { return device_fd.get(); }
 };
 
-android::base::Result<void> ConfigureReadAhead(const std::string& device_path);
+android::base::Result<void> configureReadAhead(const std::string& device_path);
 
-android::base::Result<void> PreAllocateLoopDevices(size_t num);
+android::base::Result<void> preAllocateLoopDevices(size_t num);
 
-android::base::Result<LoopbackDeviceUniqueFd> CreateLoopDevice(
-    const std::string& target, const int32_t image_offset,
-    const size_t image_size);
+android::base::Result<LoopbackDeviceUniqueFd> createLoopDevice(
+    const std::string& target, const int32_t imageOffset,
+    const size_t imageSize);
 
 using DestroyLoopFn =
     std::function<void(const std::string&, const std::string&)>;
diff --git a/apexd/apexd_main.cpp b/apexd/apexd_main.cpp
index 26d5732..c60f4fa 100644
--- a/apexd/apexd_main.cpp
+++ b/apexd/apexd_main.cpp
@@ -17,15 +17,14 @@
 #define LOG_TAG "apexd"
 
 #include <strings.h>
-#include <sys/stat.h>
 
 #include <ApexProperties.sysprop.h>
 #include <android-base/logging.h>
 
 #include "apexd.h"
 #include "apexd_checkpoint_vold.h"
-#include "apexd_lifecycle.h"
 #include "apexd_prepostinstall.h"
+#include "apexd_prop.h"
 #include "apexservice.h"
 
 #include <android-base/properties.h>
@@ -45,17 +44,12 @@
 
   if (strcmp("--bootstrap", argv[1]) == 0) {
     LOG(INFO) << "Bootstrap subcommand detected";
-    return android::apex::OnBootstrap();
+    return android::apex::onBootstrap();
   }
 
   if (strcmp("--unmount-all", argv[1]) == 0) {
     LOG(INFO) << "Unmount all subcommand detected";
-    return android::apex::UnmountAll();
-  }
-
-  if (strcmp("--otachroot-bootstrap", argv[1]) == 0) {
-    LOG(INFO) << "OTA chroot bootstrap subcommand detected";
-    return android::apex::OnOtaChrootBootstrap();
+    return android::apex::unmountAll();
   }
 
   if (strcmp("--snapshotde", argv[1]) == 0) {
@@ -68,16 +62,16 @@
       LOG(ERROR) << "Could not retrieve vold service: "
                  << vold_service_st.error();
     } else {
-      android::apex::InitializeVold(&*vold_service_st);
+      android::apex::initializeVold(&*vold_service_st);
     }
 
-    int result = android::apex::SnapshotOrRestoreDeUserData();
+    int result = android::apex::snapshotOrRestoreDeUserData();
 
     if (result == 0) {
       // Notify other components (e.g. init) that all APEXs are ready to be used
       // Note that it's important that the binder service is registered at this
       // point, since other system services might depend on it.
-      android::apex::OnAllPackagesReady();
+      android::apex::onAllPackagesReady();
     }
     return result;
   }
@@ -104,40 +98,20 @@
 
 int main(int /*argc*/, char** argv) {
   android::base::InitLogging(argv, &android::base::KernelLogger);
-  // TODO(b/158468454): add a -v flag or an external setting to change severity.
-  android::base::SetMinimumLogSeverity(android::base::INFO);
-
-  // set umask to 022 so that files/dirs created are accessible to other
-  // processes e.g.) apex-info-file.xml is supposed to be read by other
-  // processes
-  umask(022);
+  // TODO: add a -v flag or an external setting to change LogSeverity.
+  android::base::SetMinimumLogSeverity(android::base::VERBOSE);
 
   InstallSigtermSignalHandler();
 
-  android::apex::SetConfig(android::apex::kDefaultConfig);
-
-  android::apex::ApexdLifecycle& lifecycle =
-      android::apex::ApexdLifecycle::GetInstance();
-  bool booting = lifecycle.IsBooting();
-
   const bool has_subcommand = argv[1] != nullptr;
   if (!android::sysprop::ApexProperties::updatable().value_or(false)) {
+    LOG(INFO) << "This device does not support updatable APEX. Exiting";
     if (!has_subcommand) {
-      if (!booting) {
-        // We've finished booting, but for some reason somebody tried to start
-        // apexd. Simply exit.
-        return 0;
-      }
-
-      LOG(INFO) << "This device does not support updatable APEX. Exiting";
-      // Mark apexd as activated so that init can proceed.
-      android::apex::OnAllPackagesActivated(/*is_bootstrap=*/false);
+      // mark apexd as activated so that init can proceed
+      android::apex::onAllPackagesActivated();
     } else if (strcmp("--snapshotde", argv[1]) == 0) {
-      LOG(INFO) << "This device does not support updatable APEX. Exiting";
       // mark apexd as ready
-      android::apex::OnAllPackagesReady();
-    } else if (strcmp("--otachroot-bootstrap", argv[1]) == 0) {
-      return android::apex::OnOtaChrootBootstrapFlattenedApex();
+      android::apex::onAllPackagesReady();
     }
     return 0;
   }
@@ -155,21 +129,12 @@
   } else {
     vold_service = &*vold_service_st;
   }
-  android::apex::Initialize(vold_service);
+  android::apex::initialize(vold_service);
 
+  bool booting = android::apex::isBooting();
   if (booting) {
-    if (auto res = android::apex::MigrateSessionsDirIfNeeded(); !res.ok()) {
-      LOG(ERROR) << "Failed to migrate sessions to /metadata partition : "
-                 << res.error();
-    }
-    android::apex::OnStart();
-  } else {
-    // TODO(b/172911822): Trying to use data apex related ApexFileRepository
-    //  apis without initializing it should throw error. Also, unit tests should
-    //  not pass without initialization.
-    // TODO(b/172911822): Consolidate this with Initialize() when
-    //  ApexFileRepository can act as cache and re-scanning is not expensive
-    android::apex::InitializeDataApex();
+    android::apex::migrateSessionsDirIfNeeded();
+    android::apex::onStart();
   }
   android::apex::binder::CreateAndRegisterService();
   android::apex::binder::StartThreadPool();
@@ -181,8 +146,10 @@
     // themselves should wait for the ready status instead, which is set when
     // the "--snapshotde" subcommand is received and snapshot/restore is
     // complete.
-    android::apex::OnAllPackagesActivated(/*is_bootstrap=*/false);
-    lifecycle.WaitForBootStatus(android::apex::RevertActiveSessionsAndReboot);
+    android::apex::onAllPackagesActivated();
+    android::apex::waitForBootStatus(
+        android::apex::revertActiveSessionsAndReboot,
+        android::apex::bootCompletedCleanup);
   }
 
   android::apex::binder::AllowServiceShutdown();
diff --git a/apexd/apexd_prepostinstall.cpp b/apexd/apexd_prepostinstall.cpp
index 51b60b4..21b8650 100644
--- a/apexd/apexd_prepostinstall.cpp
+++ b/apexd/apexd_prepostinstall.cpp
@@ -35,7 +35,6 @@
 
 #include "apex_database.h"
 #include "apex_file.h"
-#include "apex_manifest.h"
 #include "apexd.h"
 #include "apexd_private.h"
 #include "apexd_utils.h"
@@ -43,7 +42,6 @@
 
 using android::base::Error;
 using android::base::Result;
-using ::apex::proto::ApexManifest;
 
 namespace android {
 namespace apex {
@@ -60,12 +58,14 @@
   close(STDERR_FILENO);
 }
 
+// Instead of temp mounting inside this fuction, we can make a caller do it.
+// This will align with the plan of extending temp mounting to provide a
+// way to run additional pre-reboot verification of an APEX.
+// TODO(ioffe): pass mount points instead of apex files.
 template <typename Fn>
-Result<void> StageFnInstall(const std::vector<ApexFile>& apexes,
-                            const std::vector<std::string>& mount_points, Fn fn,
+Result<void> StageFnInstall(const std::vector<ApexFile>& apexes, Fn fn,
                             const char* arg, const char* name) {
-  // TODO(b/158470023): consider supporting a session with more than one
-  //   pre-install hook.
+  // TODO: Support a session with more than one pre-install hook.
   int hook_idx = -1;
   for (size_t i = 0; i < apexes.size(); i++) {
     if (!(apexes[i].GetManifest().*fn)().empty()) {
@@ -78,24 +78,17 @@
   CHECK(hook_idx != -1);
   LOG(VERBOSE) << name << " for " << apexes[hook_idx].GetPath();
 
-  // Create invocation args.
-  std::vector<std::string> args{
-      "/system/bin/apexd", arg,
-      mount_points[hook_idx]  // Make the APEX with hook first.
-  };
-  for (size_t i = 0; i < mount_points.size(); i++) {
-    if ((int)i != hook_idx) {
-      args.push_back(mount_points[i]);
-    }
-  }
-
-  return ForkAndRun(args);
-}
-
-template <typename Fn>
-int RunFnInstall(char** in_argv, Fn fn, const char* name) {
+  std::vector<MountedApexData> mounted_apexes;
   std::vector<std::string> activation_dirs;
   auto preinstall_guard = android::base::make_scope_guard([&]() {
+    for (const auto& mount : mounted_apexes) {
+      Result<void> st = apexd_private::Unmount(mount);
+      if (!st.ok()) {
+        LOG(ERROR) << "Failed to unmount " << mount.full_path << " from "
+                   << mount.mount_point << " after " << name << ": "
+                   << st.error();
+      }
+    }
     for (const std::string& active_point : activation_dirs) {
       if (0 != rmdir(active_point.c_str())) {
         PLOG(ERROR) << "Could not delete temporary active point "
@@ -104,6 +97,54 @@
     }
   });
 
+  for (const ApexFile& apex : apexes) {
+    // 1) Mount the package.
+    std::string mount_point =
+        apexd_private::GetPackageTempMountPoint(apex.GetManifest());
+
+    auto mount_data = apexd_private::TempMountPackage(apex, mount_point);
+    if (!mount_data.ok()) {
+      return mount_data.error();
+    }
+    mounted_apexes.push_back(std::move(*mount_data));
+
+    // Given the fact, that we only allow updates of existing APEXes, all the
+    // activation points will always be already created. Only scenario, when it
+    // won't be the case might be apexservice_test. But even then, it might be
+    // safer to move active_point creation logic to run after unshare.
+    // TODO(ioffe): move creation of activation points inside RunFnInstall?
+    // 2) Ensure there is an activation point, and we will clean it up.
+    std::string active_point =
+        apexd_private::GetActiveMountPoint(apex.GetManifest());
+    if (0 == mkdir(active_point.c_str(), kMkdirMode)) {
+      activation_dirs.emplace_back(std::move(active_point));
+    } else {
+      int saved_errno = errno;
+      if (saved_errno != EEXIST) {
+        return Error() << "Unable to create mount point" << active_point << ": "
+                       << strerror(saved_errno);
+      }
+    }
+  }
+
+  // 3) Create invocation args.
+  std::vector<std::string> args{
+      "/system/bin/apexd", arg,
+      mounted_apexes[hook_idx].mount_point,  // Make the APEX with hook first.
+  };
+  for (size_t i = 0; i < mounted_apexes.size(); i++) {
+    if ((int)i != hook_idx) {
+      args.push_back(mounted_apexes[i].mount_point);
+    }
+  }
+
+  std::string error_msg;
+  int res = ForkAndRun(args, &error_msg);
+  return res == 0 ? Result<void>{} : Error() << error_msg;
+}
+
+template <typename Fn>
+int RunFnInstall(char** in_argv, Fn fn, const char* name) {
   // 1) Unshare.
   if (unshare(CLONE_NEWNS) != 0) {
     PLOG(ERROR) << "Failed to unshare() for apex " << name;
@@ -119,8 +160,7 @@
 
   std::string hook_path;
   {
-    auto bind_fn = [&fn, name,
-                    activation_dirs](const std::string& mount_point) mutable {
+    auto bind_fn = [&fn, name](const std::string& mount_point) {
       std::string hook;
       std::string active_point;
       {
@@ -143,14 +183,6 @@
         const auto& manifest = *manifest_or;
         hook = (manifest.*fn)();
         active_point = apexd_private::GetActiveMountPoint(manifest);
-        // Ensure there is an activation point. If not, create one and delete
-        // later.
-        if (0 == mkdir(active_point.c_str(), kMkdirMode)) {
-          activation_dirs.push_back(active_point);
-        } else if (errno != EEXIST) {
-          PLOG(ERROR) << "Unable to create mount point " << active_point;
-          _exit(205);
-        }
       }
 
       // 3) Activate the new apex.
@@ -201,19 +233,17 @@
 
 }  // namespace
 
-Result<void> StagePreInstall(const std::vector<ApexFile>& apexes,
-                             const std::vector<std::string>& mount_points) {
-  return StageFnInstall(apexes, mount_points, &ApexManifest::preinstallhook,
-                        "--pre-install", "pre-install");
+Result<void> StagePreInstall(const std::vector<ApexFile>& apexes) {
+  return StageFnInstall(apexes, &ApexManifest::preinstallhook, "--pre-install",
+                        "pre-install");
 }
 
 int RunPreInstall(char** in_argv) {
   return RunFnInstall(in_argv, &ApexManifest::preinstallhook, "pre-install");
 }
 
-Result<void> StagePostInstall(const std::vector<ApexFile>& apexes,
-                              const std::vector<std::string>& mount_points) {
-  return StageFnInstall(apexes, mount_points, &ApexManifest::postinstallhook,
+Result<void> StagePostInstall(const std::vector<ApexFile>& apexes) {
+  return StageFnInstall(apexes, &ApexManifest::postinstallhook,
                         "--post-install", "post-install");
 }
 
diff --git a/apexd/apexd_prepostinstall.h b/apexd/apexd_prepostinstall.h
index 65125ba..66cd2f5 100644
--- a/apexd/apexd_prepostinstall.h
+++ b/apexd/apexd_prepostinstall.h
@@ -27,20 +27,16 @@
 
 class ApexFile;
 
-// Forks into: apexd --pre-install <mount-point-of-apex-with-hook>
-// [<other-mount-points>] The caller must pass the temp mount point for each
-// apex file.
+// Temp mounts given apexes and then forks into:
+// apexd --pre-install <mount-point-of-apex-with-hook> [<other-mount-points>]
 android::base::Result<void> StagePreInstall(
-    const std::vector<ApexFile>& apexes,
-    const std::vector<std::string>& mount_points);
+    const std::vector<ApexFile>& apexes);
 int RunPreInstall(char** argv);
 
-// Forks into: apexd --post-install <mount-point-of-apex-with-hook>
-// [<other-mount-points>] The caller must pass the temp mount point for each
-// apex file.
+// Temp mounts given apexes and then forks into:
+// apexd --post-install <mount-point-of-apex-with-hook> [<other-mount-points>]
 android::base::Result<void> StagePostInstall(
-    const std::vector<ApexFile>& apexes,
-    const std::vector<std::string>& mount_points);
+    const std::vector<ApexFile>& apexes);
 int RunPostInstall(char** argv);
 
 }  // namespace apex
diff --git a/apexd/apexd_private.h b/apexd/apexd_private.h
index b3108cf..1706e08 100644
--- a/apexd/apexd_private.h
+++ b/apexd/apexd_private.h
@@ -21,7 +21,6 @@
 
 #include <android-base/result.h>
 #include "apex_database.h"
-#include "apex_file.h"
 #include "apex_manifest.h"
 
 namespace android {
@@ -33,16 +32,16 @@
 
 namespace apexd_private {
 
-std::string GetPackageMountPoint(const ::apex::proto::ApexManifest& manifest);
-std::string GetPackageTempMountPoint(
-    const ::apex::proto::ApexManifest& manifest);
-std::string GetActiveMountPoint(const ::apex::proto::ApexManifest& manifest);
+std::string GetPackageMountPoint(const ApexManifest& manifest);
+std::string GetPackageTempMountPoint(const ApexManifest& manifest);
+std::string GetActiveMountPoint(const ApexManifest& manifest);
 
 android::base::Result<void> BindMount(const std::string& target,
                                       const std::string& source);
-android::base::Result<MountedApexDatabase::MountedApexData>
-GetTempMountedApexData(const std::string& package);
-android::base::Result<void> UnmountTempMount(const ApexFile& apex);
+android::base::Result<MountedApexDatabase::MountedApexData> TempMountPackage(
+    const ApexFile& apex, const std::string& mount_point);
+android::base::Result<void> Unmount(
+    const MountedApexDatabase::MountedApexData& data);
 
 }  // namespace apexd_private
 }  // namespace apex
diff --git a/apexd/apexd_lifecycle.cpp b/apexd/apexd_prop.cpp
similarity index 74%
rename from apexd/apexd_lifecycle.cpp
rename to apexd/apexd_prop.cpp
index 41c1abe..31030e1 100644
--- a/apexd/apexd_lifecycle.cpp
+++ b/apexd/apexd_prop.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -16,28 +16,23 @@
 
 #define LOG_TAG "apexd"
 
-#include "apexd_lifecycle.h"
+#include "apexd_prop.h"
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 
 #include "apexd_utils.h"
 
+using android::base::GetBoolProperty;
 using android::base::GetProperty;
 using android::base::Result;
 using android::base::WaitForProperty;
 
 namespace android {
 namespace apex {
-
-bool ApexdLifecycle::IsBooting() {
-  auto status = GetProperty(kApexStatusSysprop, "");
-  return status != kApexStatusReady && status != kApexStatusActivated;
-}
-
-void ApexdLifecycle::WaitForBootStatus(
-    Result<void> (&revert_fn)(const std::string&, const std::string&)) {
-  while (!boot_completed_) {
+void waitForBootStatus(Result<void> (&revert_fn)(const std::string&),
+                       void (&complete_fn)()) {
+  while (!GetBoolProperty("sys.boot_completed", false)) {
     // Check for change in either crashing property or sys.boot_completed
     // Wait for updatable_crashing property change for most of the time
     // (arbitrary 30s), briefly check if boot has completed successfully,
@@ -49,7 +44,7 @@
       auto name = GetProperty("sys.init.updatable_crashing_process_name", "");
       LOG(ERROR) << "Native process '" << (name.empty() ? "[unknown]" : name)
                  << "' is crashing. Attempting a revert";
-      auto result = revert_fn(name, "");
+      auto result = revert_fn(name);
       if (!result.ok()) {
         LOG(ERROR) << "Revert failed : " << result.error();
         break;
@@ -64,9 +59,15 @@
       }
     }
   }
+  // Wait for boot to complete, and then run complete_fn.
+  // TODO(ioffe): this is a hack, instead we should have a binder call from
+  //  system_server into apexd when boot completes.
+  if (WaitForProperty("sys.boot_completed", "1", std::chrono::minutes(5))) {
+    complete_fn();
+    return;
+  } else {
+    LOG(ERROR) << "Boot never completed";
+  }
 }
-
-void ApexdLifecycle::MarkBootCompleted() { boot_completed_ = true; }
-
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apexd_prop.h b/apexd/apexd_prop.h
new file mode 100644
index 0000000..4b8a766
--- /dev/null
+++ b/apexd/apexd_prop.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef ANDROID_APEXD_APEXD_PROP_H_
+#define ANDROID_APEXD_APEXD_PROP_H_
+
+#include <android-base/result.h>
+
+namespace android {
+namespace apex {
+
+void waitForBootStatus(
+    android::base::Result<void> (&rollback_fn)(const std::string&),
+    void (&complete_fn)());
+
+}  // namespace apex
+}  // namespace android
+
+#endif  // ANDROID_APEXD_APEXD_PROP_H
diff --git a/apexd/apexd_rollback_utils.h b/apexd/apexd_rollback_utils.h
index c7fa05e..9990be2 100644
--- a/apexd/apexd_rollback_utils.h
+++ b/apexd/apexd_rollback_utils.h
@@ -25,6 +25,10 @@
 #include <android-base/result.h>
 #include <android-base/scopeguard.h>
 #include <logwrap/logwrap.h>
+#include <selinux/android.h>
+
+using android::base::Error;
+using android::base::Result;
 
 namespace android {
 namespace apex {
@@ -36,7 +40,7 @@
  * path. Note that this will fail if run before APEXes are mounted, due to a
  * dependency on runtime.
  */
-inline int32_t CopyDirectoryRecursive(const char* from, const char* to) {
+int32_t copy_directory_recursive(const char* from, const char* to) {
   const char* const argv[] = {
       kCpPath,
       "-F", /* delete any existing destination file first
@@ -58,15 +62,15 @@
  * from from_path into to_path. Note that this must be run after APEXes are
  * mounted.
  */
-inline android::base::Result<void> ReplaceFiles(const std::string& from_path,
-                                                const std::string& to_path) {
+inline Result<void> ReplaceFiles(const std::string& from_path,
+                                 const std::string& to_path) {
   namespace fs = std::filesystem;
 
   std::error_code error_code;
   fs::remove_all(to_path, error_code);
   if (error_code) {
-    return android::base::Error() << "Failed to delete existing files at "
-                                  << to_path << " : " << error_code.message();
+    return Error() << "Failed to delete existing files at " << to_path << " : "
+                   << error_code.message();
   }
 
   auto deleter = [&] {
@@ -79,15 +83,23 @@
   };
   auto scope_guard = android::base::make_scope_guard(deleter);
 
-  int rc = CopyDirectoryRecursive(from_path.c_str(), to_path.c_str());
+  int rc = copy_directory_recursive(from_path.c_str(), to_path.c_str());
   if (rc != 0) {
-    return android::base::Error() << "Failed to copy from [" << from_path
-                                  << "] to [" << to_path << "]";
+    return Error() << "Failed to copy from [" << from_path << "] to ["
+                   << to_path << "]";
   }
   scope_guard.Disable();
   return {};
 }
 
+inline Result<void> RestoreconPath(const std::string& path) {
+  unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
+  if (selinux_android_restorecon(path.c_str(), seflags) < 0) {
+    return Error() << "Failed to restorecon " << path;
+  }
+  return {};
+}
+
 }  // namespace apex
 }  // namespace android
 
diff --git a/apexd/apexd_session.cpp b/apexd/apexd_session.cpp
index defef6f..3d916c4 100644
--- a/apexd/apexd_session.cpp
+++ b/apexd/apexd_session.cpp
@@ -22,7 +22,6 @@
 #include "session_state.pb.h"
 
 #include <android-base/logging.h>
-#include <android-base/stringprintf.h>
 #include <dirent.h>
 #include <sys/stat.h>
 
@@ -33,7 +32,6 @@
 
 using android::base::Error;
 using android::base::Result;
-using android::base::StringPrintf;
 using apex::proto::SessionState;
 
 namespace android {
@@ -41,57 +39,68 @@
 
 namespace {
 
-// Starting from R, apexd prefers /metadata partition (kNewApexSessionsDir) as
-// location for sessions-related information. For devices that don't have
-// /metadata partition, apexd will fallback to the /data one
-// (kOldApexSessionsDir).
-static constexpr const char* kOldApexSessionsDir = "/data/apex/sessions";
-static constexpr const char* kNewApexSessionsDir = "/metadata/apex/sessions";
-
 static constexpr const char* kStateFileName = "state";
 
+std::string getSessionDir(int session_id) {
+  return kApexSessionsDir + "/" + std::to_string(session_id);
+}
+
+std::string getSessionStateFilePath(int session_id) {
+  return getSessionDir(session_id) + "/" + kStateFileName;
+}
+
+Result<std::string> createSessionDirIfNeeded(int session_id) {
+  // create /data/sessions
+  auto res = createDirIfNeeded(kApexSessionsDir, 0700);
+  if (!res.ok()) {
+    return res.error();
+  }
+  // create /data/sessions/session_id
+  std::string sessionDir = getSessionDir(session_id);
+  res = createDirIfNeeded(sessionDir, 0700);
+  if (!res.ok()) {
+    return res.error();
+  }
+
+  return sessionDir;
+}
+
+Result<void> deleteSessionDir(int session_id) {
+  std::string session_dir = getSessionDir(session_id);
+  LOG(DEBUG) << "Deleting " << session_dir;
+  auto path = std::filesystem::path(session_dir);
+  std::error_code error_code;
+  std::filesystem::remove_all(path, error_code);
+  if (error_code) {
+    return Error() << "Failed to delete " << session_dir << " : "
+                   << error_code.message();
+  }
+  return {};
+}
+
 }  // namespace
 
 ApexSession::ApexSession(SessionState state) : state_(std::move(state)) {}
 
-std::string ApexSession::GetSessionsDir() {
-  static std::string result;
-  static std::once_flag once_flag;
-  std::call_once(once_flag, [&]() {
-    auto status =
-        FindFirstExistingDirectory(kNewApexSessionsDir, kOldApexSessionsDir);
-    if (!status.ok()) {
-      LOG(FATAL) << status.error();
-    }
-    result = std::move(*status);
-  });
-  return result;
-}
-
-Result<void> ApexSession::MigrateToMetadataSessionsDir() {
-  return MoveDir(kOldApexSessionsDir, kNewApexSessionsDir);
-}
-
 Result<ApexSession> ApexSession::CreateSession(int session_id) {
   SessionState state;
   // Create session directory
-  std::string session_dir = GetSessionsDir() + "/" + std::to_string(session_id);
-  if (auto status = CreateDirIfNeeded(session_dir, 0700); !status.ok()) {
-    return status.error();
+  auto sessionPath = createSessionDirIfNeeded(session_id);
+  if (!sessionPath.ok()) {
+    return sessionPath.error();
   }
   state.set_id(session_id);
 
   return ApexSession(state);
 }
-
 Result<ApexSession> ApexSession::GetSessionFromFile(const std::string& path) {
   SessionState state;
-  std::fstream state_file(path, std::ios::in | std::ios::binary);
-  if (!state_file) {
+  std::fstream stateFile(path, std::ios::in | std::ios::binary);
+  if (!stateFile) {
     return Error() << "Failed to open " << path;
   }
 
-  if (!state.ParseFromIstream(&state_file)) {
+  if (!state.ParseFromIstream(&stateFile)) {
     return Error() << "Failed to parse " << path;
   }
 
@@ -99,8 +108,7 @@
 }
 
 Result<ApexSession> ApexSession::GetSession(int session_id) {
-  auto path = StringPrintf("%s/%d/%s", GetSessionsDir().c_str(), session_id,
-                           kStateFileName);
+  auto path = getSessionStateFilePath(session_id);
 
   return GetSessionFromFile(path);
 }
@@ -108,19 +116,19 @@
 std::vector<ApexSession> ApexSession::GetSessions() {
   std::vector<ApexSession> sessions;
 
-  Result<std::vector<std::string>> session_paths = ReadDir(
-      GetSessionsDir(), [](const std::filesystem::directory_entry& entry) {
+  Result<std::vector<std::string>> sessionPaths = ReadDir(
+      kApexSessionsDir, [](const std::filesystem::directory_entry& entry) {
         std::error_code ec;
         return entry.is_directory(ec);
       });
 
-  if (!session_paths.ok()) {
+  if (!sessionPaths.ok()) {
     return sessions;
   }
 
-  for (const std::string& session_dir_path : *session_paths) {
+  for (const std::string& sessionDirPath : *sessionPaths) {
     // Try to read session state
-    auto session = GetSessionFromFile(session_dir_path + "/" + kStateFileName);
+    auto session = GetSessionFromFile(sessionDirPath + "/" + kStateFileName);
     if (!session.ok()) {
       LOG(WARNING) << session.error();
       continue;
@@ -144,20 +152,20 @@
 
 std::vector<ApexSession> ApexSession::GetActiveSessions() {
   auto sessions = GetSessions();
-  std::vector<ApexSession> active_sessions;
+  std::vector<ApexSession> activeSessions;
   for (const ApexSession& session : sessions) {
     if (!session.IsFinalized() && session.GetState() != SessionState::UNKNOWN) {
-      active_sessions.push_back(session);
+      activeSessions.push_back(session);
     }
   }
-  return active_sessions;
+  return activeSessions;
 }
 
 SessionState::State ApexSession::GetState() const { return state_.state(); }
 
 int ApexSession::GetId() const { return state_.id(); }
 
-const std::string& ApexSession::GetBuildFingerprint() const {
+std::string ApexSession::GetBuildFingerprint() const {
   return state_.expected_build_fingerprint();
 }
 
@@ -181,14 +189,10 @@
 
 int ApexSession::GetRollbackId() const { return state_.rollback_id(); }
 
-const std::string& ApexSession::GetCrashingNativeProcess() const {
+std::string ApexSession::GetCrashingNativeProcess() const {
   return state_.crashing_native_process();
 }
 
-const std::string& ApexSession::GetErrorMessage() const {
-  return state_.error_message();
-}
-
 const google::protobuf::RepeatedField<int> ApexSession::GetChildSessionIds()
     const {
   return state_.child_session_ids();
@@ -226,10 +230,6 @@
   state_.set_crashing_native_process(crashing_process);
 }
 
-void ApexSession::SetErrorMessage(const std::string& error_message) {
-  state_.set_error_message(error_message);
-}
-
 void ApexSession::AddApexName(const std::string& apex_name) {
   state_.add_apex_names(apex_name);
 }
@@ -238,29 +238,19 @@
     const SessionState::State& session_state) {
   state_.set_state(session_state);
 
-  auto state_file_path = StringPrintf("%s/%d/%s", GetSessionsDir().c_str(),
-                                      state_.id(), kStateFileName);
+  auto stateFilePath = getSessionStateFilePath(state_.id());
 
-  std::fstream state_file(state_file_path,
-                          std::ios::out | std::ios::trunc | std::ios::binary);
-  if (!state_.SerializeToOstream(&state_file)) {
-    return Error() << "Failed to write state file " << state_file_path;
+  std::fstream stateFile(stateFilePath,
+                         std::ios::out | std::ios::trunc | std::ios::binary);
+  if (!state_.SerializeToOstream(&stateFile)) {
+    return Error() << "Failed to write state file " << stateFilePath;
   }
 
   return {};
 }
 
 Result<void> ApexSession::DeleteSession() const {
-  std::string session_dir = GetSessionsDir() + "/" + std::to_string(GetId());
-  LOG(INFO) << "Deleting " << session_dir;
-  auto path = std::filesystem::path(session_dir);
-  std::error_code error_code;
-  std::filesystem::remove_all(path, error_code);
-  if (error_code) {
-    return Error() << "Failed to delete " << session_dir << " : "
-                   << error_code.message();
-  }
-  return {};
+  return deleteSessionDir(GetId());
 }
 
 std::ostream& operator<<(std::ostream& out, const ApexSession& session) {
@@ -269,18 +259,5 @@
              << "]";
 }
 
-void ApexSession::DeleteFinalizedSessions() {
-  auto sessions = GetSessions();
-  for (const ApexSession& session : sessions) {
-    if (!session.IsFinalized()) {
-      continue;
-    }
-    auto result = session.DeleteSession();
-    if (!result.ok()) {
-      LOG(WARNING) << "Failed to delete finalized session: " << session.GetId();
-    }
-  }
-}
-
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apexd_session.h b/apexd/apexd_session.h
index 5c1f1e3..e0cea91 100644
--- a/apexd/apexd_session.h
+++ b/apexd/apexd_session.h
@@ -28,18 +28,10 @@
 namespace android {
 namespace apex {
 
+static const std::string kApexSessionsDir = "/metadata/apex/sessions";
+
 class ApexSession {
  public:
-  // Returns top-level directory to store sessions metadata in.
-  // If device has /metadata partition, this will return
-  // /metadata/apex/sessions, on all other devices it will return
-  // /data/apex/sessions.
-  static std::string GetSessionsDir();
-  // Migrates content of /data/apex/sessions to /metadata/apex/sessions.
-  // If device doesn't have /metadata partition this call will be a no-op.
-  // If /data/apex/sessions this call will also be a no-op.
-  static android::base::Result<void> MigrateToMetadataSessionsDir();
-
   static android::base::Result<ApexSession> CreateSession(int session_id);
   static android::base::Result<ApexSession> GetSession(int session_id);
   static std::vector<ApexSession> GetSessions();
@@ -52,9 +44,8 @@
   const google::protobuf::RepeatedField<int> GetChildSessionIds() const;
   ::apex::proto::SessionState::State GetState() const;
   int GetId() const;
-  const std::string& GetBuildFingerprint() const;
-  const std::string& GetCrashingNativeProcess() const;
-  const std::string& GetErrorMessage() const;
+  std::string GetBuildFingerprint() const;
+  std::string GetCrashingNativeProcess() const;
   bool IsFinalized() const;
   bool HasRollbackEnabled() const;
   bool IsRollback() const;
@@ -67,17 +58,15 @@
   void SetIsRollback(const bool is_rollback);
   void SetRollbackId(const int rollback_id);
   void SetCrashingNativeProcess(const std::string& crashing_process);
-  void SetErrorMessage(const std::string& error_message);
   void AddApexName(const std::string& apex_name);
 
   android::base::Result<void> UpdateStateAndCommit(
       const ::apex::proto::SessionState::State& state);
 
   android::base::Result<void> DeleteSession() const;
-  static void DeleteFinalizedSessions();
 
  private:
-  explicit ApexSession(::apex::proto::SessionState state);
+  ApexSession(::apex::proto::SessionState state);
   ::apex::proto::SessionState state_;
 
   static android::base::Result<ApexSession> GetSessionFromFile(
diff --git a/apexd/apexd_session_test.cpp b/apexd/apexd_session_test.cpp
deleted file mode 100644
index 50d0f85..0000000
--- a/apexd/apexd_session_test.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#include <filesystem>
-#include <fstream>
-#include <string>
-
-#include <errno.h>
-
-#include <android-base/file.h>
-#include <android-base/result.h>
-#include <android-base/scopeguard.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <gtest/gtest.h>
-
-#include "apexd_session.h"
-#include "apexd_test_utils.h"
-#include "apexd_utils.h"
-#include "session_state.pb.h"
-
-namespace android {
-namespace apex {
-namespace {
-
-using android::apex::testing::IsOk;
-using android::base::Join;
-using android::base::make_scope_guard;
-
-// TODO(b/170329726): add unit tests for apexd_sessions.h
-
-TEST(ApexdSessionTest, GetSessionsDirSessionsStoredInMetadata) {
-  if (access("/metadata", F_OK) != 0) {
-    GTEST_SKIP() << "Device doesn't have /metadata partition";
-  }
-
-  std::string result = ApexSession::GetSessionsDir();
-  ASSERT_EQ(result, "/metadata/apex/sessions");
-}
-
-TEST(ApexdSessionTest, GetSessionsDirNoMetadataPartitionFallbackToData) {
-  if (access("/metadata", F_OK) == 0) {
-    GTEST_SKIP() << "Device has /metadata partition";
-  }
-
-  std::string result = ApexSession::GetSessionsDir();
-  ASSERT_EQ(result, "/data/apex/sessions");
-}
-
-TEST(ApexdSessionTest, MigrateToMetadataSessionsDir) {
-  namespace fs = std::filesystem;
-
-  if (access("/metadata", F_OK) != 0) {
-    GTEST_SKIP() << "Device doesn't have /metadata partition";
-  }
-
-  // This is ugly, but does the job. To have a truly hermetic unit tests we
-  // need to refactor ApexSession class.
-  for (const auto& entry : fs::directory_iterator("/metadata/apex/sessions")) {
-    fs::remove_all(entry.path());
-  }
-
-  // This is a very ugly test set up, but to have something better we need to
-  // refactor ApexSession class.
-  class TestApexSession {
-   public:
-    TestApexSession(int id, const SessionState::State& state) {
-      path_ = "/data/apex/sessions/" + std::to_string(id);
-      if (auto status = CreateDirIfNeeded(path_, 0700); !status.ok()) {
-        ADD_FAILURE() << "Failed to create " << path_ << " : "
-                      << status.error();
-      }
-      SessionState session;
-      session.set_id(id);
-      session.set_state(state);
-      std::fstream state_file(
-          path_ + "/state", std::ios::out | std::ios::trunc | std::ios::binary);
-      if (!session.SerializeToOstream(&state_file)) {
-        ADD_FAILURE() << "Failed to write to " << path_;
-      }
-    }
-
-    ~TestApexSession() { fs::remove_all(path_); }
-
-   private:
-    std::string path_;
-  };
-
-  auto deleter = make_scope_guard([&]() {
-    fs::remove_all("/metadata/apex/sessions/239");
-    fs::remove_all("/metadata/apex/sessions/1543");
-  });
-
-  TestApexSession session1(239, SessionState::SUCCESS);
-  TestApexSession session2(1543, SessionState::ACTIVATION_FAILED);
-
-  ASSERT_TRUE(IsOk(ApexSession::MigrateToMetadataSessionsDir()));
-
-  auto sessions = ApexSession::GetSessions();
-  ASSERT_EQ(2u, sessions.size()) << Join(sessions, ',');
-
-  auto migrated_session_1 = ApexSession::GetSession(239);
-  ASSERT_TRUE(IsOk(migrated_session_1));
-  ASSERT_EQ(SessionState::SUCCESS, migrated_session_1->GetState());
-
-  auto migrated_session_2 = ApexSession::GetSession(1543);
-  ASSERT_TRUE(IsOk(migrated_session_2));
-  ASSERT_EQ(SessionState::ACTIVATION_FAILED, migrated_session_2->GetState());
-}
-
-}  // namespace
-}  // namespace apex
-}  // namespace android
diff --git a/apexd/apexd_test.cpp b/apexd/apexd_test.cpp
deleted file mode 100644
index a3ebd03..0000000
--- a/apexd/apexd_test.cpp
+++ /dev/null
@@ -1,3603 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/properties.h>
-#include <android-base/scopeguard.h>
-#include <android-base/stringprintf.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "apex_database.h"
-#include "apex_file_repository.h"
-#include "apexd.h"
-#include "apexd_checkpoint.h"
-#include "apexd_session.h"
-#include "apexd_test_utils.h"
-#include "apexd_utils.h"
-
-#include "apex_manifest.pb.h"
-#include "com_android_apex.h"
-#include "gmock/gmock-matchers.h"
-
-namespace android {
-namespace apex {
-
-namespace fs = std::filesystem;
-
-using MountedApexData = MountedApexDatabase::MountedApexData;
-using android::apex::testing::ApexFileEq;
-using android::apex::testing::IsOk;
-using android::base::GetExecutableDirectory;
-using android::base::GetProperty;
-using android::base::make_scope_guard;
-using android::base::RemoveFileIfExists;
-using android::base::Result;
-using android::base::StringPrintf;
-using android::base::unique_fd;
-using android::base::WriteStringToFile;
-using com::android::apex::testing::ApexInfoXmlEq;
-using ::testing::ByRef;
-using ::testing::HasSubstr;
-using ::testing::IsEmpty;
-using ::testing::StartsWith;
-using ::testing::UnorderedElementsAre;
-using ::testing::UnorderedElementsAreArray;
-
-static std::string GetTestDataDir() { return GetExecutableDirectory(); }
-static std::string GetTestFile(const std::string& name) {
-  return GetTestDataDir() + "/" + name;
-}
-
-static int64_t GetMTime(const std::string& path) {
-  struct stat st_buf;
-  if (stat(path.c_str(), &st_buf) != 0) {
-    PLOG(ERROR) << "Failed to stat " << path;
-    return 0;
-  }
-  return st_buf.st_mtime;
-}
-
-// A very basic mock of CheckpointInterface.
-class MockCheckpointInterface : public CheckpointInterface {
- public:
-  Result<bool> SupportsFsCheckpoints() override {
-    return supports_fs_checkpoint_;
-  }
-
-  Result<bool> NeedsCheckpoint() override { return needs_checkpoint_; }
-
-  Result<bool> NeedsRollback() override { return needs_rollback_; }
-
-  Result<void> StartCheckpoint(int32_t num_retries) override { return {}; }
-
-  Result<void> AbortChanges(const std::string& msg, bool retry) override {
-    return {};
-  }
-
-  void SetSupportsCheckpoint(bool value) { supports_fs_checkpoint_ = value; }
-
-  void SetNeedsCheckpoint(bool value) { needs_checkpoint_ = value; }
-
-  void SetNeedsRollback(bool value) { needs_rollback_ = value; }
-
- private:
-  bool supports_fs_checkpoint_, needs_checkpoint_, needs_rollback_;
-};
-
-static constexpr const char* kTestApexdStatusSysprop = "apexd.status.test";
-
-// A test fixture that provides frequently required temp directories for tests
-class ApexdUnitTest : public ::testing::Test {
- public:
-  ApexdUnitTest() {
-    built_in_dir_ = StringPrintf("%s/pre-installed-apex", td_.path);
-    data_dir_ = StringPrintf("%s/data-apex", td_.path);
-    decompression_dir_ = StringPrintf("%s/decompressed-apex", td_.path);
-    ota_reserved_dir_ = StringPrintf("%s/ota-reserved", td_.path);
-    hash_tree_dir_ = StringPrintf("%s/apex-hash-tree", td_.path);
-    staged_session_dir_ = StringPrintf("%s/staged-session-dir", td_.path);
-    config_ = {kTestApexdStatusSysprop,    {built_in_dir_},
-               data_dir_.c_str(),          decompression_dir_.c_str(),
-               ota_reserved_dir_.c_str(),  hash_tree_dir_.c_str(),
-               staged_session_dir_.c_str()};
-  }
-
-  const std::string& GetBuiltInDir() { return built_in_dir_; }
-  const std::string& GetDataDir() { return data_dir_; }
-  const std::string& GetDecompressionDir() { return decompression_dir_; }
-  const std::string& GetOtaReservedDir() { return ota_reserved_dir_; }
-  const std::string& GetHashTreeDir() { return hash_tree_dir_; }
-  const std::string GetStagedDir(int session_id) {
-    return StringPrintf("%s/session_%d", staged_session_dir_.c_str(),
-                        session_id);
-  }
-
-  std::string GetRootDigest(const ApexFile& apex) {
-    if (apex.IsCompressed()) {
-      return "";
-    }
-    auto digest = apex.VerifyApexVerity(apex.GetBundledPublicKey());
-    if (!digest.ok()) {
-      return "";
-    }
-    return digest->root_digest;
-  }
-
-  std::string AddPreInstalledApex(const std::string& apex_name) {
-    fs::copy(GetTestFile(apex_name), built_in_dir_);
-    return StringPrintf("%s/%s", built_in_dir_.c_str(), apex_name.c_str());
-  }
-
-  std::string AddDataApex(const std::string& apex_name) {
-    fs::copy(GetTestFile(apex_name), data_dir_);
-    return StringPrintf("%s/%s", data_dir_.c_str(), apex_name.c_str());
-  }
-
-  std::string AddDataApex(const std::string& apex_name,
-                          const std::string& target_name) {
-    fs::copy(GetTestFile(apex_name), data_dir_ + "/" + target_name);
-    return StringPrintf("%s/%s", data_dir_.c_str(), target_name.c_str());
-  }
-
-  // Copies the compressed apex to |built_in_dir| and decompresses it to
-  // |decompressed_dir| and then hard links to |target_dir|
-  std::string PrepareCompressedApex(const std::string& name,
-                                    const std::string& built_in_dir) {
-    fs::copy(GetTestFile(name), built_in_dir);
-    auto compressed_apex = ApexFile::Open(
-        StringPrintf("%s/%s", built_in_dir.c_str(), name.c_str()));
-    std::vector<ApexFileRef> compressed_apex_list;
-    compressed_apex_list.emplace_back(std::cref(*compressed_apex));
-    auto return_value =
-        ProcessCompressedApex(compressed_apex_list, /*is_ota_chroot*/ false);
-    return StringPrintf("%s/%s", built_in_dir.c_str(), name.c_str());
-  }
-
-  std::string PrepareCompressedApex(const std::string& name) {
-    return PrepareCompressedApex(name, built_in_dir_);
-  }
-
-  Result<ApexSession> CreateStagedSession(const std::string& apex_name,
-                                          int session_id) {
-    CreateDirIfNeeded(GetStagedDir(session_id), 0755);
-    fs::copy(GetTestFile(apex_name), GetStagedDir(session_id));
-    auto result = ApexSession::CreateSession(session_id);
-    result->SetBuildFingerprint(GetProperty("ro.build.fingerprint", ""));
-    return result;
-  }
-
- protected:
-  void SetUp() override {
-    SetConfig(config_);
-    ApexFileRepository::GetInstance().Reset(decompression_dir_);
-    ASSERT_EQ(mkdir(built_in_dir_.c_str(), 0755), 0);
-    ASSERT_EQ(mkdir(data_dir_.c_str(), 0755), 0);
-    ASSERT_EQ(mkdir(decompression_dir_.c_str(), 0755), 0);
-    ASSERT_EQ(mkdir(ota_reserved_dir_.c_str(), 0755), 0);
-    ASSERT_EQ(mkdir(hash_tree_dir_.c_str(), 0755), 0);
-    ASSERT_EQ(mkdir(staged_session_dir_.c_str(), 0755), 0);
-
-    DeleteDirContent(ApexSession::GetSessionsDir());
-  }
-
-  void TearDown() override { DeleteDirContent(ApexSession::GetSessionsDir()); }
-
- private:
-  TemporaryDir td_;
-  std::string built_in_dir_;
-  std::string data_dir_;
-  std::string decompression_dir_;
-  std::string ota_reserved_dir_;
-  std::string hash_tree_dir_;
-  std::string staged_session_dir_;
-  ApexdConfig config_;
-};
-
-// Apex that does not have pre-installed version, does not get selected
-TEST_F(ApexdUnitTest, ApexMustHavePreInstalledVersionForSelection) {
-  AddPreInstalledApex("apex.apexd_test.apex");
-  AddPreInstalledApex("com.android.apex.cts.shim.apex");
-  auto shared_lib_1 = ApexFile::Open(AddPreInstalledApex(
-      "com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
-  auto& instance = ApexFileRepository::GetInstance();
-  // Pre-installed data needs to be present so that we can add data apex
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
-  auto apexd_test_file = ApexFile::Open(AddDataApex("apex.apexd_test.apex"));
-  auto shim_v1 = ApexFile::Open(AddDataApex("com.android.apex.cts.shim.apex"));
-  // Normally both pre-installed and data apex would be activated for a shared
-  // libs apex, but if they are the same version only the data apex will be.
-  auto shared_lib_2 = ApexFile::Open(
-      AddDataApex("com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
-  const auto all_apex = instance.AllApexFilesByName();
-  // Pass a blank instance so that the data apex files are not considered
-  // pre-installed
-  const ApexFileRepository instance_blank;
-  auto result = SelectApexForActivation(all_apex, instance_blank);
-  ASSERT_EQ(result.size(), 0u);
-  // When passed proper instance they should get selected
-  result = SelectApexForActivation(all_apex, instance);
-  ASSERT_EQ(result.size(), 3u);
-  ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file)),
-                                           ApexFileEq(ByRef(*shim_v1)),
-                                           ApexFileEq(ByRef(*shared_lib_2))));
-}
-
-// Higher version gets priority when selecting for activation
-TEST_F(ApexdUnitTest, HigherVersionOfApexIsSelected) {
-  auto apexd_test_file_v2 =
-      ApexFile::Open(AddPreInstalledApex("apex.apexd_test_v2.apex"));
-  AddPreInstalledApex("com.android.apex.cts.shim.apex");
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
-  TemporaryDir data_dir;
-  AddDataApex("apex.apexd_test.apex");
-  auto shim_v2 =
-      ApexFile::Open(AddDataApex("com.android.apex.cts.shim.v2.apex"));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
-  auto all_apex = instance.AllApexFilesByName();
-  auto result = SelectApexForActivation(all_apex, instance);
-  ASSERT_EQ(result.size(), 2u);
-
-  ASSERT_THAT(result,
-              UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file_v2)),
-                                   ApexFileEq(ByRef(*shim_v2))));
-}
-
-// When versions are equal, non-pre-installed version gets priority
-TEST_F(ApexdUnitTest, DataApexGetsPriorityForSameVersions) {
-  AddPreInstalledApex("apex.apexd_test.apex");
-  AddPreInstalledApex("com.android.apex.cts.shim.apex");
-  // Initialize pre-installed APEX information
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
-  auto apexd_test_file = ApexFile::Open(AddDataApex("apex.apexd_test.apex"));
-  auto shim_v1 = ApexFile::Open(AddDataApex("com.android.apex.cts.shim.apex"));
-  // Initialize ApexFile repo
-  ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
-  auto all_apex = instance.AllApexFilesByName();
-  auto result = SelectApexForActivation(all_apex, instance);
-  ASSERT_EQ(result.size(), 2u);
-
-  ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file)),
-                                           ApexFileEq(ByRef(*shim_v1))));
-}
-
-// Both versions of shared libs can be selected when preinstalled version is
-// lower than data version
-TEST_F(ApexdUnitTest, SharedLibsCanHaveBothVersionSelected) {
-  auto shared_lib_v1 = ApexFile::Open(AddPreInstalledApex(
-      "com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
-  // Initialize pre-installed APEX information
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
-  auto shared_lib_v2 = ApexFile::Open(
-      AddDataApex("com.android.apex.test.sharedlibs_generated.v2.libvY.apex"));
-  // Initialize data APEX information
-  ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
-  auto all_apex = instance.AllApexFilesByName();
-  auto result = SelectApexForActivation(all_apex, instance);
-  ASSERT_EQ(result.size(), 2u);
-
-  ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*shared_lib_v1)),
-                                           ApexFileEq(ByRef(*shared_lib_v2))));
-}
-
-// Data version of shared libs should not be selected if lower than
-// preinstalled version
-TEST_F(ApexdUnitTest, SharedLibsDataVersionDeletedIfLower) {
-  auto shared_lib_v2 = ApexFile::Open(AddPreInstalledApex(
-      "com.android.apex.test.sharedlibs_generated.v2.libvY.apex"));
-  // Initialize pre-installed APEX information
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
-  auto shared_lib_v1 = ApexFile::Open(
-      AddDataApex("com.android.apex.test.sharedlibs_generated.v1.libvX.apex"));
-  // Initialize data APEX information
-  ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
-  auto all_apex = instance.AllApexFilesByName();
-  auto result = SelectApexForActivation(all_apex, instance);
-  ASSERT_EQ(result.size(), 1u);
-
-  ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*shared_lib_v2))));
-}
-
-TEST_F(ApexdUnitTest, ProcessCompressedApex) {
-  auto compressed_apex = ApexFile::Open(
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
-
-  std::vector<ApexFileRef> compressed_apex_list;
-  compressed_apex_list.emplace_back(std::cref(*compressed_apex));
-  auto return_value =
-      ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
-
-  std::string decompressed_file_path = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  // Assert output path is not empty
-  auto exists = PathExists(decompressed_file_path);
-  ASSERT_TRUE(IsOk(exists));
-  ASSERT_TRUE(*exists) << decompressed_file_path << " does not exist";
-
-  // Assert that decompressed apex is same as original apex
-  const std::string original_apex_file_path =
-      GetTestFile("com.android.apex.compressed.v1_original.apex");
-  auto comparison_result =
-      CompareFiles(original_apex_file_path, decompressed_file_path);
-  ASSERT_TRUE(IsOk(comparison_result));
-  ASSERT_TRUE(*comparison_result);
-
-  // Assert that return value contains decompressed APEX
-  auto decompressed_apex = ApexFile::Open(decompressed_file_path);
-  ASSERT_THAT(return_value,
-              UnorderedElementsAre(ApexFileEq(ByRef(*decompressed_apex))));
-}
-
-TEST_F(ApexdUnitTest, ProcessCompressedApexRunsVerification) {
-  auto compressed_apex_mismatch_key = ApexFile::Open(AddPreInstalledApex(
-      "com.android.apex.compressed_key_mismatch_with_original.capex"));
-  auto compressed_apex_version_mismatch = ApexFile::Open(
-      AddPreInstalledApex("com.android.apex.compressed.v1_with_v2_apex.capex"));
-
-  std::vector<ApexFileRef> compressed_apex_list;
-  compressed_apex_list.emplace_back(std::cref(*compressed_apex_mismatch_key));
-  compressed_apex_list.emplace_back(
-      std::cref(*compressed_apex_version_mismatch));
-  auto return_value =
-      ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
-  ASSERT_EQ(return_value.size(), 0u);
-}
-
-TEST_F(ApexdUnitTest, ValidateDecompressedApex) {
-  auto capex = ApexFile::Open(
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
-  auto decompressed_v1 = ApexFile::Open(
-      AddDataApex("com.android.apex.compressed.v1_original.apex"));
-
-  auto result =
-      ValidateDecompressedApex(std::cref(*capex), std::cref(*decompressed_v1));
-  ASSERT_TRUE(IsOk(result));
-
-  // Validation checks version
-  auto decompressed_v2 = ApexFile::Open(
-      AddDataApex("com.android.apex.compressed.v2_original.apex"));
-  result =
-      ValidateDecompressedApex(std::cref(*capex), std::cref(*decompressed_v2));
-  ASSERT_FALSE(IsOk(result));
-  ASSERT_THAT(
-      result.error().message(),
-      HasSubstr(
-          "Compressed APEX has different version than decompressed APEX"));
-
-  // Validation check root digest
-  auto decompressed_v1_different_digest = ApexFile::Open(AddDataApex(
-      "com.android.apex.compressed.v1_different_digest_original.apex"));
-  result = ValidateDecompressedApex(
-      std::cref(*capex), std::cref(*decompressed_v1_different_digest));
-  ASSERT_FALSE(IsOk(result));
-  ASSERT_THAT(result.error().message(),
-              HasSubstr("does not match with expected root digest"));
-
-  // Validation checks key
-  auto capex_different_key = ApexFile::Open(
-      AddDataApex("com.android.apex.compressed_different_key.capex"));
-  result = ValidateDecompressedApex(std::cref(*capex_different_key),
-                                    std::cref(*decompressed_v1));
-  ASSERT_FALSE(IsOk(result));
-  ASSERT_THAT(
-      result.error().message(),
-      HasSubstr("Public key of compressed APEX is different than original"));
-}
-
-TEST_F(ApexdUnitTest, ProcessCompressedApexCanBeCalledMultipleTimes) {
-  auto compressed_apex = ApexFile::Open(
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
-
-  std::vector<ApexFileRef> compressed_apex_list;
-  compressed_apex_list.emplace_back(std::cref(*compressed_apex));
-  auto return_value =
-      ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
-  ASSERT_EQ(return_value.size(), 1u);
-
-  // Capture the creation time of the decompressed APEX
-  std::error_code ec;
-  auto decompressed_apex_path = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  auto last_write_time_1 = fs::last_write_time(decompressed_apex_path, ec);
-  ASSERT_FALSE(ec) << "Failed to capture last write time of "
-                   << decompressed_apex_path;
-
-  // Now try to decompress the same capex again. It should not fail.
-  return_value =
-      ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
-  ASSERT_EQ(return_value.size(), 1u);
-
-  // Ensure the decompressed APEX file did not change
-  auto last_write_time_2 = fs::last_write_time(decompressed_apex_path, ec);
-  ASSERT_FALSE(ec) << "Failed to capture last write time of "
-                   << decompressed_apex_path;
-  ASSERT_EQ(last_write_time_1, last_write_time_2);
-}
-
-// Test behavior of ProcessCompressedApex when is_ota_chroot is true
-TEST_F(ApexdUnitTest, ProcessCompressedApexOnOtaChroot) {
-  auto compressed_apex = ApexFile::Open(
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex"));
-
-  std::vector<ApexFileRef> compressed_apex_list;
-  compressed_apex_list.emplace_back(std::cref(*compressed_apex));
-  auto return_value =
-      ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ true);
-  ASSERT_EQ(return_value.size(), 1u);
-
-  // Decompressed APEX should be located in decompression_dir
-  std::string decompressed_file_path =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  // Assert output path is not empty
-  auto exists = PathExists(decompressed_file_path);
-  ASSERT_TRUE(IsOk(exists));
-  ASSERT_TRUE(*exists) << decompressed_file_path << " does not exist";
-
-  // Assert that decompressed apex is same as original apex
-  const std::string original_apex_file_path =
-      GetTestFile("com.android.apex.compressed.v1_original.apex");
-  auto comparison_result =
-      CompareFiles(original_apex_file_path, decompressed_file_path);
-  ASSERT_TRUE(IsOk(comparison_result));
-  ASSERT_TRUE(*comparison_result);
-
-  // Assert that return value contains the decompressed APEX
-  auto apex_file = ApexFile::Open(decompressed_file_path);
-  ASSERT_THAT(return_value,
-              UnorderedElementsAre(ApexFileEq(ByRef(*apex_file))));
-}
-
-// When decompressing APEX, reuse existing OTA APEX
-TEST_F(ApexdUnitTest, ProcessCompressedApexReuseOtaApex) {
-  // Push a compressed APEX that will fail to decompress
-  auto compressed_apex = ApexFile::Open(AddPreInstalledApex(
-      "com.android.apex.compressed.v1_not_decompressible.capex"));
-
-  std::vector<ApexFileRef> compressed_apex_list;
-  compressed_apex_list.emplace_back(std::cref(*compressed_apex));
-
-  // If we try to decompress capex directly, it should fail since the capex
-  // pushed is faulty and cannot be decompressed
-  auto return_value =
-      ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
-  ASSERT_EQ(return_value.size(), 0u);
-
-  // But, if there is an ota_apex present for reuse, it should reuse that
-  // and avoid decompressing the faulty capex
-
-  // Push an OTA apex that should be reused to skip decompression
-  auto ota_apex_path =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
-           ota_apex_path);
-  return_value =
-      ProcessCompressedApex(compressed_apex_list, /* is_ota_chroot= */ false);
-  ASSERT_EQ(return_value.size(), 1u);
-
-  // Ota Apex should be cleaned up
-  ASSERT_FALSE(*PathExists(ota_apex_path));
-  ASSERT_EQ(return_value[0].GetPath(),
-            StringPrintf("%s/com.android.apex.compressed@1%s",
-                         GetDecompressionDir().c_str(),
-                         kDecompressedApexPackageSuffix));
-}
-
-TEST_F(ApexdUnitTest, ShouldAllocateSpaceForDecompressionNewApex) {
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
-  // A brand new compressed APEX is being introduced: selected
-  auto result =
-      ShouldAllocateSpaceForDecompression("com.android.brand.new", 1, instance);
-  ASSERT_TRUE(IsOk(result));
-  ASSERT_TRUE(*result);
-}
-
-TEST_F(ApexdUnitTest,
-       ShouldAllocateSpaceForDecompressionWasNotCompressedBefore) {
-  // Prepare fake pre-installed apex
-  AddPreInstalledApex("apex.apexd_test.apex");
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-
-  // An existing pre-installed APEX is now compressed in the OTA: selected
-  {
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.test_package", 1, instance);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_TRUE(*result);
-  }
-
-  // Even if there is a data apex (lower version)
-  // Include data apex within calculation now
-  AddDataApex("apex.apexd_test_v2.apex");
-  ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-  {
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.test_package", 3, instance);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_TRUE(*result);
-  }
-
-  // But not if data apex has equal or higher version
-  {
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.test_package", 2, instance);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_FALSE(*result);
-  }
-}
-
-TEST_F(ApexdUnitTest, ShouldAllocateSpaceForDecompressionVersionCompare) {
-  // Prepare fake pre-installed apex
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex");
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({GetBuiltInDir()})));
-  ASSERT_TRUE(IsOk(instance.AddDataApex(GetDataDir())));
-
-  {
-    // New Compressed apex has higher version than decompressed data apex:
-    // selected
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.compressed", 2, instance);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_TRUE(*result)
-        << "Higher version test with decompressed data returned false";
-  }
-
-  // Compare against decompressed data apex
-  {
-    // New Compressed apex has same version as decompressed data apex: not
-    // selected
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.compressed", 1, instance);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_FALSE(*result)
-        << "Same version test with decompressed data returned true";
-  }
-
-  {
-    // New Compressed apex has lower version than decompressed data apex:
-    // selected
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.compressed", 0, instance);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_TRUE(*result)
-        << "lower version test with decompressed data returned false";
-  }
-
-  // Replace decompressed data apex with a higher version
-  ApexFileRepository instance_new(GetDecompressionDir());
-  ASSERT_TRUE(IsOk(instance_new.AddPreInstalledApex({GetBuiltInDir()})));
-  TemporaryDir data_dir_new;
-  fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
-           data_dir_new.path);
-  ASSERT_TRUE(IsOk(instance_new.AddDataApex(data_dir_new.path)));
-
-  {
-    // New Compressed apex has higher version as data apex: selected
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.compressed", 3, instance_new);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_TRUE(*result) << "Higher version test with new data returned false";
-  }
-
-  {
-    // New Compressed apex has same version as data apex: not selected
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.compressed", 2, instance_new);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_FALSE(*result) << "Same version test with new data returned true";
-  }
-
-  {
-    // New Compressed apex has lower version than data apex: not selected
-    auto result = ShouldAllocateSpaceForDecompression(
-        "com.android.apex.compressed", 1, instance_new);
-    ASSERT_TRUE(IsOk(result));
-    ASSERT_FALSE(*result) << "lower version test with new data returned true";
-  }
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexCreatesSingleFile) {
-  TemporaryDir dest_dir;
-  // Reserving space should create a single file in dest_dir with exact size
-
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
-  auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
-  ASSERT_TRUE(IsOk(files));
-  ASSERT_EQ(files->size(), 1u);
-  EXPECT_EQ(fs::file_size((*files)[0]), 100u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexSafeToCallMultipleTimes) {
-  TemporaryDir dest_dir;
-  // Calling ReserveSpaceForCompressedApex multiple times should still create
-  // a single file
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
-  auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
-  ASSERT_TRUE(IsOk(files));
-  ASSERT_EQ(files->size(), 1u);
-  EXPECT_EQ(fs::file_size((*files)[0]), 100u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexShrinkAndGrow) {
-  TemporaryDir dest_dir;
-
-  // Create a 100 byte file
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
-
-  // Should be able to shrink and grow the reserved space
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(1000, dest_dir.path)));
-  auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
-  ASSERT_TRUE(IsOk(files));
-  ASSERT_EQ(files->size(), 1u);
-  EXPECT_EQ(fs::file_size((*files)[0]), 1000u);
-
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(10, dest_dir.path)));
-  files = ReadDir(dest_dir.path, [](auto _) { return true; });
-  ASSERT_TRUE(IsOk(files));
-  ASSERT_EQ(files->size(), 1u);
-  EXPECT_EQ(fs::file_size((*files)[0]), 10u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexDeallocateIfPassedZero) {
-  TemporaryDir dest_dir;
-
-  // Create a file first
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(100, dest_dir.path)));
-  auto files = ReadDir(dest_dir.path, [](auto _) { return true; });
-  ASSERT_TRUE(IsOk(files));
-  ASSERT_EQ(files->size(), 1u);
-
-  // Should delete the reserved file if size passed is 0
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(0, dest_dir.path)));
-  files = ReadDir(dest_dir.path, [](auto _) { return true; });
-  ASSERT_TRUE(IsOk(files));
-  ASSERT_EQ(files->size(), 0u);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCapexCleansOtaApex) {
-  TemporaryDir dest_dir;
-
-  auto ota_apex_path = StringPrintf(
-      "%s/ota_apex%s", GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  auto create_ota_apex = [&]() {
-    // Create an ota_apex first
-    fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
-             ota_apex_path);
-    auto path_exists = PathExists(ota_apex_path);
-    ASSERT_TRUE(*path_exists);
-  };
-  create_ota_apex();
-
-  // Should not delete the reserved file if size passed is negative
-  ASSERT_FALSE(IsOk(ReserveSpaceForCompressedApex(-1, dest_dir.path)));
-  auto path_exists = PathExists(ota_apex_path);
-  ASSERT_TRUE(*path_exists);
-
-  // Should delete the reserved file if size passed is 0
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(0, dest_dir.path)));
-  path_exists = PathExists(ota_apex_path);
-  ASSERT_FALSE(*path_exists);
-
-  create_ota_apex();
-  // Should delete the reserved file if size passed is positive
-  ASSERT_TRUE(IsOk(ReserveSpaceForCompressedApex(10, dest_dir.path)));
-  path_exists = PathExists(ota_apex_path);
-  ASSERT_FALSE(*path_exists);
-}
-
-TEST_F(ApexdUnitTest, ReserveSpaceForCompressedApexErrorForNegativeValue) {
-  TemporaryDir dest_dir;
-  // Should return error if negative value is passed
-  ASSERT_FALSE(IsOk(ReserveSpaceForCompressedApex(-1, dest_dir.path)));
-}
-
-// A test fixture to use for tests that mount/unmount apexes.
-class ApexdMountTest : public ApexdUnitTest {
- public:
-
-  void UnmountOnTearDown(const std::string& apex_file) {
-    to_unmount_.push_back(apex_file);
-  }
-
- protected:
-  void SetUp() final {
-    ApexdUnitTest::SetUp();
-    GetApexDatabaseForTesting().Reset();
-    ASSERT_TRUE(IsOk(SetUpApexTestEnvironment()));
-  }
-
-  void TearDown() final {
-    ApexdUnitTest::TearDown();
-    for (const auto& apex : to_unmount_) {
-      if (auto status = DeactivatePackage(apex); !status.ok()) {
-        LOG(ERROR) << "Failed to unmount " << apex << " : " << status.error();
-      }
-    }
-  }
-
- private:
-  MountNamespaceRestorer restorer_;
-  std::vector<std::string> to_unmount_;
-};
-
-// TODO(b/187864524): cover other negative scenarios.
-TEST_F(ApexdMountTest, InstallPackageRejectsApexWithoutRebootlessSupport) {
-  std::string file_path = AddPreInstalledApex("apex.apexd_test.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(GetTestFile("apex.apexd_test.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(),
-              HasSubstr("does not support non-staged update"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsNoPreInstalledApex) {
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(
-      ret.error().message(),
-      HasSubstr("No active version found for package test.apex.rebootless"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsNoHashtree) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret =
-      InstallPackage(GetTestFile("test.rebootless_apex_v2_no_hashtree.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(),
-              HasSubstr(" does not have an embedded hash tree"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsNoActiveApex) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(
-      ret.error().message(),
-      HasSubstr("No active version found for package test.apex.rebootless"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsManifestMismatch) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(
-      GetTestFile("test.rebootless_apex_manifest_mismatch.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(
-      ret.error().message(),
-      HasSubstr(
-          "Manifest inside filesystem does not match manifest outside it"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsCorrupted) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_corrupted.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(), HasSubstr("Can't verify /dev/block/dm-"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsProvidesSharedLibs) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(
-      GetTestFile("test.rebootless_apex_provides_sharedlibs.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(), HasSubstr(" is a shared libs APEX"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsProvidesNativeLibs) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(
-      GetTestFile("test.rebootless_apex_provides_native_libs.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(), HasSubstr(" provides native libs"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsRequiresSharedApexLibs) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(
-      GetTestFile("test.rebootless_apex_requires_shared_apex_libs.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(), HasSubstr(" requires shared apex libs"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsJniLibs) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_jni_libs.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(), HasSubstr(" requires JNI libs"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsAddRequiredNativeLib) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret =
-      InstallPackage(GetTestFile("test.rebootless_apex_add_native_lib.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(),
-              HasSubstr("Set of native libs required by"));
-  ASSERT_THAT(
-      ret.error().message(),
-      HasSubstr("differs from the one required by the currently active"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsRemovesRequiredNativeLib) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret = InstallPackage(
-      GetTestFile("test.rebootless_apex_remove_native_lib.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(),
-              HasSubstr("Set of native libs required by"));
-  ASSERT_THAT(
-      ret.error().message(),
-      HasSubstr("differs from the one required by the currently active"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsAppInApex) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret =
-      InstallPackage(GetTestFile("test.rebootless_apex_app_in_apex.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(), HasSubstr("contains app inside"));
-}
-
-TEST_F(ApexdMountTest, InstallPackageRejectsPrivAppInApex) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto ret =
-      InstallPackage(GetTestFile("test.rebootless_apex_priv_app_in_apex.apex"));
-  ASSERT_FALSE(IsOk(ret));
-  ASSERT_THAT(ret.error().message(), HasSubstr("contains priv-app inside"));
-}
-
-TEST_F(ApexdMountTest, InstallPackagePreInstallVersionActive) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  {
-    auto active_apex = GetActivePackage("test.apex.rebootless");
-    ASSERT_TRUE(IsOk(active_apex));
-    ASSERT_EQ(active_apex->GetPath(), file_path);
-  }
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
-  ASSERT_TRUE(IsOk(ret));
-  UnmountOnTearDown(ret->GetPath());
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/test.apex.rebootless",
-                                   "/apex/test.apex.rebootless@2"));
-
-  // Check that /apex/test.apex.rebootless is a bind mount of
-  // /apex/test.apex.rebootless@2.
-  auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
-  ASSERT_TRUE(IsOk(manifest));
-  ASSERT_EQ(2u, manifest->version());
-
-  // Check that GetActivePackage correctly reports upgraded version.
-  auto active_apex = GetActivePackage("test.apex.rebootless");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
-  // Check that pre-installed APEX is still around
-  ASSERT_EQ(0, access(file_path.c_str(), F_OK))
-      << "Can't access " << file_path << " : " << strerror(errno);
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that upgraded APEX is mounted on top of dm-verity device.
-  db.ForallMountedApexes(
-      "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
-        ASSERT_TRUE(latest);
-        ASSERT_EQ(data.full_path, ret->GetPath());
-        ASSERT_EQ(data.device_name, "test.apex.rebootless@2_1");
-      });
-}
-
-TEST_F(ApexdMountTest, InstallPackagePreInstallVersionActiveSamegrade) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  {
-    auto active_apex = GetActivePackage("test.apex.rebootless");
-    ASSERT_TRUE(IsOk(active_apex));
-    ASSERT_EQ(active_apex->GetPath(), file_path);
-  }
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
-  ASSERT_TRUE(IsOk(ret));
-  UnmountOnTearDown(ret->GetPath());
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/test.apex.rebootless",
-                                   "/apex/test.apex.rebootless@1"));
-
-  // Check that GetActivePackage correctly reports upgraded version.
-  auto active_apex = GetActivePackage("test.apex.rebootless");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
-  // Check that pre-installed APEX is still around
-  ASSERT_EQ(0, access(file_path.c_str(), F_OK))
-      << "Can't access " << file_path << " : " << strerror(errno);
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that upgraded APEX is mounted on top of dm-verity device.
-  db.ForallMountedApexes(
-      "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
-        ASSERT_TRUE(latest);
-        ASSERT_EQ(data.full_path, ret->GetPath());
-        ASSERT_EQ(data.device_name, "test.apex.rebootless@1_1");
-      });
-}
-
-TEST_F(ApexdMountTest, InstallPackageDataVersionActive) {
-  AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  std::string file_path = AddDataApex("test.rebootless_apex_v1.apex");
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  {
-    auto active_apex = GetActivePackage("test.apex.rebootless");
-    ASSERT_TRUE(IsOk(active_apex));
-    ASSERT_EQ(active_apex->GetPath(), file_path);
-  }
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
-  ASSERT_TRUE(IsOk(ret));
-  UnmountOnTearDown(ret->GetPath());
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/test.apex.rebootless",
-                                   "/apex/test.apex.rebootless@2"));
-
-  // Check that /apex/test.apex.rebootless is a bind mount of
-  // /apex/test.apex.rebootless@2.
-  auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
-  ASSERT_TRUE(IsOk(manifest));
-  ASSERT_EQ(2u, manifest->version());
-
-  // Check that GetActivePackage correctly reports upgraded version.
-  auto active_apex = GetActivePackage("test.apex.rebootless");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
-  // Check that previously active APEX was deleted.
-  ASSERT_EQ(-1, access(file_path.c_str(), F_OK));
-  ASSERT_EQ(ENOENT, errno);
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that upgraded APEX is mounted on top of dm-verity device.
-  db.ForallMountedApexes(
-      "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
-        ASSERT_TRUE(latest);
-        ASSERT_EQ(data.full_path, ret->GetPath());
-        ASSERT_EQ(data.device_name, "test.apex.rebootless@2_1");
-      });
-}
-
-TEST_F(ApexdMountTest, InstallPackageResolvesPathCollision) {
-  AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  std::string file_path = AddDataApex("test.rebootless_apex_v1.apex",
-                                      "test.apex.rebootless@1_1.apex");
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  {
-    auto active_apex = GetActivePackage("test.apex.rebootless");
-    ASSERT_TRUE(IsOk(active_apex));
-    ASSERT_EQ(active_apex->GetPath(), file_path);
-  }
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v1.apex"));
-  ASSERT_TRUE(IsOk(ret));
-  UnmountOnTearDown(ret->GetPath());
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/test.apex.rebootless",
-                                   "/apex/test.apex.rebootless@1"));
-
-  // Check that /apex/test.apex.rebootless is a bind mount of
-  // /apex/test.apex.rebootless@2.
-  auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
-  ASSERT_TRUE(IsOk(manifest));
-  ASSERT_EQ(1u, manifest->version());
-
-  // Check that GetActivePackage correctly reports upgraded version.
-  auto active_apex = GetActivePackage("test.apex.rebootless");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
-  // Check that we correctly resolved active apex path collision.
-  ASSERT_EQ(active_apex->GetPath(),
-            GetDataDir() + "/test.apex.rebootless@1_2.apex");
-
-  // Check that previously active APEX was deleted.
-  ASSERT_EQ(-1, access(file_path.c_str(), F_OK));
-  ASSERT_EQ(ENOENT, errno);
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that upgraded APEX is mounted on top of dm-verity device.
-  db.ForallMountedApexes(
-      "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
-        ASSERT_TRUE(latest);
-        ASSERT_EQ(data.full_path, ret->GetPath());
-        ASSERT_EQ(data.device_name, "test.apex.rebootless@1_2");
-      });
-}
-
-TEST_F(ApexdMountTest, InstallPackageDataVersionActiveSamegrade) {
-  AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  std::string file_path = AddDataApex("test.rebootless_apex_v2.apex");
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  {
-    auto active_apex = GetActivePackage("test.apex.rebootless");
-    ASSERT_TRUE(IsOk(active_apex));
-    ASSERT_EQ(active_apex->GetPath(), file_path);
-  }
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
-  ASSERT_TRUE(IsOk(ret));
-  UnmountOnTearDown(ret->GetPath());
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/test.apex.rebootless",
-                                   "/apex/test.apex.rebootless@2"));
-
-  // Check that /apex/test.apex.rebootless is a bind mount of
-  // /apex/test.apex.rebootless@2.
-  auto manifest = ReadManifest("/apex/test.apex.rebootless/apex_manifest.pb");
-  ASSERT_TRUE(IsOk(manifest));
-  ASSERT_EQ(2u, manifest->version());
-
-  // Check that GetActivePackage correctly reports upgraded version.
-  auto active_apex = GetActivePackage("test.apex.rebootless");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), ret->GetPath());
-
-  // Check that previously active APEX was deleted.
-  ASSERT_EQ(-1, access(file_path.c_str(), F_OK));
-  ASSERT_EQ(ENOENT, errno);
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that upgraded APEX is mounted on top of dm-verity device.
-  db.ForallMountedApexes(
-      "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
-        ASSERT_TRUE(latest);
-        ASSERT_EQ(data.full_path, ret->GetPath());
-        ASSERT_EQ(data.device_name, "test.apex.rebootless@2_1");
-      });
-}
-
-TEST_F(ApexdMountTest, InstallPackageUnmountFailsPreInstalledApexActive) {
-  std::string file_path = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  {
-    auto active_apex = GetActivePackage("test.apex.rebootless");
-    ASSERT_TRUE(IsOk(active_apex));
-    ASSERT_EQ(active_apex->GetPath(), file_path);
-  }
-
-  unique_fd fd(open("/apex/test.apex.rebootless/apex_manifest.pb",
-                    O_RDONLY | O_CLOEXEC));
-  ASSERT_NE(-1, fd.get());
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
-  ASSERT_FALSE(IsOk(ret));
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/test.apex.rebootless",
-                                   "/apex/test.apex.rebootless@1"));
-
-  // Check that GetActivePackage correctly reports upgraded version.
-  auto active_apex = GetActivePackage("test.apex.rebootless");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), file_path);
-
-  // Check that old APEX is still around
-  ASSERT_EQ(0, access(file_path.c_str(), F_OK))
-      << "Can't access " << file_path << " : " << strerror(errno);
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that upgraded APEX is mounted on top of dm-verity device.
-  db.ForallMountedApexes("test.apex.rebootless",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, file_path);
-                         });
-}
-
-TEST_F(ApexdMountTest, InstallPackageUnmountFailedUpdatedApexActive) {
-  AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  std::string file_path = AddDataApex("test.rebootless_apex_v1.apex");
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  {
-    auto active_apex = GetActivePackage("test.apex.rebootless");
-    ASSERT_TRUE(IsOk(active_apex));
-    ASSERT_EQ(active_apex->GetPath(), file_path);
-  }
-
-  unique_fd fd(open("/apex/test.apex.rebootless/apex_manifest.pb",
-                    O_RDONLY | O_CLOEXEC));
-  ASSERT_NE(-1, fd.get());
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
-  ASSERT_FALSE(IsOk(ret));
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/test.apex.rebootless",
-                                   "/apex/test.apex.rebootless@1"));
-
-  // Check that GetActivePackage correctly reports old apex.
-  auto active_apex = GetActivePackage("test.apex.rebootless");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), file_path);
-
-  // Check that old APEX is still around
-  ASSERT_EQ(0, access(file_path.c_str(), F_OK))
-      << "Can't access " << file_path << " : " << strerror(errno);
-
-  auto& db = GetApexDatabaseForTesting();
-  db.ForallMountedApexes(
-      "test.apex.rebootless", [&](const MountedApexData& data, bool latest) {
-        ASSERT_TRUE(latest);
-        ASSERT_EQ(data.full_path, file_path);
-        ASSERT_EQ(data.device_name, "test.apex.rebootless@1");
-      });
-}
-
-TEST_F(ApexdMountTest, InstallPackageUpdatesApexInfoList) {
-  auto apex_1 = AddPreInstalledApex("test.rebootless_apex_v1.apex");
-  auto apex_2 = AddPreInstalledApex("apex.apexd_test.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  UnmountOnTearDown(apex_1);
-  UnmountOnTearDown(apex_2);
-  ASSERT_TRUE(IsOk(ActivatePackage(apex_1)));
-  ASSERT_TRUE(IsOk(ActivatePackage(apex_2)));
-
-  // Call OnAllPackagesActivated to create /apex/apex-info-list.xml.
-  OnAllPackagesActivated(/* is_bootstrap= */ false);
-  // Check /apex/apex-info-list.xml was created.
-  ASSERT_EQ(0, access("/apex/apex-info-list.xml", F_OK));
-
-  auto ret = InstallPackage(GetTestFile("test.rebootless_apex_v2.apex"));
-  ASSERT_TRUE(IsOk(ret));
-  UnmountOnTearDown(ret->GetPath());
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "test.apex.rebootless",
-      /* modulePath= */ apex_1,
-      /* preinstalledModulePath= */ apex_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_2, /* preinstalledModulePath= */ apex_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_2));
-  auto apex_info_xml_3 = com::android::apex::ApexInfo(
-      /* moduleName= */ "test.apex.rebootless",
-      /* modulePath= */ ret->GetPath(),
-      /* preinstalledModulePath= */ apex_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(ret->GetPath()));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2),
-                                   ApexInfoXmlEq(apex_info_xml_3)));
-}
-
-TEST_F(ApexdMountTest, ActivatePackage) {
-  std::string file_path = AddPreInstalledApex("apex.apexd_test.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-  UnmountOnTearDown(file_path);
-
-  auto active_apex = GetActivePackage("com.android.apex.test_package");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), file_path);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1"));
-
-  ASSERT_TRUE(IsOk(DeactivatePackage(file_path)));
-  ASSERT_FALSE(IsOk(GetActivePackage("com.android.apex.test_package")));
-
-  auto new_apex_mounts = GetApexMounts();
-  ASSERT_EQ(new_apex_mounts.size(), 0u);
-}
-
-TEST_F(ApexdMountTest, ActivateDeactivateSharedLibsApex) {
-  ASSERT_EQ(mkdir("/apex/sharedlibs", 0755), 0);
-  ASSERT_EQ(mkdir("/apex/sharedlibs/lib", 0755), 0);
-  ASSERT_EQ(mkdir("/apex/sharedlibs/lib64", 0755), 0);
-  auto deleter = make_scope_guard([]() {
-    std::error_code ec;
-    fs::remove_all("/apex/sharedlibs", ec);
-    if (ec) {
-      LOG(ERROR) << "Failed to delete /apex/sharedlibs : " << ec;
-    }
-  });
-
-  std::string file_path = AddPreInstalledApex(
-      "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-
-  UnmountOnTearDown(file_path);
-  ASSERT_TRUE(IsOk(ActivatePackage(file_path)));
-
-  auto active_apex = GetActivePackage("com.android.apex.test.sharedlibs");
-  ASSERT_TRUE(IsOk(active_apex));
-  ASSERT_EQ(active_apex->GetPath(), file_path);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test.sharedlibs@1"));
-
-  ASSERT_TRUE(IsOk(DeactivatePackage(file_path)));
-  ASSERT_FALSE(IsOk(GetActivePackage("com.android.apex.test.sharedlibs")));
-
-  auto new_apex_mounts = GetApexMounts();
-  ASSERT_EQ(new_apex_mounts.size(), 0u);
-}
-
-TEST_F(ApexdMountTest, RemoveInactiveDataApex) {
-  AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-  // Add a decompressed apex that will not be mounted, so should be removed
-  auto decompressed_apex = StringPrintf("%s/com.android.apex.compressed@1%s",
-                                        GetDecompressionDir().c_str(),
-                                        kDecompressedApexPackageSuffix);
-  fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
-           decompressed_apex);
-  // Add a decompressed apex that will be mounted, so should be not be removed
-  auto active_decompressed_apex = StringPrintf(
-      "%s/com.android.apex.compressed@2%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
-           active_decompressed_apex);
-  // Apex that do not have kDecompressedApexPackageSuffix, should not be removed
-  // from decompression_dir
-  auto decompressed_different_suffix =
-      StringPrintf("%s/com.android.apex.compressed@2%s",
-                   GetDecompressionDir().c_str(), kApexPackageSuffix);
-  fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
-           decompressed_different_suffix);
-
-  AddPreInstalledApex("apex.apexd_test.apex");
-  auto data_apex = AddDataApex("apex.apexd_test.apex");
-  auto active_data_apex = AddDataApex("apex.apexd_test_v2.apex");
-
-  // Activate some of the apex
-  ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()});
-  UnmountOnTearDown(active_decompressed_apex);
-  UnmountOnTearDown(active_data_apex);
-  ASSERT_TRUE(IsOk(ActivatePackage(active_decompressed_apex)));
-  ASSERT_TRUE(IsOk(ActivatePackage(active_data_apex)));
-  // Clean up inactive apex packages
-  RemoveInactiveDataApex();
-
-  // Verify inactive apex packages have been deleted
-  ASSERT_TRUE(*PathExists(active_decompressed_apex));
-  ASSERT_TRUE(*PathExists(active_data_apex));
-  ASSERT_TRUE(*PathExists(decompressed_different_suffix));
-  ASSERT_FALSE(*PathExists(decompressed_apex));
-  ASSERT_FALSE(*PathExists(data_apex));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapOnlyPreInstalledApexes) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapFailsToScanPreInstalledApexes) {
-  AddPreInstalledApex("apex.apexd_test.apex");
-  AddPreInstalledApex("apex.apexd_test_corrupt_superblock_apex.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 1);
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasHigherVersion) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@2",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-  auto apex_info_xml_3 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_3,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2),
-                                   ApexInfoXmlEq(apex_info_xml_3)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasSameVersion) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-  auto apex_info_xml_3 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_3,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2),
-                                   ApexInfoXmlEq(apex_info_xml_3)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSystemHasHigherVersion) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test_v2.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  AddDataApex("apex.apexd_test.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@2",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasSameVersionButDifferentKey) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  AddDataApex("apex.apexd_test_different_key.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest,
-       OnOtaChrootBootstrapDataHasHigherVersionButDifferentKey) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 =
-      AddDataApex("apex.apexd_test_different_key_v2.apex");
-
-  {
-    auto apex = ApexFile::Open(apex_path_3);
-    ASSERT_TRUE(IsOk(apex));
-    ASSERT_EQ(static_cast<uint64_t>(apex->GetManifest().version()), 2ULL);
-  }
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataApexWithoutPreInstalledApex) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  AddDataApex("apex.apexd_test_different_app.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_1);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapPreInstalledSharedLibsApex) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 = AddPreInstalledApex(
-      "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@2",
-                                   "/apex/com.android.apex.test.sharedlibs@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test.sharedlibs",
-      /* modulePath= */ apex_path_2,
-      /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_2));
-  auto apex_info_xml_3 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_3,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2),
-                                   ApexInfoXmlEq(apex_info_xml_3)));
-
-  ASSERT_EQ(access("/apex/sharedlibs", F_OK), 0);
-
-  // Check /apex/sharedlibs is populated properly.
-  std::vector<std::string> sharedlibs;
-  for (const auto& p : fs::recursive_directory_iterator("/apex/sharedlibs")) {
-    if (fs::is_symlink(p)) {
-      auto src = fs::read_symlink(p.path());
-      ASSERT_EQ(p.path().filename(), src.filename());
-      sharedlibs.push_back(p.path().parent_path().string() + "->" +
-                           src.parent_path().string());
-    }
-  }
-
-  std::vector<std::string> expected = {
-      "/apex/sharedlibs/lib/libsharedlibtest.so->"
-      "/apex/com.android.apex.test.sharedlibs@1/lib/libsharedlibtest.so",
-      "/apex/sharedlibs/lib/libc++.so->"
-      "/apex/com.android.apex.test.sharedlibs@1/lib/libc++.so",
-  };
-
-  // On 64bit devices we also have lib64.
-  if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
-    expected.push_back(
-        "/apex/sharedlibs/lib64/libsharedlibtest.so->"
-        "/apex/com.android.apex.test.sharedlibs@1/lib64/libsharedlibtest.so");
-    expected.push_back(
-        "/apex/sharedlibs/lib64/libc++.so->"
-        "/apex/com.android.apex.test.sharedlibs@1/lib64/libc++.so");
-  }
-  ASSERT_THAT(sharedlibs, UnorderedElementsAreArray(expected));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSharedLibsApexBothVersions) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 = AddPreInstalledApex(
-      "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-  std::string apex_path_4 =
-      AddDataApex("com.android.apex.test.sharedlibs_generated.v2.libvY.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-  UnmountOnTearDown(apex_path_4);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@2",
-                                   "/apex/com.android.apex.test.sharedlibs@1",
-                                   "/apex/com.android.apex.test.sharedlibs@2"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test.sharedlibs",
-      /* modulePath= */ apex_path_2,
-      /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_2));
-  auto apex_info_xml_3 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_3,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_3));
-  auto apex_info_xml_4 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test.sharedlibs",
-      /* modulePath= */ apex_path_4,
-      /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(apex_path_4));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2),
-                                   ApexInfoXmlEq(apex_info_xml_3),
-                                   ApexInfoXmlEq(apex_info_xml_4)));
-
-  ASSERT_EQ(access("/apex/sharedlibs", F_OK), 0);
-
-  // Check /apex/sharedlibs is populated properly.
-  // Because we don't want to hardcode full paths (they are pretty long and have
-  // a hash in them which might change if new prebuilts are dropped in), the
-  // assertion logic is a little bit clunky.
-  std::vector<std::string> sharedlibs;
-  for (const auto& p : fs::recursive_directory_iterator("/apex/sharedlibs")) {
-    if (fs::is_symlink(p)) {
-      auto src = fs::read_symlink(p.path());
-      ASSERT_EQ(p.path().filename(), src.filename());
-      sharedlibs.push_back(p.path().parent_path().string() + "->" +
-                           src.parent_path().string());
-    }
-  }
-
-  std::vector<std::string> expected = {
-      "/apex/sharedlibs/lib/libsharedlibtest.so->"
-      "/apex/com.android.apex.test.sharedlibs@2/lib/libsharedlibtest.so",
-      "/apex/sharedlibs/lib/libsharedlibtest.so->"
-      "/apex/com.android.apex.test.sharedlibs@1/lib/libsharedlibtest.so",
-      "/apex/sharedlibs/lib/libc++.so->"
-      "/apex/com.android.apex.test.sharedlibs@1/lib/libc++.so",
-  };
-  // On 64bit devices we also have lib64.
-  if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
-    expected.push_back(
-        "/apex/sharedlibs/lib64/libsharedlibtest.so->"
-        "/apex/com.android.apex.test.sharedlibs@2/lib64/libsharedlibtest.so");
-    expected.push_back(
-        "/apex/sharedlibs/lib64/libsharedlibtest.so->"
-        "/apex/com.android.apex.test.sharedlibs@1/lib64/libsharedlibtest.so");
-    expected.push_back(
-        "/apex/sharedlibs/lib64/libc++.so->"
-        "/apex/com.android.apex.test.sharedlibs@1/lib64/libc++.so");
-  }
-
-  ASSERT_THAT(sharedlibs, UnorderedElementsAreArray(expected));
-}
-
-// Test when we move from uncompressed APEX to CAPEX via ota
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapOnlyCompressedApexes) {
-  std::string apex_path =
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Decompressed APEX should be mounted from decompression_dir
-  std::string decompressed_apex =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_decompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(decompressed_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1.chroot");
-                         });
-}
-
-// Test we decompress only once even if OnOtaChrootBootstrap is called multiple
-// times
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDecompressOnlyOnceMultipleCalls) {
-  std::string apex_path =
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Decompressed OTA APEX should be mounted
-  std::string decompressed_ota_apex =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_ota_apex);
-
-  // Capture the creation time of the OTA APEX
-  std::error_code ec;
-  auto last_write_time_1 = fs::last_write_time(decompressed_ota_apex, ec);
-  ASSERT_FALSE(ec) << "Failed to capture last write time of "
-                   << decompressed_ota_apex;
-
-  // Call OnOtaChrootBootstrap again. Since we do not hardlink decompressed APEX
-  // to /data/apex/active directory when in chroot, when selecting apex for
-  // activation, we will end up selecting compressed APEX again.
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Compare write time to ensure we did not decompress again
-  auto last_write_time_2 = fs::last_write_time(decompressed_ota_apex, ec);
-  ASSERT_FALSE(ec) << "Failed to capture last write time of "
-                   << decompressed_ota_apex << ec.message();
-  ASSERT_EQ(last_write_time_1, last_write_time_2);
-}
-
-// Test when we upgrade existing CAPEX to higher version via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapUpgradeCapex) {
-  TemporaryDir previous_built_in_dir;
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex",
-                        previous_built_in_dir.path);
-  // Place a higher version capex in current built_in_dir
-  std::string apex_path =
-      AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Upgraded decompressed APEX should be mounted from decompression dir
-  std::string decompressed_active_apex =
-      StringPrintf("%s/com.android.apex.compressed@2%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@2"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_decompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_active_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ true, /* isActive= */ true,
-      GetMTime(decompressed_active_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@2.chroot");
-                         });
-}
-
-// Test when we update existing CAPEX to same version via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSamegradeCapex) {
-  TemporaryDir previous_built_in_dir;
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex",
-                        previous_built_in_dir.path);
-  // Place a same version capex in current built_in_dir, under a different name
-  auto apex_path =
-      StringPrintf("%s/different-name.capex", GetBuiltInDir().c_str());
-  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), apex_path);
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Previously decompressed APEX should be mounted from decompression_dir
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_decompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_active_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      GetMTime(decompressed_active_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1.chroot");
-                         });
-}
-
-// Test when we update existing CAPEX to same version, but different digest
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSamegradeCapexDifferentDigest) {
-  TemporaryDir previous_built_in_dir;
-  auto different_digest_apex_path = PrepareCompressedApex(
-      "com.android.apex.compressed.v1_different_digest.capex",
-      previous_built_in_dir.path);
-  // Place a same version capex in current built_in_dir, which has different
-  // digest
-  auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // New decompressed ota APEX should be mounted with kOtaApexPackageSuffix
-  std::string decompressed_ota_apex =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_ota_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_decompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_ota_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      GetMTime(decompressed_ota_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_ota_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1.chroot");
-                         });
-
-  // Ensure decompressed apex has same digest as pre-installed
-  auto pre_installed_apex = ApexFile::Open(apex_path);
-  auto decompressed_apex = ApexFile::Open(decompressed_ota_apex);
-  auto different_digest_apex = ApexFile::Open(different_digest_apex_path);
-  ASSERT_EQ(
-      pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
-      GetRootDigest(*decompressed_apex));
-  ASSERT_NE(
-      pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
-      GetRootDigest(*different_digest_apex));
-
-  // Ensure we didn't remove previous decompressed APEX
-  std::string previous_decompressed_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  auto path_exists = PathExists(previous_decompressed_apex);
-  ASSERT_TRUE(*path_exists);
-}
-
-// Test when we update existing CAPEX to same version, but different key via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSamegradeCapexDifferentKey) {
-  TemporaryDir previous_built_in_dir;
-  PrepareCompressedApex("com.android.apex.compressed_different_key.capex",
-                        previous_built_in_dir.path);
-  // Place a same version capex in current built_in_dir, which has different key
-  auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // New decompressed APEX should be mounted from ota_reserved directory
-  std::string decompressed_active_apex =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_decompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_active_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      GetMTime(decompressed_active_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1.chroot");
-                         });
-}
-
-// Test when we remove CAPEX via OTA
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapCapexToApex) {
-  TemporaryDir previous_built_in_dir;
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex",
-                        previous_built_in_dir.path);
-  // Place a uncompressed version apex in current built_in_dir
-  std::string apex_path =
-      AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // New uncompressed APEX should be mounted
-  UnmountOnTearDown(apex_path);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_uncompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ apex_path,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_uncompressed)));
-}
-
-TEST_F(ApexdMountTest,
-       OnOtaChrootBootstrapDecompressedApexVersionDifferentThanCapex) {
-  TemporaryDir previous_built_in_dir;
-  PrepareCompressedApex("com.android.apex.compressed.v2.capex",
-                        previous_built_in_dir.path);
-  // Place a lower version capex in current built_in_dir, so that previously
-  // decompressed APEX has higher version but still doesn't get picked during
-  // selection.
-  std::string apex_path =
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Pre-installed CAPEX should be decompressed again and mounted from
-  // decompression_dir
-  std::string decompressed_active_apex =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_decompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_active_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      GetMTime(decompressed_active_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-}
-
-// Test when we update CAPEX and there is a higher version present in data
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHigherThanCapex) {
-  auto system_apex_path =
-      PrepareCompressedApex("com.android.apex.compressed.v1.capex");
-  auto data_apex_path =
-      AddDataApex("com.android.apex.compressed.v2_original.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Data APEX should be mounted
-  UnmountOnTearDown(data_apex_path);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@2"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_data = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ data_apex_path,
-      /* preinstalledModulePath= */ system_apex_path,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(data_apex_path));
-  auto apex_info_xml_system = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ system_apex_path,
-      /* preinstalledModulePath= */ system_apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(system_apex_path));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_data),
-                                   ApexInfoXmlEq(apex_info_xml_system)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, data_apex_path);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@2.chroot");
-                         });
-}
-
-// Test when we update CAPEX and there is a lower version present in data
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataLowerThanCapex) {
-  auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-  AddDataApex("com.android.apex.compressed.v1_original.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Decompressed APEX should be mounted from reserved dir
-  std::string decompressed_active_apex =
-      StringPrintf("%s/com.android.apex.compressed@2%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@2"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_active_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ true, /* isActive= */ true,
-      GetMTime(decompressed_active_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@2.chroot");
-                         });
-}
-
-// Test when we update CAPEX and there is a same version present in data
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataSameAsCapex) {
-  auto system_apex_path =
-      PrepareCompressedApex("com.android.apex.compressed.v1.capex");
-  auto data_apex_path =
-      AddDataApex("com.android.apex.compressed.v1_original.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // Data APEX should be mounted
-  UnmountOnTearDown(data_apex_path);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_data = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ data_apex_path,
-      /* preinstalledModulePath= */ system_apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ false, /* isActive= */ true, GetMTime(data_apex_path));
-  auto apex_info_xml_system = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ system_apex_path,
-      /* preinstalledModulePath= */ system_apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(system_apex_path));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_data),
-                                   ApexInfoXmlEq(apex_info_xml_system)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, data_apex_path);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1.chroot");
-                         });
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDataHasDifferentKeyThanCapex) {
-  AddDataApex("com.android.apex.compressed_different_key.capex");
-  // Place a same version capex in current built_in_dir, which has different key
-  auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  // New decompressed APEX should be mounted from ota_reserved directory
-  std::string decompressed_active_apex =
-      StringPrintf("%s/com.android.apex.compressed@1%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_decompressed = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.compressed",
-      /* modulePath= */ decompressed_active_apex,
-      /* preinstalledModulePath= */ apex_path,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      GetMTime(decompressed_active_apex));
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_decompressed)));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1.chroot");
-                         });
-}
-
-static std::string GetSelinuxContext(const std::string& file) {
-  char* ctx;
-  if (getfilecon(file.c_str(), &ctx) < 0) {
-    PLOG(ERROR) << "Failed to getfilecon " << file;
-    return "";
-  }
-  std::string result(ctx);
-  freecon(ctx);
-  return result;
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapSelinuxLabelsAreCorrect) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 = AddPreInstalledApex(
-      "com.android.apex.test.sharedlibs_generated.v1.libvX.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-
-  EXPECT_EQ(GetSelinuxContext("/apex/apex-info-list.xml"),
-            "u:object_r:apex_info_file:s0");
-
-  EXPECT_EQ(GetSelinuxContext("/apex/sharedlibs"),
-            "u:object_r:apex_mnt_dir:s0");
-
-  EXPECT_EQ(GetSelinuxContext("/apex/com.android.apex.test_package"),
-            "u:object_r:system_file:s0");
-  EXPECT_EQ(GetSelinuxContext("/apex/com.android.apex.test_package@2"),
-            "u:object_r:system_file:s0");
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapDmDevicesHaveCorrectName) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-
-  MountedApexDatabase& db = GetApexDatabaseForTesting();
-  // com.android.apex.test_package_2 should be mounted directly on top of loop
-  // device.
-  db.ForallMountedApexes("com.android.apex.test_package_2",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_THAT(data.device_name, IsEmpty());
-                           ASSERT_THAT(data.loop_name, StartsWith("/dev"));
-                         });
-  // com.android.apex.test_package should be mounted on top of dm-verity device.
-  db.ForallMountedApexes("com.android.apex.test_package",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.test_package@2.chroot");
-                           ASSERT_THAT(data.loop_name, StartsWith("/dev"));
-                         });
-}
-
-TEST_F(ApexdMountTest,
-       OnOtaChrootBootstrapFailsToActivatePreInstalledApexKeepsGoing) {
-  std::string apex_path_1 =
-      AddPreInstalledApex("apex.apexd_test_manifest_mismatch.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-  UnmountOnTearDown(apex_path_2);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 137, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ false, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest,
-       OnOtaChrootBootstrapFailsToActivateDataApexFallsBackToPreInstalled) {
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 =
-      AddDataApex("apex.apexd_test_manifest_mismatch.apex");
-
-  ASSERT_EQ(OnOtaChrootBootstrap(), 0);
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_path_1,
-      /* preinstalledModulePath= */ apex_path_1,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true, GetMTime(apex_path_1));
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_path_2, /* preinstalledModulePath= */ apex_path_2,
-      /* versionCode= */ 1, /* versionName= */ "1", /* isFactory= */ true,
-      /* isActive= */ true, GetMTime(apex_path_2));
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnOtaChrootBootstrapFlattenedApex) {
-  std::string apex_dir_1 = GetBuiltInDir() + "/com.android.apex.test_package";
-  std::string apex_dir_2 = GetBuiltInDir() + "/com.android.apex.test_package_2";
-
-  ASSERT_EQ(mkdir(apex_dir_1.c_str(), 0755), 0);
-  ASSERT_EQ(mkdir(apex_dir_2.c_str(), 0755), 0);
-
-  auto write_manifest_fn = [&](const std::string& apex_dir,
-                               const std::string& module_name, int version) {
-    using ::apex::proto::ApexManifest;
-
-    ApexManifest manifest;
-    manifest.set_name(module_name);
-    manifest.set_version(version);
-    manifest.set_versionname(std::to_string(version));
-
-    std::string out;
-    manifest.SerializeToString(&out);
-    ASSERT_TRUE(WriteStringToFile(out, apex_dir + "/apex_manifest.pb"));
-  };
-
-  write_manifest_fn(apex_dir_1, "com.android.apex.test_package", 2);
-  write_manifest_fn(apex_dir_2, "com.android.apex.test_package_2", 1);
-
-  ASSERT_EQ(OnOtaChrootBootstrapFlattenedApex(), 0);
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package_2"));
-
-  ASSERT_EQ(access("/apex/apex-info-list.xml", F_OK), 0);
-  ASSERT_EQ(GetSelinuxContext("/apex/apex-info-list.xml"),
-            "u:object_r:apex_info_file:s0");
-
-  auto info_list =
-      com::android::apex::readApexInfoList("/apex/apex-info-list.xml");
-  ASSERT_TRUE(info_list.has_value());
-  auto apex_info_xml_1 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package",
-      /* modulePath= */ apex_dir_1,
-      /* preinstalledModulePath= */ apex_dir_1,
-      /* versionCode= */ 2, /* versionName= */ "2",
-      /* isFactory= */ true, /* isActive= */ true,
-      /* lastUpdateMillis= */ 0);
-  auto apex_info_xml_2 = com::android::apex::ApexInfo(
-      /* moduleName= */ "com.android.apex.test_package_2",
-      /* modulePath= */ apex_dir_2,
-      /* preinstalledModulePath= */ apex_dir_2,
-      /* versionCode= */ 1, /* versionName= */ "1",
-      /* isFactory= */ true, /* isActive= */ true,
-      /* lastUpdateMillis= */ 0);
-
-  ASSERT_THAT(info_list->getApexInfo(),
-              UnorderedElementsAre(ApexInfoXmlEq(apex_info_xml_1),
-                                   ApexInfoXmlEq(apex_info_xml_2)));
-}
-
-TEST_F(ApexdMountTest, OnStartOnlyPreInstalledApexes) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasHigherVersion) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test_v2.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@2",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasWrongSHA) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  std::string apex_path = AddPreInstalledApex("com.android.apex.cts.shim.apex");
-  AddDataApex("com.android.apex.cts.shim.v2_wrong_sha.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  UnmountOnTearDown(apex_path);
-  OnStart();
-
-  // Check system shim apex is activated instead of the data one.
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.cts.shim",
-                                   "/apex/com.android.apex.cts.shim@1"));
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasSameVersion) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 = AddDataApex("apex.apexd_test.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  UnmountOnTearDown(apex_path_2);
-  UnmountOnTearDown(apex_path_3);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from data apex, not pre-installed one.
-  db.ForallMountedApexes("com.android.apex.test_package",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path_3);
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartSystemHasHigherVersion) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test_v2.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  AddDataApex("apex.apexd_test.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@2",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from pre-installed one.
-  db.ForallMountedApexes("com.android.apex.test_package",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path_1);
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartFailsToActivateApexOnDataFallsBackToBuiltIn) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  AddDataApex("apex.apexd_test_manifest_mismatch.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from pre-installed apex.
-  db.ForallMountedApexes("com.android.apex.test_package",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path_1);
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartApexOnDataHasWrongKeyFallsBackToBuiltIn) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  std::string apex_path_1 = AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path_2 =
-      AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  std::string apex_path_3 =
-      AddDataApex("apex.apexd_test_different_key_v2.apex");
-
-  {
-    auto apex = ApexFile::Open(apex_path_3);
-    ASSERT_TRUE(IsOk(apex));
-    ASSERT_EQ(static_cast<uint64_t>(apex->GetManifest().version()), 2ULL);
-  }
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  UnmountOnTearDown(apex_path_1);
-  UnmountOnTearDown(apex_path_2);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from pre-installed apex.
-  db.ForallMountedApexes("com.android.apex.test_package",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path_1);
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartOnlyPreInstalledCapexes) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  std::string apex_path_1 =
-      AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Decompressed APEX should be mounted
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1");
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasHigherVersionThanCapex) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-  std::string apex_path_2 =
-      AddDataApex("com.android.apex.compressed.v2_original.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  UnmountOnTearDown(apex_path_2);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@2"));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from data apex.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path_2);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@2");
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartDataHasSameVersionAsCapex) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-  std::string apex_path_2 =
-      AddDataApex("com.android.apex.compressed.v1_original.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Data APEX should be mounted
-  UnmountOnTearDown(apex_path_2);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from data apex, not pre-installed one.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path_2);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1");
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartSystemHasHigherVersionCapexThanData) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  std::string apex_path_1 =
-      AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-  AddDataApex("com.android.apex.compressed.v1_original.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Decompressed APEX should be mounted
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@2%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@2"));
-
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from compressed apex
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@2");
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartFailsToActivateApexOnDataFallsBackToCapex) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-  AddDataApex("com.android.apex.compressed.v2_manifest_mismatch.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Decompressed APEX should be mounted
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex. It should also be mounted
-  // on dm-verity device.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1");
-                         });
-}
-
-// Test scenario when we fallback to capex but it already has a decompressed
-// version on data
-TEST_F(ApexdMountTest, OnStartFallbackToAlreadyDecompressedCapex) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex");
-  AddDataApex("com.android.apex.compressed.v2_manifest_mismatch.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Decompressed APEX should be mounted
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1");
-                         });
-}
-
-// Test scenario when we fallback to capex but it has same version as corrupt
-// data apex
-TEST_F(ApexdMountTest, OnStartFallbackToCapexSameVersion) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-  // Add data apex using the common naming convention for /data/apex/active
-  // directory
-  fs::copy(GetTestFile("com.android.apex.compressed.v2_manifest_mismatch.apex"),
-           GetDataDir() + "/com.android.apex.compressed@2.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Decompressed APEX should be mounted
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@2%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@2"));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@2");
-                         });
-}
-
-TEST_F(ApexdMountTest, OnStartCapexToApex) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  TemporaryDir previous_built_in_dir;
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex",
-                        previous_built_in_dir.path);
-  auto apex_path =
-      AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Uncompressed APEX should be mounted
-  UnmountOnTearDown(apex_path);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from decompressed apex.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path);
-                           ASSERT_THAT(data.device_name, IsEmpty());
-                         });
-}
-
-// Test to ensure we do not mount decompressed APEX from /data/apex/active
-TEST_F(ApexdMountTest, OnStartOrphanedDecompressedApexInActiveDirectory) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  // Place a decompressed APEX in /data/apex/active. This apex should not
-  // be mounted since it's not in correct location. Instead, the
-  // pre-installed APEX should be mounted.
-  auto decompressed_apex_in_active_dir =
-      StringPrintf("%s/com.android.apex.compressed@1%s", GetDataDir().c_str(),
-                   kDecompressedApexPackageSuffix);
-  fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
-           decompressed_apex_in_active_dir);
-  auto apex_path =
-      AddPreInstalledApex("com.android.apex.compressed.v1_original.apex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Pre-installed APEX should be mounted
-  UnmountOnTearDown(apex_path);
-  auto& db = GetApexDatabaseForTesting();
-  // Check that pre-installed APEX has been activated
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, apex_path);
-                           ASSERT_THAT(data.device_name, IsEmpty());
-                         });
-}
-
-// Test scenario when decompressed version has different version than
-// pre-installed CAPEX
-TEST_F(ApexdMountTest, OnStartDecompressedApexVersionDifferentThanCapex) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  TemporaryDir previous_built_in_dir;
-  PrepareCompressedApex("com.android.apex.compressed.v2.capex",
-                        previous_built_in_dir.path);
-  auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Existing higher version decompressed APEX should be ignored and new
-  // pre-installed CAPEX should be decompressed and mounted
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  ASSERT_EQ(GetProperty(kTestApexdStatusSysprop, ""), "starting");
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1"));
-  auto& db = GetApexDatabaseForTesting();
-  // Check that it was mounted from newly decompressed apex.
-  db.ForallMountedApexes("com.android.apex.compressed",
-                         [&](const MountedApexData& data, bool latest) {
-                           ASSERT_TRUE(latest);
-                           ASSERT_EQ(data.full_path, decompressed_active_apex);
-                           ASSERT_EQ(data.device_name,
-                                     "com.android.apex.compressed@1");
-                         });
-}
-
-// Test that ota_apex is persisted until slot switch
-TEST_F(ApexdMountTest, OnStartOtaApexKeptUntilSlotSwitch) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  // Imagine current system has v1 capex and we have v2 incoming via ota
-  auto old_capex = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-  auto ota_apex_path =
-      StringPrintf("%s/com.android.apex.compressed@2%s",
-                   GetDecompressionDir().c_str(), kOtaApexPackageSuffix);
-  fs::copy(GetTestFile("com.android.apex.compressed.v2_original.apex"),
-           ota_apex_path.c_str());
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  // When we call OnStart for the first time, it will decompress v1 capex and
-  // activate it, while after second call it will decompress v2 capex and
-  // activate it. We need to make sure that activated APEXes are cleaned up
-  // after test finishes.
-  auto old_decompressed_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  auto new_decompressed_apex = StringPrintf(
-      "%s/com.android.apex.compressed@2%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(old_decompressed_apex);
-  UnmountOnTearDown(new_decompressed_apex);
-
-  // First try starting without slot switch. Since we are booting with
-  // old pre-installed capex, ota_apex should not be deleted
-  OnStart();
-  auto path_exists = PathExists(ota_apex_path);
-  ASSERT_TRUE(*path_exists);
-
-  // When we switch slot, the pre-installed APEX will match ota_apex
-  // and the ota_apex will end up getting renamed.
-  RemoveFileIfExists(old_capex);
-  AddPreInstalledApex("com.android.apex.compressed.v2.capex");
-  ApexFileRepository::GetInstance().Reset(GetDecompressionDir());
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-  OnStart();
-  path_exists = PathExists(ota_apex_path);
-  ASSERT_FALSE(*path_exists);
-}
-
-// Test scenario when decompressed version has same version but different
-// digest
-TEST_F(ApexdMountTest,
-       OnStartDecompressedApexVersionSameAsCapexDifferentDigest) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  // Push a CAPEX to system without decompressing it
-  auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-  auto pre_installed_apex = ApexFile::Open(apex_path);
-  // Now push an APEX with different root digest as decompressed APEX
-  auto decompressed_apex_path = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  fs::copy(GetTestFile(
-               "com.android.apex.compressed.v1_different_digest_original.apex"),
-           decompressed_apex_path);
-  auto different_digest_apex = ApexFile::Open(decompressed_apex_path);
-  auto different_digest = GetRootDigest(*different_digest_apex);
-  ASSERT_NE(
-      pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
-      different_digest);
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Existing same version decompressed APEX with different root digest should
-  // be ignored and the pre-installed CAPEX should be decompressed again.
-  UnmountOnTearDown(decompressed_apex_path);
-
-  // Ensure decompressed apex has same digest as pre-installed
-  auto decompressed_apex = ApexFile::Open(decompressed_apex_path);
-  ASSERT_EQ(
-      pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
-      GetRootDigest(*decompressed_apex));
-  ASSERT_NE(GetRootDigest(*decompressed_apex), different_digest);
-}
-
-// Test when decompressed APEX has different key than CAPEX
-TEST_F(ApexdMountTest, OnStartDecompressedApexVersionSameAsCapexDifferentKey) {
-  MockCheckpointInterface checkpoint_interface;
-  // Need to call InitializeVold before calling OnStart
-  InitializeVold(&checkpoint_interface);
-
-  TemporaryDir previous_built_in_dir;
-  auto different_key_apex_path =
-      PrepareCompressedApex("com.android.apex.compressed_different_key.capex",
-                            previous_built_in_dir.path);
-  // Place a same version capex in current built_in_dir, which has different key
-  auto apex_path = AddPreInstalledApex("com.android.apex.compressed.v1.capex");
-
-  ASSERT_RESULT_OK(
-      ApexFileRepository::GetInstance().AddPreInstalledApex({GetBuiltInDir()}));
-
-  OnStart();
-
-  // Existing same version decompressed APEX should be ignored and new
-  // pre-installed CAPEX should be decompressed and mounted
-  std::string decompressed_active_apex = StringPrintf(
-      "%s/com.android.apex.compressed@1%s", GetDecompressionDir().c_str(),
-      kDecompressedApexPackageSuffix);
-  UnmountOnTearDown(decompressed_active_apex);
-
-  // Ensure decompressed apex has same digest as pre-installed
-  auto pre_installed_apex = ApexFile::Open(apex_path);
-  auto decompressed_apex = ApexFile::Open(decompressed_active_apex);
-  auto different_key_apex = ApexFile::Open(different_key_apex_path);
-  ASSERT_EQ(
-      pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
-      GetRootDigest(*decompressed_apex));
-  ASSERT_NE(
-      pre_installed_apex->GetManifest().capexmetadata().originalapexdigest(),
-      GetRootDigest(*different_key_apex));
-}
-
-TEST_F(ApexdMountTest, PopulateFromMountsChecksPathPrefix) {
-  AddPreInstalledApex("apex.apexd_test.apex");
-  std::string apex_path = AddDataApex("apex.apexd_test_v2.apex");
-
-  // Mount an apex from decomrpession_dir
-  PrepareCompressedApex("com.android.apex.compressed.v1.capex");
-  std::string decompressed_apex =
-      StringPrintf("%s/com.android.apex.compressed@1.decompressed.apex",
-                   GetDecompressionDir().c_str());
-
-  // Mount an apex from some other directory
-  TemporaryDir td;
-  AddPreInstalledApex("apex.apexd_test_different_app.apex");
-  fs::copy(GetTestFile("apex.apexd_test_different_app.apex"), td.path);
-  std::string other_apex =
-      StringPrintf("%s/apex.apexd_test_different_app.apex", td.path);
-
-  auto& instance = ApexFileRepository::GetInstance();
-  ASSERT_RESULT_OK(instance.AddPreInstalledApex({GetBuiltInDir()}));
-
-  ASSERT_TRUE(IsOk(ActivatePackage(apex_path)));
-  ASSERT_TRUE(IsOk(ActivatePackage(decompressed_apex)));
-  ASSERT_TRUE(IsOk(ActivatePackage(other_apex)));
-
-  auto& db = GetApexDatabaseForTesting();
-  // Remember mount information for |other_apex|, since it won't be available in
-  // the database. We will need to tear it down manually.
-  std::optional<MountedApexData> other_apex_mount_data;
-  db.ForallMountedApexes(
-      "com.android.apex.test_package_2",
-      [&other_apex_mount_data](const MountedApexData& data, bool latest) {
-        if (latest) {
-          other_apex_mount_data.emplace(data);
-        }
-      });
-  UnmountOnTearDown(apex_path);
-  UnmountOnTearDown(decompressed_apex);
-  ASSERT_TRUE(other_apex_mount_data.has_value());
-  auto deleter = make_scope_guard([&other_apex_mount_data]() {
-    if (!other_apex_mount_data.has_value()) {
-      return;
-    }
-    if (umount2("/apex/com.android.apex.test_package_2", 0) != 0) {
-      PLOG(ERROR) << "Failed to unmount /apex/com.android.apex.test_package_2";
-    }
-    auto res = Unmount(*other_apex_mount_data, /* deferred= */ false);
-    if (!res.ok()) {
-      LOG(ERROR) << res.error();
-    }
-  });
-
-  auto apex_mounts = GetApexMounts();
-  ASSERT_THAT(apex_mounts,
-              UnorderedElementsAre("/apex/com.android.apex.test_package",
-                                   "/apex/com.android.apex.test_package@2",
-                                   "/apex/com.android.apex.compressed",
-                                   "/apex/com.android.apex.compressed@1",
-                                   "/apex/com.android.apex.test_package_2",
-                                   "/apex/com.android.apex.test_package_2@1"));
-
-  // C