Allow OatFileAssistant::Create to take std::nullopt for the context.
Partially cherry picked from
commit 12f45c41158de6f6737efb102161f86f462d9290.
Bug: 249984283
Test: m test-art-host-gtest-art_runtime_tests
Change-Id: I7ebe2aa745d0da31242034a27f92b24dbdb08740
Merged-In: I7ebe2aa745d0da31242034a27f92b24dbdb08740
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index c04ff5a..a9f380d 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -616,6 +616,8 @@
return nullptr;
}
+ // The API doesn't support passing a class loader context, so skip the class loader context check
+ // and assume that it's OK.
OatFileAssistant oat_file_assistant(filename.c_str(),
target_instruction_set,
/* context= */ nullptr,
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 389479c..9e0c173 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -226,7 +226,7 @@
std::unique_ptr<OatFileAssistant> OatFileAssistant::Create(
const std::string& filename,
const std::string& isa_str,
- const std::string& context_str,
+ const std::optional<std::string>& context_str,
bool load_executable,
bool only_load_trusted_executable,
OatFileAssistantContext* ofa_context,
@@ -238,20 +238,23 @@
return nullptr;
}
- std::unique_ptr<ClassLoaderContext> tmp_context = ClassLoaderContext::Create(context_str.c_str());
- if (tmp_context == nullptr) {
- *error_msg = StringPrintf("Class loader context '%s' is invalid", context_str.c_str());
- return nullptr;
- }
+ std::unique_ptr<ClassLoaderContext> tmp_context = nullptr;
+ if (context_str.has_value()) {
+ tmp_context = ClassLoaderContext::Create(context_str->c_str());
+ if (tmp_context == nullptr) {
+ *error_msg = StringPrintf("Class loader context '%s' is invalid", context_str->c_str());
+ return nullptr;
+ }
- if (!tmp_context->OpenDexFiles(android::base::Dirname(filename.c_str()),
- /*context_fds=*/{},
- /*only_read_checksums=*/true)) {
- *error_msg =
- StringPrintf("Failed to load class loader context files for '%s' with context '%s'",
- filename.c_str(),
- context_str.c_str());
- return nullptr;
+ if (!tmp_context->OpenDexFiles(android::base::Dirname(filename.c_str()),
+ /*context_fds=*/{},
+ /*only_read_checksums=*/true)) {
+ *error_msg =
+ StringPrintf("Failed to load class loader context files for '%s' with context '%s'",
+ filename.c_str(),
+ context_str->c_str());
+ return nullptr;
+ }
}
auto assistant = std::make_unique<OatFileAssistant>(filename.c_str(),
@@ -1182,6 +1185,11 @@
}
bool OatFileAssistant::ClassLoaderContextIsOkay(const OatFile& oat_file) const {
+ if (context_ == nullptr) {
+ // The caller requests to skip the check.
+ return true;
+ }
+
if (oat_file.IsBackedByVdexOnly()) {
// Only a vdex file, we don't depend on the class loader context.
return true;
@@ -1193,12 +1201,6 @@
return true;
}
- if (context_ == nullptr) {
- // When no class loader context is provided (which happens for deprecated
- // DexFile APIs), just assume it is OK.
- return true;
- }
-
ClassLoaderContext::VerificationResult matches = context_->VerifyClassLoaderContextMatch(
oat_file.GetClassLoaderContext(),
/*verify_names=*/ true,
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index ce069d2..2d0a150 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -146,6 +146,8 @@
// device. For example, on an arm device, use arm or arm64. An oat file can
// be loaded executable only if the ISA matches the current runtime.
//
+ // context should be the class loader context to check against, or null to skip the check.
+ //
// load_executable should be true if the caller intends to try and load
// executable code for this dex location.
//
@@ -182,7 +184,7 @@
static std::unique_ptr<OatFileAssistant> Create(
const std::string& filename,
const std::string& isa_str,
- const std::string& context_str,
+ const std::optional<std::string>& context_str,
bool load_executable,
bool only_load_trusted_executable,
OatFileAssistantContext* ofa_context,
@@ -523,6 +525,8 @@
std::string dex_location_;
+ // The class loader context to check against, or null representing that the check should be
+ // skipped.
ClassLoaderContext* context_;
// Whether or not the parent directory of the dex file is writable.
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 2904ecb..090532c 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -23,6 +23,7 @@
#include <functional>
#include <iterator>
#include <memory>
+#include <optional>
#include <string>
#include <type_traits>
#include <vector>
@@ -78,33 +79,40 @@
// Verify the static method (called from PM for dumpsys).
// This variant does not check class loader context.
if (!check_context) {
- std::string compilation_filter1;
- std::string compilation_reason1;
+ std::string compilation_filter;
+ std::string compilation_reason;
OatFileAssistant::GetOptimizationStatus(file,
kRuntimeISA,
- &compilation_filter1,
- &compilation_reason1,
+ &compilation_filter,
+ &compilation_reason,
MaybeGetOatFileAssistantContext());
- ASSERT_EQ(expected_filter_name, compilation_filter1);
- ASSERT_EQ(expected_reason, compilation_reason1);
+ ASSERT_EQ(expected_filter_name, compilation_filter);
+ ASSERT_EQ(expected_reason, compilation_reason);
}
// Verify the instance methods (called at runtime and from artd).
OatFileAssistant assistant = CreateOatFileAssistant(file.c_str(), context);
+ VerifyOptimizationStatusWithInstance(
+ &assistant, expected_filter_name, expected_reason, expected_odex_status);
+ }
- std::string odex_location3; // ignored
- std::string compilation_filter3;
- std::string compilation_reason3;
- std::string odex_status3;
+ void VerifyOptimizationStatusWithInstance(OatFileAssistant* assistant,
+ const std::string& expected_filter,
+ const std::string& expected_reason,
+ const std::string& expected_odex_status) {
+ std::string odex_location; // ignored
+ std::string compilation_filter;
+ std::string compilation_reason;
+ std::string odex_status;
- assistant.GetOptimizationStatus(
- &odex_location3, &compilation_filter3, &compilation_reason3, &odex_status3);
+ assistant->GetOptimizationStatus(
+ &odex_location, &compilation_filter, &compilation_reason, &odex_status);
- ASSERT_EQ(expected_filter_name, compilation_filter3);
- ASSERT_EQ(expected_reason, compilation_reason3);
- ASSERT_EQ(expected_odex_status, odex_status3);
+ ASSERT_EQ(expected_filter, compilation_filter);
+ ASSERT_EQ(expected_reason, compilation_reason);
+ ASSERT_EQ(expected_odex_status, odex_status);
}
bool InsertNewBootClasspathEntry(const std::string& src, std::string* error_msg) {
@@ -2377,7 +2385,33 @@
ASSERT_NE(oat_file_assistant, nullptr);
// Verify that the created instance is usable.
- VerifyOptimizationStatus(dex_location, default_context_.get(), "speed", "install", "up-to-date");
+ VerifyOptimizationStatusWithInstance(oat_file_assistant.get(), "speed", "install", "up-to-date");
+}
+
+TEST_P(OatFileAssistantTest, CreateWithNullContext) {
+ std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
+ std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
+ Copy(GetDexSrc1(), dex_location);
+ GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
+
+ auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
+
+ std::unique_ptr<ClassLoaderContext> context;
+ std::string error_msg;
+ std::unique_ptr<OatFileAssistant> oat_file_assistant =
+ OatFileAssistant::Create(dex_location,
+ GetInstructionSetString(kRuntimeISA),
+ /*context_str=*/std::nullopt,
+ /*load_executable=*/false,
+ /*only_load_trusted_executable=*/true,
+ MaybeGetOatFileAssistantContext(),
+ &context,
+ &error_msg);
+ ASSERT_NE(oat_file_assistant, nullptr);
+ ASSERT_EQ(context, nullptr);
+
+ // Verify that the created instance is usable.
+ VerifyOptimizationStatusWithInstance(oat_file_assistant.get(), "speed", "install", "up-to-date");
}
TEST_P(OatFileAssistantTest, ErrorOnInvalidIsaString) {