Revert^2 "Store and check apex-versions in boot images."

This reverts commit 5bd22087faeb2caf5057aaab63717afab082f447.

Reason for revert: Fixed the breakage by skipping the check for the
  boot image in the ART APEX.

Bug: 211973309
Test: atest odsign_e2e_tests
Test: Build a system image, flash it to device and run
  `atest art_standalone_dexpreopt_tests`.
Test: Build an ART APEX, install it to a device (to simulate the MTS
  environment), and run `atest art_standalone_oatdump_tests`.
Change-Id: I396c3c8577f5169744d96bb1d9714111e5f7bbe6
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 154b1ca..a3bab85 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1564,6 +1564,8 @@
       key_value_store_->Put(OatHeader::kCompilationReasonKey, compilation_reason_);
     }
 
+    Runtime* runtime = Runtime::Current();
+
     if (IsBootImage()) {
       // If we're compiling the boot image, store the boot classpath into the Key-Value store.
       // We use this when loading the boot image.
@@ -1571,7 +1573,6 @@
     } else if (IsBootImageExtension()) {
       // Validate the boot class path and record the dependency on the loaded boot images.
       TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
-      Runtime* runtime = Runtime::Current();
       std::string full_bcp = android::base::Join(runtime->GetBootClassPathLocations(), ':');
       std::string extension_part = ":" + android::base::Join(dex_locations_, ':');
       if (!android::base::EndsWith(full_bcp, extension_part)) {
@@ -1590,18 +1591,12 @@
     } else {
       if (CompilerFilter::DependsOnImageChecksum(original_compiler_filter)) {
         TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
-        Runtime* runtime = Runtime::Current();
         key_value_store_->Put(OatHeader::kBootClassPathKey,
                               android::base::Join(runtime->GetBootClassPathLocations(), ':'));
         ArrayRef<ImageSpace* const> image_spaces(runtime->GetHeap()->GetBootImageSpaces());
         key_value_store_->Put(
             OatHeader::kBootClassPathChecksumsKey,
             gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces, bcp_dex_files));
-
-        std::string versions = apex_versions_argument_.empty()
-            ? runtime->GetApexVersions()
-            : apex_versions_argument_;
-        key_value_store_->Put(OatHeader::kApexVersionsKey, versions);
       }
 
       // Open dex files for class path.
@@ -1643,6 +1638,14 @@
       key_value_store_->Put(OatHeader::kClassPathKey, class_path_key);
     }
 
+    if (IsBootImage() ||
+        IsBootImageExtension() ||
+        CompilerFilter::DependsOnImageChecksum(original_compiler_filter)) {
+      std::string versions =
+          apex_versions_argument_.empty() ? runtime->GetApexVersions() : apex_versions_argument_;
+      key_value_store_->Put(OatHeader::kApexVersionsKey, versions);
+    }
+
     // Now that we have finalized key_value_store_, start writing the .rodata section.
     // Among other things, this creates type lookup tables that speed up the compilation.
     {
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 13a424b..5c2d84c 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -227,6 +227,7 @@
       SafeMap<std::string, std::string> key_value_store;
       key_value_store.Put(OatHeader::kBootClassPathKey,
                           android::base::Join(out_helper.dex_file_locations, ':'));
+      key_value_store.Put(OatHeader::kApexVersionsKey, Runtime::Current()->GetApexVersions());
 
       std::vector<std::unique_ptr<ElfWriter>> elf_writers;
       std::vector<std::unique_ptr<OatWriter>> oat_writers;
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 952b528..c8ce0b7 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -35,6 +35,7 @@
 #include "base/callee_save_type.h"
 #include "base/enums.h"
 #include "base/file_utils.h"
+#include "base/globals.h"
 #include "base/macros.h"
 #include "base/memfd.h"
 #include "base/os.h"
@@ -3474,6 +3475,41 @@
       << ",name=\"" << GetName() << "\"]";
 }
 
+bool ImageSpace::ValidateApexVersions(const OatFile& oat_file, std::string* error_msg) {
+  // For a boot image, the key value store only exists in the first OAT file. Skip other OAT files.
+  if (oat_file.GetOatHeader().GetKeyValueStoreSize() == 0) {
+    return true;
+  }
+
+  // The OAT files in the ART APEX is built on host, so they don't have the right APEX versions. It
+  // is safe to assume that they are always up-to-date because they are shipped along with the
+  // runtime and the dex files.
+  if (kIsTargetBuild && android::base::StartsWith(oat_file.GetLocation(), GetArtRoot())) {
+    return true;
+  }
+
+  const char* oat_apex_versions =
+      oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kApexVersionsKey);
+  if (oat_apex_versions == nullptr) {
+    *error_msg = StringPrintf("ValidateApexVersions failed to get APEX versions from oat file '%s'",
+                              oat_file.GetLocation().c_str());
+    return false;
+  }
+  // For a boot image, it can be generated from a subset of the bootclasspath.
+  // For an app image, some dex files get compiled with a subset of the bootclasspath.
+  // For such cases, the OAT APEX versions will be a prefix of the runtime APEX versions.
+  if (!android::base::StartsWith(Runtime::Current()->GetApexVersions(), oat_apex_versions)) {
+    *error_msg = StringPrintf(
+        "ValidateApexVersions found APEX versions mismatch between oat file '%s' and the runtime "
+        "(Oat file: '%s', Runtime: '%s')",
+        oat_file.GetLocation().c_str(),
+        oat_apex_versions,
+        Runtime::Current()->GetApexVersions().c_str());
+    return false;
+  }
+  return true;
+}
+
 bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::string* error_msg) {
   return ValidateOatFile(oat_file, error_msg, ArrayRef<const std::string>(), ArrayRef<const int>());
 }
@@ -3482,6 +3518,10 @@
                                  std::string* error_msg,
                                  ArrayRef<const std::string> dex_filenames,
                                  ArrayRef<const int> dex_fds) {
+  if (!ValidateApexVersions(oat_file, error_msg)) {
+    return false;
+  }
+
   const ArtDexFileLoader dex_file_loader;
   size_t dex_file_index = 0;
   for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) {
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index d366b5b..8a93f2b 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -267,6 +267,9 @@
       const std::string& image_location,
       bool boot_image_extension = false);
 
+  // Returns true if the APEX versions in the OAT file match the current APEX versions.
+  static bool ValidateApexVersions(const OatFile& oat_file, std::string* error_msg);
+
   // Returns true if the dex checksums in the given oat file match the
   // checksums of the original dex files on disk. This is intended to be used
   // to validate the boot image oat file, which may contain dex entries from
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index c303a7b..46a4d0e 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -413,19 +413,6 @@
   return true;
 }
 
-static bool ValidateApexVersions(const OatFile& oat_file) {
-  const char* oat_apex_versions =
-      oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kApexVersionsKey);
-  if (oat_apex_versions == nullptr) {
-    return false;
-  }
-  // Some dex files get compiled with a subset of the boot classpath (for
-  // example currently system server is compiled with DEX2OAT_BOOTCLASSPATH).
-  // For such cases, the oat apex versions will be a prefix of the runtime apex
-  // versions.
-  return android::base::StartsWith(Runtime::Current()->GetApexVersions(), oat_apex_versions);
-}
-
 OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
   // Verify the ART_USE_READ_BARRIER state.
   // TODO: Don't fully reject files due to read barrier state. If they contain
@@ -456,8 +443,8 @@
       VLOG(oat) << "Oat image checksum does not match image checksum.";
       return kOatBootImageOutOfDate;
     }
-    if (!ValidateApexVersions(file)) {
-      VLOG(oat) << "Apex versions do not match.";
+    if (!gc::space::ImageSpace::ValidateApexVersions(file, &error_msg)) {
+      VLOG(oat) << error_msg;
       return kOatBootImageOutOfDate;
     }
   } else {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 5f52010..48a6640 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1548,6 +1548,9 @@
   // Generational CC collection is currently only compatible with Baker read barriers.
   bool use_generational_cc = kUseBakerReadBarrier && xgc_option.generational_cc;
 
+  // Cache the apex versions.
+  InitializeApexVersions();
+
   heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
                        runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
                        runtime_options.GetOrDefault(Opt::HeapMinFree),
@@ -1825,9 +1828,6 @@
   boot_class_path_checksums_ = gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces,
                                                                                 bcp_dex_files);
 
-  // Cache the apex versions.
-  InitializeApexVersions();
-
   CHECK(class_linker_ != nullptr);
 
   verifier::ClassVerifier::Init(class_linker_);