Cache boot classpath checksums at runtime init.

To speed up oat file checksums check.

Test: test.py
Bug: 191828947
Change-Id: I2fe97a5626220470ec3edf457a3a24e7d50ce6d7
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index f323647..1518195 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -646,15 +646,24 @@
 
   Runtime* runtime = Runtime::Current();
   std::string error_msg;
-  bool result = gc::space::ImageSpace::VerifyBootClassPathChecksums(
-      oat_boot_class_path_checksums_view,
-      oat_boot_class_path_view,
-      ArrayRef<const std::string>(runtime->GetImageLocations()),
-      ArrayRef<const std::string>(runtime->GetBootClassPathLocations()),
-      ArrayRef<const std::string>(runtime->GetBootClassPath()),
-      ArrayRef<const int>(runtime->GetBootClassPathFds()),
-      isa_,
-      &error_msg);
+  bool result = false;
+  // Fast path when the runtime boot classpath cheksums and boot classpath
+  // locations directly match.
+  if (oat_boot_class_path_checksums_view == runtime->GetBootClassPathChecksums() &&
+      isa_ == kRuntimeISA &&
+      oat_boot_class_path_view == android::base::Join(runtime->GetBootClassPathLocations(), ":")) {
+    result = true;
+  } else {
+    result = gc::space::ImageSpace::VerifyBootClassPathChecksums(
+        oat_boot_class_path_checksums_view,
+        oat_boot_class_path_view,
+        ArrayRef<const std::string>(runtime->GetImageLocations()),
+        ArrayRef<const std::string>(runtime->GetBootClassPathLocations()),
+        ArrayRef<const std::string>(runtime->GetBootClassPath()),
+        ArrayRef<const int>(runtime->GetBootClassPathFds()),
+        isa_,
+        &error_msg);
+  }
   if (!result) {
     VLOG(oat) << "Failed to verify checksums of oat file " << oat_file.GetLocation()
         << " error: " << error_msg;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 8af3558..707bb02 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1796,6 +1796,14 @@
     }
   }
 
+  // Now that the boot image space is set, cache the boot classpath checksums,
+  // to be used when validating oat files.
+  ArrayRef<gc::space::ImageSpace* const> image_spaces(GetHeap()->GetBootImageSpaces());
+  ArrayRef<const DexFile* const> bcp_dex_files(GetClassLinker()->GetBootClassPath());
+  boot_class_path_checksums_ = gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces,
+                                                                                bcp_dex_files);
+
+  // Cache the apex versions.
   InitializeApexVersions();
 
   CHECK(class_linker_ != nullptr);
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 180eeda..75c52cb 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -291,6 +291,12 @@
     return boot_class_path_fds_;
   }
 
+  // Returns the checksums for the boot image, extensions and extra boot class path dex files,
+  // based on the image spaces and boot class path dex files loaded in memory.
+  const std::string& GetBootClassPathChecksums() const {
+    return boot_class_path_checksums_;
+  }
+
   const std::string& GetClassPathString() const {
     return class_path_string_;
   }
@@ -1120,6 +1126,7 @@
 
   std::vector<std::string> boot_class_path_;
   std::vector<std::string> boot_class_path_locations_;
+  std::string boot_class_path_checksums_;
   std::vector<int> boot_class_path_fds_;
   std::string class_path_string_;
   std::vector<std::string> properties_;