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 28fd9b9..c998e20 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -198,6 +198,10 @@
   return HasOriginalDexFiles() ? kDex2OatNeeded : kNoDexOptNeeded;
 }
 
+bool OatFileAssistant::IsUpToDate() {
+  return OatFileIsUpToDate() || OdexFileIsUpToDate();
+}
+
 OatFileAssistant::ResultOfAttemptToUpdate
 OatFileAssistant::MakeUpToDate(CompilerFilter::Filter target, std::string* error_msg) {
   switch (GetDexOptNeeded(target)) {
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 34925cd..63d5022 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 8bebf80..aff479f 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -588,22 +588,24 @@
 
   const OatFile* source_oat_file = nullptr;
 
-  // Update the oat file on disk if we can. This may fail, but that's okay.
-  // Best effort is all that matters here.
-  switch (oat_file_assistant.MakeUpToDate(filter_, /*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. This may fail, but that's okay.
+    // Best effort is all that matters here.
+    switch (oat_file_assistant.MakeUpToDate(filter_, /*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.