Add a method to OatFileAssistantContext to fetch all information.

artd can be multi-threaded, so it needs OatFileAssistantContext to be
thread-safe. This CL adds `OatFileAssistantContext::FetchAll`, which
fetches all information and makes subsequent operations read-only. artd
calls it the first time it initalizes OatFileAssistantContext.

Bug: 229268202
Test: adb shell pm art get-optimization-status \
  com.google.android.youtube
Change-Id: Iacc36655e2cdbc7cb74b3f3cbf7f9ac1a1ffc28e
Merged-In: Iacc36655e2cdbc7cb74b3f3cbf7f9ac1a1ffc28e
(cherry picked from commit 93a13dab243e0141fadacb3137776aff882a1a69)
diff --git a/libartbase/arch/instruction_set.cc b/libartbase/arch/instruction_set.cc
index 9ec66fe..10a9919 100644
--- a/libartbase/arch/instruction_set.cc
+++ b/libartbase/arch/instruction_set.cc
@@ -17,6 +17,8 @@
 #include "instruction_set.h"
 
 #include "android-base/logging.h"
+#include "android-base/properties.h"
+#include "android-base/stringprintf.h"
 #include "base/bit_utils.h"
 #include "base/globals.h"
 
@@ -91,6 +93,45 @@
   UNREACHABLE();
 }
 
+std::vector<InstructionSet> GetSupportedInstructionSets(std::string* error_msg) {
+  std::string zygote_kinds = android::base::GetProperty("ro.zygote", {});
+  if (zygote_kinds.empty()) {
+    *error_msg = "Unable to get Zygote kinds";
+    return {};
+  }
+
+  switch (kRuntimeISA) {
+    case InstructionSet::kArm:
+    case InstructionSet::kArm64:
+      if (zygote_kinds == "zygote64_32" || zygote_kinds == "zygote32_64") {
+        return {InstructionSet::kArm64, InstructionSet::kArm};
+      } else if (zygote_kinds == "zygote64") {
+        return {InstructionSet::kArm64};
+      } else if (zygote_kinds == "zygote32") {
+        return {InstructionSet::kArm};
+      } else {
+        *error_msg = android::base::StringPrintf("Unknown Zygote kinds '%s'", zygote_kinds.c_str());
+        return {};
+      }
+    case InstructionSet::kX86:
+    case InstructionSet::kX86_64:
+      if (zygote_kinds == "zygote64_32" || zygote_kinds == "zygote32_64") {
+        return {InstructionSet::kX86_64, InstructionSet::kX86};
+      } else if (zygote_kinds == "zygote64") {
+        return {InstructionSet::kX86_64};
+      } else if (zygote_kinds == "zygote32") {
+        return {InstructionSet::kX86};
+      } else {
+        *error_msg = android::base::StringPrintf("Unknown Zygote kinds '%s'", zygote_kinds.c_str());
+        return {};
+      }
+    default:
+      *error_msg = android::base::StringPrintf("Unknown runtime ISA '%s'",
+                                               GetInstructionSetString(kRuntimeISA));
+      return {};
+  }
+}
+
 namespace instruction_set_details {
 
 static_assert(IsAligned<kPageSize>(kArmStackOverflowReservedBytes), "ARM gap not page aligned");
diff --git a/libartbase/arch/instruction_set.h b/libartbase/arch/instruction_set.h
index faf881d..155b186 100644
--- a/libartbase/arch/instruction_set.h
+++ b/libartbase/arch/instruction_set.h
@@ -19,6 +19,7 @@
 
 #include <iosfwd>
 #include <string>
+#include <vector>
 
 #include "base/enums.h"
 #include "base/macros.h"
@@ -195,6 +196,9 @@
   InstructionSetAbort(isa);
 }
 
+// Returns the instruction sets supported by the device, or an empty list on failure.
+std::vector<InstructionSet> GetSupportedInstructionSets(std::string* error_msg);
+
 namespace instruction_set_details {
 
 #if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
diff --git a/runtime/oat_file_assistant_context.cc b/runtime/oat_file_assistant_context.cc
index d282d03..becc329 100644
--- a/runtime/oat_file_assistant_context.cc
+++ b/runtime/oat_file_assistant_context.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "oat_file_assistant_context.h"
+
 #include <memory>
 #include <string>
 #include <vector>
@@ -23,11 +25,11 @@
 #include "arch/instruction_set.h"
 #include "base/array_ref.h"
 #include "base/logging.h"
+#include "base/mem_map.h"
 #include "class_linker.h"
 #include "dex/art_dex_file_loader.h"
 #include "gc/heap.h"
 #include "gc/space/image_space.h"
-#include "oat_file_assistant_context.h"
 
 namespace art {
 
@@ -42,6 +44,8 @@
   DCHECK_IMPLIES(
       runtime_options_->boot_class_path_fds != nullptr,
       runtime_options_->boot_class_path.size() == runtime_options_->boot_class_path_fds->size());
+  // Opening dex files and boot images require MemMap.
+  MemMap::Init();
 }
 
 OatFileAssistantContext::OatFileAssistantContext(Runtime* runtime)
@@ -90,6 +94,23 @@
   return *runtime_options_;
 }
 
+bool OatFileAssistantContext::FetchAll(std::string* error_msg) {
+  std::vector<InstructionSet> isas = GetSupportedInstructionSets(error_msg);
+  if (isas.empty()) {
+    return false;
+  }
+  for (InstructionSet isa : isas) {
+    GetBootImageInfoList(isa);
+  }
+  for (size_t i = 0; i < runtime_options_->boot_class_path.size(); i++) {
+    if (GetBcpChecksums(i, error_msg) == nullptr) {
+      return false;
+    }
+  }
+  GetApexVersions();
+  return true;
+}
+
 const std::vector<OatFileAssistantContext::BootImageInfo>&
 OatFileAssistantContext::GetBootImageInfoList(InstructionSet isa) {
   if (auto it = boot_image_info_list_by_isa_.find(isa); it != boot_image_info_list_by_isa_.end()) {
diff --git a/runtime/oat_file_assistant_context.h b/runtime/oat_file_assistant_context.h
index 3288dc0..5f42ad9 100644
--- a/runtime/oat_file_assistant_context.h
+++ b/runtime/oat_file_assistant_context.h
@@ -30,6 +30,7 @@
 // A helper class for OatFileAssistant that fetches and caches information including boot image
 // checksums, bootclasspath checksums, and APEX versions. The same instance can be reused across
 // OatFileAssistant calls on different dex files for different instruction sets.
+// This class is not thread-safe until `FetchAll` is called.
 class OatFileAssistantContext {
  public:
   // Options that a runtime would take.
@@ -64,6 +65,9 @@
   explicit OatFileAssistantContext(Runtime* runtime);
   // Returns runtime options.
   const RuntimeOptions& GetRuntimeOptions() const;
+  // Fetches all information that hasn't been fetched from disk amd caches it. All operations will
+  // be read-only after a successful call to this function.
+  bool FetchAll(std::string* error_msg);
   // Returns information about the boot image of the given instruction set.
   const std::vector<BootImageInfo>& GetBootImageInfoList(InstructionSet isa);
   // Returns the checksums of the dex files in the BCP jar at the given index, or nullptr on error.