summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2025-02-03 12:26:05 +0000
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2025-02-21 09:51:24 -0800
commit3174b53128da59b571b3693119e1a41d4764bc6e (patch)
treec2cdaaf4be9e6a69c5d4d529845425ab21b483dd
parenta7d85a831f0a330ce9914c57ae146fc03193451c (diff)
Refactor OatFileAssistant - Step 1.
This change splits OatFileInfo into subclasses, one for each file type. This allows different file types to have its own fields. For example, oat type and vdex type support FDs, while dm type doesn't. Besides, this change makes the code cleaner because each file type can now have its own logic of loading the file in its own subclass. Later, we'll add one more subclass for the SDM file type, which will have its own fields for the paths to the DM file and the SDC file coressponding to the SDM file, and its own logic to load the files. This change is supposed to be no-op. Bug: 377474232 Test: atest art_standalone_runtime_tests Change-Id: I3e831602b0337f9fe6438a7e0958bab3f91fd035
-rw-r--r--runtime/oat/oat_file_assistant.cc389
-rw-r--r--runtime/oat/oat_file_assistant.h180
2 files changed, 335 insertions, 234 deletions
diff --git a/runtime/oat/oat_file_assistant.cc b/runtime/oat/oat_file_assistant.cc
index b6276f52d2..6f90228d3c 100644
--- a/runtime/oat/oat_file_assistant.cc
+++ b/runtime/oat/oat_file_assistant.cc
@@ -116,11 +116,6 @@ OatFileAssistant::OatFileAssistant(const char* dex_location,
isa_(isa),
load_executable_(load_executable),
only_load_trusted_executable_(only_load_trusted_executable),
- odex_(this, /*is_oat_location=*/false),
- oat_(this, /*is_oat_location=*/true),
- vdex_for_odex_(this, /*is_oat_location=*/false),
- vdex_for_oat_(this, /*is_oat_location=*/true),
- dm_(this, /*is_oat_location=*/false),
zip_fd_(zip_fd) {
CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
CHECK_IMPLIES(load_executable, context != nullptr) << "Loading executable without a context";
@@ -167,41 +162,81 @@ OatFileAssistant::OatFileAssistant(const char* dex_location,
// Get the odex filename.
std::string error_msg;
std::string odex_file_name;
- if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
- odex_.Reset(odex_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd);
- std::string vdex_file_name = GetVdexFilename(odex_file_name);
- // We dup FDs as the odex_ will claim ownership.
- vdex_for_odex_.Reset(vdex_file_name,
- UseFdToReadFiles(),
- DupCloexec(zip_fd),
- DupCloexec(vdex_fd),
- DupCloexec(oat_fd));
- } else {
+ if (!DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
}
+ // Get the oat filename.
+ std::string oat_file_name;
if (!UseFdToReadFiles()) {
- // Get the oat filename.
- std::string oat_file_name;
- if (DexLocationToOatFilename(dex_location_,
- isa_,
- GetRuntimeOptions().deny_art_apex_data_files,
- &oat_file_name,
- &error_msg)) {
- oat_.Reset(oat_file_name, /*use_fd=*/false);
- std::string vdex_file_name = GetVdexFilename(oat_file_name);
- vdex_for_oat_.Reset(vdex_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd);
- std::string dm_file_name = GetDmFilename(dex_location);
- dm_.Reset(dm_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd);
- } else if (kIsTargetAndroid) {
- // No need to warn on host. We are probably in oatdump, where we only need OatFileAssistant to
- // validate BCP checksums.
- LOG(WARNING) << "Failed to determine oat file name for dex location " << dex_location_ << ": "
- << error_msg;
+ if (!DexLocationToOatFilename(dex_location_,
+ isa_,
+ GetRuntimeOptions().deny_art_apex_data_files,
+ &oat_file_name,
+ &error_msg)) {
+ if (kIsTargetAndroid) {
+ // No need to warn on host. We are probably in oatdump, where we only need OatFileAssistant
+ // to validate BCP checksums.
+ LOG(WARNING) << "Failed to determine oat file name for dex location " << dex_location_
+ << ": " << error_msg;
+ }
}
}
+
+ if (!oat_file_name.empty() && !UseFdToReadFiles()) {
+ // The oat location. This is for apps on readonly filesystems (typically, system apps and
+ // incremental apps). This must be prioritized over the odex location, because the odex location
+ // probably has the dexpreopt artifacts for such apps.
+ info_list_.push_back(std::make_unique<OatFileInfoBackedByOat>(this,
+ oat_file_name,
+ /*is_oat_location=*/true,
+ /*use_fd=*/false));
+ }
+
+ if (!odex_file_name.empty()) {
+ // The odex location, which is the most common.
+ info_list_.push_back(std::make_unique<OatFileInfoBackedByOat>(this,
+ odex_file_name,
+ /*is_oat_location=*/false,
+ UseFdToReadFiles(),
+ zip_fd,
+ vdex_fd,
+ oat_fd));
+ }
+
+ // When there is no odex/oat available (e.g., they are both out of date), we look for a useable
+ // vdex file.
+
+ if (!oat_file_name.empty() && !UseFdToReadFiles()) {
+ // The vdex-only file next to 'oat_`.
+ info_list_.push_back(std::make_unique<OatFileInfoBackedByVdex>(this,
+ GetVdexFilename(oat_file_name),
+ /*is_oat_location=*/true,
+ /*use_fd=*/false));
+ }
+
+ if (!odex_file_name.empty()) {
+ // The vdex-only file next to `odex_`.
+ // We dup FDs as the odex_ will claim ownership.
+ info_list_.push_back(std::make_unique<OatFileInfoBackedByVdex>(this,
+ GetVdexFilename(odex_file_name),
+ /*is_oat_location=*/false,
+ UseFdToReadFiles(),
+ DupCloexec(zip_fd),
+ DupCloexec(vdex_fd)));
+ }
+
+ if (!UseFdToReadFiles()) {
+ // A .dm file may be available, look for it.
+ info_list_.push_back(
+ std::make_unique<OatFileInfoBackedByDm>(this, GetDmFilename(dex_location_)));
+ }
}
+// Must be defined outside of the class, to prevent inlining, which causes callers to access hidden
+// symbols used by the destructor. `NOINLINE` doesn't work.
+OatFileAssistant::~OatFileAssistant() = default;
+
std::unique_ptr<OatFileAssistant> OatFileAssistant::Create(
const std::string& filename,
const std::string& isa_str,
@@ -293,7 +328,7 @@ int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target_compiler_fil
}
DexOptNeeded dexopt_needed = info.GetDexOptNeeded(
target_compiler_filter, GetDexOptTrigger(target_compiler_filter, profile_changed, downgrade));
- if (dexopt_needed != kNoDexOptNeeded && (&info == &dm_)) {
+ if (dexopt_needed != kNoDexOptNeeded && info.GetType() == OatFileType::kDm) {
// The usable vdex file is in the DM file. This information cannot be encoded in the integer.
// Return kDex2OatFromScratch so that neither the vdex in the "oat" location nor the vdex in the
// "odex" location will be picked by installd.
@@ -380,9 +415,23 @@ std::optional<bool> OatFileAssistant::HasDexFiles(std::string* error_msg) {
return checksum.has_value();
}
-OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() { return odex_.Status(); }
+OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
+ for (const std::unique_ptr<OatFileInfo>& info : info_list_) {
+ if (info->GetType() == OatFileType::kOat && !info->IsOatLocation()) {
+ return info->Status();
+ }
+ }
+ return kOatCannotOpen;
+}
-OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() { return oat_.Status(); }
+OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
+ for (const std::unique_ptr<OatFileInfo>& info : info_list_) {
+ if (info->GetType() == OatFileType::kOat && info->IsOatLocation()) {
+ return info->Status();
+ }
+ }
+ return kOatCannotOpen;
+}
bool OatFileAssistant::DexChecksumUpToDate(const OatFile& file, std::string* error_msg) {
if (!file.ContainsDexCode()) {
@@ -787,59 +836,39 @@ bool OatFileAssistant::IsPrimaryBootImageUsable() {
OatFileAssistant::OatFileInfo& OatFileAssistant::GetBestInfo() {
ScopedTrace trace("GetBestInfo");
- auto log_status = [&](std::string_view location, OatFileInfo* info) {
- if (!VLOG_IS_ON(oat) || !info->FileExists()) {
- return;
- }
- std::string error_msg;
- OatStatus status = info->Status(&error_msg);
- std::string message = ART_FORMAT(
- "GetBestInfo: {} ({}) is {}", location, info->DisplayFilename(), fmt::streamed(status));
- const OatFile* file = info->GetFile();
- if (file != nullptr) {
- message += ART_FORMAT(" with filter '{}' executable '{}'",
- fmt::streamed(file->GetCompilerFilter()),
- file->IsExecutable());
- }
- if (!info->IsUseable()) {
- message += ": " + error_msg;
+ for (const std::unique_ptr<OatFileInfo>& info : info_list_) {
+ if (VLOG_IS_ON(oat) && info->FileExists()) {
+ std::string error_msg;
+ OatStatus status = info->Status(&error_msg);
+ std::string message = ART_FORMAT("GetBestInfo: {} ({}) is {}",
+ info->GetLocationDebugString(),
+ info->DisplayFilename(),
+ fmt::streamed(status));
+ const OatFile* file = info->GetFile();
+ if (file != nullptr) {
+ message += ART_FORMAT(" with filter '{}' executable '{}'",
+ fmt::streamed(file->GetCompilerFilter()),
+ file->IsExecutable());
+ }
+ if (!info->IsUseable()) {
+ message += ": " + error_msg;
+ }
+ VLOG(oat) << message;
}
- VLOG(oat) << message;
- };
-
- // If the oat location is useable, take it. This must be an app on a readonly filesystem
- // (typically, a system app or an incremental app). This must be prioritized over the odex
- // location, because the odex location probably has the dexpreopt artifacts.
- log_status("odex in dalvik-cache", &oat_);
- if (oat_.IsUseable()) {
- return oat_;
- }
-
- // The odex location, which is the most common.
- log_status("odex next to the dex file", &odex_);
- if (odex_.IsUseable()) {
- return odex_;
- }
-
- // No odex/oat available, look for a useable vdex file.
- log_status("vdex in dalvik-cache", &vdex_for_oat_);
- if (vdex_for_oat_.IsUseable()) {
- return vdex_for_oat_;
- }
- log_status("vdex next to the dex file", &vdex_for_odex_);
- if (vdex_for_odex_.IsUseable()) {
- return vdex_for_odex_;
- }
- // A .dm file may be available, look for it.
- log_status("dm", &dm_);
- if (dm_.IsUseable()) {
- return dm_;
+ if (info->IsUseable()) {
+ return *info;
+ }
}
- // No usable artifact. Pick the odex if it exists, or the oat if not.
+ // No usable artifact. Pick the oat or odex if they exist, or empty info if not.
VLOG(oat) << ART_FORMAT("GetBestInfo: {} has no usable artifacts", dex_location_);
- return (odex_.Status() == kOatCannotOpen) ? oat_ : odex_;
+ for (const std::unique_ptr<OatFileInfo>& info : info_list_) {
+ if (info->GetType() == OatFileType::kOat && info->Status() != kOatCannotOpen) {
+ return *info;
+ }
+ }
+ return empty_info_;
}
std::unique_ptr<gc::space::ImageSpace> OatFileAssistant::OpenImageSpace(const OatFile* oat_file) {
@@ -857,18 +886,12 @@ std::unique_ptr<gc::space::ImageSpace> OatFileAssistant::OpenImageSpace(const Oa
return ret;
}
-OatFileAssistant::OatFileInfo::OatFileInfo(OatFileAssistant* oat_file_assistant,
- bool is_oat_location)
- : oat_file_assistant_(oat_file_assistant), is_oat_location_(is_oat_location) {}
+bool OatFileAssistant::OatFileInfo::IsOatLocation() const { return is_oat_location_; }
-bool OatFileAssistant::OatFileInfo::IsOatLocation() { return is_oat_location_; }
-
-const std::string* OatFileAssistant::OatFileInfo::Filename() {
- return filename_provided_ ? &filename_ : nullptr;
-}
+const std::string* OatFileAssistant::OatFileInfo::Filename() const { return &filename_; }
-const char* OatFileAssistant::OatFileInfo::DisplayFilename() {
- return filename_provided_ ? filename_.c_str() : "unknown";
+const char* OatFileAssistant::OatFileInfo::DisplayFilename() const {
+ return !filename_.empty() ? filename_.c_str() : "unknown";
}
bool OatFileAssistant::OatFileInfo::IsUseable() {
@@ -937,14 +960,19 @@ OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
}
bool OatFileAssistant::OatFileInfo::FileExists() const {
- return use_fd_ || (!filename_.empty() && OS::FileExists(filename_.c_str()));
+ return !filename_.empty() && OS::FileExists(filename_.c_str());
+}
+
+bool OatFileAssistant::OatFileInfoBackedByOat::FileExists() const {
+ return use_fd_ || OatFileInfo::FileExists();
+}
+
+bool OatFileAssistant::OatFileInfoBackedByVdex::FileExists() const {
+ return use_fd_ || OatFileInfo::FileExists();
}
const OatFile* OatFileAssistant::OatFileInfo::GetFile(/*out*/ std::string* error_msg) {
CHECK(!file_released_) << "GetFile called after oat file released.";
- if (!filename_provided_) {
- return nullptr;
- }
if (!file_.has_value()) {
if (LocationIsOnArtApexData(filename_) &&
@@ -963,87 +991,92 @@ const OatFile* OatFileAssistant::OatFileInfo::GetFile(/*out*/ std::string* error
return file_->first.get();
}
-std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::LoadFile(std::string* error_msg) const {
- if (filename_.ends_with(kVdexExtension)) {
- // Check to see if there is a vdex file we can make use of.
- std::unique_ptr<VdexFile> vdex;
- if (use_fd_) {
- if (vdex_fd_ < 0) {
- *error_msg = "vdex_fd not provided";
- return nullptr;
- }
- struct stat s;
- if (fstat(vdex_fd_, &s) < 0) {
- *error_msg = ART_FORMAT("Failed getting length of the vdex file: {}", strerror(errno));
- return nullptr;
- }
- vdex = VdexFile::Open(vdex_fd_,
- s.st_size,
- filename_,
- /*low_4gb=*/false,
- error_msg);
- } else {
- vdex = VdexFile::Open(filename_,
- /*low_4gb=*/false,
- error_msg);
- }
- if (vdex == nullptr) {
- *error_msg = ART_FORMAT("Unable to open vdex file: {}", *error_msg);
+std::unique_ptr<OatFile> OatFileAssistant::OatFileInfoBackedByOat::LoadFile(
+ std::string* error_msg) const {
+ bool executable = oat_file_assistant_->load_executable_;
+ if (executable && oat_file_assistant_->only_load_trusted_executable_) {
+ executable = LocationIsTrusted(filename_, /*trust_art_apex_data_files=*/true);
+ }
+
+ if (use_fd_) {
+ if (oat_fd_ < 0 || vdex_fd_ < 0) {
+ *error_msg = "oat_fd or vdex_fd not provided";
return nullptr;
}
- return std::unique_ptr<OatFile>(OatFile::OpenFromVdex(zip_fd_,
- std::move(vdex),
- oat_file_assistant_->dex_location_,
- oat_file_assistant_->context_,
- error_msg));
- } else if (filename_.ends_with(kDmExtension)) {
- // Check to see if there is a vdex file we can make use of.
- std::unique_ptr<ZipArchive> dm_file(ZipArchive::Open(filename_.c_str(), error_msg));
- if (dm_file == nullptr) {
+ ArrayRef<const std::string> dex_locations(&oat_file_assistant_->dex_location_,
+ /*size=*/1u);
+ return std::unique_ptr<OatFile>(OatFile::Open(zip_fd_,
+ vdex_fd_,
+ oat_fd_,
+ filename_,
+ executable,
+ /*low_4gb=*/false,
+ dex_locations,
+ /*dex_files=*/{},
+ /*reservation=*/nullptr,
+ error_msg));
+ } else {
+ return std::unique_ptr<OatFile>(OatFile::Open(/*zip_fd=*/-1,
+ filename_,
+ filename_,
+ executable,
+ /*low_4gb=*/false,
+ oat_file_assistant_->dex_location_,
+ error_msg));
+ }
+}
+
+std::unique_ptr<OatFile> OatFileAssistant::OatFileInfoBackedByVdex::LoadFile(
+ std::string* error_msg) const {
+ // Check to see if there is a vdex file we can make use of.
+ std::unique_ptr<VdexFile> vdex;
+ if (use_fd_) {
+ if (vdex_fd_ < 0) {
+ *error_msg = "vdex_fd not provided";
return nullptr;
}
- std::unique_ptr<VdexFile> vdex(VdexFile::OpenFromDm(filename_, *dm_file, error_msg));
- if (vdex == nullptr) {
+ struct stat s;
+ if (fstat(vdex_fd_, &s) < 0) {
+ *error_msg = ART_FORMAT("Failed getting length of the vdex file: {}", strerror(errno));
return nullptr;
}
- return std::unique_ptr<OatFile>(OatFile::OpenFromVdex(/*zip_fd=*/-1,
- std::move(vdex),
- oat_file_assistant_->dex_location_,
- oat_file_assistant_->context_,
- error_msg));
+ vdex = VdexFile::Open(vdex_fd_,
+ s.st_size,
+ filename_,
+ /*low_4gb=*/false,
+ error_msg);
} else {
- bool executable = oat_file_assistant_->load_executable_;
- if (executable && oat_file_assistant_->only_load_trusted_executable_) {
- executable = LocationIsTrusted(filename_, /*trust_art_apex_data_files=*/true);
- }
+ vdex = VdexFile::Open(filename_,
+ /*low_4gb=*/false,
+ error_msg);
+ }
+ if (vdex == nullptr) {
+ *error_msg = ART_FORMAT("Unable to open vdex file: {}", *error_msg);
+ return nullptr;
+ }
+ return std::unique_ptr<OatFile>(OatFile::OpenFromVdex(zip_fd_,
+ std::move(vdex),
+ oat_file_assistant_->dex_location_,
+ oat_file_assistant_->context_,
+ error_msg));
+}
- if (use_fd_) {
- if (oat_fd_ < 0 || vdex_fd_ < 0) {
- *error_msg = "oat_fd or vdex_fd not provided";
- return nullptr;
- }
- ArrayRef<const std::string> dex_locations(&oat_file_assistant_->dex_location_,
- /*size=*/1u);
- return std::unique_ptr<OatFile>(OatFile::Open(zip_fd_,
- vdex_fd_,
- oat_fd_,
- filename_,
- executable,
- /*low_4gb=*/false,
- dex_locations,
- /*dex_files=*/{},
- /*reservation=*/nullptr,
- error_msg));
- } else {
- return std::unique_ptr<OatFile>(OatFile::Open(/*zip_fd=*/-1,
- filename_,
- filename_,
- executable,
- /*low_4gb=*/false,
- oat_file_assistant_->dex_location_,
- error_msg));
- }
+std::unique_ptr<OatFile> OatFileAssistant::OatFileInfoBackedByDm::LoadFile(
+ std::string* error_msg) const {
+ // Check to see if there is a vdex file we can make use of.
+ std::unique_ptr<ZipArchive> dm_file(ZipArchive::Open(filename_.c_str(), error_msg));
+ if (dm_file == nullptr) {
+ return nullptr;
+ }
+ std::unique_ptr<VdexFile> vdex(VdexFile::OpenFromDm(filename_, *dm_file, error_msg));
+ if (vdex == nullptr) {
+ return nullptr;
}
+ return std::unique_ptr<OatFile>(OatFile::OpenFromVdex(/*zip_fd=*/-1,
+ std::move(vdex),
+ oat_file_assistant_->dex_location_,
+ oat_file_assistant_->context_,
+ error_msg));
}
bool OatFileAssistant::OatFileInfo::ShouldRecompileForFilter(CompilerFilter::Filter target,
@@ -1144,22 +1177,6 @@ bool OatFileAssistant::OatFileInfo::IsExecutable() {
return (file != nullptr && file->IsExecutable());
}
-void OatFileAssistant::OatFileInfo::Reset() {
- file_ = std::nullopt;
- status_ = std::nullopt;
-}
-
-void OatFileAssistant::OatFileInfo::Reset(
- const std::string& filename, bool use_fd, int zip_fd, int vdex_fd, int oat_fd) {
- filename_provided_ = true;
- filename_ = filename;
- use_fd_ = use_fd;
- zip_fd_ = zip_fd;
- vdex_fd_ = vdex_fd;
- oat_fd_ = oat_fd;
- Reset();
-}
-
std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFile() {
file_released_ = true;
return std::move(file_->first);
@@ -1296,7 +1313,7 @@ bool OatFileAssistant::ZipFileOnlyContainsUncompressedDex() {
OatFileAssistant::Location OatFileAssistant::GetLocation(OatFileInfo& info) {
if (info.IsUseable()) {
- if (&info == &dm_) {
+ if (info.GetType() == OatFileType::kDm) {
return kLocationDm;
} else if (info.IsOatLocation()) {
return kLocationOat;
diff --git a/runtime/oat/oat_file_assistant.h b/runtime/oat/oat_file_assistant.h
index 85021bea33..562bcde19b 100644
--- a/runtime/oat/oat_file_assistant.h
+++ b/runtime/oat/oat_file_assistant.h
@@ -25,6 +25,7 @@
#include <string_view>
#include <utility>
#include <variant>
+#include <vector>
#include "arch/instruction_set.h"
#include "base/compiler_filter.h"
@@ -183,6 +184,8 @@ class OatFileAssistant {
int oat_fd,
int zip_fd);
+ EXPORT ~OatFileAssistant();
+
// A convenient factory function that accepts ISA, class loader context, and compiler filter in
// strings. Returns the created instance and ClassLoaderContext on success, or returns nullptr and
// outputs an error message if it fails to parse the input strings.
@@ -296,6 +299,8 @@ class OatFileAssistant {
// ASLR. The odex file is treated as if it were read-only.
//
// Returns the status of the odex file for the dex location.
+ //
+ // For testing purposes only.
OatStatus OdexFileStatus();
// When the dex files is compiled on the target device, the oat file is the
@@ -303,6 +308,8 @@ class OatFileAssistant {
// (possibly-out-of-date) offset for ASLR.
//
// Returns the status of the oat file for the dex location.
+ //
+ // For testing purposes only.
OatStatus OatFileStatus();
OatStatus GetBestStatus() {
@@ -371,20 +378,34 @@ class OatFileAssistant {
/*out*/ std::string* error_msg);
private:
+ enum class OatFileType {
+ kNone,
+ kOat,
+ kVdex,
+ kDm,
+ };
+
class OatFileInfo {
public:
- // Initially the info is for no file in particular. It will treat the
- // file as out of date until Reset is called with a real filename to use
- // the cache for.
- // Pass true for is_oat_location if the information associated with this
- // OatFileInfo is for the oat location, as opposed to the odex location.
- OatFileInfo(OatFileAssistant* oat_file_assistant, bool is_oat_location);
+ // Empty info. Treated as kOatCannotOpen.
+ // Use constructors in subclasses to construct a real instance.
+ explicit OatFileInfo(OatFileAssistant* oat_file_assistant)
+ : oat_file_assistant_(oat_file_assistant), filename_(""), is_oat_location_(false) {}
+
+ virtual ~OatFileInfo() = default;
+
+ // ART code is compiled with `-fno-rtti`, so we need a virtual function to return type
+ // information.
+ virtual OatFileType GetType() { return OatFileType::kNone; }
- bool IsOatLocation();
+ // Returns a string indicating the location of the oat file, for debugging purposes only.
+ virtual const char* GetLocationDebugString() { return "none"; }
- const std::string* Filename();
+ bool IsOatLocation() const;
- const char* DisplayFilename();
+ const std::string* Filename() const;
+
+ const char* DisplayFilename() const;
// Returns true if this oat file can be used for running code. The oat
// file can be used for running code as long as it is not out of date with
@@ -404,7 +425,7 @@ class OatFileAssistant {
const DexOptTrigger dexopt_trigger);
// Returns true if the file exists.
- bool FileExists() const;
+ virtual bool FileExists() const;
// Returns the loaded file.
// Loads the file if needed. Returns null if the file failed to load.
@@ -415,18 +436,6 @@ class OatFileAssistant {
// Returns true if the file is opened executable.
bool IsExecutable();
- // Clear any cached information about the file that depends on the
- // contents of the file. This does not reset the provided filename.
- void Reset();
-
- // Clear any cached information and switch to getting info about the oat
- // file with the given filename.
- void Reset(const std::string& filename,
- bool use_fd,
- int zip_fd = -1,
- int vdex_fd = -1,
- int oat_fd = -1);
-
// Release the loaded oat file for runtime use.
// Returns null if the oat file hasn't been loaded or is out of date.
// Ensures the returned file is not loaded executable if it has unuseable
@@ -442,9 +451,27 @@ class OatFileAssistant {
// TODO(b/256664509): Clean this up.
bool CheckDisableCompactDex();
- private:
- std::unique_ptr<OatFile> LoadFile(std::string* error_msg) const;
+ protected:
+ // Constructs a real instance.
+ // Pass true for is_oat_location if the information associated with this
+ // OatFileInfo is for the oat location, as opposed to the odex location.
+ OatFileInfo(OatFileAssistant* oat_file_assistant,
+ const std::string& filename,
+ bool is_oat_location)
+ : oat_file_assistant_(oat_file_assistant),
+ filename_(filename),
+ is_oat_location_(is_oat_location) {}
+
+ // Loads the file.
+ virtual std::unique_ptr<OatFile> LoadFile(std::string* error_msg) const {
+ *error_msg = "Not implemented";
+ return nullptr;
+ }
+
+ OatFileAssistant* const oat_file_assistant_;
+ const std::string filename_;
+ private:
// Returns true if the oat file is usable but at least one dexopt trigger is matched. This
// function should only be called if the oat file is usable.
bool ShouldRecompileForFilter(CompilerFilter::Filter target,
@@ -458,17 +485,8 @@ class OatFileAssistant {
// the OatFileInfo object.
std::unique_ptr<OatFile> ReleaseFile();
- OatFileAssistant* oat_file_assistant_;
const bool is_oat_location_;
- bool filename_provided_ = false;
- std::string filename_;
-
- int zip_fd_ = -1;
- int oat_fd_ = -1;
- int vdex_fd_ = -1;
- bool use_fd_ = false;
-
// A pair of the loaded file and the error message, if `GetFile` has been attempted.
// `std::nullopt` if `GetFile` has not been attempted.
std::optional<std::pair<std::unique_ptr<OatFile>, std::string>> file_ = std::nullopt;
@@ -483,6 +501,82 @@ class OatFileAssistant {
bool file_released_ = false;
};
+ class OatFileInfoBackedByOat : public OatFileInfo {
+ public:
+ OatFileInfoBackedByOat(OatFileAssistant* oat_file_assistant,
+ const std::string& filename,
+ bool is_oat_location,
+ bool use_fd,
+ int zip_fd = -1,
+ int vdex_fd = -1,
+ int oat_fd = -1)
+ : OatFileInfo(oat_file_assistant, filename, is_oat_location),
+ use_fd_(use_fd),
+ zip_fd_(zip_fd),
+ vdex_fd_(vdex_fd),
+ oat_fd_(oat_fd) {}
+
+ OatFileType GetType() override { return OatFileType::kOat; }
+
+ const char* GetLocationDebugString() override {
+ return IsOatLocation() ? "odex in dalvik-cache" : "odex next to the dex file";
+ }
+
+ bool FileExists() const override;
+
+ protected:
+ std::unique_ptr<OatFile> LoadFile(std::string* error_msg) const override;
+
+ private:
+ const bool use_fd_;
+ const int zip_fd_;
+ const int vdex_fd_;
+ const int oat_fd_;
+ };
+
+ class OatFileInfoBackedByVdex : public OatFileInfo {
+ public:
+ OatFileInfoBackedByVdex(OatFileAssistant* oat_file_assistant,
+ const std::string& filename,
+ bool is_oat_location,
+ bool use_fd,
+ int zip_fd = -1,
+ int vdex_fd = -1)
+ : OatFileInfo(oat_file_assistant, filename, is_oat_location),
+ use_fd_(use_fd),
+ zip_fd_(zip_fd),
+ vdex_fd_(vdex_fd) {}
+
+ OatFileType GetType() override { return OatFileType::kVdex; }
+
+ const char* GetLocationDebugString() override {
+ return IsOatLocation() ? "vdex in dalvik-cache" : "vdex next to the dex file";
+ }
+
+ bool FileExists() const override;
+
+ protected:
+ std::unique_ptr<OatFile> LoadFile(std::string* error_msg) const override;
+
+ private:
+ const bool use_fd_;
+ const int zip_fd_;
+ const int vdex_fd_;
+ };
+
+ class OatFileInfoBackedByDm : public OatFileInfo {
+ public:
+ OatFileInfoBackedByDm(OatFileAssistant* oat_file_assistant, const std::string& filename)
+ : OatFileInfo(oat_file_assistant, filename, /*is_oat_location=*/false) {}
+
+ OatFileType GetType() override { return OatFileType::kDm; }
+
+ const char* GetLocationDebugString() override { return "dm"; }
+
+ protected:
+ std::unique_ptr<OatFile> LoadFile(std::string* error_msg) const override;
+ };
+
// Return info for the best oat file.
OatFileInfo& GetBestInfo();
@@ -564,21 +658,11 @@ class OatFileAssistant {
std::optional<std::string> cached_required_dex_checksums_error_;
bool required_dex_checksums_attempted_ = false;
- // The AOT-compiled file of an app when the APK of the app is in /data.
- OatFileInfo odex_;
- // The AOT-compiled file of an app when the APK of the app is on a read-only partition
- // (for example /system).
- OatFileInfo oat_;
-
- // The vdex-only file next to `odex_` when `odex_' cannot be used (for example
- // it is out of date).
- OatFileInfo vdex_for_odex_;
- // The vdex-only file next to 'oat_` when `oat_' cannot be used (for example
- // it is out of date).
- OatFileInfo vdex_for_oat_;
-
- // The vdex-only file next to the apk.
- OatFileInfo dm_;
+ // Empty oat file info, used as a placeholder.
+ OatFileInfo empty_info_ = OatFileInfo(this);
+
+ // Oat file info candidates, ordered by precedence.
+ std::vector<std::unique_ptr<OatFileInfo>> info_list_;
// File descriptor corresponding to apk, dex file, or zip.
int zip_fd_;