Revert "Use compiler filter to determine oat file status."

Bots are red. Tentative reverting as this is likely the offender.

Bug: 27689078

This reverts commit a62d2f04a6ecf804f8a78e722a6ca8ccb2dfa931.

Change-Id: I3ec6947a5a4be878ff81f26f17dc36a209734e2a
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index f67da3f..426c3ca 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -186,7 +186,6 @@
   runtime/base/variant_map_test.cc \
   runtime/base/unix_file/fd_file_test.cc \
   runtime/class_linker_test.cc \
-  runtime/compiler_filter_test.cc \
   runtime/dex_file_test.cc \
   runtime/dex_file_verifier_test.cc \
   runtime/dex_instruction_test.cc \
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index 7c9ce1e..dd24220 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -109,7 +109,7 @@
     return false;
   }
   // Don't compile class initializers unless kEverything.
-  if ((compiler_options_->GetCompilerFilter() != CompilerFilter::kEverything) &&
+  if ((compiler_options_->GetCompilerFilter() != CompilerOptions::kEverything) &&
      ((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) {
     return false;
   }
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 1bd4c3a..f5969aa 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -52,7 +52,7 @@
   // because we don't want to include the PassManagerOptions definition from the header file.
 }
 
-CompilerOptions::CompilerOptions(CompilerFilter::Filter compiler_filter,
+CompilerOptions::CompilerOptions(CompilerFilter compiler_filter,
                                  size_t huge_method_threshold,
                                  size_t large_method_threshold,
                                  size_t small_method_threshold,
@@ -147,7 +147,25 @@
 bool CompilerOptions::ParseCompilerOption(const StringPiece& option, UsageFn Usage) {
   if (option.starts_with("--compiler-filter=")) {
     const char* compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
-    if (!CompilerFilter::ParseCompilerFilter(compiler_filter_string, &compiler_filter_)) {
+    if (strcmp(compiler_filter_string, "verify-none") == 0) {
+      compiler_filter_ = CompilerOptions::kVerifyNone;
+    } else if (strcmp(compiler_filter_string, "interpret-only") == 0) {
+      compiler_filter_ = CompilerOptions::kInterpretOnly;
+    } else if (strcmp(compiler_filter_string, "verify-at-runtime") == 0) {
+      compiler_filter_ = CompilerOptions::kVerifyAtRuntime;
+    } else if (strcmp(compiler_filter_string, "space") == 0) {
+      compiler_filter_ = CompilerOptions::kSpace;
+    } else if (strcmp(compiler_filter_string, "balanced") == 0) {
+      compiler_filter_ = CompilerOptions::kBalanced;
+    } else if (strcmp(compiler_filter_string, "speed") == 0) {
+      compiler_filter_ = CompilerOptions::kSpeed;
+    } else if (strcmp(compiler_filter_string, "everything") == 0) {
+      compiler_filter_ = CompilerOptions::kEverything;
+    } else if (strcmp(compiler_filter_string, "time") == 0) {
+      compiler_filter_ = CompilerOptions::kTime;
+    } else if (strcmp(compiler_filter_string, "verify-profile") == 0) {
+      compiler_filter_ = CompilerOptions::kVerifyProfile;
+    } else {
       Usage("Unknown --compiler-filter value %s", compiler_filter_string);
     }
   } else if (option == "--compile-pic") {
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index c67ab6e..11a4e06 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -22,7 +22,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "compiler_filter.h"
 #include "globals.h"
 #include "utils.h"
 
@@ -30,8 +29,20 @@
 
 class CompilerOptions FINAL {
  public:
+  enum CompilerFilter {
+    kVerifyNone,          // Skip verification and compile nothing except JNI stubs.
+    kInterpretOnly,       // Verify, and compile only JNI stubs.
+    kVerifyAtRuntime,     // Only compile JNI stubs and verify at runtime.
+    kSpace,               // Maximize space savings.
+    kBalanced,            // Try to get the best performance return on compilation investment.
+    kSpeed,               // Maximize runtime performance.
+    kEverything,          // Force compilation of everything capable of being compiled.
+    kTime,                // Compile methods, but minimize compilation time.
+    kVerifyProfile,       // Verify only the classes in the profile.
+  };
+
   // Guide heuristics to determine whether to compile method if profile data not available.
-  static const CompilerFilter::Filter kDefaultCompilerFilter = CompilerFilter::kSpeed;
+  static const CompilerFilter kDefaultCompilerFilter = kSpeed;
   static const size_t kDefaultHugeMethodThreshold = 10000;
   static const size_t kDefaultLargeMethodThreshold = 600;
   static const size_t kDefaultSmallMethodThreshold = 60;
@@ -53,7 +64,7 @@
   CompilerOptions();
   ~CompilerOptions();
 
-  CompilerOptions(CompilerFilter::Filter compiler_filter,
+  CompilerOptions(CompilerFilter compiler_filter,
                   size_t huge_method_threshold,
                   size_t large_method_threshold,
                   size_t small_method_threshold,
@@ -77,32 +88,40 @@
                   bool dump_cfg_append,
                   bool force_determinism);
 
-  CompilerFilter::Filter GetCompilerFilter() const {
+  CompilerFilter GetCompilerFilter() const {
     return compiler_filter_;
   }
 
-  void SetCompilerFilter(CompilerFilter::Filter compiler_filter) {
+  void SetCompilerFilter(CompilerFilter compiler_filter) {
     compiler_filter_ = compiler_filter;
   }
 
   bool VerifyAtRuntime() const {
-    return compiler_filter_ == CompilerFilter::kVerifyAtRuntime;
+    return compiler_filter_ == CompilerOptions::kVerifyAtRuntime;
   }
 
   bool IsCompilationEnabled() const {
-    return CompilerFilter::IsCompilationEnabled(compiler_filter_);
+    return compiler_filter_ != CompilerOptions::kVerifyNone &&
+           compiler_filter_ != CompilerOptions::kInterpretOnly &&
+           compiler_filter_ != CompilerOptions::kVerifyAtRuntime &&
+           compiler_filter_ != CompilerOptions::kVerifyProfile;
   }
 
   bool IsVerificationEnabled() const {
-    return CompilerFilter::IsVerificationEnabled(compiler_filter_);
+    return compiler_filter_ != CompilerOptions::kVerifyNone &&
+           compiler_filter_ != CompilerOptions::kVerifyAtRuntime;
   }
 
   bool NeverVerify() const {
-    return compiler_filter_ == CompilerFilter::kVerifyNone;
+    return compiler_filter_ == CompilerOptions::kVerifyNone;
+  }
+
+  bool IsExtractOnly() const {
+    return compiler_filter_ == CompilerOptions::kVerifyAtRuntime;
   }
 
   bool VerifyOnlyProfile() const {
-    return compiler_filter_ == CompilerFilter::kVerifyProfile;
+    return compiler_filter_ == CompilerOptions::kVerifyProfile;
   }
 
   size_t GetHugeMethodThreshold() const {
@@ -252,7 +271,7 @@
   void ParseLargeMethodMax(const StringPiece& option, UsageFn Usage);
   void ParseHugeMethodMax(const StringPiece& option, UsageFn Usage);
 
-  CompilerFilter::Filter compiler_filter_;
+  CompilerFilter compiler_filter_;
   size_t huge_method_threshold_;
   size_t large_method_threshold_;
   size_t small_method_threshold_;
@@ -298,6 +317,7 @@
 
   DISALLOW_COPY_AND_ASSIGN(CompilerOptions);
 };
+std::ostream& operator<<(std::ostream& os, const CompilerOptions::CompilerFilter& rhs);
 
 }  // namespace art
 
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 082d159..124afbc 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -145,8 +145,8 @@
 bool HGraphBuilder::SkipCompilation(const DexFile::CodeItem& code_item,
                                     size_t number_of_branches) {
   const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
-  CompilerFilter::Filter compiler_filter = compiler_options.GetCompilerFilter();
-  if (compiler_filter == CompilerFilter::kEverything) {
+  CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter();
+  if (compiler_filter == CompilerOptions::kEverything) {
     return false;
   }
 
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 125c00d..f1c5581 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -655,7 +655,7 @@
   // code units is bigger than 128.
   static constexpr size_t kSpaceFilterOptimizingThreshold = 128;
   const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
-  if ((compiler_options.GetCompilerFilter() == CompilerFilter::kSpace)
+  if ((compiler_options.GetCompilerFilter() == CompilerOptions::kSpace)
       && (code_item->insns_size_in_code_units_ > kSpaceFilterOptimizingThreshold)) {
     MaybeRecordStat(MethodCompilationStat::kNotCompiledSpaceFilter);
     return nullptr;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ec6f96f..ede0bda 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -257,14 +257,11 @@
                 "|verify-at-runtime"
                 "|verify-profile"
                 "|interpret-only"
-                "|time"
-                "|space-profile"
                 "|space"
                 "|balanced"
-                "|speed-profile"
                 "|speed"
-                "|everything-profile"
-                "|everything):");
+                "|everything"
+                "|time):");
   UsageError("      select compiler filter.");
   UsageError("      verify-profile requires a --profile(-fd) to also be passed in.");
   UsageError("      Example: --compiler-filter=everything");
@@ -801,6 +798,10 @@
       Usage("Profile file should not be specified with both --profile-file-fd and --profile-file");
     }
 
+    if (compiler_options_->VerifyOnlyProfile() && !have_profile_file && !have_profile_fd) {
+      Usage("verify-profile compiler filter must be used with a profile file or fd");
+    }
+
     if (!parser_options->oat_symbols.empty()) {
       oat_unstripped_ = std::move(parser_options->oat_symbols);
     }
@@ -833,14 +834,14 @@
     // time here, which is orthogonal to space.
     if (compiler_options_->inline_depth_limit_ == CompilerOptions::kUnsetInlineDepthLimit) {
       compiler_options_->inline_depth_limit_ =
-          (compiler_options_->compiler_filter_ == CompilerFilter::kSpace)
+          (compiler_options_->compiler_filter_ == CompilerOptions::kSpace)
           // Implementation of the space filter: limit inlining depth.
           ? CompilerOptions::kSpaceFilterInlineDepthLimit
           : CompilerOptions::kDefaultInlineDepthLimit;
     }
     if (compiler_options_->inline_max_code_units_ == CompilerOptions::kUnsetInlineMaxCodeUnits) {
       compiler_options_->inline_max_code_units_ =
-          (compiler_options_->compiler_filter_ == CompilerFilter::kSpace)
+          (compiler_options_->compiler_filter_ == CompilerOptions::kSpace)
           // Implementation of the space filter: limit inlining max code units.
           ? CompilerOptions::kSpaceFilterInlineMaxCodeUnits
           : CompilerOptions::kDefaultInlineMaxCodeUnits;
@@ -1028,8 +1029,11 @@
     key_value_store_->Put(
         OatHeader::kNativeDebuggableKey,
         compiler_options_->GetNativeDebuggable() ? OatHeader::kTrueValue : OatHeader::kFalseValue);
-    key_value_store_->Put(OatHeader::kCompilerFilter,
-        CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter()));
+    if (compiler_options_->IsExtractOnly()) {
+      key_value_store_->Put(OatHeader::kCompilationType, OatHeader::kExtractOnlyValue);
+    } else if (UseProfileGuidedCompilation()) {
+      key_value_store_->Put(OatHeader::kCompilationType, OatHeader::kProfileGuideCompiledValue);
+    }
   }
 
   // Parse the arguments from the command line. In case of an unrecognized option or impossible
@@ -1318,7 +1322,13 @@
         return false;
       }
 
-      if (CompilerFilter::DependsOnImageChecksum(compiler_options_->GetCompilerFilter())) {
+      if (compiler_options_->IsExtractOnly()) {
+        // ExtractOnly oat files only contain non-quickened DEX code and are
+        // therefore independent of the image file.
+        image_file_location_oat_checksum_ = 0u;
+        image_file_location_oat_data_begin_ = 0u;
+        image_patch_delta_ = 0;
+      } else {
         TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
         std::vector<gc::space::ImageSpace*> image_spaces =
             Runtime::Current()->GetHeap()->GetBootImageSpaces();
@@ -1335,10 +1345,6 @@
         if (!image_file_location.empty()) {
           key_value_store_->Put(OatHeader::kImageLocationKey, image_file_location);
         }
-      } else {
-        image_file_location_oat_checksum_ = 0u;
-        image_file_location_oat_data_begin_ = 0u;
-        image_patch_delta_ = 0;
       }
 
       // Open dex files for class path.
@@ -1450,7 +1456,7 @@
         num_methods += dex_file->NumMethodIds();
       }
       if (num_methods <= compiler_options_->GetNumDexMethodsThreshold()) {
-        compiler_options_->SetCompilerFilter(CompilerFilter::kSpeed);
+        compiler_options_->SetCompilerFilter(CompilerOptions::kSpeed);
         VLOG(compiler) << "Below method threshold, compiling anyways";
       }
     }
@@ -1851,7 +1857,7 @@
   }
 
   bool UseProfileGuidedCompilation() const {
-    return CompilerFilter::DependsOnProfile(compiler_options_->GetCompilerFilter());
+    return !profile_file_.empty() || (profile_file_fd_ != kInvalidFd);
   }
 
   bool LoadProfile() {
@@ -1859,7 +1865,7 @@
 
     profile_compilation_info_.reset(new ProfileCompilationInfo());
     ScopedFlock flock;
-    bool success = true;
+    bool success = false;
     std::string error;
     if (profile_file_fd_ != -1) {
       // The file doesn't need to be flushed so don't check the usage.
@@ -1868,7 +1874,7 @@
       if (flock.Init(&file, &error)) {
         success = profile_compilation_info_->Load(profile_file_fd_);
       }
-    } else if (profile_file_ != "") {
+    } else {
       if (flock.Init(profile_file_.c_str(), O_RDONLY, /* block */ true, &error)) {
         success = profile_compilation_info_->Load(flock.GetFile()->Fd());
       }
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 0c6541e..fc96acf 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -44,7 +44,6 @@
   class_table.cc \
   code_simulator_container.cc \
   common_throws.cc \
-  compiler_filter.cc \
   debugger.cc \
   dex_file.cc \
   dex_file_verifier.cc \
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index f58af5a..729957f 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -72,7 +72,7 @@
   filename_ = getenv("ANDROID_DATA");
   filename_ += "/TmpFile-XXXXXX";
   int fd = mkstemp(&filename_[0]);
-  CHECK_NE(-1, fd) << strerror(errno) << " for " << filename_;
+  CHECK_NE(-1, fd);
   file_.reset(new File(fd, GetFilename(), true));
 }
 
diff --git a/runtime/compiler_filter.cc b/runtime/compiler_filter.cc
deleted file mode 100644
index 31a1bc1..0000000
--- a/runtime/compiler_filter.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "compiler_filter.h"
-
-#include "utils.h"
-
-namespace art {
-
-bool CompilerFilter::IsCompilationEnabled(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kVerifyNone:
-    case CompilerFilter::kVerifyAtRuntime:
-    case CompilerFilter::kVerifyProfile:
-    case CompilerFilter::kInterpretOnly: return false;
-
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kBalanced:
-    case CompilerFilter::kTime:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverythingProfile:
-    case CompilerFilter::kEverything: return true;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::IsVerificationEnabled(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kVerifyNone:
-    case CompilerFilter::kVerifyAtRuntime: return false;
-
-    case CompilerFilter::kVerifyProfile:
-    case CompilerFilter::kInterpretOnly:
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kBalanced:
-    case CompilerFilter::kTime:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverythingProfile:
-    case CompilerFilter::kEverything: return true;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::DependsOnImageChecksum(Filter filter) {
-  // We run dex2dex with verification, so the oat file will depend on the
-  // image checksum if verification is enabled.
-  return IsVerificationEnabled(filter);
-}
-
-bool CompilerFilter::DependsOnProfile(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kVerifyNone:
-    case CompilerFilter::kVerifyAtRuntime:
-    case CompilerFilter::kInterpretOnly:
-    case CompilerFilter::kSpace:
-    case CompilerFilter::kBalanced:
-    case CompilerFilter::kTime:
-    case CompilerFilter::kSpeed:
-    case CompilerFilter::kEverything: return false;
-
-    case CompilerFilter::kVerifyProfile:
-    case CompilerFilter::kSpaceProfile:
-    case CompilerFilter::kSpeedProfile:
-    case CompilerFilter::kEverythingProfile: return true;
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::IsAsGoodAs(Filter current, Filter target) {
-  return current >= target;
-}
-
-std::string CompilerFilter::NameOfFilter(Filter filter) {
-  switch (filter) {
-    case CompilerFilter::kVerifyNone: return "verify-none";
-    case CompilerFilter::kVerifyAtRuntime: return "verify-at-runtime";
-    case CompilerFilter::kVerifyProfile: return "verify-profile";
-    case CompilerFilter::kInterpretOnly: return "interpret-only";
-    case CompilerFilter::kSpaceProfile: return "space-profile";
-    case CompilerFilter::kSpace: return "space";
-    case CompilerFilter::kBalanced: return "balanced";
-    case CompilerFilter::kTime: return "time";
-    case CompilerFilter::kSpeedProfile: return "speed-profile";
-    case CompilerFilter::kSpeed: return "speed";
-    case CompilerFilter::kEverythingProfile: return "everything-profile";
-    case CompilerFilter::kEverything: return "everything";
-  }
-  UNREACHABLE();
-}
-
-bool CompilerFilter::ParseCompilerFilter(const char* option, Filter* filter) {
-  CHECK(filter != nullptr);
-
-  if (strcmp(option, "verify-none") == 0) {
-    *filter = kVerifyNone;
-  } else if (strcmp(option, "interpret-only") == 0) {
-    *filter = kInterpretOnly;
-  } else if (strcmp(option, "verify-profile") == 0) {
-    *filter = kVerifyProfile;
-  } else if (strcmp(option, "verify-at-runtime") == 0) {
-    *filter = kVerifyAtRuntime;
-  } else if (strcmp(option, "space") == 0) {
-    *filter = kSpace;
-  } else if (strcmp(option, "space-profile") == 0) {
-    *filter = kSpaceProfile;
-  } else if (strcmp(option, "balanced") == 0) {
-    *filter = kBalanced;
-  } else if (strcmp(option, "speed") == 0) {
-    *filter = kSpeed;
-  } else if (strcmp(option, "speed-profile") == 0) {
-    *filter = kSpeedProfile;
-  } else if (strcmp(option, "everything") == 0) {
-    *filter = kEverything;
-  } else if (strcmp(option, "everything-profile") == 0) {
-    *filter = kEverythingProfile;
-  } else if (strcmp(option, "time") == 0) {
-    *filter = kTime;
-  } else {
-    return false;
-  }
-  return true;
-}
-
-std::ostream& operator<<(std::ostream& os, const CompilerFilter::Filter& rhs) {
-  return os << CompilerFilter::NameOfFilter(rhs);
-}
-
-}  // namespace art
diff --git a/runtime/compiler_filter.h b/runtime/compiler_filter.h
deleted file mode 100644
index 1bea8b4..0000000
--- a/runtime/compiler_filter.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_COMPILER_FILTER_H_
-#define ART_RUNTIME_COMPILER_FILTER_H_
-
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-
-namespace art {
-
-class CompilerFilter FINAL {
- public:
-  // Note: Order here matters. Later filter choices are considered "as good
-  // as" earlier filter choices.
-  enum Filter {
-    kVerifyNone,          // Skip verification and compile nothing except JNI stubs.
-    kVerifyAtRuntime,     // Only compile JNI stubs and verify at runtime.
-    kVerifyProfile,       // Verify only the classes in the profile.
-    kInterpretOnly,       // Verify, and compile only JNI stubs.
-    kTime,                // Compile methods, but minimize compilation time.
-    kSpaceProfile,        // Maximize space savings based on profile.
-    kSpace,               // Maximize space savings.
-    kBalanced,            // Good performance return on compilation investment.
-    kSpeedProfile,        // Maximize runtime performance based on profile.
-    kSpeed,               // Maximize runtime performance.
-    kEverythingProfile,   // Compile everything capable of being compiled based on profile.
-    kEverything,          // Compile everything capable of being compiled.
-  };
-
-  // Returns true if an oat file with this compiler filter contains
-  // compiled executable code.
-  static bool IsCompilationEnabled(Filter filter);
-
-  // Returns true if this compiler filter requires running verification.
-  static bool IsVerificationEnabled(Filter filter);
-
-  // Returns true if an oat file with this compiler filter depends on the
-  // boot image checksum.
-  static bool DependsOnImageChecksum(Filter filter);
-
-  // Returns true if an oat file with this compiler filter depends on a
-  // profile.
-  static bool DependsOnProfile(Filter filter);
-
-  // Returns true if the 'current' compiler filter is considered at least as
-  // good as the 'target' compilation type.
-  // For example: kSpeed is as good as kInterpretOnly, but kInterpretOnly is
-  // not as good as kSpeed.
-  static bool IsAsGoodAs(Filter current, Filter target);
-
-  // Return the flag name of the given filter.
-  // For example: given kVerifyAtRuntime, returns "verify-at-runtime".
-  // The name returned corresponds to the name accepted by
-  // ParseCompilerFilter.
-  static std::string NameOfFilter(Filter filter);
-
-  // Parse the compiler filter from the given name.
-  // Returns true and sets filter to the parsed value if name refers to a
-  // valid filter. Returns false if no filter matches that name.
-  // 'filter' must be non-null.
-  static bool ParseCompilerFilter(const char* name, /*out*/Filter* filter);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CompilerFilter);
-};
-
-std::ostream& operator<<(std::ostream& os, const CompilerFilter::Filter& rhs);
-
-}  // namespace art
-
-#endif  // ART_RUNTIME_COMPILER_FILTER_H_
diff --git a/runtime/compiler_filter_test.cc b/runtime/compiler_filter_test.cc
deleted file mode 100644
index c603be6..0000000
--- a/runtime/compiler_filter_test.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "compiler_filter.h"
-
-#include <gtest/gtest.h>
-
-namespace art {
-
-static void TestCompilerFilterName(CompilerFilter::Filter filter, std::string name) {
-  CompilerFilter::Filter parsed;
-  EXPECT_TRUE(CompilerFilter::ParseCompilerFilter(name.c_str(), &parsed));
-  EXPECT_EQ(filter, parsed);
-
-  EXPECT_EQ(name, CompilerFilter::NameOfFilter(filter));
-}
-
-// Verify the dexopt status values from dalvik.system.DexFile
-// match the OatFileAssistant::DexOptStatus values.
-TEST(CompilerFilterTest, ParseCompilerFilter) {
-  CompilerFilter::Filter filter;
-
-  TestCompilerFilterName(CompilerFilter::kVerifyNone, "verify-none");
-  TestCompilerFilterName(CompilerFilter::kVerifyAtRuntime, "verify-at-runtime");
-  TestCompilerFilterName(CompilerFilter::kVerifyProfile, "verify-profile");
-  TestCompilerFilterName(CompilerFilter::kInterpretOnly, "interpret-only");
-  TestCompilerFilterName(CompilerFilter::kTime, "time");
-  TestCompilerFilterName(CompilerFilter::kSpaceProfile, "space-profile");
-  TestCompilerFilterName(CompilerFilter::kSpace, "space");
-  TestCompilerFilterName(CompilerFilter::kBalanced, "balanced");
-  TestCompilerFilterName(CompilerFilter::kSpeedProfile, "speed-profile");
-  TestCompilerFilterName(CompilerFilter::kSpeed, "speed");
-  TestCompilerFilterName(CompilerFilter::kEverythingProfile, "everything-profile");
-  TestCompilerFilterName(CompilerFilter::kEverything, "everything");
-
-  EXPECT_FALSE(CompilerFilter::ParseCompilerFilter("super-awesome-filter", &filter));
-}
-
-}  // namespace art
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 3397989..f1e0fa7 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -348,8 +348,7 @@
 static jint GetDexOptNeeded(JNIEnv* env,
                             const char* filename,
                             const char* instruction_set,
-                            const char* compiler_filter_name,
-                            bool profile_changed) {
+                            const int target_compilation_type_mask) {
   if ((filename == nullptr) || !OS::FileExists(filename)) {
     LOG(ERROR) << "DexFile_getDexOptNeeded file '" << filename << "' does not exist";
     ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
@@ -366,24 +365,17 @@
     return -1;
   }
 
-  CompilerFilter::Filter filter;
-  if (!CompilerFilter::ParseCompilerFilter(compiler_filter_name, &filter)) {
-    ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
-    std::string message(StringPrintf("Compiler filter %s is invalid.", compiler_filter_name));
-    env->ThrowNew(iae.get(), message.c_str());
-    return -1;
-  }
-
   // TODO: Verify the dex location is well formed, and throw an IOException if
   // not?
-
-  OatFileAssistant oat_file_assistant(filename, target_instruction_set, profile_changed, false);
+  OatFileAssistant oat_file_assistant(filename, target_compilation_type_mask,
+      target_instruction_set, false);
 
   // Always treat elements of the bootclasspath as up-to-date.
   if (oat_file_assistant.IsInBootClassPath()) {
     return OatFileAssistant::kNoDexOptNeeded;
   }
-  return oat_file_assistant.GetDexOptNeeded(filter);
+
+  return oat_file_assistant.GetDexOptNeeded();
 }
 
 static jint DexFile_getDexOptNeeded(JNIEnv* env,
@@ -401,18 +393,10 @@
     return -1;
   }
 
-  // TODO: Take profile changed and compiler filter as arguments.
-  // For now, we use "speed" by default, unless EXTRACT_ONLY = 0x4 was
-  // included in the mask.
-  const char* compiler_filter = "speed";
-  if (javaTargetCompilationTypeMask & 0x4) {
-    compiler_filter = "verify-at-runtime";
-  }
   return GetDexOptNeeded(env,
                          filename.c_str(),
                          instruction_set.c_str(),
-                         compiler_filter,
-                         /*profile_changed*/false);
+                         javaTargetCompilationTypeMask);
 }
 
 // public API
@@ -423,8 +407,7 @@
       env,
       filename.c_str(),
       instruction_set,
-      "speed-profile",
-      /*profile_changed*/false);
+      OatFileAssistant::kFullCompilation | OatFileAssistant::kProfileGuideCompilation);
   return (status != OatFileAssistant::kNoDexOptNeeded) ? JNI_TRUE : JNI_FALSE;
 }
 
diff --git a/runtime/oat.cc b/runtime/oat.cc
index d13999a..ed99cba 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -29,6 +29,8 @@
 constexpr uint8_t OatHeader::kOatVersion[4];
 constexpr const char OatHeader::kTrueValue[];
 constexpr const char OatHeader::kFalseValue[];
+constexpr const char OatHeader::kExtractOnlyValue[];
+constexpr const char OatHeader::kProfileGuideCompiledValue[];
 
 static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
   size_t estimate = 0U;
@@ -470,13 +472,16 @@
   return IsKeyEnabled(OatHeader::kNativeDebuggableKey);
 }
 
-CompilerFilter::Filter OatHeader::GetCompilerFilter() const {
-  CompilerFilter::Filter filter;
-  const char* key_value = GetStoreValueByKey(kCompilerFilter);
-  CHECK(key_value != nullptr) << "compiler-filter not found in oat header";
-  CHECK(CompilerFilter::ParseCompilerFilter(key_value, &filter))
-      << "Invalid compiler-filter in oat header: " << key_value;
-  return filter;
+bool OatHeader::IsExtractOnly() const {
+  return KeyHasValue(kCompilationType,
+                     kExtractOnlyValue,
+                     sizeof(kExtractOnlyValue));
+}
+
+bool OatHeader::IsProfileGuideCompiled() const {
+  return KeyHasValue(kCompilationType,
+                     kProfileGuideCompiledValue,
+                     sizeof(kProfileGuideCompiledValue));
 }
 
 bool OatHeader::KeyHasValue(const char* key, const char* value, size_t value_size) const {
diff --git a/runtime/oat.h b/runtime/oat.h
index 0dcc52e..1d6c076 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -21,7 +21,6 @@
 
 #include "arch/instruction_set.h"
 #include "base/macros.h"
-#include "compiler_filter.h"
 #include "dex_file.h"
 #include "safe_map.h"
 
@@ -32,7 +31,7 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
-  static constexpr uint8_t kOatVersion[] = { '0', '7', '6', '\0' };
+  static constexpr uint8_t kOatVersion[] = { '0', '7', '5', '\0' };
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
@@ -40,12 +39,14 @@
   static constexpr const char* kPicKey = "pic";
   static constexpr const char* kDebuggableKey = "debuggable";
   static constexpr const char* kNativeDebuggableKey = "native-debuggable";
-  static constexpr const char* kCompilerFilter = "compiler-filter";
+  static constexpr const char* kCompilationType = "compilation-type";
   static constexpr const char* kClassPathKey = "classpath";
   static constexpr const char* kBootClassPath = "bootclasspath";
 
   static constexpr const char kTrueValue[] = "true";
   static constexpr const char kFalseValue[] = "false";
+  static constexpr const char kExtractOnlyValue[] = "extract-only";
+  static constexpr const char kProfileGuideCompiledValue[] = "profile-guide";
 
 
   static OatHeader* Create(InstructionSet instruction_set,
@@ -111,7 +112,8 @@
   bool IsPic() const;
   bool IsDebuggable() const;
   bool IsNativeDebuggable() const;
-  CompilerFilter::Filter GetCompilerFilter() const;
+  bool IsExtractOnly() const;
+  bool IsProfileGuideCompiled() const;
 
  private:
   bool KeyHasValue(const char* key, const char* value, size_t value_size) const;
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 9ae033f..033ea56 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1257,8 +1257,12 @@
   return GetOatHeader().IsDebuggable();
 }
 
-CompilerFilter::Filter OatFile::GetCompilerFilter() const {
-  return GetOatHeader().GetCompilerFilter();
+bool OatFile::IsExtractOnly() const {
+  return GetOatHeader().IsExtractOnly();
+}
+
+bool OatFile::IsProfileGuideCompiled() const {
+  return GetOatHeader().IsProfileGuideCompiled();
 }
 
 static constexpr char kDexClassPathEncodingSeparator = '*';
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 21aeab4..7af77ae 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -92,7 +92,9 @@
   // Indicates whether the oat file was compiled with full debugging capability.
   bool IsDebuggable() const;
 
-  CompilerFilter::Filter GetCompilerFilter() const;
+  bool IsExtractOnly() const;
+
+  bool IsProfileGuideCompiled() const;
 
   const std::string& GetLocation() const {
     return location_;
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 67c8e65..cbc0ec6 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -44,18 +44,19 @@
 namespace art {
 
 OatFileAssistant::OatFileAssistant(const char* dex_location,
+                                   const int target_compilation_type_mask,
                                    const InstructionSet isa,
-                                   bool profile_changed,
                                    bool load_executable)
-    : OatFileAssistant(dex_location, nullptr, isa, profile_changed, load_executable)
+    : OatFileAssistant(dex_location, nullptr, target_compilation_type_mask, isa, load_executable)
 { }
 
 OatFileAssistant::OatFileAssistant(const char* dex_location,
                                    const char* oat_location,
+                                   const int target_compilation_type_mask,
                                    const InstructionSet isa,
-                                   bool profile_changed,
                                    bool load_executable)
-    : isa_(isa), profile_changed_(profile_changed), load_executable_(load_executable) {
+    : target_compilation_type_mask_(target_compilation_type_mask), isa_(isa),
+      load_executable_(load_executable) {
   CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
   dex_location_.assign(dex_location);
 
@@ -115,78 +116,42 @@
   return true;
 }
 
-bool OatFileAssistant::OatFileCompilerFilterIsOkay(CompilerFilter::Filter target) {
-  const OatFile* oat_file = GetOatFile();
-  if (oat_file != nullptr) {
-    CompilerFilter::Filter current = oat_file->GetCompilerFilter();
-    return CompilerFilter::IsAsGoodAs(current, target);
-  }
-  return false;
+// Returns the compilation mode of the given oat file.
+static OatFileAssistant::CompilationType GetCompilationType(const OatFile& oat_file) {
+    if (oat_file.IsExtractOnly()) {
+      return OatFileAssistant::kExtractOnly;
+    }
+    if (oat_file.IsProfileGuideCompiled()) {
+      return OatFileAssistant::kProfileGuideCompilation;
+    }
+    // Assume that if the oat files is not extract-only or profile-guide compiled
+    // then it must be fully compiled.
+    // NB: this does not necessary mean that the oat file is actually fully compiled. It
+    // might have been compiled in a different way (e.g. interpret-only) which does
+    // not record a type in the header.
+    return OatFileAssistant::kFullCompilation;
 }
 
-bool OatFileAssistant::OdexFileCompilerFilterIsOkay(CompilerFilter::Filter target) {
-  const OatFile* odex_file = GetOdexFile();
-  if (odex_file != nullptr) {
-    CompilerFilter::Filter current = odex_file->GetCompilerFilter();
-    return CompilerFilter::IsAsGoodAs(current, target);
-  }
-  return false;
-}
-
-OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target) {
-  bool compilation_desired = CompilerFilter::IsCompilationEnabled(target);
-
-  // See if the oat file is in good shape as is.
-  bool oat_okay = OatFileCompilerFilterIsOkay(target);
-  if (oat_okay) {
-    if (compilation_desired) {
-      if (OatFileIsUpToDate()) {
-        return kNoDexOptNeeded;
-      }
-    } else {
-      if (!OatFileIsOutOfDate()) {
-        return kNoDexOptNeeded;
-      }
-    }
+OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded() {
+  if (OatFileIsUpToDate() || OdexFileIsUpToDate()) {
+    return kNoDexOptNeeded;
   }
 
-  // See if the odex file is in good shape as is.
-  bool odex_okay = OdexFileCompilerFilterIsOkay(target);
-  if (odex_okay) {
-    if (compilation_desired) {
-      if (OdexFileIsUpToDate()) {
-        return kNoDexOptNeeded;
-      }
-    } else {
-      if (!OdexFileIsOutOfDate()) {
-        return kNoDexOptNeeded;
-      }
-    }
+  if (OdexFileNeedsRelocation()) {
+    return kPatchOatNeeded;
   }
 
-  // See if we can get an up-to-date file by running patchoat.
-  if (compilation_desired) {
-    if (odex_okay && OdexFileNeedsRelocation()) {
-      // TODO: don't return kPatchOatNeeded if the odex file contains no
-      // patch information.
-      return kPatchOatNeeded;
-    }
-
-    if (oat_okay && OatFileNeedsRelocation()) {
-      // TODO: don't return kSelfPatchOatNeeded if the oat file contains no
-      // patch information.
-      return kSelfPatchOatNeeded;
-    }
+  if (OatFileNeedsRelocation()) {
+    return kSelfPatchOatNeeded;
   }
 
-  // We can only run dex2oat if there are original dex files.
   return HasOriginalDexFiles() ? kDex2OatNeeded : kNoDexOptNeeded;
 }
 
-bool OatFileAssistant::MakeUpToDate(CompilerFilter::Filter target, std::string* error_msg) {
-  switch (GetDexOptNeeded(target)) {
+bool OatFileAssistant::MakeUpToDate(std::string* error_msg) {
+  switch (GetDexOptNeeded()) {
     case kNoDexOptNeeded: return true;
-    case kDex2OatNeeded: return GenerateOatFile(target, error_msg);
+    case kDex2OatNeeded: return GenerateOatFile(error_msg);
     case kPatchOatNeeded: return RelocateOatFile(OdexFileName(), error_msg);
     case kSelfPatchOatNeeded: return RelocateOatFile(OatFileName(), error_msg);
   }
@@ -445,6 +410,11 @@
 }
 
 bool OatFileAssistant::GivenOatFileIsOutOfDate(const OatFile& file) {
+  // Verify the file satisfies the desired compilation type.
+  if ((target_compilation_type_mask_ & GetCompilationType(file)) == 0) {
+    return true;
+  }
+
   // Verify the dex checksum.
   // Note: GetOatDexFile will return null if the dex checksum doesn't match
   // what we provide, which verifies the primary dex checksum for us.
@@ -487,38 +457,36 @@
     }
   }
 
-  CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
-  VLOG(oat) << "Compiler filter for " << file.GetLocation() << " is " << current_compiler_filter;
+  if (file.IsExtractOnly()) {
+    VLOG(oat) << "Oat file is extract-only. Image checksum test skipped.";
+    if (kIsDebugBuild) {
+      // Sanity check that no classes have compiled code. Does not test that
+      // the DEX code has not been quickened.
+      std::string error_msg;
+      for (const OatFile::OatDexFile* current : file.GetOatDexFiles()) {
+        std::unique_ptr<const DexFile> dex_file = current->OpenDexFile(&error_msg);
+        DCHECK(dex_file != nullptr);
+        for (size_t i = 0, e = dex_file->NumClassDefs(); i < e; ++i) {
+          DCHECK_EQ(current->GetOatClass(i).GetType(), kOatClassNoneCompiled);
+        }
+      }
+    }
+    return false;
+  }
 
   // Verify the image checksum
-  if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
-    const ImageInfo* image_info = GetImageInfo();
-    if (image_info == nullptr) {
-      VLOG(oat) << "No image for oat image checksum to match against.";
-      return true;
-    }
-
-    if (file.GetOatHeader().GetImageFileLocationOatChecksum() != image_info->oat_checksum) {
-      VLOG(oat) << "Oat image checksum does not match image checksum.";
-      return true;
-    }
-  } else {
-    VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter;
+  const ImageInfo* image_info = GetImageInfo();
+  if (image_info == nullptr) {
+    VLOG(oat) << "No image for oat image checksum to match against.";
+    return true;
   }
 
-  // Verify the profile hasn't changed recently.
-  // TODO: Move this check to OatFileCompilerFilterIsOkay? Nothing bad should
-  // happen if we use an oat file compiled with an out-of-date profile.
-  if (CompilerFilter::DependsOnProfile(current_compiler_filter)) {
-    if (profile_changed_) {
-      VLOG(oat) << "The profile has changed recently.";
-      return true;
-    }
-  } else {
-    VLOG(oat) << "Profile check skipped for compiler filter " << current_compiler_filter;
+  if (file.GetOatHeader().GetImageFileLocationOatChecksum() != image_info->oat_checksum) {
+    VLOG(oat) << "Oat image checksum does not match image checksum.";
+    return true;
   }
 
-  // Everything looks good; the dex file is not out of date.
+  // The checksums are all good; the dex file is not out of date.
   return false;
 }
 
@@ -531,49 +499,40 @@
     return false;
   }
 
-  CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
+  if (file.IsPic() || file.IsExtractOnly()) {
+    // Oat files compiled in PIC mode do not require relocation and extract-only
+    // oat files do not contain any compiled code. Skip the relocation test.
+    VLOG(oat) << "Oat relocation test skipped.";
+    return true;
+  }
 
-  // Don't consider an oat file as up-to-date with compiled code unless
-  // compilation is enabled. This ensures we fall back to a non-executable oat
-  // file if there is no compiled code.
-  if (!CompilerFilter::IsCompilationEnabled(current_compiler_filter)) {
-    VLOG(oat) << "Compilation not enabled for " << current_compiler_filter;
+  const ImageInfo* image_info = GetImageInfo();
+  if (image_info == nullptr) {
+    VLOG(oat) << "No image to check oat relocation against.";
     return false;
   }
 
-  if (!file.IsPic()) {
-    const ImageInfo* image_info = GetImageInfo();
-    if (image_info == nullptr) {
-      VLOG(oat) << "No image to check oat relocation against.";
-      return false;
-    }
+  // Verify the oat_data_begin recorded for the image in the oat file matches
+  // the actual oat_data_begin for boot.oat in the image.
+  const OatHeader& oat_header = file.GetOatHeader();
+  uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
+  if (oat_data_begin != image_info->oat_data_begin) {
+    VLOG(oat) << file.GetLocation() <<
+      ": Oat file image oat_data_begin (" << oat_data_begin << ")"
+      << " does not match actual image oat_data_begin ("
+      << image_info->oat_data_begin << ")";
+    return false;
+  }
 
-    // Verify the oat_data_begin recorded for the image in the oat file matches
-    // the actual oat_data_begin for boot.oat in the image.
-    const OatHeader& oat_header = file.GetOatHeader();
-    uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
-    if (oat_data_begin != image_info->oat_data_begin) {
-      VLOG(oat) << file.GetLocation() <<
-        ": Oat file image oat_data_begin (" << oat_data_begin << ")"
-        << " does not match actual image oat_data_begin ("
-        << image_info->oat_data_begin << ")";
-      return false;
-    }
-
-    // Verify the oat_patch_delta recorded for the image in the oat file matches
-    // the actual oat_patch_delta for the image.
-    int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
-    if (oat_patch_delta != image_info->patch_delta) {
-      VLOG(oat) << file.GetLocation() <<
-        ": Oat file image patch delta (" << oat_patch_delta << ")"
-        << " does not match actual image patch delta ("
-        << image_info->patch_delta << ")";
-      return false;
-    }
-  } else {
-    // Oat files compiled in PIC mode do not require relocation and extract-only
-    // oat files do not contain any compiled code. Skip the relocation test.
-    VLOG(oat) << "Oat relocation test skipped for PIC oat file";
+  // Verify the oat_patch_delta recorded for the image in the oat file matches
+  // the actual oat_patch_delta for the image.
+  int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
+  if (oat_patch_delta != image_info->patch_delta) {
+    VLOG(oat) << file.GetLocation() <<
+      ": Oat file image patch delta (" << oat_patch_delta << ")"
+      << " does not match actual image patch delta ("
+      << image_info->patch_delta << ")";
+    return false;
   }
   return true;
 }
@@ -630,9 +589,18 @@
   return true;
 }
 
-bool OatFileAssistant::GenerateOatFile(CompilerFilter::Filter target, std::string* error_msg) {
+bool OatFileAssistant::GenerateOatFile(std::string* error_msg) {
   CHECK(error_msg != nullptr);
 
+  // TODO: Currently we only know how to make a fully-compiled oat file.
+  // Perhaps we should support generating other kinds of oat files?
+  if ((target_compilation_type_mask_ & kFullCompilation) == 0) {
+    *error_msg = "Generation of oat file for dex location " + dex_location_
+      + " not attempted because full compilation was not specified"
+      + " as an acceptable target compilation type.";
+    return false;
+  }
+
   Runtime* runtime = Runtime::Current();
   if (!runtime->IsDex2OatEnabled()) {
     *error_msg = "Generation of oat file for dex location " + dex_location_
@@ -674,7 +642,6 @@
   args.push_back("--dex-file=" + dex_location_);
   args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
   args.push_back("--oat-location=" + oat_file_name);
-  args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(target));
 
   if (!Dex2Oat(args, error_msg)) {
     // Manually delete the file. This ensures there is no garbage left over if
@@ -784,7 +751,8 @@
 
 std::string OatFileAssistant::DalvikCacheDirectory() {
   // Note: We don't cache this, because it will only be called once by
-  // OatFileName.
+  // OatFileName, and we don't care about the performance of the profiling
+  // code, which isn't used in practice.
 
   // TODO: The work done in GetDalvikCache is overkill for what we need.
   // Ideally a new API for getting the DalvikCacheDirectory the way we want
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 452cd84..893aea2 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -24,7 +24,6 @@
 #include "arch/instruction_set.h"
 #include "base/scoped_flock.h"
 #include "base/unix_file/fd_file.h"
-#include "compiler_filter.h"
 #include "oat_file.h"
 #include "os.h"
 #include "profiler.h"
@@ -86,6 +85,20 @@
     kOatUpToDate,
   };
 
+  // Represents the different compilation types of oat files that OatFileAssitant
+  // and external GetDexOptNeeded callers care about.
+  // Note: these should be able to be used as part of a mask.
+  enum CompilationType {
+    // Matches Java: dalvik.system.DexFile.COMPILATION_TYPE_FULL = 1
+    kFullCompilation = 1,
+
+    // Matches Java: dalvik.system.DexFile.COMPILATION_TYPE_PROFILE_GUIDE = 2
+    kProfileGuideCompilation = 2,
+
+    // Matches Java: dalvik.system.DexFile.COMPILATION_TYPE_EXTRACT_ONLY = 4
+    kExtractOnly = 4,
+  };
+
   // Constructs an OatFileAssistant object to assist the oat file
   // corresponding to the given dex location with the target instruction set.
   //
@@ -97,26 +110,27 @@
   // Note: Currently the dex_location must have an extension.
   // TODO: Relax this restriction?
   //
+  // The target compilation type specifies a set of CompilationTypes that
+  // should be considered up to date. An oat file compiled in a way not
+  // included in the set is considered out of date. For example, to consider
+  // otherwise up-to-date fully compiled and profile-guide compiled oat
+  // files as up to date, but to consider extract-only files as out of date,
+  // specify: (kFullCompilation | kProfileGuideCompilation).
+  //
   // The isa should be either the 32 bit or 64 bit variant for the current
   // device. For example, on an arm device, use arm or arm64. An oat file can
   // be loaded executable only if the ISA matches the current runtime.
-  //
-  // profile_changed should be true if the profile has recently changed
-  // for this dex location.
-  //
-  // load_executable should be true if the caller intends to try and load
-  // executable code for this dex location.
   OatFileAssistant(const char* dex_location,
+                   int target_compilation_type_mask,
                    const InstructionSet isa,
-                   bool profile_changed,
                    bool load_executable);
 
   // Constructs an OatFileAssistant, providing an explicit target oat_location
   // to use instead of the standard oat location.
   OatFileAssistant(const char* dex_location,
                    const char* oat_location,
+                   int target_compilation_type_mask,
                    const InstructionSet isa,
-                   bool profile_changed,
                    bool load_executable);
 
   ~OatFileAssistant();
@@ -144,18 +158,16 @@
   bool Lock(std::string* error_msg);
 
   // Return what action needs to be taken to produce up-to-date code for this
-  // dex location that is at least as good as an oat file generated with the
-  // given compiler filter.
-  DexOptNeeded GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter);
+  // dex location.
+  DexOptNeeded GetDexOptNeeded();
 
   // Attempts to generate or relocate the oat file as needed to make it up to
-  // date with in a way that is at least as good as an oat file generated with
-  // the given compiler filter.
+  // date.
   // Returns true on success.
   //
   // If there is a failure, the value of error_msg will be set to a string
   // describing why there was failure. error_msg must not be null.
-  bool MakeUpToDate(CompilerFilter::Filter target_compiler_filter, std::string* error_msg);
+  bool MakeUpToDate(std::string* error_msg);
 
   // Returns an oat file that can be used for loading dex files.
   // Returns null if no suitable oat file was found.
@@ -239,7 +251,7 @@
   // describing why there was failure. error_msg must not be null.
   bool RelocateOatFile(const std::string* input_file, std::string* error_msg);
 
-  // Generate the oat file from the dex file using the given compiler filter.
+  // Generate the oat file from the dex file.
   // This does not check the current status before attempting to generate the
   // oat file.
   // Returns true on success.
@@ -247,7 +259,7 @@
   //
   // If there is a failure, the value of error_msg will be set to a string
   // describing why there was failure. error_msg must not be null.
-  bool GenerateOatFile(CompilerFilter::Filter filter, std::string* error_msg);
+  bool GenerateOatFile(std::string* error_msg);
 
   // Executes dex2oat using the current runtime configuration overridden with
   // the given arguments. This does not check to see if dex2oat is enabled in
@@ -303,10 +315,6 @@
   // The caller shouldn't clean up or free the returned pointer.
   const OatFile* GetOdexFile();
 
-  // Returns true if the compiler filter used to generate the odex file is at
-  // least as good as the given target filter.
-  bool OdexFileCompilerFilterIsOkay(CompilerFilter::Filter target);
-
   // Returns true if the odex file is opened executable.
   bool OdexFileIsExecutable();
 
@@ -319,10 +327,6 @@
   // The caller shouldn't clean up or free the returned pointer.
   const OatFile* GetOatFile();
 
-  // Returns true if the compiler filter used to generate the oat file is at
-  // least as good as the given target filter.
-  bool OatFileCompilerFilterIsOkay(CompilerFilter::Filter target);
-
   // Returns true if the oat file is opened executable.
   bool OatFileIsExecutable();
 
@@ -342,14 +346,12 @@
   ScopedFlock flock_;
 
   std::string dex_location_;
+  const int target_compilation_type_mask_;
 
   // In a properly constructed OatFileAssistant object, isa_ should be either
   // the 32 or 64 bit variant for the current device.
   const InstructionSet isa_ = kNone;
 
-  // Whether the profile has recently changed.
-  bool profile_changed_ = false;
-
   // Whether we will attempt to load oat files executable.
   bool load_executable_ = false;
 
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index e5146ae..046d8ae 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -188,8 +188,7 @@
   // Generate a non-PIC odex file for the purposes of test.
   // The generated odex file will be un-relocated.
   void GenerateOdexForTest(const std::string& dex_location,
-                           const std::string& odex_location,
-                           CompilerFilter::Filter filter) {
+                           const std::string& odex_location) {
     // To generate an un-relocated odex file, we first compile a relocated
     // version of the file, then manually call patchoat to make it look as if
     // it is unrelocated.
@@ -197,12 +196,11 @@
     std::vector<std::string> args;
     args.push_back("--dex-file=" + dex_location);
     args.push_back("--oat-file=" + relocated_odex_location);
-    args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
+    args.push_back("--include-patch-information");
 
     // We need to use the quick compiler to generate non-PIC code, because
     // the optimizing compiler always generates PIC.
     args.push_back("--compiler-backend=Quick");
-    args.push_back("--include-patch-information");
 
     std::string error_msg;
     ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
@@ -229,25 +227,21 @@
                                                      dex_location.c_str(),
                                                      &error_msg));
     ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
-    EXPECT_FALSE(odex_file->IsPic());
-    EXPECT_EQ(filter, odex_file->GetCompilerFilter());
 
-    if (CompilerFilter::IsCompilationEnabled(filter)) {
-      const std::vector<gc::space::ImageSpace*> image_spaces =
+    const std::vector<gc::space::ImageSpace*> image_spaces =
         runtime->GetHeap()->GetBootImageSpaces();
-      ASSERT_TRUE(!image_spaces.empty() && image_spaces[0] != nullptr);
-      const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
-      const OatHeader& oat_header = odex_file->GetOatHeader();
-      EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum());
-      EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
-          oat_header.GetImageFileLocationOatDataBegin());
-      EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta());
-    }
+    ASSERT_TRUE(!image_spaces.empty() && image_spaces[0] != nullptr);
+    const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
+    const OatHeader& oat_header = odex_file->GetOatHeader();
+    EXPECT_FALSE(odex_file->IsPic());
+    EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum());
+    EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
+        oat_header.GetImageFileLocationOatDataBegin());
+    EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta());
   }
 
   void GeneratePicOdexForTest(const std::string& dex_location,
-                              const std::string& odex_location,
-                              CompilerFilter::Filter filter) {
+                              const std::string& odex_location) {
     // Temporarily redirect the dalvik cache so dex2oat doesn't find the
     // relocated image file.
     std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp";
@@ -255,7 +249,6 @@
     std::vector<std::string> args;
     args.push_back("--dex-file=" + dex_location);
     args.push_back("--oat-file=" + odex_location);
-    args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
     args.push_back("--compile-pic");
     args.push_back("--runtime-arg");
     args.push_back("-Xnorelocate");
@@ -274,7 +267,55 @@
                                                      &error_msg));
     ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
     EXPECT_TRUE(odex_file->IsPic());
-    EXPECT_EQ(filter, odex_file->GetCompilerFilter());
+  }
+
+  void GenerateExtractOnlyOdexForTest(const std::string& dex_location,
+                                      const std::string& odex_location) {
+    std::vector<std::string> args;
+    args.push_back("--dex-file=" + dex_location);
+    args.push_back("--oat-file=" + odex_location);
+    args.push_back("--compiler-filter=verify-at-runtime");
+    std::string error_msg;
+    ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
+
+    // Verify the odex file was generated as expected.
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+                                                     odex_location.c_str(),
+                                                     nullptr,
+                                                     nullptr,
+                                                     false,
+                                                     /*low_4gb*/false,
+                                                     dex_location.c_str(),
+                                                     &error_msg));
+    ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
+    EXPECT_TRUE(odex_file->IsExtractOnly());
+    EXPECT_EQ(odex_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0u);
+    EXPECT_EQ(odex_file->GetOatHeader().GetImageFileLocationOatDataBegin(), 0u);
+    EXPECT_EQ(odex_file->GetOatHeader().GetImagePatchDelta(), 0);
+  }
+
+  void GenerateProfileGuideOdexForTest(const std::string& dex_location,
+                                       const std::string& odex_location) {
+    std::vector<std::string> args;
+    args.push_back("--dex-file=" + dex_location);
+    args.push_back("--oat-file=" + odex_location);
+    ScratchFile profile_file;
+    args.push_back("--profile-file=" + profile_file.GetFilename());
+    std::string error_msg;
+    ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
+
+    // Verify the odex file was generated as expected.
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+                                                     odex_location.c_str(),
+                                                     nullptr,
+                                                     nullptr,
+                                                     false,
+                                                     /*low_4gb*/false,
+                                                     dex_location.c_str(),
+                                                     &error_msg));
+    printf("error %s", error_msg.c_str());
+    ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
+    EXPECT_TRUE(odex_file->IsProfileGuideCompiled());
   }
 
  private:
@@ -341,32 +382,12 @@
 
 // Generate an oat file for the purposes of test, as opposed to testing
 // generation of oat files.
-static void GenerateOatForTest(const char* dex_location, CompilerFilter::Filter filter) {
-  // Use an oat file assistant to find the proper oat location.
-  OatFileAssistant ofa(dex_location, kRuntimeISA, false, false);
-  const std::string* oat_location = ofa.OatFileName();
-  ASSERT_TRUE(oat_location != nullptr);
+static void GenerateOatForTest(const char* dex_location) {
+  OatFileAssistant oat_file_assistant(dex_location,
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
 
-  std::vector<std::string> args;
-  args.push_back("--dex-file=" + std::string(dex_location));
-  args.push_back("--oat-file=" + *oat_location);
-  args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
-  args.push_back("--runtime-arg");
-  args.push_back("-Xnorelocate");
   std::string error_msg;
-  ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
-
-  // Verify the oat file was generated as expected.
-  std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_location->c_str(),
-                                                  oat_location->c_str(),
-                                                  nullptr,
-                                                  nullptr,
-                                                  false,
-                                                  /*low_4gb*/false,
-                                                  dex_location,
-                                                  &error_msg));
-  ASSERT_TRUE(oat_file.get() != nullptr) << error_msg;
-  EXPECT_EQ(filter, oat_file->GetCompilerFilter());
+  ASSERT_TRUE(oat_file_assistant.GenerateOatFile(&error_msg)) << error_msg;
 }
 
 // Case: We have a DEX file, but no OAT file for it.
@@ -375,16 +396,10 @@
   std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
   Copy(GetDexSrc1(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
 
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
@@ -405,15 +420,15 @@
 TEST_F(OatFileAssistantTest, NoDexNoOat) {
   std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
 
   // Trying to make the oat file up to date should not fail or crash.
   std::string error_msg;
-  EXPECT_TRUE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg));
+  EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg));
 
   // Trying to get the best oat file should fail, but not crash.
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
@@ -425,19 +440,12 @@
 TEST_F(OatFileAssistantTest, OatUpToDate) {
   std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOatForTest(dex_location.c_str());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
-
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
   EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
@@ -450,68 +458,16 @@
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 }
 
-// Case: We have a DEX file and speed-profile OAT file for it.
-// Expect: The status is kNoDexOptNeeded if the profile hasn't changed.
-TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
-  std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
-  Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
-
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
-
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
-
-  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
-  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
-  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
-  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
-  EXPECT_TRUE(oat_file_assistant.OatFileExists());
-  EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
-  EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
-  EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
-  EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
-}
-
-// Case: We have a DEX file and speed-profile OAT file for it.
-// Expect: The status is kNoDex2OatNeeded if the profile has changed.
-TEST_F(OatFileAssistantTest, ProfileOatOutOfDate) {
-  std::string dex_location = GetScratchDir() + "/ProfileOatOutOfDate.jar";
-  Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
-
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true, false);
-
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
-
-  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
-  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
-  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
-  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
-  EXPECT_TRUE(oat_file_assistant.OatFileExists());
-  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
-  EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
-  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
-  EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OatFileStatus());
-  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
-}
-
 // Case: We have a MultiDEX file and up-to-date OAT file for it.
 // Expect: The status is kNoDexOptNeeded and we load all dex files.
 TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
   std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
   Copy(GetMultiDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOatForTest(dex_location.c_str());
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 
   // Verify we can load both dex files.
@@ -530,15 +486,15 @@
 
   // Compile code for GetMultiDexSrc1.
   Copy(GetMultiDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOatForTest(dex_location.c_str());
 
   // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
   // is out of date.
   Copy(GetMultiDexSrc2(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 }
 
@@ -557,7 +513,6 @@
   args.push_back("--dex-file=" + dex_location);
   args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
   args.push_back("--oat-file=" + oat_location);
-  args.push_back("--compiler-filter=speed");
 
   std::string error_msg;
   ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
@@ -565,7 +520,8 @@
   // Verify we can load both dex files.
   OatFileAssistant oat_file_assistant(dex_location.c_str(),
                                       oat_location.c_str(),
-                                      kRuntimeISA, false, true);
+                                      OatFileAssistant::kFullCompilation,
+                                      kRuntimeISA, true);
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
   EXPECT_TRUE(oat_file->IsExecutable());
@@ -582,14 +538,12 @@
   // We create a dex, generate an oat for it, then overwrite the dex with a
   // different dex to make the oat out of date.
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOatForTest(dex_location.c_str());
   Copy(GetDexSrc2(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
@@ -609,15 +563,13 @@
 
   // Create the dex and odex files
   Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location, odex_location);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
-  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
@@ -642,16 +594,16 @@
 
   // Create the dex and odex files
   Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location, odex_location);
 
   // Strip the dex file
   Copy(GetStrippedDexSrc1(), dex_location);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
-  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
@@ -664,10 +616,9 @@
 
   // Make the oat file up to date.
   std::string error_msg;
-  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
@@ -695,24 +646,20 @@
 
   // Create the oat file from a different dex file so it looks out of date.
   Copy(GetDexSrc2(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOatForTest(dex_location.c_str());
 
   // Create the odex file
   Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location, odex_location);
 
   // Strip the dex file.
   Copy(GetStrippedDexSrc1(), dex_location);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
-  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,  // Can't run dex2oat because dex file is stripped.
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
@@ -726,12 +673,9 @@
 
   // Make the oat file up to date.
   std::string error_msg;
-  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,  // Can't run dex2oat because dex file is stripped.
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
@@ -761,14 +705,10 @@
   Copy(GetStrippedDexSrc1(), dex_location);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
@@ -782,10 +722,9 @@
 
   // Make the oat file up to date. This should have no effect.
   std::string error_msg;
-  EXPECT_TRUE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+  EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
@@ -807,17 +746,12 @@
 
   // Create the dex and odex files
   Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, oat_location, CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location, oat_location);
 
   OatFileAssistant oat_file_assistant(dex_location.c_str(),
-      oat_location.c_str(), kRuntimeISA, false, true);
+      oat_location.c_str(), OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
-  EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+  EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
@@ -832,10 +766,9 @@
 
   // Make the oat file up to date.
   std::string error_msg;
-  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
@@ -866,7 +799,7 @@
 
   // Create the dex and odex files
   Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location, odex_location);
 
   // Create the oat file by copying the odex so they are located in the same
   // place in memory.
@@ -874,10 +807,9 @@
 
   // Verify things don't go bad.
   OatFileAssistant oat_file_assistant(dex_location.c_str(),
-      oat_location.c_str(), kRuntimeISA, false, true);
+      oat_location.c_str(), OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
-  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
@@ -906,15 +838,13 @@
 
   // Create the dex and odex files
   Copy(GetDexSrc1(), dex_location);
-  GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+  GeneratePicOdexForTest(dex_location, odex_location);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
@@ -926,28 +856,27 @@
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 }
 
-// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
-// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
-TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
-  std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
-  std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
+// Case: We have a DEX file and a ExtractOnly ODEX file, but no OAT file.
+// Expect: The status is kNoDexOptNeeded, because ExtractOnly contains no code.
+TEST_F(OatFileAssistantTest, DexExtractOnlyOdexNoOat) {
+  std::string dex_location = GetScratchDir() + "/DexExtractOnlyOdexNoOat.jar";
+  std::string odex_location = GetOdexDir() + "/DexExtractOnlyOdexNoOat.odex";
 
   // Create the dex and odex files
   Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime);
+  GenerateExtractOnlyOdexForTest(dex_location, odex_location);
 
   // Verify the status.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation | OatFileAssistant::kExtractOnly,
+      kRuntimeISA, false);
 
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_TRUE(oat_file_assistant.OdexFileExists());
   EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
-  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
+  EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate());
   EXPECT_FALSE(oat_file_assistant.OatFileExists());
   EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
   EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
@@ -960,10 +889,11 @@
   std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
 
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOatForTest(dex_location.c_str());
 
   // Load the oat using an oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -973,35 +903,17 @@
   EXPECT_EQ(1u, dex_files.size());
 }
 
-// Case: We have a DEX file and up-to-date non-executable OAT file for it.
-// Expect: We should load a non-executable dex file.
-TEST_F(OatFileAssistantTest, LoadNonExecOatUpToDate) {
-  std::string dex_location = GetScratchDir() + "/LoadNonExecOatUpToDate.jar";
-
-  Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kInterpretOnly);
-
-  // Load the oat using an oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
-
-  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
-  ASSERT_TRUE(oat_file.get() != nullptr);
-  EXPECT_FALSE(oat_file->IsExecutable());
-  std::vector<std::unique_ptr<const DexFile>> dex_files;
-  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
-  EXPECT_EQ(1u, dex_files.size());
-}
-
 // Case: We have a DEX file and up-to-date OAT file for it.
 // Expect: Loading non-executable should load the oat non-executable.
 TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
   std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
 
   Copy(GetDexSrc1(), dex_location);
-  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
+  GenerateOatForTest(dex_location.c_str());
 
   // Load the oat using an oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1021,9 +933,10 @@
   Copy(GetDexSrc1(), dex_location);
 
   OatFileAssistant oat_file_assistant(
-      dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true);
+      dex_location.c_str(), oat_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
   std::string error_msg;
-  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1035,7 +948,8 @@
   EXPECT_TRUE(OS::FileExists(oat_location.c_str()));
 
   // Verify it didn't create an oat in the default location.
-  OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant ofm(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
   EXPECT_FALSE(ofm.OatFileExists());
 }
 
@@ -1051,9 +965,10 @@
   Copy(GetDexSrc1(), dex_location);
 
   OatFileAssistant oat_file_assistant(
-      dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true);
+      dex_location.c_str(), oat_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
   std::string error_msg;
-  ASSERT_FALSE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg));
+  ASSERT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg));
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() == nullptr);
@@ -1066,9 +981,10 @@
   std::string oat_location = GetScratchDir() + "/GenNoDex.oat";
 
   OatFileAssistant oat_file_assistant(
-      dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true);
+      dex_location.c_str(), oat_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
   std::string error_msg;
-  ASSERT_FALSE(oat_file_assistant.GenerateOatFile(CompilerFilter::kSpeed, &error_msg));
+  ASSERT_FALSE(oat_file_assistant.GenerateOatFile(&error_msg));
 }
 
 // Turn an absolute path into a path relative to the current working
@@ -1114,11 +1030,11 @@
   Copy(GetDexSrc1(), abs_dex_location);
 
   std::string dex_location = MakePathRelative(abs_dex_location);
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
   EXPECT_FALSE(oat_file_assistant.OatFileExists());
   EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
@@ -1132,11 +1048,11 @@
 TEST_F(OatFileAssistantTest, ShortDexLocation) {
   std::string dex_location = "/xx";
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
-  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
   EXPECT_FALSE(oat_file_assistant.OatFileExists());
   EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
@@ -1147,7 +1063,7 @@
 
   // Trying to make it up to date should have no effect.
   std::string error_msg;
-  EXPECT_TRUE(oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg));
+  EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg));
   EXPECT_TRUE(error_msg.empty());
 }
 
@@ -1157,10 +1073,10 @@
   std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
   Copy(GetDexSrc1(), dex_location);
 
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
 
-  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
-      oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
 
   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   EXPECT_FALSE(oat_file_assistant.OdexFileExists());
@@ -1252,10 +1168,11 @@
 
   // Create the dex and odex files
   Copy(GetDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location, odex_location);
 
   // Load the oat using an executable oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1274,10 +1191,11 @@
 
   // Create the dex and odex files
   Copy(GetMultiDexSrc1(), dex_location);
-  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
+  GenerateOdexForTest(dex_location, odex_location);
 
   // Load the oat using an executable oat file assistant.
-  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true);
+  OatFileAssistant oat_file_assistant(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, true);
 
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1305,6 +1223,45 @@
         "/foo/bar/baz_noext", kArm, &odex_file, &error_msg));
 }
 
+// Case: We have a DEX file, extract-only ODEX, and fully compiled OAT.
+// Expect: The status depends on the target compilation type mask.
+TEST_F(OatFileAssistantTest, TargetCompilationType) {
+  std::string dex_location = GetScratchDir() + "/TargetCompilationType.jar";
+  std::string odex_location = GetOdexDir() + "/TargetCompilationType.odex";
+  Copy(GetDexSrc1(), dex_location);
+  GenerateExtractOnlyOdexForTest(dex_location, odex_location);
+  GenerateOatForTest(dex_location.c_str());
+
+  OatFileAssistant ofa_full(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation, kRuntimeISA, false);
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, ofa_full.GetDexOptNeeded());
+  EXPECT_FALSE(ofa_full.IsInBootClassPath());
+  EXPECT_TRUE(ofa_full.OdexFileIsOutOfDate());
+  EXPECT_TRUE(ofa_full.OatFileIsUpToDate());
+
+  OatFileAssistant ofa_extract(dex_location.c_str(),
+      OatFileAssistant::kExtractOnly, kRuntimeISA, false);
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, ofa_extract.GetDexOptNeeded());
+  EXPECT_FALSE(ofa_extract.IsInBootClassPath());
+  EXPECT_TRUE(ofa_extract.OdexFileIsUpToDate());
+  EXPECT_TRUE(ofa_extract.OatFileIsOutOfDate());
+
+  OatFileAssistant ofa_profile(dex_location.c_str(),
+      OatFileAssistant::kProfileGuideCompilation, kRuntimeISA, false);
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, ofa_profile.GetDexOptNeeded());
+  EXPECT_FALSE(ofa_profile.IsInBootClassPath());
+  EXPECT_TRUE(ofa_profile.OdexFileIsOutOfDate());
+  EXPECT_TRUE(ofa_profile.OatFileIsOutOfDate());
+
+  OatFileAssistant ofa_extract_full(dex_location.c_str(),
+      OatFileAssistant::kFullCompilation | OatFileAssistant::kExtractOnly,
+      kRuntimeISA, false);
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, ofa_extract_full.GetDexOptNeeded());
+  EXPECT_FALSE(ofa_extract_full.IsInBootClassPath());
+  EXPECT_TRUE(ofa_extract_full.OdexFileIsUpToDate());
+  EXPECT_TRUE(ofa_extract_full.OatFileIsUpToDate());
+}
+
 // Verify the dexopt status values from dalvik.system.DexFile
 // match the OatFileAssistant::DexOptStatus values.
 TEST_F(OatFileAssistantTest, DexOptStatusValues) {
@@ -1339,12 +1296,28 @@
   ASSERT_FALSE(self_patchoat_needed == nullptr);
   EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, self_patchoat_needed->GetInt(dexfile.Get()));
+
+    ArtField* compilation_type_full = mirror::Class::FindStaticField(
+      soa.Self(), dexfile, "COMPILATION_TYPE_FULL", "I");
+  ASSERT_FALSE(compilation_type_full == nullptr);
+  EXPECT_EQ(compilation_type_full->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
+  EXPECT_EQ(OatFileAssistant::kFullCompilation, compilation_type_full->GetInt(dexfile.Get()));
+
+  ArtField* compilation_type_profile_guide = mirror::Class::FindStaticField(
+      soa.Self(), dexfile, "COMPILATION_TYPE_PROFILE_GUIDE", "I");
+  ASSERT_FALSE(compilation_type_profile_guide == nullptr);
+  EXPECT_EQ(compilation_type_profile_guide->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
+  EXPECT_EQ(OatFileAssistant::kProfileGuideCompilation,
+            compilation_type_profile_guide->GetInt(dexfile.Get()));
+
+  ArtField* compilation_type_extract_only = mirror::Class::FindStaticField(
+      soa.Self(), dexfile, "COMPILATION_TYPE_EXTRACT_ONLY", "I");
+  ASSERT_FALSE(compilation_type_extract_only == nullptr);
+  EXPECT_EQ(compilation_type_extract_only->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
+  EXPECT_EQ(OatFileAssistant::kExtractOnly, compilation_type_extract_only->GetInt(dexfile.Get()));
 }
 
 // TODO: More Tests:
-//  * Image checksum change is out of date for kIntepretOnly, but not
-//    kVerifyAtRuntime. But target of kVerifyAtRuntime still says current
-//    kInterpretOnly is out of date.
 //  * Test class linker falls back to unquickened dex for DexNoOat
 //  * Test class linker falls back to unquickened dex for MultiDexNoOat
 //  * Test using secondary isa
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 34b00a0..3ec3826 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -308,10 +308,13 @@
   Locks::mutator_lock_->AssertNotHeld(self);
   Runtime* const runtime = Runtime::Current();
 
+  int target_compilation_type_mask = OatFileAssistant::kFullCompilation
+    | OatFileAssistant::kProfileGuideCompilation
+    | OatFileAssistant::kExtractOnly;
   OatFileAssistant oat_file_assistant(dex_location,
                                       oat_location,
+                                      target_compilation_type_mask,
                                       kRuntimeISA,
-                                      /*profile_changed*/false,
                                       !runtime->IsAotCompiler());
 
   // Lock the target oat location to avoid races generating and loading the
@@ -327,7 +330,7 @@
 
   // Update the oat file on disk if we can. This may fail, but that's okay.
   // Best effort is all that matters here.
-  if (!oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, /*out*/ &error_msg)) {
+  if (!oat_file_assistant.MakeUpToDate(/*out*/&error_msg)) {
     LOG(INFO) << error_msg;
   }
 
@@ -481,7 +484,15 @@
     if (ContainsElement(boot_oat_files, oat_file.get())) {
       continue;
     }
-    os << oat_file->GetLocation() << ": " << oat_file->GetCompilerFilter() << "\n";
+    // Use "platform-default" if it's neither extract nor profile guided.
+    // Saying 'full' could be misleading if for example the platform uses
+    // compiler filters.
+    const char* status = oat_file->IsExtractOnly()
+        ? OatHeader::kExtractOnlyValue
+        : oat_file->IsProfileGuideCompiled()
+            ? OatHeader::kProfileGuideCompiledValue
+            : "platform-default";
+    os << oat_file->GetLocation() << ": " << status << "\n";
   }
 }
 
diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc
index 0dab400..82e1fc8 100644
--- a/test/117-nopatchoat/nopatchoat.cc
+++ b/test/117-nopatchoat/nopatchoat.cc
@@ -54,8 +54,7 @@
     }
 
     const OatFile* oat_file = oat_dex_file->GetOatFile();
-    return !oat_file->IsPic()
-        && CompilerFilter::IsCompilationEnabled(oat_file->GetCompilerFilter());
+    return !oat_file->IsPic() && !oat_file->IsExtractOnly();
   }
 };