Make class loader context fail for unknown class loaders

Update OatFileAssistant to fail the class loader check when getting an
unknown (null) class loader. The code is only use in GetDexoptNeeded paths
and does not affect the runtime behaviour.

This will enable dexoptanalyzer to provide the right answer for dex files
whose class loader changes often.

Test: test-art-host
Bug: 147208643
Change-Id: I869109e669e68afe094e7703ed574575b98d7cc6
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index b411118..7454993 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -319,10 +319,10 @@
     }
 
     int dexoptNeeded = oat_file_assistant->GetDexOptNeeded(compiler_filter_,
-                                                           assume_profile_changed_,
-                                                           downgrade_,
                                                            class_loader_context.get(),
-                                                           context_fds_);
+                                                           context_fds_,
+                                                           assume_profile_changed_,
+                                                           downgrade_);
 
     // Convert OatFileAssitant codes to dexoptanalyzer codes.
     switch (dexoptNeeded) {
diff --git a/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc
index 65b5035..651fa4a 100644
--- a/dexoptanalyzer/dexoptanalyzer_test.cc
+++ b/dexoptanalyzer/dexoptanalyzer_test.cc
@@ -36,7 +36,7 @@
   int Analyze(const std::string& dex_file,
               CompilerFilter::Filter compiler_filter,
               bool assume_profile_changed,
-              const std::string& class_loader_context) {
+              const char* class_loader_context) {
     std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd();
     std::vector<std::string> argv_str;
     argv_str.push_back(dexoptanalyzer_cmd);
@@ -52,8 +52,8 @@
     argv_str.push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
     argv_str.push_back("--image=" + GetImageLocation());
     argv_str.push_back("--android-data=" + android_data_);
-    if (!class_loader_context.empty()) {
-      argv_str.push_back("--class-loader-context=" + class_loader_context);
+    if (class_loader_context != nullptr) {
+      argv_str.push_back("--class-loader-context=" + std::string(class_loader_context));
     }
 
     std::string error;
@@ -78,13 +78,19 @@
               CompilerFilter::Filter compiler_filter,
               bool assume_profile_changed = false,
               bool downgrade = false,
-              const std::string& class_loader_context = "") {
+              const char* class_loader_context = "PCL[]") {
     int dexoptanalyzerResult = Analyze(
         dex_file, compiler_filter, assume_profile_changed, class_loader_context);
     dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
     OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable=*/ false);
+    std::vector<int> context_fds;
+
+    std::unique_ptr<ClassLoaderContext> context = class_loader_context == nullptr
+        ? nullptr
+        : ClassLoaderContext::Create(class_loader_context);
+
     int assistantResult = oat_file_assistant.GetDexOptNeeded(
-        compiler_filter, assume_profile_changed, downgrade);
+        compiler_filter, context.get(), context_fds, assume_profile_changed, downgrade);
     EXPECT_EQ(assistantResult, dexoptanalyzerResult);
   }
 };
@@ -100,6 +106,7 @@
   Verify(dex_location, CompilerFilter::kExtract);
   Verify(dex_location, CompilerFilter::kQuicken);
   Verify(dex_location, CompilerFilter::kSpeedProfile);
+  Verify(dex_location, CompilerFilter::kSpeed, false, false, nullptr);
 }
 
 // Case: We have a DEX file and up-to-date OAT file for it.
@@ -112,6 +119,7 @@
   Verify(dex_location, CompilerFilter::kQuicken);
   Verify(dex_location, CompilerFilter::kExtract);
   Verify(dex_location, CompilerFilter::kEverything);
+  Verify(dex_location, CompilerFilter::kSpeed, false, false, nullptr);
 }
 
 // Case: We have a DEX file and speed-profile OAT file for it.
@@ -325,7 +333,6 @@
   // Generate the odex to get the class loader context also open the dex files.
   GenerateOdexForTest(dex_location1, odex_location1, CompilerFilter::kSpeed, /* compilation_reason= */ nullptr, /* extra_args= */ { class_loader_context_option });
 
-  Verify(dex_location1, CompilerFilter::kSpeed, false, false, class_loader_context);
+  Verify(dex_location1, CompilerFilter::kSpeed, false, false, class_loader_context.c_str());
 }
-
 }  // namespace art
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 37a524b..d2b5edf 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -576,10 +576,12 @@
     return OatFileAssistant::kNoDexOptNeeded;
   }
 
+  std::vector<int> context_fds;
   return oat_file_assistant.GetDexOptNeeded(filter,
+                                            context.get(),
+                                            context_fds,
                                             profile_changed,
-                                            downgrade,
-                                            context.get());
+                                            downgrade);
 }
 
 static jstring DexFile_getDexFileStatus(JNIEnv* env,
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 96df61e..f374883 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -185,16 +185,16 @@
 }
 
 int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target,
-                                      bool profile_changed,
-                                      bool downgrade,
                                       ClassLoaderContext* class_loader_context,
-                                      const std::vector<int>& context_fds) {
+                                      const std::vector<int>& context_fds,
+                                      bool profile_changed,
+                                      bool downgrade) {
   OatFileInfo& info = GetBestInfo();
   DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target,
-                                                    profile_changed,
-                                                    downgrade,
                                                     class_loader_context,
-                                                    context_fds);
+                                                    context_fds,
+                                                    profile_changed,
+                                                    downgrade);
   if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) {
     return dexopt_needed;
   }
@@ -797,10 +797,10 @@
 
 OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
     CompilerFilter::Filter target,
-    bool profile_changed,
-    bool downgrade,
     ClassLoaderContext* context,
-    const std::vector<int>& context_fds) {
+    const std::vector<int>& context_fds,
+    bool profile_changed,
+    bool downgrade) {
 
   bool filter_okay = CompilerFilterIsOkay(target, profile_changed, downgrade);
   bool class_loader_context_okay = ClassLoaderContextIsOkay(context, context_fds);
@@ -905,9 +905,12 @@
     return true;
   }
 
+
   if (context == nullptr) {
-    VLOG(oat) << "ClassLoaderContext check ignored: null context";
-    return true;
+    // TODO(calin): stop using null for the unkown contexts.
+    // b/148494302 introduces runtime encoding for unknown context which will make this possible.
+    VLOG(oat) << "ClassLoaderContext check failed: uknown(null) context";
+    return false;
   }
 
   size_t dir_index = oat_file_assistant_->dex_location_.rfind('/');
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index b5812f9..aa4d83b 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -144,10 +144,10 @@
   // the oat location. Returns a negative status code if the status refers to
   // the oat file in the odex location.
   int GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
+                      ClassLoaderContext* context,
+                      const std::vector<int>& context_fds,
                       bool profile_changed = false,
-                      bool downgrade = false,
-                      ClassLoaderContext* context = nullptr,
-                      const std::vector<int>& context_fds = std::vector<int>());
+                      bool downgrade = false);
 
   // Returns true if there is up-to-date code for this dex location,
   // irrespective of the compiler filter of the up-to-date code.
@@ -292,10 +292,10 @@
     // downgrade should be true if the purpose of dexopt is to downgrade the
     // compiler filter.
     DexOptNeeded GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
-                                 bool profile_changed,
-                                 bool downgrade,
                                  ClassLoaderContext* context,
-                                 const std::vector<int>& context_fds);
+                                 const std::vector<int>& context_fds,
+                                 bool profile_changed,
+                                 bool downgrade);
 
     // Returns the loaded file.
     // Loads the file if needed. Returns null if the file failed to load.
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 32ae42e..ed47ca3 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -62,6 +62,7 @@
       VerifyOptimizationStatus(
           file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
   }
+
   void InsertNewBootClasspathEntry() {
     std::string extra_dex_filename = GetMultiDexSrc1();
     Runtime* runtime = Runtime::Current();
@@ -70,6 +71,33 @@
       runtime->boot_class_path_locations_.push_back(extra_dex_filename);
     }
   }
+
+  int GetDexOptNeeded(OatFileAssistant* assistant,
+                      CompilerFilter::Filter compiler_filter,
+                      bool profile_changed) {
+    std::vector<int> context_fds;
+    return GetDexOptNeeded(assistant,
+        compiler_filter,
+        ClassLoaderContext::Default(),
+        context_fds,
+        profile_changed,
+        /*downgrade=*/ false);
+  }
+
+  int GetDexOptNeeded(
+      OatFileAssistant* assistant,
+      CompilerFilter::Filter compiler_filter,
+      const std::unique_ptr<ClassLoaderContext>& context = ClassLoaderContext::Default(),
+      const std::vector<int>& context_fds = std::vector<int>(),
+      bool profile_changed = false,
+      bool downgrade = false) {
+    return assistant->GetDexOptNeeded(
+        compiler_filter,
+        context.get(),
+        context_fds,
+        profile_changed,
+        downgrade);
+  }
 };
 
 class ScopedNonWritable {
@@ -189,11 +217,9 @@
   std::unique_ptr<ClassLoaderContext> relative_context =
       ClassLoaderContext::Create("PCL[ContextDex.jar]");
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(
+            GetDexOptNeeded(&oat_file_assistant,
                 CompilerFilter::kDefaultCompilerFilter,
-                /* profile_changed= */ false,
-                /* downgrade= */ false,
-                relative_context.get()));
+                relative_context));
 }
 
 // Case: We have a DEX file, but no OAT file for it.
@@ -205,13 +231,13 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -229,7 +255,7 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
 
   // Trying to get the best oat file should fail, but not crash.
@@ -250,13 +276,13 @@
       dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
 
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -282,13 +308,13 @@
       dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
 
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -317,13 +343,13 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -351,13 +377,13 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -392,13 +418,13 @@
                                       odex_fd.get(),
                                       zip_fd.get());
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -430,9 +456,9 @@
                                       /* oat_fd= */ -1,
                                       zip_fd.get());
   EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
@@ -464,7 +490,7 @@
                                       zip_fd.get());
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
@@ -487,7 +513,7 @@
                                       /* oat_fd= */ -1,
                                       zip_fd);
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
 }
@@ -513,7 +539,7 @@
   // depends on the boot image and is out of date with respect to the boot
   // image.
   EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   // Make sure we don't crash in this case when we dump the status. We don't
   // care what the actual dumped value is.
@@ -534,7 +560,7 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 }
 
 // Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
@@ -566,7 +592,7 @@
   // depends on the boot image and is out of date with respect to the boot
   // image.
   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 }
 
 // Case: We have a DEX file and speed-profile OAT file for it.
@@ -589,13 +615,13 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, false));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken, false));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, true));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken, true));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -621,7 +647,7 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 
   // Verify we can load both dex files.
@@ -657,7 +683,7 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 }
 
@@ -714,9 +740,9 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -738,7 +764,7 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 }
 
 // Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
@@ -755,7 +781,7 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 }
 
 // Case: We have a DEX file and an OAT file out of date with respect to the
@@ -779,11 +805,11 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -814,9 +840,9 @@
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -837,9 +863,9 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -867,7 +893,7 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
 
   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -903,11 +929,11 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,  // Compiling from the .vdex file
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -934,11 +960,11 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kQuicken));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -946,7 +972,7 @@
   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -969,7 +995,7 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-            oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+            GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -999,9 +1025,9 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
@@ -1141,7 +1167,7 @@
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
 }
@@ -1155,7 +1181,7 @@
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
@@ -1170,7 +1196,7 @@
   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
 
   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+      GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
@@ -1381,30 +1407,28 @@
 
   // Update the context by overriding the jar file.
   Copy(GetMultiDexSrc2(), context_location);
-  std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
-  ASSERT_TRUE(updated_context != nullptr);
 
   {
+    std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
+    ASSERT_TRUE(updated_context != nullptr);
     OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
     // DexOptNeeded should advise compilation from scratch when the context changes.
     EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
-              oat_file_assistant.GetDexOptNeeded(
+              GetDexOptNeeded(&oat_file_assistant,
                     CompilerFilter::kDefaultCompilerFilter,
-                    /* profile_changed= */ false,
-                    /* downgrade= */ false,
-                    updated_context.get()));
+                    updated_context));
   }
   {
+    std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
+    ASSERT_TRUE(updated_context != nullptr);
     OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
     // Now check that DexOptNeeded does not advise compilation if we only extracted the file.
     args.push_back("--compiler-filter=extract");
     ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
     EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-              oat_file_assistant.GetDexOptNeeded(
+              GetDexOptNeeded(&oat_file_assistant,
                     CompilerFilter::kExtract,
-                    /* profile_changed= */ false,
-                    /* downgrade= */ false,
-                    updated_context.get()));
+                    updated_context));
   }
 }