Pass the same fd when compiling due to boot image update.

Test: device boots, apps get installed, OTA uses same vdex.
Change-Id: I913062630640f31a18d23b2f62afd74986322e6a
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 37f3290..4713b9d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1149,7 +1149,13 @@
             ALOGE("installd cannot compute input vdex location for '%s'\n", path);
             return -1;
         }
-        in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+        if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
+            // When we dex2oat because iof boot image change, we are going to update
+            // in-place the vdex file.
+            in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
+        } else {
+            in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+        }
     }
 
     // Infer the name of the output VDEX and create it.
@@ -1157,14 +1163,26 @@
     if (out_vdex_path_str.empty()) {
         return -1;
     }
-    Dex2oatFileWrapper<std::function<void ()>> out_vdex_fd(
-            open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
-            [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
-    if (out_vdex_fd.get() < 0) {
-        ALOGE("installd cannot open '%s' for output during dexopt\n", out_vdex_path_str.c_str());
-        return -1;
+    Dex2oatFileWrapper<std::function<void ()>> out_vdex_wrapper_fd;
+    int out_vdex_fd = -1;
+
+    // If we are compiling because the boot image is out of date, we do not
+    // need to recreate a vdex, and can use the same existing one.
+    if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
+            in_vdex_fd != -1 &&
+            in_vdex_path_str == out_vdex_path_str) {
+        out_vdex_fd = in_vdex_fd;
+    } else {
+        out_vdex_wrapper_fd.reset(
+              open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+        out_vdex_fd = out_vdex_wrapper_fd.get();
+        if (out_vdex_fd < 0) {
+            ALOGE("installd cannot open '%s' for output during dexopt\n", out_vdex_path_str.c_str());
+            return -1;
+        }
     }
-    if (!set_permissions_and_ownership(out_vdex_fd.get(), is_public,
+    if (!set_permissions_and_ownership(out_vdex_fd, is_public,
                 uid, out_vdex_path_str.c_str())) {
         return -1;
     }
@@ -1247,7 +1265,7 @@
             run_patchoat(input_fd.get(),
                          in_vdex_fd.get(),
                          out_oat_fd.get(),
-                         out_vdex_fd.get(),
+                         out_vdex_fd,
                          input_file,
                          in_vdex_path_str.c_str(),
                          out_oat_path,
@@ -1260,7 +1278,7 @@
             run_dex2oat(input_fd.get(),
                         out_oat_fd.get(),
                         in_vdex_fd.get(),
-                        out_vdex_fd.get(),
+                        out_vdex_fd,
                         image_fd.get(),
                         input_file_name,
                         out_oat_path,
@@ -1291,7 +1309,7 @@
 
     // We've been successful, don't delete output.
     out_oat_fd.SetCleanup(false);
-    out_vdex_fd.SetCleanup(false);
+    out_vdex_wrapper_fd.SetCleanup(false);
     image_fd.SetCleanup(false);
     reference_profile_fd.SetCleanup(false);