Add a helper class OfaContext for OatFileAssistant.

OfaContext fetches and caches information including boot image
checksums, bootclasspath checksums, and APEX versions.

This change eliminates the unnecessary reads of the art files,
oat files, and dex files in the slow path of app oat header validation
on app startup. After this change, there is no longer a "fast path" and
a "slow path". Instead, OfaContext always gets the boot image checksums
and BCP checksums from the runtime. (Trace before:
http://screen/6CPziPGmG92Mrw2, Trace after:
http://screen/gzpUEcJ3R78fWiJ)

OfaContext can be kept on the caller side so that the cache can be
reused, making callers like artd faster on repetitive calls to
OatFileAssistant. After this change, calling Artd::getOptimizationStatus
100 times takes 600ms less total time. For example, running
`adb shell pm art get-optimization-status com.google.android.youtube`
100 times took 3.2s on average on Cuttlefish before this change, but now
takes 2.6s after this change.

In addition, after this change, the responsibilities of
OatFileAssistant and ImageSpace are divided in a better way. ImageSpace
is purely responsible for loading and validating boot images. It is no
longer responsible for validating app oat headers. Instead, this
responsibility is now taken by OatFileAssistant.

`--validate-bcp` is removed from dexoptanalyzer because no one is using
it.

Partially cherry picked from
commit 8e515fb047e548fed89decb18d677d30fb708a9c.

Bug: 238394854
Bug: 229268202
Test: m test-art-host-gtest-art_runtime_tests
Test: atest ArtGtestsTargetChroot
Test: art/test.py --host -r
Test: atest art_standalone_dexpreopt_tests
Test: atest odsign_e2e_tests_full
Merged-In: I83b43684d78c91e649300929ca2f348c626e1cab
Change-Id: I5a4bf68e32fcafe14ed474c4b3946da1421585ce
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 9ce215b..ce069d2 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -22,6 +22,7 @@
 #include <optional>
 #include <sstream>
 #include <string>
+#include <variant>
 
 #include "arch/instruction_set.h"
 #include "base/compiler_filter.h"
@@ -30,6 +31,7 @@
 #include "base/unix_file/fd_file.h"
 #include "class_loader_context.h"
 #include "oat_file.h"
+#include "oat_file_assistant_context.h"
 
 namespace art {
 
@@ -90,26 +92,6 @@
     kOatUpToDate,
   };
 
-  // Options that a runtime would take if the OAT file were going to be loaded by the runtime.
-  // Note that the struct only keeps references, so the caller must keep the objects alive during
-  // the lifetime of OatFileAssistant.
-  struct RuntimeOptions {
-    // Required. See `-Ximage`.
-    const std::vector<std::string>& image_locations;
-    // Required. See `-Xbootclasspath`.
-    const std::vector<std::string>& boot_class_path;
-    // Required. See `-Xbootclasspath-locations`.
-    const std::vector<std::string>& boot_class_path_locations;
-    // Optional. See `-Xbootclasspathfds`.
-    const std::vector<int>* const boot_class_path_fds = nullptr;
-    // Optional. See `-Xdeny-art-apex-data-files`.
-    const bool deny_art_apex_data_files = false;
-    // Required. A string that represents the apex versions of boot classpath jars. See
-    // `Runtime::apex_versions_` for the encoding format. Can be obtained from
-    // `Runtime::GetApexVersions(boot_class_path_locations)`.
-    const std::string& apex_versions;
-  };
-
   // A bit field to represent the conditions where dexopt should be performed.
   struct DexOptTrigger {
     // Dexopt should be performed if the target compiler filter is better than the current compiler
@@ -178,7 +160,7 @@
                    ClassLoaderContext* context,
                    bool load_executable,
                    bool only_load_trusted_executable = false,
-                   std::unique_ptr<RuntimeOptions> runtime_options = nullptr);
+                   OatFileAssistantContext* ofa_context = nullptr);
 
   // Similar to this(const char*, const InstructionSet, bool), however, if a valid zip_fd is
   // provided, vdex, oat, and zip files will be read from vdex_fd, oat_fd and zip_fd respectively.
@@ -188,7 +170,7 @@
                    ClassLoaderContext* context,
                    bool load_executable,
                    bool only_load_trusted_executable,
-                   std::unique_ptr<RuntimeOptions> runtime_options,
+                   OatFileAssistantContext* ofa_context,
                    int vdex_fd,
                    int oat_fd,
                    int zip_fd);
@@ -203,7 +185,7 @@
       const std::string& context_str,
       bool load_executable,
       bool only_load_trusted_executable,
-      std::unique_ptr<RuntimeOptions> runtime_options,
+      OatFileAssistantContext* ofa_context,
       /*out*/ std::unique_ptr<ClassLoaderContext>* context,
       /*out*/ std::string* error_msg);
 
@@ -277,7 +259,7 @@
                                     InstructionSet isa,
                                     std::string* out_compilation_filter,
                                     std::string* out_compilation_reason,
-                                    std::unique_ptr<RuntimeOptions> runtime_options = nullptr);
+                                    OatFileAssistantContext* ofa_context = nullptr);
 
   // Open and returns an image space associated with the oat file.
   static std::unique_ptr<gc::space::ImageSpace> OpenImageSpace(const OatFile* oat_file);
@@ -374,6 +356,16 @@
 
   bool ClassLoaderContextIsOkay(const OatFile& oat_file) const;
 
+  // Validates the boot class path checksum of an OatFile.
+  bool ValidateBootClassPathChecksums(const OatFile& oat_file);
+
+  // Validates the given bootclasspath and bootclasspath checksums found in an oat header.
+  static bool ValidateBootClassPathChecksums(OatFileAssistantContext* ofa_context,
+                                             InstructionSet isa,
+                                             std::string_view oat_checksums,
+                                             std::string_view oat_boot_class_path,
+                                             /*out*/ std::string* error_msg);
+
  private:
   class OatFileInfo {
    public:
@@ -502,9 +494,6 @@
   // dex_location_ dex file.
   const std::vector<uint32_t>* GetRequiredDexChecksums();
 
-  // Validates the boot class path checksum of an OatFile.
-  bool ValidateBootClassPathChecksums(const OatFile& oat_file);
-
   // Returns whether there is at least one boot image usable.
   bool IsPrimaryBootImageUsable();
 
@@ -515,6 +504,23 @@
                                  bool profile_changed,
                                  bool downgrade);
 
+  // Returns the pointer to the owned or unowned instance of OatFileAssistantContext.
+  OatFileAssistantContext* GetOatFileAssistantContext() {
+    if (std::holds_alternative<OatFileAssistantContext*>(ofa_context_)) {
+      return std::get<OatFileAssistantContext*>(ofa_context_);
+    } else {
+      return std::get<std::unique_ptr<OatFileAssistantContext>>(ofa_context_).get();
+    }
+  }
+
+  // The runtime options taken from the active runtime or the input.
+  //
+  // All member functions should get runtime options from this variable rather than referencing the
+  // active runtime. This is to allow OatFileAssistant to function without an active runtime.
+  const OatFileAssistantContext::RuntimeOptions& GetRuntimeOptions() {
+    return GetOatFileAssistantContext()->GetRuntimeOptions();
+  }
+
   std::string dex_location_;
 
   ClassLoaderContext* context_;
@@ -535,12 +541,6 @@
   // Will be set during GetRequiredDexChecksums.
   bool zip_file_only_contains_uncompressed_dex_ = true;
 
-  // The runtime options taken from the active runtime or the input.
-  //
-  // All member functions should get runtime options from this variable rather than referencing the
-  // active runtime. This is to allow OatFileAssistant to function without an active runtime.
-  std::unique_ptr<RuntimeOptions> runtime_options_;
-
   // Cached value of the required dex checksums.
   // This should be accessed only by the GetRequiredDexChecksums() method.
   std::vector<uint32_t> cached_required_dex_checksums_;
@@ -568,9 +568,8 @@
   // File descriptor corresponding to apk, dex file, or zip.
   int zip_fd_;
 
-  std::string cached_boot_class_path_;
-  std::string cached_boot_class_path_checksums_;
-  std::optional<bool> cached_is_boot_image_usable_ = std::nullopt;
+  // Owned or unowned instance of OatFileAssistantContext.
+  std::variant<std::unique_ptr<OatFileAssistantContext>, OatFileAssistantContext*> ofa_context_;
 
   friend class OatFileAssistantTest;