Only compile dex files if they are not up to date.

Instead of trying to compile them all the time, and relying on file
permissions to keep us from overwriting up-to-date dex files with
different compiler filters.

Bug: 27641809
Bug: 28639246
Bug: 28826195
Change-Id: Ie717089d58517427b6f9a522b48146761c57a1a9
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 64b40b7..218c490 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -220,6 +220,10 @@
   return true;
 }
 
+bool OatFileAssistant::IsUpToDate() {
+  return OatFileIsUpToDate() || OdexFileIsUpToDate();
+}
+
 OatFileAssistant::ResultOfAttemptToUpdate
 OatFileAssistant::MakeUpToDate(std::string* error_msg) {
   CompilerFilter::Filter target;
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index f48cdf3..bb7b408 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -149,6 +149,10 @@
   // given compiler filter.
   DexOptNeeded GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter);
 
+  // Returns true if there is up-to-date code for this dex location,
+  // irrespective of the compiler filter of the up-to-date code.
+  bool IsUpToDate();
+
   // Return code used when attempting to generate updated code.
   enum ResultOfAttemptToUpdate {
     kUpdateFailed,        // We tried making the code up to date, but
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 0af6716..c6a59c2 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -586,23 +586,25 @@
 
   const OatFile* source_oat_file = nullptr;
 
-  // Update the oat file on disk if we can, based on the --compiler-filter
-  // option derived from the current runtime options.
-  // This may fail, but that's okay. Best effort is all that matters here.
-  switch (oat_file_assistant.MakeUpToDate(/*out*/ &error_msg)) {
-    case OatFileAssistant::kUpdateFailed:
-      LOG(WARNING) << error_msg;
-      break;
+  if (!oat_file_assistant.IsUpToDate()) {
+    // Update the oat file on disk if we can, based on the --compiler-filter
+    // option derived from the current runtime options.
+    // This may fail, but that's okay. Best effort is all that matters here.
+    switch (oat_file_assistant.MakeUpToDate(/*out*/ &error_msg)) {
+      case OatFileAssistant::kUpdateFailed:
+        LOG(WARNING) << error_msg;
+        break;
 
-    case OatFileAssistant::kUpdateNotAttempted:
-      // Avoid spamming the logs if we decided not to attempt making the oat
-      // file up to date.
-      VLOG(oat) << error_msg;
-      break;
+      case OatFileAssistant::kUpdateNotAttempted:
+        // Avoid spamming the logs if we decided not to attempt making the oat
+        // file up to date.
+        VLOG(oat) << error_msg;
+        break;
 
-    case OatFileAssistant::kUpdateSucceeded:
-      // Nothing to do.
-      break;
+      case OatFileAssistant::kUpdateSucceeded:
+        // Nothing to do.
+        break;
+    }
   }
 
   // Get the oat file on disk.