diff options
author | 2017-11-02 22:03:50 +0000 | |
---|---|---|
committer | 2017-11-02 22:03:50 +0000 | |
commit | ab13432123bc22c997f9dbb12596f05ce782561a (patch) | |
tree | 4908e0efa37fb7bc2abef12ad113de8cf9767697 | |
parent | 36ea6b4a6e76fa0507e81bfad7af311c93cec389 (diff) | |
parent | c12bf4c0b6e760f5f1e4255705ac5c3c90fa0c13 (diff) |
Merge "Add zip-fd support in dexoptanalyzer"
-rw-r--r-- | dexoptanalyzer/dexoptanalyzer.cc | 38 | ||||
-rw-r--r-- | runtime/base/file_magic.cc | 23 | ||||
-rw-r--r-- | runtime/base/file_magic.h | 3 | ||||
-rw-r--r-- | runtime/dex_file_loader.cc | 12 | ||||
-rw-r--r-- | runtime/dex_file_loader.h | 7 | ||||
-rw-r--r-- | runtime/oat_file_assistant.cc | 116 | ||||
-rw-r--r-- | runtime/oat_file_assistant.h | 24 | ||||
-rw-r--r-- | runtime/oat_file_assistant_test.cc | 65 |
8 files changed, 189 insertions, 99 deletions
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc index 7e9ecabed5..39c9b9993b 100644 --- a/dexoptanalyzer/dexoptanalyzer.cc +++ b/dexoptanalyzer/dexoptanalyzer.cc @@ -103,6 +103,8 @@ NO_RETURN static void Usage(const char *fmt, ...) { UsageError(""); UsageError(" --vdex-fd=number: file descriptor of the vdex file corresponding to the oat file"); UsageError(""); + UsageError(" --zip-fd=number: specifies a file descriptor corresponding to the dex file."); + UsageError(""); UsageError(" --downgrade: optional, if the purpose of dexopt is to downgrade the dex file"); UsageError(" By default, dexopt considers upgrade case."); UsageError(""); @@ -175,8 +177,19 @@ class DexoptAnalyzer FINAL { downgrade_ = true; } else if (option.starts_with("--oat-fd")) { oat_fd_ = std::stoi(option.substr(strlen("--oat-fd=")).ToString(), nullptr, 0); + if (oat_fd_ < 0) { + Usage("Invalid --oat-fd %d", oat_fd_); + } } else if (option.starts_with("--vdex-fd")) { vdex_fd_ = std::stoi(option.substr(strlen("--vdex-fd=")).ToString(), nullptr, 0); + if (vdex_fd_ < 0) { + Usage("Invalid --vdex-fd %d", vdex_fd_); + } + } else if (option.starts_with("--zip-fd")) { + zip_fd_ = std::stoi(option.substr(strlen("--zip-fd=")).ToString(), nullptr, 0); + if (zip_fd_ < 0) { + Usage("Invalid --zip-fd %d", zip_fd_); + } } else if (option.starts_with("--class-loader-context=")) { std::string context_str = option.substr(strlen("--class-loader-context=")).ToString(); class_loader_context_ = ClassLoaderContext::Create(context_str); @@ -199,12 +212,6 @@ class DexoptAnalyzer FINAL { Usage("--image unspecified and ANDROID_ROOT not set or image file does not exist."); } } - if (oat_fd_ > 0 && vdex_fd_ < 0) { - Usage("A valid --vdex-fd must also be provided with --oat-fd."); - } - if (oat_fd_ < 0 && vdex_fd_ > 0) { - Usage("A valid --oat-fd must also be provided with --vdex-fd."); - } } bool CreateRuntime() { @@ -248,17 +255,12 @@ class DexoptAnalyzer FINAL { std::unique_ptr<Runtime> runtime(Runtime::Current()); std::unique_ptr<OatFileAssistant> oat_file_assistant; - if (oat_fd_ != -1 && vdex_fd_ != -1) { - oat_file_assistant = std::make_unique<OatFileAssistant>(dex_file_.c_str(), - isa_, - false /*load_executable*/, - vdex_fd_, - oat_fd_); - } else { - oat_file_assistant = std::make_unique<OatFileAssistant>(dex_file_.c_str(), - isa_, - false /*load_executable*/); - } + oat_file_assistant = std::make_unique<OatFileAssistant>(dex_file_.c_str(), + isa_, + false /*load_executable*/, + vdex_fd_, + oat_fd_, + zip_fd_); // Always treat elements of the bootclasspath as up-to-date. // TODO(calin): this check should be in OatFileAssistant. if (oat_file_assistant->IsInBootClassPath()) { @@ -295,6 +297,8 @@ class DexoptAnalyzer FINAL { std::string image_; int oat_fd_ = -1; int vdex_fd_ = -1; + // File descriptor corresponding to apk, dex_file, or zip. + int zip_fd_ = -1; }; static int dexoptAnalyze(int argc, char** argv) { diff --git a/runtime/base/file_magic.cc b/runtime/base/file_magic.cc index 30b4f0559d..dffb9b43a1 100644 --- a/runtime/base/file_magic.cc +++ b/runtime/base/file_magic.cc @@ -37,19 +37,26 @@ File OpenAndReadMagic(const char* filename, uint32_t* magic, std::string* error_ *error_msg = StringPrintf("Unable to open '%s' : %s", filename, strerror(errno)); return File(); } - int n = TEMP_FAILURE_RETRY(read(fd.Fd(), magic, sizeof(*magic))); - if (n != sizeof(*magic)) { - *error_msg = StringPrintf("Failed to find magic in '%s'", filename); - return File(); - } - if (lseek(fd.Fd(), 0, SEEK_SET) != 0) { - *error_msg = StringPrintf("Failed to seek to beginning of file '%s' : %s", filename, - strerror(errno)); + if (!ReadMagicAndReset(fd.Fd(), magic, error_msg)) { + StringPrintf("Error in reading magic from file %s: %s", filename, error_msg->c_str()); return File(); } return fd; } +bool ReadMagicAndReset(int fd, uint32_t* magic, std::string* error_msg) { + int n = TEMP_FAILURE_RETRY(read(fd, magic, sizeof(*magic))); + if (n != sizeof(*magic)) { + *error_msg = StringPrintf("Failed to find magic"); + return false; + } + if (lseek(fd, 0, SEEK_SET) != 0) { + *error_msg = StringPrintf("Failed to seek to beginning of file : %s", strerror(errno)); + return false; + } + return true; +} + bool IsZipMagic(uint32_t magic) { return (('P' == ((magic >> 0) & 0xff)) && ('K' == ((magic >> 8) & 0xff))); diff --git a/runtime/base/file_magic.h b/runtime/base/file_magic.h index 1c9effdb50..e7bd706a5c 100644 --- a/runtime/base/file_magic.h +++ b/runtime/base/file_magic.h @@ -27,6 +27,9 @@ namespace art { // Open file and read magic number File OpenAndReadMagic(const char* filename, uint32_t* magic, std::string* error_msg); +// Read magic number and reset pointer to SEEK_SET. +bool ReadMagicAndReset(int fd, uint32_t* magic, std::string* error_msg); + // Check whether the given magic matches a known file type. bool IsZipMagic(uint32_t magic); diff --git a/runtime/dex_file_loader.cc b/runtime/dex_file_loader.cc index 06e3397754..bc9276985b 100644 --- a/runtime/dex_file_loader.cc +++ b/runtime/dex_file_loader.cc @@ -103,11 +103,19 @@ bool DexFileLoader::IsVersionAndMagicValid(const uint8_t* magic) { bool DexFileLoader::GetMultiDexChecksums(const char* filename, std::vector<uint32_t>* checksums, - std::string* error_msg) { + std::string* error_msg, + int zip_fd) { CHECK(checksums != nullptr); uint32_t magic; - File fd = OpenAndReadMagic(filename, &magic, error_msg); + File fd; + if (zip_fd != -1) { + if (ReadMagicAndReset(zip_fd, &magic, error_msg)) { + fd = File(zip_fd, false /* check_usage */); + } + } else { + fd = OpenAndReadMagic(filename, &magic, error_msg); + } if (fd.Fd() == -1) { DCHECK(!error_msg->empty()); return false; diff --git a/runtime/dex_file_loader.h b/runtime/dex_file_loader.h index 97c886ac7d..17631234b3 100644 --- a/runtime/dex_file_loader.h +++ b/runtime/dex_file_loader.h @@ -50,10 +50,15 @@ class DexFileLoader { // For .dex files, this is the single header checksum. // For zip files, this is the zip entry CRC32 checksum for classes.dex and // each additional multidex entry classes2.dex, classes3.dex, etc. + // If a valid zip_fd is provided the file content will be read directly from + // the descriptor and `filename` will be used as alias for error logging. If + // zip_fd is -1, the method will try to open the `filename` and read the + // content from it. // Return true if the checksums could be found, false otherwise. static bool GetMultiDexChecksums(const char* filename, std::vector<uint32_t>* checksums, - std::string* error_msg); + std::string* error_msg, + int zip_fd = -1); // Check whether a location denotes a multidex dex file. This is a very simple check: returns // whether the string contains the separator character. diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 9f6bf695f0..97b2aecd82 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -71,15 +71,34 @@ std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStat 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 @@ OatFileAssistant::OatFileAssistant(const char* dex_location, 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 @@ OatFileAssistant::OatFileAssistant(const char* dex_location, 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 @@ OatFileAssistant::~OatFileAssistant() { } } +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::ResultOfAttemptToUpdate 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 @@ const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums() { 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 @@ const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() { 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 @@ OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() { 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 @@ const OatFile* OatFileAssistant::OatFileInfo::GetFile() { 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 @@ void OatFileAssistant::OatFileInfo::Reset() { 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(); diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h index 44d8bd8ff3..6c01c1e880 100644 --- a/runtime/oat_file_assistant.h +++ b/runtime/oat_file_assistant.h @@ -121,9 +121,17 @@ class OatFileAssistant { // executable code for this dex location. OatFileAssistant(const char* dex_location, const InstructionSet isa, + bool load_executable); + + // Similar to this(const char*, const InstructionSet, bool), however, if a valid zip_fd is + // provided, vdex, oat, and zip files will be read from vdex_fd, oat_fd and zip_fd respectively. + // Otherwise, dex_location will be used to construct necessary filenames. + OatFileAssistant(const char* dex_location, + const InstructionSet isa, bool load_executable, - int vdex_fd = -1, - int oat_fd = -1); + int vdex_fd, + int oat_fd, + int zip_fd); ~OatFileAssistant(); @@ -351,7 +359,7 @@ class OatFileAssistant { // Clear any cached information and switch to getting info about the oat // file with the given filename. - void Reset(const std::string& filename, int vdex_fd = -1, int oat_fd = -1); + void Reset(const std::string& filename, bool use_fd, 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. @@ -390,6 +398,7 @@ class OatFileAssistant { int oat_fd_ = -1; int vdex_fd_ = -1; + bool use_fd_ = false; bool load_attempted_ = false; std::unique_ptr<OatFile> file_; @@ -420,6 +429,12 @@ class OatFileAssistant { // Return info for the best oat file. OatFileInfo& GetBestInfo(); + // Returns true when vdex/oat/odex files should be read from file descriptors. + // The method checks the value of zip_fd_, and if the value is valid, returns + // true. This is required to have a deterministic behavior around how different + // files are being read. + bool UseFdToReadFiles(); + // Returns true if the dex checksums in the given vdex file are up to date // with respect to the dex location. If the dex checksums are not up to // date, error_msg is updated with a message describing the problem. @@ -482,6 +497,9 @@ class OatFileAssistant { OatFileInfo odex_; OatFileInfo oat_; + // File descriptor corresponding to apk, dex file, or zip. + int zip_fd_; + // Cached value of the image info. // Use the GetImageInfo method rather than accessing these directly. // TODO: The image info should probably be moved out of the oat file diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index d12c331801..bd500ebe77 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -241,12 +241,14 @@ TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) { android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY)); android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY)); + android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY)); OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, vdex_fd.get(), - odex_fd.get()); + odex_fd.get(), + zip_fd.get()); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, @@ -262,12 +264,12 @@ TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) { EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } -// Case: Passing valid odex fd, however, invalid fd for vdex with -// the dex file. -// Expect: The status is kDex2oatFromScratch. -TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) { +// Case: Passing invalid odex fd and valid vdex and zip fds. +// Expect: The status should be kDex2OatForBootImage. +TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) { std::string dex_location = GetScratchDir() + "/OatUpToDate.jar"; std::string odex_location = GetScratchDir() + "/OatUpToDate.odex"; + std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex"; Copy(GetDexSrc1(), dex_location); GenerateOatForTest(dex_location.c_str(), @@ -277,26 +279,31 @@ TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) { false, false); - android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY)); + android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY)); + android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY)); OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, - -1, - odex_fd.get()); - EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, + vdex_fd.get(), + -1 /* oat_fd */, + zip_fd.get()); + EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); - EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); + EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage, + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); + + EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); + EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus()); EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } -// Case: Passing valid vdex fd, however, invalid fd for odex with -// the dex file. -// Expect: The status is kDex2oatFromScratch. -TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) { +// Case: Passing invalid vdex fd and valid odex and zip fds. +// Expect: The status should be kDex2OatFromScratch. +TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) { std::string dex_location = GetScratchDir() + "/OatUpToDate.jar"; std::string odex_location = GetScratchDir() + "/OatUpToDate.odex"; - std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex"; Copy(GetDexSrc1(), dex_location); GenerateOatForTest(dex_location.c_str(), @@ -306,36 +313,38 @@ TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) { false, false); - android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY)); + android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY)); + android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY)); OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, - vdex_fd.get(), - -1); - // Even though the vdex file is up to date, because we don't have the oat - // file, we can't know that the vdex depends on the boot image and is up to - // date with respect to the boot image. Instead we must assume the vdex file - // depends on the boot image and is out of date with respect to the boot - // image. - EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage, + -1 /* vdex_fd */, + odex_fd.get(), + zip_fd.get()); + + EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); - EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus()); + EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); + EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); } -// Case: Passing invalid vdex and odex fd with the dex file. +// Case: Passing invalid vdex and odex fd with valid zip fd. // Expect: The status is kDex2oatFromScratch. TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) { std::string dex_location = GetScratchDir() + "/OatUpToDate.jar"; Copy(GetDexSrc1(), dex_location); + android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY)); OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, - -1, - -1); + -1 /* vdex_fd */, + -1 /* oat_fd */, + zip_fd); EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); |