Add zip-fd support in dexoptanalyzer
Test: installd flow(manual), oat_file_assistant_test
(cherry-picked from commit 89455b30a30de68d389cef68748a01e13ea1356)
Bug: 67111829
Change-Id: Icf24c671ee060c75ba53932a7ccbe422e0ceb2e0
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 9f6bf69..97b2aec 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -71,15 +71,34 @@
OatFileAssistant::OatFileAssistant(const char* dex_location,
const InstructionSet isa,
+ bool load_executable)
+ : OatFileAssistant(dex_location,
+ isa, load_executable,
+ -1 /* vdex_fd */,
+ -1 /* oat_fd */,
+ -1 /* zip_fd */) {}
+
+
+OatFileAssistant::OatFileAssistant(const char* dex_location,
+ const InstructionSet isa,
bool load_executable,
int vdex_fd,
- int oat_fd)
+ int oat_fd,
+ int zip_fd)
: isa_(isa),
load_executable_(load_executable),
odex_(this, /*is_oat_location*/ false),
- oat_(this, /*is_oat_location*/ true) {
+ oat_(this, /*is_oat_location*/ true),
+ zip_fd_(zip_fd) {
CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
+ if (zip_fd < 0) {
+ CHECK_LE(oat_fd, 0) << "zip_fd must be provided with valid oat_fd. zip_fd=" << zip_fd
+ << " oat_fd=" << oat_fd;
+ CHECK_LE(vdex_fd, 0) << "zip_fd must be provided with valid vdex_fd. zip_fd=" << zip_fd
+ << " vdex_fd=" << vdex_fd;;
+ }
+
// Try to get the realpath for the dex location.
//
// This is OK with respect to dalvik cache naming scheme because we never
@@ -113,18 +132,20 @@
std::string error_msg;
std::string odex_file_name;
if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
- odex_.Reset(odex_file_name, vdex_fd, oat_fd);
+ odex_.Reset(odex_file_name, UseFdToReadFiles(), vdex_fd, oat_fd);
} else {
LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
}
- // Get the oat filename.
- std::string oat_file_name;
- if (DexLocationToOatFilename(dex_location_, isa_, &oat_file_name, &error_msg)) {
- oat_.Reset(oat_file_name);
- } else {
- LOG(WARNING) << "Failed to determine oat file name for dex location "
- << dex_location_ << ": " << error_msg;
+ if (!UseFdToReadFiles()) {
+ // Get the oat filename.
+ std::string oat_file_name;
+ if (DexLocationToOatFilename(dex_location_, isa_, &oat_file_name, &error_msg)) {
+ oat_.Reset(oat_file_name, false /* use_fd */);
+ } else {
+ LOG(WARNING) << "Failed to determine oat file name for dex location "
+ << dex_location_ << ": " << error_msg;
+ }
}
// Check if the dex directory is writable.
@@ -134,9 +155,11 @@
size_t pos = dex_location_.rfind('/');
if (pos == std::string::npos) {
LOG(WARNING) << "Failed to determine dex file parent directory: " << dex_location_;
- } else {
+ } else if (!UseFdToReadFiles()) {
+ // We cannot test for parent access when using file descriptors. That's ok
+ // because in this case we will always pick the odex file anyway.
std::string parent = dex_location_.substr(0, pos);
- if (access(parent.c_str(), W_OK) == 0 || oat_fd > 0) {
+ if (access(parent.c_str(), W_OK) == 0) {
dex_parent_writable_ = true;
} else {
VLOG(oat) << "Dex parent of " << dex_location_ << " is not writable: " << strerror(errno);
@@ -151,6 +174,10 @@
}
}
+bool OatFileAssistant::UseFdToReadFiles() {
+ return zip_fd_ >= 0;
+}
+
bool OatFileAssistant::IsInBootClassPath() {
// Note: We check the current boot class path, regardless of the ISA
// specified by the user. This is okay, because the boot class path should
@@ -237,6 +264,9 @@
OatFileAssistant::MakeUpToDate(bool profile_changed,
ClassLoaderContext* class_loader_context,
std::string* error_msg) {
+ // The method doesn't use zip_fd_ and directly opens dex files at dex_locations_.
+ CHECK_EQ(-1, zip_fd_) << "MakeUpToDate should not be called with zip_fd";
+
CompilerFilter::Filter target;
if (!GetRuntimeCompilerFilterOption(&target, error_msg)) {
return kUpdateNotAttempted;
@@ -869,7 +899,8 @@
std::string error_msg;
if (DexFileLoader::GetMultiDexChecksums(dex_location_.c_str(),
&cached_required_dex_checksums_,
- &error_msg)) {
+ &error_msg,
+ zip_fd_)) {
required_dex_checksums_found_ = true;
has_original_dex_files_ = true;
} else {
@@ -932,7 +963,7 @@
OatFileAssistant::OatFileInfo& OatFileAssistant::GetBestInfo() {
// TODO(calin): Document the side effects of class loading when
// running dalvikvm command line.
- if (dex_parent_writable_) {
+ if (dex_parent_writable_ || UseFdToReadFiles()) {
// If the parent of the dex file is writable it means that we can
// create the odex file. In this case we unconditionally pick the odex
// as the best oat file. This corresponds to the regular use case when
@@ -1021,26 +1052,28 @@
std::string error_msg;
std::string vdex_filename = GetVdexFilename(filename_);
std::unique_ptr<VdexFile> vdex;
- if (vdex_fd_ == -1) {
+ if (use_fd_) {
+ if (vdex_fd_ >= 0) {
+ struct stat s;
+ int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd_, &s));
+ if (rc == -1) {
+ error_msg = StringPrintf("Failed getting length of the vdex file %s.", strerror(errno));
+ } else {
+ vdex = VdexFile::Open(vdex_fd_,
+ s.st_size,
+ vdex_filename,
+ false /*writable*/,
+ false /*low_4gb*/,
+ false /* unquicken */,
+ &error_msg);
+ }
+ }
+ } else {
vdex = VdexFile::Open(vdex_filename,
false /*writeable*/,
false /*low_4gb*/,
false /*unquicken*/,
&error_msg);
- } else {
- struct stat s;
- int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd_, &s));
- if (rc == -1) {
- PLOG(WARNING) << "Failed getting length of vdex file";
- } else {
- vdex = VdexFile::Open(vdex_fd_,
- s.st_size,
- vdex_filename,
- false /*writable*/,
- false /*low_4gb*/,
- false /* unquicken */,
- &error_msg);
- }
}
if (vdex == nullptr) {
status_ = kOatCannotOpen;
@@ -1116,16 +1149,18 @@
load_attempted_ = true;
if (filename_provided_) {
std::string error_msg;
- if (oat_fd_ != -1 && vdex_fd_ != -1) {
- file_.reset(OatFile::Open(vdex_fd_,
- oat_fd_,
- filename_.c_str(),
- nullptr,
- nullptr,
- oat_file_assistant_->load_executable_,
- false /* low_4gb */,
- oat_file_assistant_->dex_location_.c_str(),
- &error_msg));
+ if (use_fd_) {
+ if (oat_fd_ >= 0 && vdex_fd_ >= 0) {
+ file_.reset(OatFile::Open(vdex_fd_,
+ oat_fd_,
+ filename_.c_str(),
+ nullptr,
+ nullptr,
+ oat_file_assistant_->load_executable_,
+ false /* low_4gb */,
+ oat_file_assistant_->dex_location_.c_str(),
+ &error_msg));
+ }
} else {
file_.reset(OatFile::Open(filename_.c_str(),
filename_.c_str(),
@@ -1203,10 +1238,11 @@
status_attempted_ = false;
}
-void OatFileAssistant::OatFileInfo::Reset(const std::string& filename, int vdex_fd,
+void OatFileAssistant::OatFileInfo::Reset(const std::string& filename, bool use_fd, int vdex_fd,
int oat_fd) {
filename_provided_ = true;
filename_ = filename;
+ use_fd_ = use_fd;
vdex_fd_ = vdex_fd;
oat_fd_ = oat_fd;
Reset();