summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2022-06-24 23:14:24 +0100
committer Treehugger Robot <treehugger-gerrit@google.com> 2022-07-04 16:25:06 +0000
commitdbfa799b5e9d48a4f93410da37b199aaa8878d9b (patch)
tree485471e2addb3bf236cbd3459e0fe99a45598978
parent865006d268317b0ebd9e9a28671e8157e3983726 (diff)
Add a new version of `GetDexOptNeeded`.
The new version has two improvements: - It takes a bit field `DexOptTrigger` as an input instead of `profile_changed` and `downgrade`. The bit field gives the caller more flexibility to customize the conditions to trigger dexopt. - It returns the result in a more structured way: a boolean representing whether dexopt should be performed and an object containing whether the vdex file is usable and the location of the usable files. The old version is refactored so that it shares the same underlying logic with the new version. The behavior of the old version remains unchanged. Bug: 229268202 Test: m test-art-host-gtest-art_runtime_tests Change-Id: I2841b8b0494e1bc7e0a57f0690d817b67bde64dc Merged-In: I2841b8b0494e1bc7e0a57f0690d817b67bde64dc (cherry picked from commit af72f6cf8762bbebe472b8562df116efe4327a9c)
-rw-r--r--dex2oat/Android.bp3
-rw-r--r--dex2oat/dex2oat_vdex_test.cc19
-rw-r--r--dexoptanalyzer/Android.bp1
-rw-r--r--runtime/Android.bp2
-rw-r--r--runtime/dex2oat_environment_test.h21
-rw-r--r--runtime/oat_file_assistant.cc104
-rw-r--r--runtime/oat_file_assistant.h76
-rw-r--r--runtime/oat_file_assistant_test.cc844
8 files changed, 871 insertions, 199 deletions
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index 26cbd51459..e6116e9ae2 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -599,6 +599,9 @@ art_cc_test {
":art-gtest-jars-Nested",
":generate-boot-image",
],
+ shared_libs: [
+ "libziparchive",
+ ],
test_config: "art_standalone_dex2oat_cts_tests.xml",
test_suites: ["cts"],
}
diff --git a/dex2oat/dex2oat_vdex_test.cc b/dex2oat/dex2oat_vdex_test.cc
index 895e9c21e3..df76d58980 100644
--- a/dex2oat/dex2oat_vdex_test.cc
+++ b/dex2oat/dex2oat_vdex_test.cc
@@ -19,10 +19,8 @@
#include "common_runtime_test.h"
#include "dex2oat_environment_test.h"
-
#include "vdex_file.h"
#include "verifier/verifier_deps.h"
-#include "ziparchive/zip_writer.h"
namespace art {
@@ -113,23 +111,6 @@ class Dex2oatVdexTest : public Dex2oatEnvironmentTest {
return deps->GetVerifiedClasses(dex_file)[class_def_idx];
}
- void CreateDexMetadata(const std::string& vdex, const std::string& out_dm) {
- // Read the vdex bytes.
- std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex.c_str()));
- std::vector<uint8_t> data(vdex_file->GetLength());
- ASSERT_TRUE(vdex_file->ReadFully(data.data(), data.size()));
-
- // Zip the content.
- FILE* file = fopen(out_dm.c_str(), "wb");
- ZipWriter writer(file);
- writer.StartEntry("primary.vdex", ZipWriter::kAlign32);
- writer.WriteBytes(data.data(), data.size());
- writer.FinishEntry();
- writer.Finish();
- fflush(file);
- fclose(file);
- }
-
std::string GetFilename(const std::unique_ptr<const DexFile>& dex_file) {
const std::string& str = dex_file->GetLocation();
size_t idx = str.rfind('/');
diff --git a/dexoptanalyzer/Android.bp b/dexoptanalyzer/Android.bp
index 43953da901..66b0901c68 100644
--- a/dexoptanalyzer/Android.bp
+++ b/dexoptanalyzer/Android.bp
@@ -85,6 +85,7 @@ art_cc_defaults {
name: "art_dexoptanalyzer_tests_defaults",
shared_libs: [
"libunwindstack",
+ "libziparchive",
],
data: [
":art-gtest-jars-LinkageTest",
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 7390953121..c5cd7c57da 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -676,6 +676,7 @@ art_cc_defaults {
],
shared_libs: [
"libbase",
+ "libziparchive",
],
static_libs: [
"libprocinfo",
@@ -846,6 +847,7 @@ art_cc_defaults {
],
shared_libs: [
"libunwindstack",
+ "libziparchive",
],
header_libs: [
"art_cmdlineparser_headers", // For parsed_options_test.
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index 964b7f3fff..166464f28d 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -21,8 +21,6 @@
#include <string>
#include <vector>
-#include <gtest/gtest.h>
-
#include "base/file_utils.h"
#include "base/os.h"
#include "base/stl_util.h"
@@ -34,8 +32,10 @@
#include "exec_utils.h"
#include "gc/heap.h"
#include "gc/space/image_space.h"
+#include "gtest/gtest.h"
#include "oat_file_assistant.h"
#include "runtime.h"
+#include "ziparchive/zip_writer.h"
namespace art {
@@ -233,6 +233,23 @@ class Dex2oatEnvironmentTest : public CommonRuntimeTest {
return res.status_code;
}
+ void CreateDexMetadata(const std::string& vdex, const std::string& out_dm) {
+ // Read the vdex bytes.
+ std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex.c_str()));
+ std::vector<uint8_t> data(vdex_file->GetLength());
+ ASSERT_TRUE(vdex_file->ReadFully(data.data(), data.size()));
+
+ // Zip the content.
+ FILE* file = fopen(out_dm.c_str(), "wb");
+ ZipWriter writer(file);
+ writer.StartEntry("primary.vdex", ZipWriter::kAlign32);
+ writer.WriteBytes(data.data(), data.size());
+ writer.FinishEntry();
+ writer.Finish();
+ fflush(file);
+ fclose(file);
+ }
+
private:
std::string scratch_dir_;
std::string odex_oat_dir_;
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index b69d2af3f6..e111b27308 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -295,19 +295,70 @@ bool OatFileAssistant::IsInBootClassPath() {
return false;
}
-int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target,
+OatFileAssistant::DexOptTrigger OatFileAssistant::GetDexOptTrigger(
+ CompilerFilter::Filter target_compiler_filter [[gnu::unused]],
+ bool profile_changed,
+ bool downgrade) {
+ OatFileInfo& info = GetBestInfo();
+
+ if (!info.IsUseable()) {
+ // Essentially always recompile.
+ return OatFileAssistant::DexOptTrigger{.targetFilterIsBetter = true};
+ }
+
+ const OatFile* file = info.GetFile();
+ DCHECK(file != nullptr);
+
+ CompilerFilter::Filter current = file->GetCompilerFilter();
+ if (profile_changed && CompilerFilter::DependsOnProfile(current)) {
+ // Since the profile has been changed, we should re-compile even if the compilation does not
+ // make the compiler filter better.
+ return OatFileAssistant::DexOptTrigger{
+ .targetFilterIsBetter = true, .targetFilterIsSame = true, .targetFilterIsWorse = true};
+ }
+
+ if (downgrade) {
+ // The caller's intention is to downgrade the compiler filter. We should only re-compile if the
+ // target compiler filter is worse than the current one.
+ return OatFileAssistant::DexOptTrigger{.targetFilterIsWorse = true};
+ }
+
+ // This is the usual case. The caller's intention is to see if a better oat file can be generated.
+ return OatFileAssistant::DexOptTrigger{.targetFilterIsBetter = true,
+ .primaryBootImageBecomesUsable = true};
+}
+
+int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
bool profile_changed,
bool downgrade) {
OatFileInfo& info = GetBestInfo();
- DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target,
- profile_changed,
- downgrade);
+ DexOptNeeded dexopt_needed = info.GetDexOptNeeded(
+ target_compiler_filter, GetDexOptTrigger(target_compiler_filter, profile_changed, downgrade));
if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) {
return dexopt_needed;
}
return -dexopt_needed;
}
+bool OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
+ DexOptTrigger dexopt_trigger,
+ /*out*/ DexOptStatus* dexopt_status) {
+ OatFileInfo& info = GetBestInfo();
+ DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target_compiler_filter, dexopt_trigger);
+ if (info.IsUseable()) {
+ if (&info == &dm_for_oat_ || &info == &dm_for_odex_) {
+ dexopt_status->location_ = kLocationDm;
+ } else if (info.IsOatLocation()) {
+ dexopt_status->location_ = kLocationOat;
+ } else {
+ dexopt_status->location_ = kLocationOdex;
+ }
+ } else {
+ dexopt_status->location_ = kLocationNoneOrError;
+ }
+ return dexopt_needed != kNoDexOptNeeded;
+}
+
bool OatFileAssistant::IsUpToDate() {
return GetBestInfo().Status() == kOatUpToDate;
}
@@ -925,14 +976,16 @@ OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() {
}
OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
- CompilerFilter::Filter target,
- bool profile_changed,
- bool downgrade) {
-
+ CompilerFilter::Filter target_compiler_filter, const DexOptTrigger dexopt_trigger) {
if (IsUseable()) {
- return CompilerFilterIsOkay(target, profile_changed, downgrade)
- ? kNoDexOptNeeded
- : kDex2OatForFilter;
+ return ShouldRecompileForFilter(target_compiler_filter, dexopt_trigger) ? kDex2OatForFilter :
+ kNoDexOptNeeded;
+ }
+
+ // In this case, the oat file is not usable. If the caller doesn't seek for a better compiler
+ // filter (e.g., the caller wants to downgrade), then we should not recompile.
+ if (!dexopt_trigger.targetFilterIsBetter) {
+ return kNoDexOptNeeded;
}
if (Status() == kOatBootImageOutOfDate) {
@@ -1052,25 +1105,24 @@ const OatFile* OatFileAssistant::OatFileInfo::GetFile() {
return file_.get();
}
-bool OatFileAssistant::OatFileInfo::CompilerFilterIsOkay(
- CompilerFilter::Filter target, bool profile_changed, bool downgrade) {
+bool OatFileAssistant::OatFileInfo::ShouldRecompileForFilter(CompilerFilter::Filter target,
+ const DexOptTrigger dexopt_trigger) {
const OatFile* file = GetFile();
- if (file == nullptr) {
- return false;
- }
+ DCHECK(file != nullptr);
CompilerFilter::Filter current = file->GetCompilerFilter();
- if (profile_changed && CompilerFilter::DependsOnProfile(current)) {
- VLOG(oat) << "Compiler filter not okay because Profile changed";
- return false;
+ if (dexopt_trigger.targetFilterIsBetter && CompilerFilter::IsBetter(target, current)) {
+ return true;
}
-
- if (downgrade) {
- return !CompilerFilter::IsBetter(current, target);
+ if (dexopt_trigger.targetFilterIsSame && current == target) {
+ return true;
+ }
+ if (dexopt_trigger.targetFilterIsWorse && CompilerFilter::IsBetter(current, target)) {
+ return true;
}
- if (CompilerFilter::DependsOnImageChecksum(current) &&
- CompilerFilter::IsAsGoodAs(current, target)) {
+ if (dexopt_trigger.primaryBootImageBecomesUsable &&
+ CompilerFilter::DependsOnImageChecksum(current)) {
// If the oat file has been compiled without an image, and the runtime is
// now running with an image loaded from disk, return that we need to
// re-compile. The recompilation will generate a better oat file, and with an app
@@ -1081,11 +1133,11 @@ bool OatFileAssistant::OatFileInfo::CompilerFilterIsOkay(
!StartsWith(oat_boot_class_path_checksums, "i") &&
oat_file_assistant_->IsPrimaryBootImageUsable()) {
DCHECK(!file->GetOatHeader().RequiresImage());
- return false;
+ return true;
}
}
- return CompilerFilter::IsAsGoodAs(current, target);
+ return false;
}
bool OatFileAssistant::ClassLoaderContextIsOkay(const OatFile& oat_file) const {
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index abbd896c7b..e33d1853c8 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -112,6 +112,45 @@ class OatFileAssistant {
const std::string& apex_versions;
};
+ // A bit field to represent the conditions where dexopt should be performed.
+ struct DexOptTrigger {
+ // Dexopt should be performed if the target compiler filter is better than the current compiler
+ // filter. See `CompilerFilter::IsBetter`.
+ bool targetFilterIsBetter : 1;
+ // Dexopt should be performed if the target compiler filter is the same as the current compiler
+ // filter.
+ bool targetFilterIsSame : 1;
+ // Dexopt should be performed if the target compiler filter is worse than the current compiler
+ // filter. See `CompilerFilter::IsBetter`.
+ bool targetFilterIsWorse : 1;
+ // Dexopt should be performed if the current oat file was compiled without a primary image,
+ // and the runtime is now running with a primary image loaded from disk.
+ bool primaryBootImageBecomesUsable : 1;
+ };
+
+ // Represents the location of the current oat file and/or vdex file.
+ enum Location {
+ // Does not exist, or an error occurs.
+ kLocationNoneOrError = 0,
+ // In the global "dalvik-cache" folder.
+ kLocationOat = 1,
+ // In the "oat" folder next to the dex file.
+ kLocationOdex = 2,
+ // In the DM file. This means the only usable file is the vdex file.
+ kLocationDm = 3,
+ };
+
+ // Represents the status of the current oat file and/or vdex file.
+ class DexOptStatus {
+ public:
+ Location GetLocation() { return location_; }
+ bool IsVdexUsable() { return location_ != kLocationNoneOrError; }
+
+ private:
+ Location location_ = kLocationNoneOrError;
+ friend class OatFileAssistant;
+ };
+
// Constructs an OatFileAssistant object to assist the oat file
// corresponding to the given dex location with the target instruction set.
//
@@ -190,10 +229,18 @@ class OatFileAssistant {
// Returns a positive status code if the status refers to the oat file in
// the oat location. Returns a negative status code if the status refers to
// the oat file in the odex location.
+ //
+ // Deprecated. Use the other overload.
int GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
bool profile_changed = false,
bool downgrade = false);
+ // Returns true if dexopt needs to be performed with respect to the given target compilation
+ // filter and dexopt trigger. Also returns the status of the current oat file and/or vdex file.
+ bool GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
+ const DexOptTrigger dexopt_trigger,
+ /*out*/ DexOptStatus* dexopt_status);
+
// Returns true if there is up-to-date code for this dex location,
// irrespective of the compiler filter of the up-to-date code.
bool IsUpToDate();
@@ -354,15 +401,10 @@ class OatFileAssistant {
// Returns the status of this oat file.
OatStatus Status();
- // Return the DexOptNeeded value for this oat file with respect to the
- // given target_compilation_filter.
- // profile_changed should be true to indicate the profile has recently
- // changed for this dex location.
- // downgrade should be true if the purpose of dexopt is to downgrade the
- // compiler filter.
+ // Return the DexOptNeeded value for this oat file with respect to the given target compilation
+ // filter and dexopt trigger.
DexOptNeeded GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
- bool profile_changed,
- bool downgrade);
+ const DexOptTrigger dexopt_trigger);
// Returns the loaded file.
// Loads the file if needed. Returns null if the file failed to load.
@@ -395,13 +437,10 @@ class OatFileAssistant {
std::unique_ptr<OatFile> ReleaseFileForUse();
private:
- // Returns true if the compiler filter used to generate the file is at
- // least as good as the given target filter. profile_changed should be
- // true to indicate the profile has recently changed for this dex
- // location.
- // downgrade should be true if the purpose of dexopt is to downgrade the
- // compiler filter.
- bool CompilerFilterIsOkay(CompilerFilter::Filter target, bool profile_changed, bool downgrade);
+ // 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,
+ const DexOptTrigger dexopt_trigger);
// Release the loaded oat file.
// Returns null if the oat file hasn't been loaded.
@@ -471,6 +510,13 @@ class OatFileAssistant {
// Returns whether there is at least one boot image usable.
bool IsPrimaryBootImageUsable();
+ // Returns the trigger for the deprecated overload of `GetDexOptNeeded`.
+ //
+ // Deprecated. Do not use in new code.
+ DexOptTrigger GetDexOptTrigger(CompilerFilter::Filter target_compiler_filter,
+ bool profile_changed,
+ bool downgrade);
+
std::string dex_location_;
ClassLoaderContext* context_;
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 87fe2cb004..e6ab9ff2ed 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -20,6 +20,7 @@
#include <gtest/gtest.h>
#include <sys/param.h>
+#include <cmath>
#include <functional>
#include <memory>
#include <string>
@@ -113,15 +114,40 @@ class OatFileAssistantTest : public OatFileAssistantBaseTest,
}
}
- int GetDexOptNeeded(
- OatFileAssistant* assistant,
- CompilerFilter::Filter compiler_filter,
- bool profile_changed = false,
- bool downgrade = false) {
- return assistant->GetDexOptNeeded(
- compiler_filter,
- profile_changed,
- downgrade);
+ // Verifies the current version of `GetDexOptNeeded` (called from artd).
+ void VerifyGetDexOptNeeded(OatFileAssistant* assistant,
+ CompilerFilter::Filter compiler_filter,
+ OatFileAssistant::DexOptTrigger dexopt_trigger,
+ bool expected_dexopt_needed,
+ bool expected_is_vdex_usable,
+ OatFileAssistant::Location expected_location) {
+ OatFileAssistant::DexOptStatus status;
+ EXPECT_EQ(
+ assistant->GetDexOptNeeded(compiler_filter, dexopt_trigger, &status),
+ expected_dexopt_needed);
+ EXPECT_EQ(status.IsVdexUsable(), expected_is_vdex_usable);
+ EXPECT_EQ(status.GetLocation(), expected_location);
+ }
+
+ // Verifies all versions of `GetDexOptNeeded` with the default dexopt trigger.
+ void VerifyGetDexOptNeededDefault(OatFileAssistant* assistant,
+ CompilerFilter::Filter compiler_filter,
+ bool expected_dexopt_needed,
+ bool expected_is_vdex_usable,
+ OatFileAssistant::Location expected_location,
+ int expected_legacy_result) {
+ // Verify the current version (called from artd).
+ VerifyGetDexOptNeeded(assistant,
+ compiler_filter,
+ default_trigger_,
+ expected_dexopt_needed,
+ expected_is_vdex_usable,
+ expected_location);
+
+ // Verify the legacy version (called from PM).
+ EXPECT_EQ(
+ assistant->GetDexOptNeeded(compiler_filter, /*profile_changed=*/false, /*downgrade=*/false),
+ expected_legacy_result);
}
static std::unique_ptr<ClassLoaderContext> InitializeDefaultContext() {
@@ -177,6 +203,8 @@ class OatFileAssistantTest : public OatFileAssistantBaseTest,
std::unique_ptr<ClassLoaderContext> default_context_ = InitializeDefaultContext();
bool with_runtime_;
+ const OatFileAssistant::DexOptTrigger default_trigger_{.targetFilterIsBetter = true,
+ .primaryBootImageBecomesUsable = true};
};
class ScopedNonWritable {
@@ -306,8 +334,12 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
OatFileAssistant oat_file_assistant =
CreateOatFileAssistant(dex_location.c_str(), relative_context.get());
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kDefaultCompilerFilter));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kDefaultCompilerFilter,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
}
// Case: We have a DEX file, but no OAT file for it.
@@ -320,14 +352,30 @@ TEST_P(OatFileAssistantTest, DexNoOat) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile));
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -347,8 +395,12 @@ TEST_P(OatFileAssistantTest, NoDexNoOat) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
EXPECT_FALSE(oat_file_assistant.HasDexFiles());
// Trying to get the best oat file should fail, but not crash.
@@ -369,14 +421,30 @@ TEST_P(OatFileAssistantTest, OdexUpToDate) {
// Force the use of oat location by making the dex parent not writable.
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kEverything,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -403,14 +471,30 @@ TEST_P(OatFileAssistantTest, OdexUpToDatePartialBootImage) {
// Force the use of oat location by making the dex parent not writable.
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kEverything,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -441,14 +525,30 @@ TEST_P(OatFileAssistantTest, OdexUpToDateSymLink) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kEverything,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -477,14 +577,30 @@ TEST_P(OatFileAssistantTest, OatUpToDate) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kEverything,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -520,14 +636,30 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithFd) {
vdex_fd.get(),
odex_fd.get(),
zip_fd.get());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kEverything,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -559,12 +691,24 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
vdex_fd.get(),
/*oat_fd=*/-1,
zip_fd.get());
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kEverything,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -596,8 +740,12 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
odex_fd.get(),
zip_fd.get());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
@@ -621,8 +769,12 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
/*vdex_fd=*/-1,
/*oat_fd=*/-1,
zip_fd);
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
}
@@ -644,10 +796,18 @@ TEST_P(OatFileAssistantTest, VdexUpToDateNoOdex) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
// Make sure we don't crash in this case when we dump the status. We don't
// care what the actual dumped value is.
@@ -669,8 +829,12 @@ TEST_P(OatFileAssistantTest, EmptyVdexOdex) {
auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
}
// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
@@ -700,8 +864,12 @@ TEST_P(OatFileAssistantTest, VdexUpToDateNoOat) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatForFilter);
}
// Case: We have a DEX file and speed-profile OAT file for it.
@@ -725,14 +893,50 @@ TEST_P(OatFileAssistantTest, ProfileOatUpToDate) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ default_trigger_,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat);
+ EXPECT_EQ(
+ OatFileAssistant::kNoDexOptNeeded,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, /*profile_changed=*/false));
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ default_trigger_,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat);
EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, false));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify, false));
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, true));
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerify, /*profile_changed=*/false));
+
+ OatFileAssistant::DexOptTrigger profile_changed_trigger = default_trigger_;
+ profile_changed_trigger.targetFilterIsSame = true;
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ profile_changed_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat);
+ EXPECT_EQ(
+ OatFileAssistant::kDex2OatForFilter,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, /*profile_changed=*/true));
+
+ // We should not recompile even if `profile_changed` is true because the compiler filter should
+ // not be downgraded.
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ profile_changed_trigger,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat);
+ // The legacy implementation is wrong.
+ // TODO(jiakaiz): Fix it.
EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify, true));
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerify, /*profile_changed=*/true));
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -761,8 +965,12 @@ TEST_P(OatFileAssistantTest, MultiDexOatUpToDate) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str(),
/*context=*/nullptr,
/*load_executable=*/true);
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
EXPECT_TRUE(oat_file_assistant.HasDexFiles());
// Verify we can load both dex files.
@@ -801,8 +1009,12 @@ TEST_P(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
EXPECT_TRUE(oat_file_assistant.HasDexFiles());
}
@@ -829,10 +1041,18 @@ TEST_P(OatFileAssistantTest, OatDexOutOfDate) {
auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -858,8 +1078,12 @@ TEST_P(OatFileAssistantTest, VdexDexOutOfDate) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
}
// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
@@ -877,8 +1101,12 @@ TEST_P(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
}
// Case: We have a DEX file and an OAT file out of date with respect to the
@@ -903,12 +1131,24 @@ TEST_P(OatFileAssistantTest, OatImageOutOfDate) {
auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -971,10 +1211,18 @@ TEST_P(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOat,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -996,10 +1244,18 @@ TEST_P(OatFileAssistantTest, DexOdexNoOat) {
// Verify the status.
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -1023,20 +1279,36 @@ TEST_P(OatFileAssistantTest, ResourceOnlyDex) {
// Verify the status.
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
EXPECT_FALSE(oat_file_assistant.HasDexFiles());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -1062,8 +1334,12 @@ TEST_P(OatFileAssistantTest, OdexOatOverlap) {
/*context=*/nullptr,
/*load_executable=*/true);
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -1096,10 +1372,18 @@ TEST_P(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
// Verify the status.
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -1258,8 +1542,12 @@ TEST_P(OatFileAssistantTest, NonAbsoluteDexLocation) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
}
@@ -1274,8 +1562,12 @@ TEST_P(OatFileAssistantTest, ShortDexLocation) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
EXPECT_FALSE(oat_file_assistant.HasDexFiles());
@@ -1291,8 +1583,12 @@ TEST_P(OatFileAssistantTest, LongDexExtension) {
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError,
+ /*expected_legacy_result=*/OatFileAssistant::kDex2OatFromScratch);
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -1525,8 +1821,12 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
OatFileAssistant oat_file_assistant =
CreateOatFileAssistant(dex_location.c_str(), updated_context.get());
// DexOptNeeded should advise compilation for filter when the context changes.
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kDefaultCompilerFilter));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kDefaultCompilerFilter,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/-OatFileAssistant::kDex2OatForFilter);
}
{
std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
@@ -1541,8 +1841,12 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
OatFileAssistant oat_file_assistant =
CreateOatFileAssistant(dex_location.c_str(), updated_context.get());
// Now check that DexOptNeeded does not advise compilation if we only extracted the file.
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
}
{
std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
@@ -1557,11 +1861,277 @@ TEST_P(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
OatFileAssistant oat_file_assistant =
CreateOatFileAssistant(dex_location.c_str(), updated_context.get());
// Now check that DexOptNeeded does not advise compilation if we only verify the file.
- EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
+ VerifyGetDexOptNeededDefault(&oat_file_assistant,
+ CompilerFilter::kExtract,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex,
+ /*expected_legacy_result=*/OatFileAssistant::kNoDexOptNeeded);
}
}
+// Case: We have a DEX file and speed-profile ODEX file for it. The caller's intention is to
+// downgrade the compiler filter.
+// Expect: Dexopt should be performed only if the target compiler filter is worse than the current
+// one.
+TEST_P(OatFileAssistantTest, Downgrade) {
+ std::string dex_location = GetScratchDir() + "/TestDex.jar";
+ std::string odex_location = GetOdexDir() + "/TestDex.odex";
+ Copy(GetDexSrc1(), dex_location);
+ GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeedProfile);
+
+ auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
+
+ OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
+ OatFileAssistant::DexOptTrigger downgrade_trigger{.targetFilterIsWorse = true};
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ downgrade_trigger,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex);
+ EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kSpeed, /*profile_changed=*/false, /*downgrade=*/true));
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ downgrade_trigger,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex);
+ EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kSpeedProfile, /*profile_changed=*/false, /*downgrade=*/true));
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ downgrade_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex);
+ EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kVerify, /*profile_changed=*/false, /*downgrade=*/true));
+}
+
+// Case: We have a DEX file but we don't have an ODEX file for it. The caller's intention is to
+// downgrade the compiler filter.
+// Expect: Dexopt should never be performed regardless of the target compiler filter.
+// The legacy implementation is wrong.
+// TODO(jiakaiz): Fix it.
+TEST_P(OatFileAssistantTest, DowngradeNoOdex) {
+ std::string dex_location = GetScratchDir() + "/TestDex.jar";
+ Copy(GetDexSrc1(), dex_location);
+
+ auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
+
+ OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
+ OatFileAssistant::DexOptTrigger downgrade_trigger{.targetFilterIsWorse = true};
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ downgrade_trigger,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError);
+ EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kSpeed, /*profile_changed=*/false, /*downgrade=*/true));
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ downgrade_trigger,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError);
+ EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kSpeedProfile, /*profile_changed=*/false, /*downgrade=*/true));
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ downgrade_trigger,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError);
+ EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kVerify, /*profile_changed=*/false, /*downgrade=*/true));
+}
+
+// Case: We have a DEX file and speed-profile ODEX file for it. The legacy version is called with
+// both `profile_changed` and `downgrade` being true. This won't happen in the real case. Just to be
+// complete.
+// Expect: The behavior should be as `profile_changed` is false and `downgrade` is true.
+// The legacy implementation is wrong.
+// TODO(jiakaiz): Fix it.
+TEST_P(OatFileAssistantTest, ProfileChangedDowngrade) {
+ std::string dex_location = GetScratchDir() + "/TestDex.jar";
+ std::string odex_location = GetOdexDir() + "/TestDex.odex";
+ Copy(GetDexSrc1(), dex_location);
+ GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeedProfile);
+
+ auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
+
+ OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
+
+ EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kSpeed, /*profile_changed=*/true, /*downgrade=*/true));
+
+ EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kSpeedProfile, /*profile_changed=*/true, /*downgrade=*/true));
+
+ EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
+ oat_file_assistant.GetDexOptNeeded(
+ CompilerFilter::kVerify, /*profile_changed=*/true, /*downgrade=*/true));
+}
+
+// Case: We have a DEX file and speed-profile ODEX file for it. The caller's intention is to force
+// the compilation.
+// Expect: Dexopt should be performed regardless of the target compiler filter. The VDEX file is
+// usable.
+//
+// The legacy version does not support this case. Historically, Package Manager does not take the
+// result from OatFileAssistant for forced compilation. It uses an arbitrary non-zero value instead.
+// Therefore, we don't test the legacy version here.
+TEST_P(OatFileAssistantTest, Force) {
+ std::string dex_location = GetScratchDir() + "/TestDex.jar";
+ std::string odex_location = GetOdexDir() + "/TestDex.odex";
+ Copy(GetDexSrc1(), dex_location);
+ GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeedProfile);
+
+ auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
+
+ OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
+ OatFileAssistant::DexOptTrigger force_trigger{.targetFilterIsBetter = true,
+ .targetFilterIsSame = true,
+ .targetFilterIsWorse = true,
+ .primaryBootImageBecomesUsable = true};
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ force_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex);
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ force_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex);
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ force_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationOdex);
+}
+
+// Case: We have a DEX file but we don't have an ODEX file for it. The caller's intention is to
+// force the compilation.
+// Expect: Dexopt should be performed regardless of the target compiler filter. No VDEX file is
+// usable.
+//
+// The legacy version does not support this case. Historically, Package Manager does not take the
+// result from OatFileAssistant for forced compilation. It uses an arbitrary non-zero value instead.
+// Therefore, we don't test the legacy version here.
+TEST_P(OatFileAssistantTest, ForceNoOdex) {
+ std::string dex_location = GetScratchDir() + "/TestDex.jar";
+ Copy(GetDexSrc1(), dex_location);
+
+ auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
+
+ OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
+ OatFileAssistant::DexOptTrigger force_trigger{.targetFilterIsBetter = true,
+ .targetFilterIsSame = true,
+ .targetFilterIsWorse = true,
+ .primaryBootImageBecomesUsable = true};
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ force_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError);
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ force_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError);
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ force_trigger,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/false,
+ /*expected_location=*/OatFileAssistant::kLocationNoneOrError);
+}
+
+// Case: We have a DEX file and a DM file for it.
+// Expect: Dexopt should be performed if the compiler filter is better than "verify". The location
+// should be kLocationDm.
+//
+// The legacy version is wrong this case. It returns kDex2OatForFilter with an arbitrary sign if the
+// target compiler filter is better than "verify".
+// TODO(jiakaiz): Fix it.
+TEST_P(OatFileAssistantTest, DmUpToDate) {
+ std::string dex_location = GetScratchDir() + "/TestDex.jar";
+ std::string dm_location = GetScratchDir() + "/TestDex.dm";
+ std::string odex_location = GetOdexDir() + "/TestDex.odex";
+ std::string vdex_location = GetOdexDir() + "/TestDex.vdex";
+ Copy(GetDexSrc1(), dex_location);
+
+ // Generate temporary ODEX and VDEX files in order to create the DM file from.
+ GenerateOdexForTest(
+ dex_location, odex_location, CompilerFilter::kVerify, "install", {"--copy-dex-files=false"});
+
+ CreateDexMetadata(vdex_location, dm_location);
+
+ // Cleanup the temporary files.
+ ASSERT_EQ(0, unlink(odex_location.c_str()));
+ ASSERT_EQ(0, unlink(vdex_location.c_str()));
+
+ auto scoped_maybe_without_runtime = ScopedMaybeWithoutRuntime();
+
+ OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeed,
+ default_trigger_,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationDm);
+ EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
+ abs(oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)));
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kSpeedProfile,
+ default_trigger_,
+ /*expected_dexopt_needed=*/true,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationDm);
+ EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
+ abs(oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile)));
+
+ VerifyGetDexOptNeeded(&oat_file_assistant,
+ CompilerFilter::kVerify,
+ default_trigger_,
+ /*expected_dexopt_needed=*/false,
+ /*expected_is_vdex_usable=*/true,
+ /*expected_location=*/OatFileAssistant::kLocationDm);
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
+ abs(oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerify)));
+}
+
// Test that GetLocation of a dex file is the same whether the dex
// filed is backed by an oat file or not.
TEST_F(OatFileAssistantBaseTest, GetDexLocation) {