ART: Don't attempt write flock if not zygote

When loading an image, don't attempt a RDWR flock if the process
is not the zygote. The lock will be rejected as the process does
not have permission to write the file.

Bug: 28011897

(cherry picked from commit fff377b13469b8c84ce55ee20b10ca80a5a0813d)

Change-Id: I567934c4e9a9a13e9131711240e9ecfdd58b69f7
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 22bf5f9..a84b366 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -407,7 +407,7 @@
                                     &is_global_cache);
   }
 
-  if (Runtime::Current()->IsZygote() && !secondary_image) {
+  if (is_zygote && !secondary_image) {
     MarkZygoteStart(image_isa, Runtime::Current()->GetZygoteMaxFailedBoots());
   }
 
@@ -444,7 +444,7 @@
             // Whether we can write to the cache.
             success = false;
           } else if (secondary_image) {
-            if (Runtime::Current()->IsZygote()) {
+            if (is_zygote) {
               // Secondary image is out of date. Clear cache and exit to let it retry from scratch.
               LOG(ERROR) << "Cannot patch secondary image '" << image_location
                          << "', clearing dalvik_cache and restarting zygote.";
@@ -503,7 +503,16 @@
       // descriptor (and the associated exclusive lock) to be released when
       // we leave Create.
       ScopedFlock image_lock;
-      image_lock.Init(image_filename->c_str(), error_msg);
+      // Should this be a RDWR lock? This is only a defensive measure, as at
+      // this point the image should exist.
+      // However, only the zygote can write into the global dalvik-cache, so
+      // restrict to zygote processes, or any process that isn't using
+      // /data/dalvik-cache (which we assume to be allowed to write there).
+      const bool rw_lock = is_zygote || !is_global_cache;
+      image_lock.Init(image_filename->c_str(),
+                      rw_lock ? (O_CREAT | O_RDWR) : O_RDONLY /* flags */,
+                      true /* block */,
+                      error_msg);
       VLOG(startup) << "Using image file " << image_filename->c_str() << " for image location "
                     << image_location;
       // If we are in /system we can assume the image is good. We can also