Application image support for installd DO NOT MERGE

DO NOT MERGE

sort of
(cherry picked from commit edc8bc48fbf143e35578bf6cccf980dfab076196)

Bug: 22858531

Change-Id: I5a9dfcf67d2232e8755886085e9ba1bb37494d39
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 1b99582..0acc419 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -742,7 +742,7 @@
     return strcmp(tmp_property_value, "true") == 0;
 }
 
-static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
+static void run_dex2oat(int zip_fd, int oat_fd, int image_fd, const char* input_file_name,
     const char* output_file_name, int swap_fd, const char *instruction_set,
     bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool use_jit)
 {
@@ -822,6 +822,8 @@
     char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX];
     bool have_dex2oat_swap_fd = false;
     char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN];
+    bool have_dex2oat_image_fd = false;
+    char dex2oat_image_fd[strlen("--app-image-fd=") + MAX_INT_LEN];
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
     sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
@@ -834,6 +836,10 @@
         have_dex2oat_swap_fd = true;
         sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
     }
+    if (image_fd >= 0) {
+        have_dex2oat_image_fd = true;
+        sprintf(dex2oat_image_fd, "--app-image-fd=%d", image_fd);
+    }
 
     // use the JIT if either it's specified as a dexopt flag or if the property is set
     use_jit = use_jit || check_boolean_property("debug.usejit");
@@ -875,6 +881,7 @@
                      + (have_dex2oat_compiler_filter_flag ? 1 : 0)
                      + (have_dex2oat_threads_flag ? 1 : 0)
                      + (have_dex2oat_swap_fd ? 1 : 0)
+                     + (have_dex2oat_image_fd ? 1 : 0)
                      + (have_dex2oat_relocation_skip_flag ? 2 : 0)
                      + (generate_debug_info ? 1 : 0)
                      + (debuggable ? 1 : 0)
@@ -909,6 +916,9 @@
     if (have_dex2oat_swap_fd) {
         argv[i++] = dex2oat_swap_fd;
     }
+    if (have_dex2oat_image_fd) {
+        argv[i++] = dex2oat_image_fd;
+    }
     if (generate_debug_info) {
         argv[i++] = "--generate-debug-info";
     }
@@ -1057,9 +1067,10 @@
     struct stat input_stat;
     char out_path[PKG_PATH_MAX];
     char swap_file_name[PKG_PATH_MAX];
+    char image_path[PKG_PATH_MAX];
     const char *input_file;
     char in_odex_path[PKG_PATH_MAX];
-    int res, input_fd=-1, out_fd=-1, swap_fd=-1;
+    int res, input_fd=-1, out_fd=-1, image_fd=-1, swap_fd=-1;
     bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
     bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
     bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
@@ -1162,6 +1173,33 @@
         }
     }
 
+    // Open the image file if there is room in the file path.
+    if (strlen(out_path) + strlen(".art") < PKG_PATH_MAX) {
+        strcpy(image_path, out_path);
+        // Trim the extension.
+        int pos = strlen(image_path);
+        for (; pos >= 0 && image_path[pos] != '.'; --pos) {}
+        if (pos != 0) {
+          image_path[pos] = '\0';  // Trim extension
+        }
+        strcat(image_path, ".art");
+        unlink(image_path);
+        image_fd = open(image_path, O_RDWR | O_CREAT | O_EXCL, 0600);
+        if (image_fd < 0) {
+            // Could not create swap file. Optimistically go on and hope that we can compile
+            // without it.
+            ALOGE("installd could not create '%s' for image file during dexopt\n", image_path);
+        } else if (fchmod(image_fd,
+                       S_IRUSR|S_IWUSR|S_IRGRP |
+                       (is_public ? S_IROTH : 0)) < 0) {
+            ALOGE("installd cannot chmod '%s' during dexopt\n", image_path);
+            image_fd = -1;
+        } else if (fchown(image_fd, AID_SYSTEM, uid) < 0) {
+            ALOGE("installd cannot chown '%s' during dexopt\n", image_path);
+            image_fd = -1;
+        }
+     }
+
     ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
 
     pid_t pid;
@@ -1202,7 +1240,7 @@
             } else {
                 input_file_name++;
             }
-            run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd,
+            run_dex2oat(input_fd, out_fd, image_fd, input_file_name, out_path, swap_fd,
                         instruction_set, vm_safe_mode, debuggable, boot_complete, use_jit);
         } else {
             ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
@@ -1225,9 +1263,12 @@
 
     close(out_fd);
     close(input_fd);
-    if (swap_fd != -1) {
+    if (swap_fd >= 0) {
         close(swap_fd);
     }
+    if (image_fd >= 0) {
+        close(image_fd);
+    }
     return 0;
 
 fail:
@@ -1238,6 +1279,12 @@
     if (input_fd >= 0) {
         close(input_fd);
     }
+    if (swap_fd >= 0) {
+        close(swap_fd);
+    }
+    if (image_fd >= 0) {
+        close(image_fd);
+    }
     return -1;
 }